aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Tsou <ttsou@vt.edu>2012-03-07 19:55:59 -0500
committerAlexander Chemeris <Alexander.Chemeris@gmail.com>2013-06-24 01:46:34 +0400
commit711e6afddf46a3ad231521ff44836b0613a17743 (patch)
tree7dfc209bc69fb8f3651df540d5544c5977941450
parent222688d3dc67bf93bf76d719213dd65b3ccdbd5e (diff)
multi-arfcn, trx: modify radio interface for multi-channel use
The radio interface needs to feed the device I/O buffers synchronously in order to drive the channelizer. Asynchronous channel access occurs opposite the radio interface through a bank of thread-safe FIFO's or priority queue's on receive and transmit sides respectively. Setup 'M' channels and allow only a subset to be active at a given time. When a channel is unused, there is no need to feed the particular receive FIFO or pull data from the channel priority queue. Signed-off-by: Thomas Tsou <ttsou@vt.edu>
-rw-r--r--Transceiver52M/radioInterface.cpp134
-rw-r--r--Transceiver52M/radioInterface.h31
2 files changed, 116 insertions, 49 deletions
diff --git a/Transceiver52M/radioInterface.cpp b/Transceiver52M/radioInterface.cpp
index 3cc15db..69c76ed 100644
--- a/Transceiver52M/radioInterface.cpp
+++ b/Transceiver52M/radioInterface.cpp
@@ -1,5 +1,5 @@
/*
-* Copyright 2008, 2009 Free Software Foundation, Inc.
+* Copyright 2008, 2009, 2012 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.
@@ -58,13 +58,27 @@ RadioInterface::RadioInterface(RadioDevice *wRadio,
samplesPerSymbol(wSPS), powerScaling(1.0),
loadTest(false)
{
+ int i;
+
mClock.set(wStartTime);
+
+ for (i = 0; i < CHAN_M; i++) {
+ chanActive[i] = false;
+ }
}
+RadioInterface::~RadioInterface(void)
+{
+ int i;
+
+ close();
-RadioInterface::~RadioInterface(void) {
- if (rcvBuffer!=NULL) delete rcvBuffer;
- //mReceiveFIFO.clear();
+ for (i = 0; i < CHAN_M; i++) {
+ if (rcvBuffer[i] != NULL)
+ delete rcvBuffer[i];
+ if (sendBuffer[i] != NULL)
+ delete sendBuffer[i];
+ }
}
double RadioInterface::fullScaleInputValue(void) {
@@ -111,15 +125,15 @@ int RadioInterface::radioifyVector(signalVector &wVector,
return wVector.size();
}
-int RadioInterface::unRadioifyVector(float *floatVector,
- signalVector& newVector)
+int RadioInterface::unRadioifyVector(float *floatVector, int offset,
+ signalVector &newVector)
{
int i;
signalVector::iterator itr = newVector.begin();
for (i = 0; i < newVector.size(); i++) {
- *itr++ = Complex<float>(floatVector[2 * i + 0],
- floatVector[2 * i + 1]);
+ *itr++ = Complex<float>(floatVector[offset + 2 * i + 0],
+ floatVector[offset + 2 * i + 1]);
}
return newVector.size();
@@ -136,8 +150,13 @@ bool RadioInterface::tuneRx(double freq)
}
-void RadioInterface::start()
+bool RadioInterface::start()
{
+ int i;
+
+ if (mOn)
+ return false;
+
LOG(INFO) << "starting radio interface...";
#ifdef USRP1
mAlignRadioServiceLoopThread.start((void * (*)(void*))AlignRadioServiceLoopAdapter,
@@ -150,11 +169,17 @@ void RadioInterface::start()
mRadio->updateAlignment(writeTimestamp-10000);
mRadio->updateAlignment(writeTimestamp-10000);
- sendBuffer = new float[2*2*INCHUNK*samplesPerSymbol];
- rcvBuffer = new float[2*2*OUTCHUNK*samplesPerSymbol];
-
+ for (i = 0; i < CHAN_M; i++) {
+ sendBuffer[i] = new float[8*2*INCHUNK];
+ rcvBuffer[i] = new float[8*2*OUTCHUNK];
+ }
+
+ /* Init I/O specific variables if applicable */
+ init();
+
mOn = true;
+ return true;
}
#ifdef USRP1
@@ -173,22 +198,62 @@ void RadioInterface::alignRadio() {
}
#endif
-void RadioInterface::driveTransmitRadio(signalVector &radioBurst, bool zeroBurst) {
+void RadioInterface::driveTransmitRadio(signalVector **radioBurst, bool *zeroBurst)
+{
+ int i;
- if (!mOn) return;
+ if (!mOn)
+ return;
- radioifyVector(radioBurst, sendBuffer + 2 * sendCursor, powerScaling, zeroBurst);
+ for (i = 0; i < CHAN_M; i++) {
+ if (chanActive[i]) {
+ radioifyVector(*radioBurst[i], sendBuffer[i] + 2 * sendCursor,
+ powerScaling, zeroBurst[i]);
+ }
+ }
- sendCursor += radioBurst.size();
+ /*
+ * All bursts should be the same size since all transceivers are
+ * tied with a single clock in the radio interface.
+ */
+ sendCursor += radioBurst[0]->size();
pushBuffer();
}
-void RadioInterface::driveReceiveRadio() {
+void shiftRxBuffers(float **buf, int offset, int len, bool *active)
+{
+ int i;
+
+ for (i = 0; i < CHAN_M; i++) {
+ if (active[i]) {
+ memmove(buf[i], buf[i] + offset, sizeof(float) * len);
+ }
+ }
+}
+
+void RadioInterface::loadVectors(unsigned tN, int samplesPerBurst,
+ int idx, GSM::Time rxClock)
+{
+ int i;
- if (!mOn) return;
+ for (i = 0; i < CHAN_M; i++) {
+ if (chanActive[i]) {
+ signalVector rxVector(samplesPerBurst);
+ unRadioifyVector(rcvBuffer[i], idx * 2, rxVector);
+ radioVector *rxBurst = new radioVector(rxVector, rxClock);
+ mReceiveFIFO[i].write(rxBurst);
+ }
+ }
+}
- if (mReceiveFIFO.size() > 8) return;
+void RadioInterface::driveReceiveRadio()
+{
+ if (!mOn)
+ return;
+
+ if (mReceiveFIFO[0].size() > 8)
+ return;
pullBuffer();
@@ -198,40 +263,29 @@ void RadioInterface::driveReceiveRadio() {
int rcvSz = rcvCursor;
int readSz = 0;
const int symbolsPerSlot = gSlotLen + 8;
+ int samplesPerBurst = (symbolsPerSlot + (tN % 4 == 0)) * samplesPerSymbol;
// while there's enough data in receive buffer, form received
// GSM bursts and pass up to Transceiver
// Using the 157-156-156-156 symbols per timeslot format.
- while (rcvSz > (symbolsPerSlot + (tN % 4 == 0))*samplesPerSymbol) {
- signalVector rxVector((symbolsPerSlot + (tN % 4 == 0))*samplesPerSymbol);
- unRadioifyVector(rcvBuffer+readSz*2,rxVector);
- GSM::Time tmpTime = rcvClock;
+ while (rcvSz >= samplesPerBurst) {
if (rcvClock.FN() >= 0) {
- //LOG(DEBUG) << "FN: " << rcvClock.FN();
- radioVector *rxBurst = NULL;
- if (!loadTest)
- rxBurst = new radioVector(rxVector,tmpTime);
- else {
- if (tN % 4 == 0)
- rxBurst = new radioVector(*finalVec9,tmpTime);
- else
- rxBurst = new radioVector(*finalVec,tmpTime);
- }
- mReceiveFIFO.put(rxBurst);
+ loadVectors(tN, samplesPerBurst, readSz, rcvClock);
}
- mClock.incTN();
+
+ mClock.incTN();
rcvClock.incTN();
- //if (mReceiveFIFO.size() >= 16) mReceiveFIFO.wait(8);
- //LOG(DEBUG) << "receiveFIFO: wrote radio vector at time: " << mClock.get() << ", new size: " << mReceiveFIFO.size() ;
- readSz += (symbolsPerSlot+(tN % 4 == 0))*samplesPerSymbol;
- rcvSz -= (symbolsPerSlot+(tN % 4 == 0))*samplesPerSymbol;
+
+ readSz += samplesPerBurst;
+ rcvSz -= samplesPerBurst;
tN = rcvClock.TN();
+ samplesPerBurst = (symbolsPerSlot + (tN % 4 == 0)) * samplesPerSymbol;
}
if (readSz > 0) {
rcvCursor -= readSz;
- memmove(rcvBuffer,rcvBuffer+2*readSz,sizeof(float) * 2 * rcvCursor);
+ shiftRxBuffers(rcvBuffer, 2 * readSz, 2 * rcvCursor, chanActive);
}
}
diff --git a/Transceiver52M/radioInterface.h b/Transceiver52M/radioInterface.h
index 9344de5..5dbca13 100644
--- a/Transceiver52M/radioInterface.h
+++ b/Transceiver52M/radioInterface.h
@@ -1,5 +1,5 @@
/*
-* Copyright 2008 Free Software Foundation, Inc.
+* Copyright 2008, 2012 Free Software Foundation, Inc.
*
* This software is distributed under multiple licenses; see the COPYING file in the main directory for licensing information for this specific distribuion.
*
@@ -23,9 +23,11 @@
#include "radioClock.h"
/** samples per GSM symbol */
-#define SAMPSPERSYM 1
+#define SAMPSPERSYM 1
#define INCHUNK (625)
#define OUTCHUNK (625)
+#define CHAN_M 5
+
static const unsigned gSlotLen = 148; ///< number of symbols per slot, not counting guard periods
@@ -36,15 +38,17 @@ protected:
Thread mAlignRadioServiceLoopThread; ///< thread that synchronizes transmit and receive sections
- VectorFIFO mReceiveFIFO; ///< FIFO that holds receive bursts
+ VectorFIFO mReceiveFIFO[CHAN_M]; ///< FIFO that holds receive bursts
RadioDevice *mRadio; ///< the USRP object
- float *sendBuffer;
+ float *sendBuffer[CHAN_M];
unsigned sendCursor;
- float *rcvBuffer;
+ float *rcvBuffer[CHAN_M];
unsigned rcvCursor;
+
+ bool chanActive[CHAN_M];
bool underrun; ///< indicates writes to USRP are too slow
bool overrun; ///< indicates reads from USRP are too slow
@@ -65,6 +69,8 @@ protected:
signalVector *finalVec, *finalVec9;
private:
+ /** initialize I/O internals */
+ bool init();
/** format samples to USRP */
int radioifyVector(signalVector &wVector,
@@ -73,7 +79,7 @@ private:
bool zero);
/** format samples from USRP */
- int unRadioifyVector(float *floatVector, signalVector &wVector);
+ int unRadioifyVector(float *floatVector, int offset, signalVector &wVector);
/** push GSM bursts into the transmit buffer */
virtual void pushBuffer(void);
@@ -81,10 +87,17 @@ private:
/** pull GSM bursts from the receive buffer */
virtual void pullBuffer(void);
+ /** load receive vectors into FIFO's */
+ void loadVectors(unsigned tN, int samplesPerBurst, int index, GSM::Time rxClock);
+
public:
/** start the interface */
- void start();
+ bool start();
+ bool started() { return mOn; };
+
+ /** shutdown interface */
+ void close();
/** constructor */
RadioInterface(RadioDevice* wRadio = NULL,
@@ -106,7 +119,7 @@ public:
void attach(RadioDevice *wRadio, int wRadioOversampling);
/** return the receive FIFO */
- VectorFIFO* receiveFIFO() { return &mReceiveFIFO;}
+ VectorFIFO* receiveFIFO(int num) { return &mReceiveFIFO[num];}
/** return the basestation clock */
RadioClock* getClock(void) { return &mClock;};
@@ -124,7 +137,7 @@ public:
double getRxGain(void);
/** drive transmission of GSM bursts */
- void driveTransmitRadio(signalVector &radioBurst, bool zeroBurst);
+ void driveTransmitRadio(signalVector **radioBurst, bool *zeroBurst);
/** drive reception of GSM bursts */
void driveReceiveRadio();