mirror of
https://gitea.osmocom.org/cellular-infrastructure/osmo-trx.git
synced 2025-11-02 13:13:17 +00:00
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>
This commit is contained in:
committed by
Alexander Chemeris
parent
222688d3dc
commit
711e6afddf
@@ -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;
|
||||
|
||||
RadioInterface::~RadioInterface(void) {
|
||||
if (rcvBuffer!=NULL) delete rcvBuffer;
|
||||
//mReceiveFIFO.clear();
|
||||
close();
|
||||
|
||||
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;
|
||||
|
||||
if (!mOn) return;
|
||||
for (i = 0; i < CHAN_M; i++) {
|
||||
if (active[i]) {
|
||||
memmove(buf[i], buf[i] + offset, sizeof(float) * len);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (mReceiveFIFO.size() > 8) return;
|
||||
void RadioInterface::loadVectors(unsigned tN, int samplesPerBurst,
|
||||
int idx, GSM::Time rxClock)
|
||||
{
|
||||
int i;
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
Reference in New Issue
Block a user