aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Transceiver52M/Makefile.am2
-rw-r--r--Transceiver52M/Resampler.cpp32
-rw-r--r--Transceiver52M/Resampler.h9
-rw-r--r--Transceiver52M/radioBuffer.cpp228
-rw-r--r--Transceiver52M/radioBuffer.h45
-rw-r--r--Transceiver52M/radioInterface.cpp202
-rw-r--r--Transceiver52M/radioInterface.h26
-rw-r--r--Transceiver52M/radioInterfaceDiversity.cpp47
-rw-r--r--Transceiver52M/radioInterfaceResamp.cpp81
-rw-r--r--Transceiver52M/sigProcLib.cpp1
-rw-r--r--Transceiver52M/signalVector.cpp9
-rw-r--r--Transceiver52M/signalVector.h1
12 files changed, 426 insertions, 257 deletions
diff --git a/Transceiver52M/Makefile.am b/Transceiver52M/Makefile.am
index 4ec06e0..ec72f8c 100644
--- a/Transceiver52M/Makefile.am
+++ b/Transceiver52M/Makefile.am
@@ -54,6 +54,7 @@ COMMON_SOURCES = \
radioInterface.cpp \
radioVector.cpp \
radioClock.cpp \
+ radioBuffer.cpp \
sigProcLib.cpp \
signalVector.cpp \
Transceiver.cpp
@@ -72,6 +73,7 @@ noinst_HEADERS = \
radioVector.h \
radioClock.h \
radioDevice.h \
+ radioBuffer.h \
sigProcLib.h \
signalVector.h \
Transceiver.h \
diff --git a/Transceiver52M/Resampler.cpp b/Transceiver52M/Resampler.cpp
index e4b66a7..070adda 100644
--- a/Transceiver52M/Resampler.cpp
+++ b/Transceiver52M/Resampler.cpp
@@ -167,22 +167,13 @@ void Resampler::computePath()
}
}
-int Resampler::rotate(float *in, size_t in_len, float *out, size_t out_len)
+int Resampler::rotate(const float *in, size_t in_len, float *out, size_t out_len)
{
int n, path;
- int hist_len = filt_len - 1;
if (!check_vec_len(in_len, out_len, p, q))
return -1;
- if (history_on) {
- memcpy(&in[-2 * hist_len],
- history, hist_len * 2 * sizeof(float));
- } else {
- memset(&in[-2 * hist_len], 0,
- hist_len * 2 * sizeof(float));
- }
-
/* Generate output from precomputed input/output paths */
for (size_t i = 0; i < out_len; i++) {
n = in_index[i];
@@ -194,27 +185,15 @@ int Resampler::rotate(float *in, size_t in_len, float *out, size_t out_len)
n, 1, 1, 0);
}
- /* Save history */
- if (history_on) {
- memcpy(history, &in[2 * (in_len - hist_len)],
- hist_len * 2 * sizeof(float));
- }
-
return out_len;
}
bool Resampler::init(float bw)
{
- size_t hist_len = filt_len - 1;
-
/* Filterbank filter internals */
if (initFilters(bw) < 0)
return false;
- /* History buffer */
- history = new float[2 * hist_len];
- memset(history, 0, 2 * hist_len * sizeof(float));
-
/* Precompute filterbank paths */
in_index = new size_t[MAX_OUTPUT_LEN];
out_path = new size_t[MAX_OUTPUT_LEN];
@@ -228,14 +207,8 @@ size_t Resampler::len()
return filt_len;
}
-void Resampler::enableHistory(bool on)
-{
- history_on = on;
-}
-
Resampler::Resampler(size_t p, size_t q, size_t filt_len)
- : in_index(NULL), out_path(NULL), partitions(NULL),
- history(NULL), history_on(true)
+ : in_index(NULL), out_path(NULL), partitions(NULL)
{
this->p = p;
this->q = q;
@@ -246,7 +219,6 @@ Resampler::~Resampler()
{
releaseFilters();
- delete history;
delete in_index;
delete out_path;
}
diff --git a/Transceiver52M/Resampler.h b/Transceiver52M/Resampler.h
index 072ec92..c9f9787 100644
--- a/Transceiver52M/Resampler.h
+++ b/Transceiver52M/Resampler.h
@@ -52,18 +52,13 @@ public:
* Input and output vector lengths must of be equal multiples of the
* rational conversion rate denominator and numerator respectively.
*/
- int rotate(float *in, size_t in_len, float *out, size_t out_len);
+ int rotate(const float *in, size_t in_len, float *out, size_t out_len);
/* Get filter length
* @return number of taps in each filter partition
*/
size_t len();
- /*
- * Enable/disable history
- */
- void enableHistory(bool on);
-
private:
size_t p;
size_t q;
@@ -72,8 +67,6 @@ private:
size_t *out_path;
float **partitions;
- float *history;
- bool history_on;
bool initFilters(float bw);
void releaseFilters();
diff --git a/Transceiver52M/radioBuffer.cpp b/Transceiver52M/radioBuffer.cpp
new file mode 100644
index 0000000..9e6f079
--- /dev/null
+++ b/Transceiver52M/radioBuffer.cpp
@@ -0,0 +1,228 @@
+/*
+ * Segmented Ring Buffer
+ *
+ * Copyright (C) 2015 Ettus Research LLC
+ *
+ * Author: Tom Tsou <tom@tsou.cc>
+ *
+ * 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 <string.h>
+#include <iostream>
+#include "radioBuffer.h"
+
+RadioBuffer::RadioBuffer(size_t numSegments, size_t segmentLen,
+ size_t hLen, bool outDirection)
+ : writeIndex(0), readIndex(0), availSamples(0)
+{
+ if (!outDirection)
+ hLen = 0;
+
+ buffer = new float[2 * (hLen + numSegments * segmentLen)];
+ bufferLen = numSegments * segmentLen;
+
+ segments.resize(numSegments);
+
+ for (size_t i = 0; i < numSegments; i++)
+ segments[i] = &buffer[2 * (hLen + i * segmentLen)];
+
+ this->outDirection = outDirection;
+ this->numSegments = numSegments;
+ this->segmentLen = segmentLen;
+ this->hLen = hLen;
+}
+
+RadioBuffer::~RadioBuffer()
+{
+ delete buffer;
+}
+
+void RadioBuffer::reset()
+{
+ writeIndex = 0;
+ readIndex = 0;
+ availSamples = 0;
+}
+
+/*
+ * Output direction
+ *
+ * Return a pointer to the oldest segment or NULL if a complete segment is not
+ * available.
+ */
+const float *RadioBuffer::getReadSegment()
+{
+ if (!outDirection) {
+ std::cout << "Invalid direction" << std::endl;
+ return NULL;
+ }
+ if (availSamples < segmentLen) {
+ std::cout << "Not enough samples " << std::endl;
+ std::cout << availSamples << " available per segment "
+ << segmentLen << std::endl;
+ return NULL;
+ }
+
+ size_t num = readIndex / segmentLen;
+
+ if (num >= numSegments) {
+ std::cout << "Invalid segment" << std::endl;
+ return NULL;
+ } else if (!num) {
+ memcpy(buffer,
+ &buffer[2 * bufferLen],
+ hLen * 2 * sizeof(float));
+ }
+
+ availSamples -= segmentLen;
+ readIndex = (readIndex + segmentLen) % bufferLen;
+
+ return segments[num];
+}
+
+/*
+ * Output direction
+ *
+ * Write a non-segment length of samples to the buffer.
+ */
+bool RadioBuffer::write(const float *wr, size_t len)
+{
+ if (!outDirection) {
+ std::cout << "Invalid direction" << std::endl;
+ return false;
+ }
+ if (availSamples + len > bufferLen) {
+ std::cout << "Insufficient space" << std::endl;
+ std::cout << bufferLen - availSamples << " available per write "
+ << len << std::endl;
+ return false;
+ }
+
+ if (writeIndex + len <= bufferLen) {
+ memcpy(&buffer[2 * (writeIndex + hLen)],
+ wr, len * 2 * sizeof(float));
+ } else {
+ size_t len0 = bufferLen - writeIndex;
+ size_t len1 = len - len0;
+ memcpy(&buffer[2 * (writeIndex + hLen)], wr, len0 * 2 * sizeof(float));
+ memcpy(&buffer[2 * hLen], &wr[2 * len0], len1 * 2 * sizeof(float));
+ }
+
+ availSamples += len;
+ writeIndex = (writeIndex + len) % bufferLen;
+
+ return true;
+}
+
+bool RadioBuffer::zero(size_t len)
+{
+ if (!outDirection) {
+ std::cout << "Invalid direction" << std::endl;
+ return false;
+ }
+ if (availSamples + len > bufferLen) {
+ std::cout << "Insufficient space" << std::endl;
+ std::cout << bufferLen - availSamples << " available per zero "
+ << len << std::endl;
+ return false;
+ }
+
+ if (writeIndex + len <= bufferLen) {
+ memset(&buffer[2 * (writeIndex + hLen)],
+ 0, len * 2 * sizeof(float));
+ } else {
+ size_t len0 = bufferLen - writeIndex;
+ size_t len1 = len - len0;
+ memset(&buffer[2 * (writeIndex + hLen)], 0, len0 * 2 * sizeof(float));
+ memset(&buffer[2 * hLen], 0, len1 * 2 * sizeof(float));
+ }
+
+ availSamples += len;
+ writeIndex = (writeIndex + len) % bufferLen;
+
+ return true;
+}
+
+/*
+ * Input direction
+ */
+float *RadioBuffer::getWriteSegment()
+{
+ if (outDirection) {
+ std::cout << "Invalid direction" << std::endl;
+ return NULL;
+ }
+ if (bufferLen - availSamples < segmentLen) {
+ std::cout << "Insufficient samples" << std::endl;
+ std::cout << bufferLen - availSamples
+ << " available for segment " << segmentLen
+ << std::endl;
+ return NULL;
+ }
+ if (writeIndex % segmentLen) {
+ std::cout << "Internal segment error" << std::endl;
+ return NULL;
+ }
+
+ size_t num = writeIndex / segmentLen;
+
+ if (num >= numSegments)
+ return NULL;
+
+ availSamples += segmentLen;
+ writeIndex = (writeIndex + segmentLen) % bufferLen;
+
+ return segments[num];
+}
+
+bool RadioBuffer::zeroWriteSegment()
+{
+ float *segment = getWriteSegment();
+ if (!segment)
+ return false;
+
+ memset(segment, 0, segmentLen * 2 * sizeof(float));
+
+ return true;
+}
+
+bool RadioBuffer::read(float *rd, size_t len)
+{
+ if (outDirection) {
+ std::cout << "Invalid direction" << std::endl;
+ return false;
+ }
+ if (availSamples < len) {
+ std::cout << "Insufficient samples" << std::endl;
+ std::cout << availSamples << " available for "
+ << len << std::endl;
+ return false;
+ }
+
+ if (readIndex + len <= bufferLen) {
+ memcpy(rd, &buffer[2 * readIndex], len * 2 * sizeof(float));
+ } else {
+ size_t len0 = bufferLen - readIndex;
+ size_t len1 = len - len0;
+ memcpy(rd, &buffer[2 * readIndex], len0 * 2 * sizeof(float));
+ memcpy(&rd[2 * len0], buffer, len1 * 2 * sizeof(float));
+ }
+
+ availSamples -= len;
+ readIndex = (readIndex + len) % bufferLen;
+
+ return true;
+}
diff --git a/Transceiver52M/radioBuffer.h b/Transceiver52M/radioBuffer.h
new file mode 100644
index 0000000..afb6e63
--- /dev/null
+++ b/Transceiver52M/radioBuffer.h
@@ -0,0 +1,45 @@
+#include <stdlib.h>
+#include <stddef.h>
+#include <vector>
+
+class RadioBuffer {
+public:
+ RadioBuffer(size_t numSegments, size_t segmentLen,
+ size_t hLen, bool outDirection);
+
+ ~RadioBuffer();
+
+ const size_t getSegmentLen() { return segmentLen; };
+ const size_t getNumSegments() { return numSegments; };
+ const size_t getAvailSamples() { return availSamples; };
+ const size_t getAvailSegments() { return availSamples / segmentLen; };
+
+ const size_t getFreeSamples()
+ {
+ return bufferLen - availSamples;
+ }
+
+ const size_t getFreeSegments()
+ {
+ return getFreeSamples() / segmentLen;
+ }
+
+ void reset();
+
+ /* Output direction */
+ const float *getReadSegment();
+ bool write(const float *wr, size_t len);
+ bool zero(size_t len);
+
+ /* Input direction */
+ float *getWriteSegment();
+ bool zeroWriteSegment();
+ bool read(float *rd, size_t len);
+
+private:
+ size_t writeIndex, readIndex, availSamples;
+ size_t bufferLen, numSegments, segmentLen, hLen;
+ float *buffer;
+ std::vector<float *> segments;
+ bool outDirection;
+};
diff --git a/Transceiver52M/radioInterface.cpp b/Transceiver52M/radioInterface.cpp
index b719c94..052b439 100644
--- a/Transceiver52M/radioInterface.cpp
+++ b/Transceiver52M/radioInterface.cpp
@@ -1,26 +1,23 @@
/*
-* Copyright 2008, 2009 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/>.
-
-*/
+ * Radio device interface
+ *
+ * Copyright (C) 2008-2014 Free Software Foundation, Inc.
+ * Copyright (C) 2015 Ettus Research LLC
+ *
+ * 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 "Resampler.h"
@@ -37,8 +34,8 @@ RadioInterface::RadioInterface(RadioDevice *wRadio, size_t tx_sps,
size_t rx_sps, size_t chans, size_t diversity,
int wReceiveOffset, GSM::Time wStartTime)
: mRadio(wRadio), mSPSTx(tx_sps), mSPSRx(rx_sps), mChans(chans),
- mMIMO(diversity), sendCursor(0), recvCursor(0), underrun(false),
- overrun(false), receiveOffset(wReceiveOffset), mOn(false)
+ mMIMO(diversity), underrun(false), overrun(false),
+ receiveOffset(wReceiveOffset), mOn(false)
{
mClock.set(wStartTime);
}
@@ -65,35 +62,20 @@ bool RadioInterface::init(int type)
powerScaling.resize(mChans);
for (size_t i = 0; i < mChans; i++) {
- sendBuffer[i] = new signalVector(CHUNK * mSPSTx);
- recvBuffer[i] = new signalVector(NUMCHUNKS * CHUNK * mSPSRx);
+ sendBuffer[i] = new RadioBuffer(NUMCHUNKS, CHUNK * mSPSTx, 0, true);
+ recvBuffer[i] = new RadioBuffer(NUMCHUNKS, CHUNK * mSPSRx, 0, false);
- convertSendBuffer[i] = new short[sendBuffer[i]->size() * 2];
- convertRecvBuffer[i] = new short[recvBuffer[i]->size() * 2];
+ convertSendBuffer[i] = new short[CHUNK * mSPSTx * 2];
+ convertRecvBuffer[i] = new short[CHUNK * mSPSRx * 2];
powerScaling[i] = 1.0;
}
- sendCursor = 0;
- recvCursor = 0;
-
return true;
}
void RadioInterface::close()
{
- for (size_t i = 0; i < sendBuffer.size(); i++)
- delete sendBuffer[i];
-
- for (size_t i = 0; i < recvBuffer.size(); i++)
- delete recvBuffer[i];
-
- for (size_t i = 0; i < convertSendBuffer.size(); i++)
- delete convertSendBuffer[i];
-
- for (size_t i = 0; i < convertRecvBuffer.size(); i++)
- delete convertRecvBuffer[i];
-
sendBuffer.resize(0);
recvBuffer.resize(0);
convertSendBuffer.resize(0);
@@ -132,35 +114,26 @@ int RadioInterface::setPowerAttenuation(int atten, size_t chan)
}
int RadioInterface::radioifyVector(signalVector &wVector,
- float *retVector,
- bool zero)
+ size_t chan, bool zero)
{
- if (zero) {
- memset(retVector, 0, wVector.size() * 2 * sizeof(float));
- return wVector.size();
- }
-
- memcpy(retVector, wVector.begin(), wVector.size() * 2 * sizeof(float));
+ if (zero)
+ sendBuffer[chan]->zero(wVector.size());
+ else
+ sendBuffer[chan]->write((float *) wVector.begin(), wVector.size());
return wVector.size();
}
-int RadioInterface::unRadioifyVector(float *floatVector,
- signalVector& newVector)
+int RadioInterface::unRadioifyVector(signalVector *newVector, size_t chan)
{
- signalVector::iterator itr = newVector.begin();
-
- if (newVector.size() > recvCursor) {
+ if (newVector->size() > recvBuffer[chan]->getAvailSamples()) {
LOG(ALERT) << "Insufficient number of samples in receive buffer";
return -1;
}
- for (size_t i = 0; i < newVector.size(); i++) {
- *itr++ = Complex<float>(floatVector[2 * i + 0],
- floatVector[2 * i + 1]);
- }
+ recvBuffer[chan]->read((float *) newVector->begin(), newVector->size());
- return newVector.size();
+ return newVector->size();
}
bool RadioInterface::tuneTx(double freq, size_t chan)
@@ -187,8 +160,10 @@ bool RadioInterface::start()
if (!mRadio->start())
return false;
- recvCursor = 0;
- sendCursor = 0;
+ for (size_t i = 0; i < mChans; i++) {
+ sendBuffer[i]->reset();
+ recvBuffer[i]->reset();
+ }
writeTimestamp = mRadio->initialWriteTimestamp();
readTimestamp = mRadio->initialReadTimestamp();
@@ -239,14 +214,10 @@ void RadioInterface::driveTransmitRadio(std::vector<signalVector *> &bursts,
if (!mOn)
return;
- for (size_t i = 0; i < mChans; i++) {
- radioifyVector(*bursts[i],
- (float *) (sendBuffer[i]->begin() + sendCursor), zeros[i]);
- }
-
- sendCursor += bursts[0]->size();
+ for (size_t i = 0; i < mChans; i++)
+ radioifyVector(*bursts[i], i, zeros[i]);
- pushBuffer();
+ while (pushBuffer());
}
bool RadioInterface::driveReceiveRadio()
@@ -261,8 +232,7 @@ bool RadioInterface::driveReceiveRadio()
GSM::Time rcvClock = mClock.get();
rcvClock.decTN(receiveOffset);
unsigned tN = rcvClock.TN();
- int recvSz = recvCursor;
- int readSz = 0;
+ int recvSz = recvBuffer[0]->getAvailSamples();
const int symbolsPerSlot = gSlotLen + 8;
int burstSize;
@@ -285,11 +255,8 @@ bool RadioInterface::driveReceiveRadio()
for (size_t i = 0; i < mChans; i++) {
burst = new radioVector(rcvClock, burstSize, head, mMIMO);
- for (size_t n = 0; n < mMIMO; n++) {
- unRadioifyVector((float *)
- (recvBuffer[mMIMO * i + n]->begin() + readSz),
- *burst->getVector(n));
- }
+ for (size_t n = 0; n < mMIMO; n++)
+ unRadioifyVector(burst->getVector(n), i);
if (mReceiveFIFO[i].size() < 32)
mReceiveFIFO[i].write(burst);
@@ -299,7 +266,6 @@ bool RadioInterface::driveReceiveRadio()
mClock.incTN();
rcvClock.incTN();
- readSz += burstSize;
recvSz -= burstSize;
tN = rcvClock.TN();
@@ -308,16 +274,6 @@ bool RadioInterface::driveReceiveRadio()
burstSize = (symbolsPerSlot + (tN % 4 == 0)) * mSPSRx;
}
- if (readSz > 0) {
- for (size_t i = 0; i < recvBuffer.size(); i++) {
- memmove(recvBuffer[i]->begin(),
- recvBuffer[i]->begin() + readSz,
- (recvCursor - readSz) * 2 * sizeof(float));
- }
-
- recvCursor -= readSz;
- }
-
return true;
}
@@ -339,74 +295,66 @@ VectorFIFO* RadioInterface::receiveFIFO(size_t chan)
double RadioInterface::setRxGain(double dB, size_t chan)
{
- if (mRadio)
- return mRadio->setRxGain(dB, chan);
- else
- return -1;
+ return mRadio->setRxGain(dB, chan);
}
double RadioInterface::getRxGain(size_t chan)
{
- if (mRadio)
- return mRadio->getRxGain(chan);
- else
- return -1;
+ return mRadio->getRxGain(chan);
}
/* Receive a timestamped chunk from the device */
void RadioInterface::pullBuffer()
{
bool local_underrun;
- int num_recv;
- float *output;
+ size_t numRecv, segmentLen = recvBuffer[0]->getSegmentLen();
- if (recvCursor > recvBuffer[0]->size() - CHUNK)
+ if (recvBuffer[0]->getFreeSegments() <= 0)
return;
/* Outer buffer access size is fixed */
- num_recv = mRadio->readSamples(convertRecvBuffer,
- CHUNK,
- &overrun,
- readTimestamp,
- &local_underrun);
- if (num_recv != CHUNK) {
- LOG(ALERT) << "Receive error " << num_recv;
+ numRecv = mRadio->readSamples(convertRecvBuffer,
+ segmentLen,
+ &overrun,
+ readTimestamp,
+ &local_underrun);
+
+ if (numRecv != segmentLen) {
+ LOG(ALERT) << "Receive error " << numRecv;
return;
}
for (size_t i = 0; i < mChans; i++) {
- output = (float *) (recvBuffer[i]->begin() + recvCursor);
- convert_short_float(output, convertRecvBuffer[i], 2 * num_recv);
+ convert_short_float(recvBuffer[i]->getWriteSegment(),
+ convertRecvBuffer[i],
+ segmentLen * 2);
}
underrun |= local_underrun;
-
- readTimestamp += num_recv;
- recvCursor += num_recv;
+ readTimestamp += numRecv;
}
/* Send timestamped chunk to the device with arbitrary size */
-void RadioInterface::pushBuffer()
+bool RadioInterface::pushBuffer()
{
- int num_sent;
+ size_t numSent, segmentLen = sendBuffer[0]->getSegmentLen();
- if (sendCursor < CHUNK)
- return;
-
- if (sendCursor > sendBuffer[0]->size())
- LOG(ALERT) << "Send buffer overflow";
+ if (sendBuffer[0]->getAvailSegments() < 1)
+ return false;
for (size_t i = 0; i < mChans; i++) {
convert_float_short(convertSendBuffer[i],
- (float *) sendBuffer[i]->begin(),
- powerScaling[i], 2 * sendCursor);
+ (float *) sendBuffer[0]->getReadSegment(),
+ powerScaling[i],
+ segmentLen * 2);
}
- /* Send the all samples in the send buffer */
- num_sent = mRadio->writeSamples(convertSendBuffer,
- sendCursor,
- &underrun,
- writeTimestamp);
- writeTimestamp += num_sent;
- sendCursor = 0;
+ /* Send the all samples in the send buffer */
+ numSent = mRadio->writeSamples(convertSendBuffer,
+ segmentLen,
+ &underrun,
+ writeTimestamp);
+ writeTimestamp += numSent;
+
+ return true;
}
diff --git a/Transceiver52M/radioInterface.h b/Transceiver52M/radioInterface.h
index ce06578..1f225a2 100644
--- a/Transceiver52M/radioInterface.h
+++ b/Transceiver52M/radioInterface.h
@@ -20,6 +20,7 @@
#include "radioDevice.h"
#include "radioVector.h"
#include "radioClock.h"
+#include "radioBuffer.h"
#include "Resampler.h"
static const unsigned gSlotLen = 148; ///< number of symbols per slot, not counting guard periods
@@ -40,10 +41,8 @@ protected:
size_t mChans;
size_t mMIMO;
- std::vector<signalVector *> sendBuffer;
- std::vector<signalVector *> recvBuffer;
- unsigned sendCursor;
- unsigned recvCursor;
+ std::vector<RadioBuffer *> sendBuffer;
+ std::vector<RadioBuffer *> recvBuffer;
std::vector<short *> convertRecvBuffer;
std::vector<short *> convertSendBuffer;
@@ -61,16 +60,14 @@ protected:
private:
- /** format samples to USRP */
- int radioifyVector(signalVector &wVector,
- float *floatVector,
- bool zero);
+ /** format samples to USRP */
+ int radioifyVector(signalVector &wVector, size_t chan, bool zero);
/** format samples from USRP */
- int unRadioifyVector(float *floatVector, signalVector &wVector);
+ int unRadioifyVector(signalVector *wVector, size_t chan);
/** push GSM bursts into the transmit buffer */
- virtual void pushBuffer(void);
+ virtual bool pushBuffer(void);
/** pull GSM bursts from the receive buffer */
virtual void pullBuffer(void);
@@ -152,20 +149,15 @@ void *AlignRadioServiceLoopAdapter(RadioInterface*);
#endif
class RadioInterfaceResamp : public RadioInterface {
-
private:
- signalVector *innerSendBuffer;
signalVector *outerSendBuffer;
- signalVector *innerRecvBuffer;
signalVector *outerRecvBuffer;
- void pushBuffer();
+ bool pushBuffer();
void pullBuffer();
public:
-
RadioInterfaceResamp(RadioDevice* wRadio, size_t wSPS = 4, size_t chans = 1);
-
~RadioInterfaceResamp();
bool init(int type);
@@ -184,7 +176,7 @@ public:
bool tuneRx(double freq, size_t chan);
private:
- std::vector<Resampler *> dnsamplers;
+ Resampler *dnsampler;
std::vector<float> phases;
signalVector *outerRecvBuffer;
diff --git a/Transceiver52M/radioInterfaceDiversity.cpp b/Transceiver52M/radioInterfaceDiversity.cpp
index 8e921b1..b3973e5 100644
--- a/Transceiver52M/radioInterfaceDiversity.cpp
+++ b/Transceiver52M/radioInterfaceDiversity.cpp
@@ -65,14 +65,11 @@ RadioInterfaceDiversity::~RadioInterfaceDiversity()
void RadioInterfaceDiversity::close()
{
delete outerRecvBuffer;
+ delete dnsampler;
+ dnsampler = NULL;
outerRecvBuffer = NULL;
- for (size_t i = 0; i < dnsamplers.size(); i++) {
- delete dnsamplers[i];
- dnsamplers[i] = NULL;
- }
-
if (recvBuffer.size())
recvBuffer[0] = NULL;
@@ -98,15 +95,16 @@ bool RadioInterfaceDiversity::setupDiversityChannels()
return false;
}
+ dnsampler = new Resampler(resamp_inrate, resamp_outrate);
+ if (!dnsampler->init()) {
+ LOG(ALERT) << "Rx resampler failed to initialize";
+ return false;
+ }
+
/* One Receive buffer and downsampler per diversity channel */
for (size_t i = 0; i < mMIMO * mChans; i++) {
- dnsamplers[i] = new Resampler(resamp_inrate, resamp_outrate);
- if (!dnsamplers[i]->init()) {
- LOG(ALERT) << "Rx resampler failed to initialize";
- return false;
- }
-
- recvBuffer[i] = new signalVector(inner_rx_len);
+ recvBuffer[i] = new RadioBuffer(NUMCHUNKS,
+ resamp_inchunk, 0, false);
}
return true;
@@ -115,7 +113,7 @@ bool RadioInterfaceDiversity::setupDiversityChannels()
/* Initialize I/O specific objects */
bool RadioInterfaceDiversity::init(int type)
{
- int tx_len, outer_rx_len;
+ int outer_rx_len;
if ((mMIMO != 2) || (mChans != 2)) {
LOG(ALERT) << "Unsupported channel configuration " << mChans;
@@ -128,13 +126,11 @@ bool RadioInterfaceDiversity::init(int type)
convertSendBuffer.resize(mChans);
convertRecvBuffer.resize(mChans);
mReceiveFIFO.resize(mChans);
- dnsamplers.resize(mChans * mMIMO);
phases.resize(mChans);
if (!setupDiversityChannels())
return false;
- tx_len = CHUNK * mSPSTx;
outer_rx_len = resamp_outchunk;
for (size_t i = 0; i < mChans; i++) {
@@ -142,11 +138,11 @@ bool RadioInterfaceDiversity::init(int type)
convertRecvBuffer[i] = new short[outer_rx_len * 2];
/* Send buffers (not-resampled) */
- sendBuffer[i] = new signalVector(tx_len);
- convertSendBuffer[i] = new short[tx_len * 2];
+ sendBuffer[i] = new RadioBuffer(NUMCHUNKS, CHUNK * mSPSTx, 0, true);
+ convertSendBuffer[i] = new short[CHUNK * mSPSTx * 2];
}
- outerRecvBuffer = new signalVector(outer_rx_len, dnsamplers[0]->len());
+ outerRecvBuffer = new signalVector(outer_rx_len, dnsampler->len());
return true;
}
@@ -182,7 +178,7 @@ void RadioInterfaceDiversity::pullBuffer()
signalVector *shift, *base;
float *in, *out, rate = -mFreqSpacing * 2.0 * M_PI / 1.08333333e6;
- if (recvCursor > recvBuffer[0]->size() - resamp_inchunk)
+ if (recvBuffer[0]->getFreeSegments() <= 0)
return;
/* Outer buffer access size is fixed */
@@ -211,10 +207,10 @@ void RadioInterfaceDiversity::pullBuffer()
/* Diversity path 1 */
base = outerRecvBuffer;
in = (float *) base->begin();
- out = (float *) (recvBuffer[path0]->begin() + recvCursor);
+ out = (float *) recvBuffer[path0]->getWriteSegment();
- rc = dnsamplers[2 * i + 0]->rotate(in, resamp_outchunk,
- out, resamp_inchunk);
+ rc = dnsampler->rotate(in, resamp_outchunk,
+ out, resamp_inchunk);
if (rc < 0) {
LOG(ALERT) << "Sample rate downsampling error";
}
@@ -226,15 +222,15 @@ void RadioInterfaceDiversity::pullBuffer()
/* Diversity path 2 */
shift = new signalVector(base->size(), base->getStart());
in = (float *) shift->begin();
- out = (float *) (recvBuffer[path1]->begin() + recvCursor);
+ out = (float *) recvBuffer[path1]->getWriteSegment();
rate = i ? -rate : rate;
if (!frequencyShift(shift, base, rate, phases[i], &phases[i])) {
LOG(ALERT) << "Frequency shift failed";
}
- rc = dnsamplers[2 * i + 1]->rotate(in, resamp_outchunk,
- out, resamp_inchunk);
+ rc = dnsampler->rotate(in, resamp_outchunk,
+ out, resamp_inchunk);
if (rc < 0) {
LOG(ALERT) << "Sample rate downsampling error";
}
@@ -244,5 +240,4 @@ void RadioInterfaceDiversity::pullBuffer()
underrun |= local_underrun;
readTimestamp += (TIMESTAMP) resamp_outchunk;
- recvCursor += resamp_inchunk;
}
diff --git a/Transceiver52M/radioInterfaceResamp.cpp b/Transceiver52M/radioInterfaceResamp.cpp
index f898d65..26dd40b 100644
--- a/Transceiver52M/radioInterfaceResamp.cpp
+++ b/Transceiver52M/radioInterfaceResamp.cpp
@@ -1,8 +1,10 @@
/*
* Radio device interface with sample rate conversion
- * Written by Thomas Tsou <tom@tsou.cc>
*
- * Copyright 2011, 2012, 2013 Free Software Foundation, Inc.
+ * Copyright (C) 2011-2014 Free Software Foundation, Inc.
+ * Copyright (C) 2015 Ettus Research LLC
+ *
+ * Author: Tom Tsou <tom@tsou.cc>
*
* 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
@@ -58,8 +60,8 @@ static size_t resamp_outchunk = 0;
RadioInterfaceResamp::RadioInterfaceResamp(RadioDevice *wRadio,
size_t sps, size_t chans)
: RadioInterface(wRadio, sps, chans),
- innerSendBuffer(NULL), outerSendBuffer(NULL),
- innerRecvBuffer(NULL), outerRecvBuffer(NULL)
+ outerSendBuffer(NULL),
+ outerRecvBuffer(NULL)
{
}
@@ -70,17 +72,13 @@ RadioInterfaceResamp::~RadioInterfaceResamp()
void RadioInterfaceResamp::close()
{
- delete innerSendBuffer;
delete outerSendBuffer;
- delete innerRecvBuffer;
delete outerRecvBuffer;
delete upsampler;
delete dnsampler;
- innerSendBuffer = NULL;
outerSendBuffer = NULL;
- innerRecvBuffer = NULL;
outerRecvBuffer = NULL;
upsampler = NULL;
@@ -157,21 +155,18 @@ bool RadioInterfaceResamp::init(int type)
* and requires headroom equivalent to the filter length. Low
* rate buffers are allocated in the main radio interface code.
*/
- innerSendBuffer =
- new signalVector(NUMCHUNKS * resamp_inchunk, upsampler->len());
+ sendBuffer[0] = new RadioBuffer(NUMCHUNKS, resamp_inchunk,
+ upsampler->len(), true);
+ recvBuffer[0] = new RadioBuffer(NUMCHUNKS * 20, resamp_inchunk, 0, false);
+
outerSendBuffer =
new signalVector(NUMCHUNKS * resamp_outchunk);
outerRecvBuffer =
new signalVector(resamp_outchunk, dnsampler->len());
- innerRecvBuffer =
- new signalVector(NUMCHUNKS * resamp_inchunk / mSPSTx);
convertSendBuffer[0] = new short[outerSendBuffer->size() * 2];
convertRecvBuffer[0] = new short[outerRecvBuffer->size() * 2];
- sendBuffer[0] = innerSendBuffer;
- recvBuffer[0] = innerRecvBuffer;
-
return true;
}
@@ -181,7 +176,7 @@ void RadioInterfaceResamp::pullBuffer()
bool local_underrun;
int rc, num_recv;
- if (recvCursor > innerRecvBuffer->size() - resamp_inchunk)
+ if (recvBuffer[0]->getFreeSegments() <= 0)
return;
/* Outer buffer access size is fixed */
@@ -204,57 +199,47 @@ void RadioInterfaceResamp::pullBuffer()
/* Write to the end of the inner receive buffer */
rc = dnsampler->rotate((float *) outerRecvBuffer->begin(),
resamp_outchunk,
- (float *) (innerRecvBuffer->begin() + recvCursor),
+ recvBuffer[0]->getWriteSegment(),
resamp_inchunk);
if (rc < 0) {
LOG(ALERT) << "Sample rate upsampling error";
}
- recvCursor += resamp_inchunk;
+ /* Set history for the next chunk */
+ outerRecvBuffer->updateHistory();
}
/* Send a timestamped chunk to the device */
-void RadioInterfaceResamp::pushBuffer()
+bool RadioInterfaceResamp::pushBuffer()
{
- int rc, chunks, num_sent;
- int inner_len, outer_len;
-
- if (sendCursor < resamp_inchunk)
- return;
-
- if (sendCursor > innerSendBuffer->size())
- LOG(ALERT) << "Send buffer overflow";
+ int rc;
+ size_t numSent;
- chunks = sendCursor / resamp_inchunk;
-
- inner_len = chunks * resamp_inchunk;
- outer_len = chunks * resamp_outchunk;
+ if (sendBuffer[0]->getAvailSegments() <= 0)
+ return false;
/* Always send from the beginning of the buffer */
- rc = upsampler->rotate((float *) innerSendBuffer->begin(), inner_len,
- (float *) outerSendBuffer->begin(), outer_len);
+ rc = upsampler->rotate(sendBuffer[0]->getReadSegment(),
+ resamp_inchunk,
+ (float *) outerSendBuffer->begin(),
+ resamp_outchunk);
if (rc < 0) {
LOG(ALERT) << "Sample rate downsampling error";
}
convert_float_short(convertSendBuffer[0],
(float *) outerSendBuffer->begin(),
- powerScaling[0], 2 * outer_len);
-
- num_sent = mRadio->writeSamples(convertSendBuffer,
- outer_len,
- &underrun,
- writeTimestamp);
- if (num_sent != outer_len) {
- LOG(ALERT) << "Transmit error " << num_sent;
+ powerScaling[0], 2 * resamp_outchunk);
+
+ numSent = mRadio->writeSamples(convertSendBuffer,
+ resamp_outchunk,
+ &underrun,
+ writeTimestamp);
+ if (numSent != resamp_outchunk) {
+ LOG(ALERT) << "Transmit error " << numSent;
}
- /* Shift remaining samples to beginning of buffer */
- memmove(innerSendBuffer->begin(),
- innerSendBuffer->begin() + inner_len,
- (sendCursor - inner_len) * 2 * sizeof(float));
+ writeTimestamp += resamp_outchunk;
- writeTimestamp += outer_len;
- sendCursor -= inner_len;
- assert(sendCursor >= 0);
+ return true;
}
diff --git a/Transceiver52M/sigProcLib.cpp b/Transceiver52M/sigProcLib.cpp
index 477449f..7a032b3 100644
--- a/Transceiver52M/sigProcLib.cpp
+++ b/Transceiver52M/sigProcLib.cpp
@@ -2128,7 +2128,6 @@ bool sigProcLibSetup()
goto fail;
}
- dnsampler->enableHistory(false);
dnsampler_in = new signalVector(DOWNSAMPLE_IN_LEN, dnsampler->len());
return true;
diff --git a/Transceiver52M/signalVector.cpp b/Transceiver52M/signalVector.cpp
index 4b4099e..798a3c7 100644
--- a/Transceiver52M/signalVector.cpp
+++ b/Transceiver52M/signalVector.cpp
@@ -50,6 +50,15 @@ size_t signalVector::getStart() const
return mStart - mData;
}
+size_t signalVector::updateHistory()
+{
+ size_t num = getStart();
+
+ memmove(mData, mStart + this->size() - num, num * sizeof(complex));
+
+ return num;
+}
+
Symmetry signalVector::getSymmetry() const
{
return symmetry;
diff --git a/Transceiver52M/signalVector.h b/Transceiver52M/signalVector.h
index c9cb105..38541fe 100644
--- a/Transceiver52M/signalVector.h
+++ b/Transceiver52M/signalVector.h
@@ -32,6 +32,7 @@ public:
/** Return head room */
size_t getStart() const;
+ size_t updateHistory();
Symmetry getSymmetry() const;
void setSymmetry(Symmetry symmetry);