laforge
/
openbts-osmo
Archived
1
0
Fork 0

transceiver: separate I/O portion of radio interface implementation

Move push and pull of buffers into a dedicated file. This will
allow us to swap out resampling, non-resampling, and possibly
floating point device interfaces while presenting a single
floating point abstration in the interface itself.

Signed-off-by: Thomas Tsou <ttsou@vt.edu>
This commit is contained in:
Thomas Tsou 2011-10-09 23:36:21 -04:00
parent f5575b9240
commit 7e3692c087
4 changed files with 137 additions and 93 deletions

View File

@ -47,7 +47,8 @@ COMMON_SOURCES = \
Transceiver.cpp Transceiver.cpp
libtransceiver_la_SOURCES = \ libtransceiver_la_SOURCES = \
$(COMMON_SOURCES) $(COMMON_SOURCES) \
radioIO.cpp
noinst_PROGRAMS = \ noinst_PROGRAMS = \
USRPping \ USRPping \

View File

@ -0,0 +1,91 @@
/*
* Radio device I/O interface
* 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>
/* Device side buffers */
static short rx_buf[OUTCHUNK * 2 * 2];
static short tx_buf[INCHUNK * 2 * 2];
/* Complex float to short conversion */
static int float_to_short(short *shrt_out, float *flt_in, int num)
{
int i;
for (i = 0; i < num; i++) {
shrt_out[2 * i + 0] = flt_in[2 * i + 0];
shrt_out[2 * i + 1] = flt_in[2 * i + 1];
}
return i;
}
/* Comlpex short to float conversion */
static int short_to_float(float *flt_out, short *shrt_in, int num)
{
int i;
for (i = 0; i < num; i++) {
flt_out[2 * i + 0] = shrt_in[2 * i + 0];
flt_out[2 * i + 1] = shrt_in[2 * i + 1];
}
return 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);
LOG(DEBUG) << "Rx read " << num_rd << " samples from device";
assert(num_rd == OUTCHUNK);
underrun |= local_underrun;
readTimestamp += (TIMESTAMP) num_rd;
short_to_float(rcvBuffer + 2 * rcvCursor, rx_buf, num_rd);
rcvCursor += num_rd;
}
/* Send timestamped chunk to the device with arbitrary size */
void RadioInterface::pushBuffer()
{
if (sendCursor < INCHUNK)
return;
float_to_short(tx_buf, sendBuffer, sendCursor);
/* Write samples. Fail if we don't get what we want. */
int num_smpls = mRadio->writeSamples(tx_buf,
sendCursor,
&underrun,
writeTimestamp);
assert(num_smpls == sendCursor);
writeTimestamp += (TIMESTAMP) num_smpls;
sendCursor = 0;
}

View File

