From 7e3692c0871a6e4cc442737018ec27370a54cd7f Mon Sep 17 00:00:00 2001 From: Thomas Tsou Date: Sun, 9 Oct 2011 23:36:21 -0400 Subject: [PATCH] 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 --- public-trunk/Transceiver52M/Makefile.am | 3 +- public-trunk/Transceiver52M/radioIO.cpp | 91 +++++++++++++ .../Transceiver52M/radioInterface.cpp | 122 ++++++------------ public-trunk/Transceiver52M/radioInterface.h | 14 +- 4 files changed, 137 insertions(+), 93 deletions(-) create mode 100644 public-trunk/Transceiver52M/radioIO.cpp diff --git a/public-trunk/Transceiver52M/Makefile.am b/public-trunk/Transceiver52M/Makefile.am index c209018..395d7e9 100644 --- a/public-trunk/Transceiver52M/Makefile.am +++ b/public-trunk/Transceiver52M/Makefile.am @@ -47,7 +47,8 @@ COMMON_SOURCES = \ Transceiver.cpp libtransceiver_la_SOURCES = \ - $(COMMON_SOURCES) + $(COMMON_SOURCES) \ + radioIO.cpp noinst_PROGRAMS = \ USRPping \ diff --git a/public-trunk/Transceiver52M/radioIO.cpp b/public-trunk/Transceiver52M/radioIO.cpp new file mode 100644 index 0000000..9956e87 --- /dev/null +++ b/public-trunk/Transceiver52M/radioIO.cpp @@ -0,0 +1,91 @@ +/* + * Radio device I/O interface + * Written by Thomas Tsou + * + * 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 . + * See the COPYING file in the main directory for details. + */ + +#include +#include + +/* 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; +} diff --git a/public-trunk/Transceiver52M/radioInterface.cpp b/public-trunk/Transceiver52M/radioInterface.cpp index 0e63b7c..6a3b771 100644 --- a/public-trunk/Transceiver52M/radioInterface.cpp +++ b/public-trunk/Transceiver52M/radioInterface.cpp @@ -25,6 +25,8 @@ #include "radioInterface.h" #include +bool started = false; + RadioInterface::RadioInterface(RadioDevice *wRadio, int wReceiveOffset, int wRadioOversampling, @@ -71,93 +73,40 @@ void RadioInterface::setPowerAttenuation(double atten) powerScaling = 1.0/sqrt(pow(10, (digAtten/10.0))); } -short *RadioInterface::radioifyVector(signalVector &wVector, - short *retVector, - float scale, - bool zeroOut) +int RadioInterface::radioifyVector(signalVector &wVector, + float *retVector, + float scale, + bool zero) { + int i; signalVector::iterator itr = wVector.begin(); - short *shortItr = retVector; - if (zeroOut) { - while (itr < wVector.end()) { - *shortItr++ = 0; - *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++; - } + + if (zero) { + memset(retVector, 0, wVector.size() * 2 * sizeof(float)); + return wVector.size(); } - 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(); - short *shortItr = shortVector; - while (itr < newVector.end()) { - *itr++ = Complex(*shortItr,*(shortItr+1)); - shortItr += 2; + + for (i = 0; i < newVector.size(); i++) { + *itr++ = Complex(floatVector[2 * i + 0], + floatVector[2 * i + 1]); } -} - - -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; - + return newVector.size(); } bool RadioInterface::tuneTx(double freq) @@ -176,14 +125,17 @@ void RadioInterface::start() LOG(INFO) << "starting radio interface..."; mAlignRadioServiceLoopThread.start((void * (*)(void*))AlignRadioServiceLoopAdapter, (void*)this); - mOn = true; writeTimestamp = mRadio->initialWriteTimestamp(); readTimestamp = mRadio->initialReadTimestamp(); mRadio->start(); LOG(DEBUG) << "Radio started"; 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) @@ -204,9 +156,9 @@ void RadioInterface::driveTransmitRadio(signalVector &radioBurst, bool zeroBurst if (!mOn) return; - radioifyVector(radioBurst, sendBuffer+sendCursor, powerScaling, zeroBurst); + radioifyVector(radioBurst, sendBuffer + 2 * sendCursor, powerScaling, zeroBurst); - sendCursor += (radioBurst.size()*2); + sendCursor += radioBurst.size(); pushBuffer(); } @@ -222,7 +174,7 @@ void RadioInterface::driveReceiveRadio() { GSM::Time rcvClock = mClock.get(); rcvClock.decTN(receiveOffset); unsigned tN = rcvClock.TN(); - int rcvSz = rcvCursor/2; + int rcvSz = rcvCursor; int readSz = 0; const int symbolsPerSlot = gSlotLen + 8; @@ -248,9 +200,9 @@ void RadioInterface::driveReceiveRadio() { tN = rcvClock.TN(); } - if (readSz > 0) { - rcvCursor -= 2*readSz; - memmove(rcvBuffer,rcvBuffer+2*readSz,sizeof(short)*rcvCursor); + if (readSz > 0) { + rcvCursor -= readSz; + memmove(rcvBuffer,rcvBuffer+2*readSz,sizeof(float) * 2 * rcvCursor); } } diff --git a/public-trunk/Transceiver52M/radioInterface.h b/public-trunk/Transceiver52M/radioInterface.h index 398ad0d..1216a63 100644 --- a/public-trunk/Transceiver52M/radioInterface.h +++ b/public-trunk/Transceiver52M/radioInterface.h @@ -47,10 +47,10 @@ private: RadioDevice *mRadio; ///< the USRP object - short sendBuffer[2*2*INCHUNK]; + float *sendBuffer; unsigned sendCursor; - short rcvBuffer[2*2*OUTCHUNK]; + float *rcvBuffer; unsigned rcvCursor; bool underrun; ///< indicates writes to USRP are too slow @@ -70,13 +70,13 @@ private: double powerScaling; /** format samples to USRP */ - short *radioifyVector(signalVector &wVector, - short *shortVector, - float scale, - bool zeroOut); + int radioifyVector(signalVector &wVector, + float *floatVector, + float scale, + bool zero); /** format samples from USRP */ - void unRadioifyVector(short *shortVector, signalVector &wVector); + int unRadioifyVector(float *floatVector, signalVector &wVector); /** push GSM bursts into the transmit buffer */ void pushBuffer(void);