diff options
author | Thomas Tsou <ttsou@vt.edu> | 2012-03-07 19:55:59 -0500 |
---|---|---|
committer | Alexander Chemeris <Alexander.Chemeris@gmail.com> | 2013-06-24 01:46:34 +0400 |
commit | 711e6afddf46a3ad231521ff44836b0613a17743 (patch) | |
tree | 7dfc209bc69fb8f3651df540d5544c5977941450 /Transceiver52M | |
parent | 222688d3dc67bf93bf76d719213dd65b3ccdbd5e (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>
Diffstat (limited to 'Transceiver52M')
-rw-r--r-- | Transceiver52M/radioInterface.cpp | 134 | ||||
-rw-r--r-- | Transceiver52M/radioInterface.h | 31 |
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(); |