@ -25,6 +25,8 @@
#include "radioInterface.h" #include "radioInterface.h"
#include <Logger.h> #include <Logger.h>
bool started = false;
RadioInterface::RadioInterface(RadioDevice *wRadio, RadioInterface::RadioInterface(RadioDevice *wRadio,
int wReceiveOffset, int wReceiveOffset,
int wRadioOversampling, int wRadioOversampling,
@ -71,93 +73,40 @@ void RadioInterface::setPowerAttenuation(double atten)
powerScaling = 1.0/sqrt(pow(10, (digAtten/10.0))); powerScaling = 1.0/sqrt(pow(10, (digAtten/10.0)));
} }
short *RadioInterface::radioifyVector(signalVector &wVector, int RadioInterface::radioifyVector(signalVector &wVector,
short *retVector, float *retVector,
float scale, float scale,
bool zeroOut) bool zero)
{ {
int i;
signalVector::iterator itr = wVector.begin(); signalVector::iterator itr = wVector.begin();
short *shortItr = retVector;
if (zeroOut) { if (zero) {
while (itr < wVector.end()) { memset(retVector, 0, wVector.size() * 2 * sizeof(float));
*shortItr++ = 0; return wVector.size();
*shortItr++ = 0;
itr++;
}
} else if (scale != 1.0) {
while (itr < wVector.end()) {
*shortItr++ = (short) (itr->real() * scale);
*shortItr++ = (short) (itr->imag() * scale);
itr++;
}
} else {
while (itr < wVector.end()) {
*shortItr++ = (short) (itr->real());
*shortItr++ = (short) (itr->imag());
itr++;
}
} }
return retVector; for (i = 0; i < wVector.size(); i++) {
retVector[2 * i + 0] = itr->real() * scale;
retVector[2 * i + 1] = itr->imag() * scale;
itr++;
}
return wVector.size();
} }
void RadioInterface::unRadioifyVector(short *shortVector, signalVector& newVector) int RadioInterface::unRadioifyVector(float *floatVector,
signalVector& newVector)
{ {
int i;
signalVector::iterator itr = newVector.begin(); signalVector::iterator itr = newVector.begin();
short *shortItr = shortVector;
while (itr < newVector.end()) { for (i = 0; i < newVector.size(); i++) {
*itr++ = Complex<float>(*shortItr,*(shortItr+1)); *itr++ = Complex<float>(floatVector[2 * i + 0],
shortItr += 2; floatVector[2 * i + 1]);
} }
} return newVector.size();
bool started = false;
void RadioInterface::pushBuffer(void) {
if (sendCursor < 2*INCHUNK) return;
// send resampleVector
int samplesWritten = mRadio->writeSamples(sendBuffer,
INCHUNK,
&underrun,
writeTimestamp);
writeTimestamp += (TIMESTAMP) samplesWritten;
if (sendCursor > 2*samplesWritten)
memcpy(sendBuffer,sendBuffer+samplesWritten*2,sizeof(short)*2*(sendCursor-2*samplesWritten));
sendCursor = sendCursor - 2*samplesWritten;
}
void RadioInterface::pullBuffer(void)
{
bool localUnderrun;
// receive receiveVector
short* shortVector = rcvBuffer+rcvCursor;
int samplesRead = mRadio->readSamples(shortVector,OUTCHUNK,&overrun,readTimestamp,&localUnderrun);
underrun |= localUnderrun;
readTimestamp += (TIMESTAMP) samplesRead;
while (samplesRead < OUTCHUNK) {
int oldSamplesRead = samplesRead;
samplesRead += mRadio->readSamples(shortVector+2*samplesRead,
OUTCHUNK-samplesRead,
&overrun,
readTimestamp,
&localUnderrun);
underrun |= localUnderrun;
readTimestamp += (TIMESTAMP) (samplesRead - oldSamplesRead);
}
LOG(DEBUG) << "samplesRead " << samplesRead;
rcvCursor += samplesRead*2;
} }
bool RadioInterface::tuneTx(double freq) bool RadioInterface::tuneTx(double freq)
@ -176,14 +125,17 @@ void RadioInterface::start()
LOG(INFO) << "starting radio interface..."; LOG(INFO) << "starting radio interface...";
mAlignRadioServiceLoopThread.start((void * (*)(void*))AlignRadioServiceLoopAdapter, mAlignRadioServiceLoopThread.start((void * (*)(void*))AlignRadioServiceLoopAdapter,
(void*)this); (void*)this);
mOn = true;
writeTimestamp = mRadio->initialWriteTimestamp(); writeTimestamp = mRadio->initialWriteTimestamp();
readTimestamp = mRadio->initialReadTimestamp(); readTimestamp = mRadio->initialReadTimestamp();
mRadio->start(); mRadio->start();
LOG(DEBUG) << "Radio started"; LOG(DEBUG) << "Radio started";
mRadio->updateAlignment(writeTimestamp-10000); mRadio->updateAlignment(writeTimestamp-10000);
mRadio->updateAlignment(writeTimestamp-10000); mRadio->updateAlignment(writeTimestamp-10000);
LOG(DEBUG) << "radio interface started!";
sendBuffer = new float[2*2*INCHUNK*samplesPerSymbol];
rcvBuffer = new float[2*2*OUTCHUNK*samplesPerSymbol];
mOn = true;
} }
void *AlignRadioServiceLoopAdapter(RadioInterface *radioInterface) void *AlignRadioServiceLoopAdapter(RadioInterface *radioInterface)
@ -204,9 +156,9 @@ void RadioInterface::driveTransmitRadio(signalVector &radioBurst, bool zeroBurst
if (!mOn) return; if (!mOn) return;
radioifyVector(radioBurst, sendBuffer+sendCursor, powerScaling, zeroBurst); radioifyVector(radioBurst, sendBuffer + 2 * sendCursor, powerScaling, zeroBurst);
sendCursor += (radioBurst.size()*2); sendCursor += radioBurst.size();
pushBuffer(); pushBuffer();
} }
@ -222,7 +174,7 @@ void RadioInterface::driveReceiveRadio() {
GSM::Time rcvClock = mClock.get(); GSM::Time rcvClock = mClock.get();
rcvClock.decTN(receiveOffset); rcvClock.decTN(receiveOffset);
unsigned tN = rcvClock.TN(); unsigned tN = rcvClock.TN();
int rcvSz = rcvCursor/2; int rcvSz = rcvCursor;
int readSz = 0; int readSz = 0;
const int symbolsPerSlot = gSlotLen + 8; const int symbolsPerSlot = gSlotLen + 8;
@ -248,9 +200,9 @@ void RadioInterface::driveReceiveRadio() {
tN = rcvClock.TN(); tN = rcvClock.TN();
} }
if (readSz > 0) { if (readSz > 0) {
rcvCursor -= 2*readSz; rcvCursor -= readSz;
memmove(rcvBuffer,rcvBuffer+2*readSz,sizeof(short)*rcvCursor); memmove(rcvBuffer,rcvBuffer+2*readSz,sizeof(float) * 2 * rcvCursor);
} }
} }

View File

@ -47,10 +47,10 @@ private:
RadioDevice *mRadio; ///< the USRP object RadioDevice *mRadio; ///< the USRP object
short sendBuffer[2*2*INCHUNK]; float *sendBuffer;
unsigned sendCursor; unsigned sendCursor;
short rcvBuffer[2*2*OUTCHUNK]; float *rcvBuffer;
unsigned rcvCursor; unsigned rcvCursor;
bool underrun; ///< indicates writes to USRP are too slow bool underrun; ///< indicates writes to USRP are too slow
@ -70,13 +70,13 @@ private:
double powerScaling; double powerScaling;
/** format samples to USRP */ /** format samples to USRP */
short *radioifyVector(signalVector &wVector, int radioifyVector(signalVector &wVector,
short *shortVector, float *floatVector,
float scale, float scale,
bool zeroOut); bool zero);
/** format samples from USRP */ /** format samples from USRP */
void unRadioifyVector(short *shortVector, signalVector &wVector); int unRadioifyVector(float *floatVector, signalVector &wVector);
/** push GSM bursts into the transmit buffer */ /** push GSM bursts into the transmit buffer */
void pushBuffer(void); void pushBuffer(void);