diff --git a/Transceiver52M/Makefile.am b/Transceiver52M/Makefile.am index 4ec06e00..ec72f8cf 100644 --- a/Transceiver52M/Makefile.am +++ b/Transceiver52M/Makefile.am @@ -54,6 +54,7 @@ COMMON_SOURCES = \ radioInterface.cpp \ radioVector.cpp \ radioClock.cpp \ + radioBuffer.cpp \ sigProcLib.cpp \ signalVector.cpp \ Transceiver.cpp @@ -72,6 +73,7 @@ noinst_HEADERS = \ radioVector.h \ radioClock.h \ radioDevice.h \ + radioBuffer.h \ sigProcLib.h \ signalVector.h \ Transceiver.h \ diff --git a/Transceiver52M/Resampler.cpp b/Transceiver52M/Resampler.cpp index e4b66a70..070adda3 100644 --- a/Transceiver52M/Resampler.cpp +++ b/Transceiver52M/Resampler.cpp @@ -167,22 +167,13 @@ void Resampler::computePath() } } -int Resampler::rotate(float *in, size_t in_len, float *out, size_t out_len) +int Resampler::rotate(const float *in, size_t in_len, float *out, size_t out_len) { int n, path; - int hist_len = filt_len - 1; if (!check_vec_len(in_len, out_len, p, q)) return -1; - if (history_on) { - memcpy(&in[-2 * hist_len], - history, hist_len * 2 * sizeof(float)); - } else { - memset(&in[-2 * hist_len], 0, - hist_len * 2 * sizeof(float)); - } - /* Generate output from precomputed input/output paths */ for (size_t i = 0; i < out_len; i++) { n = in_index[i]; @@ -194,27 +185,15 @@ int Resampler::rotate(float *in, size_t in_len, float *out, size_t out_len) n, 1, 1, 0); } - /* Save history */ - if (history_on) { - memcpy(history, &in[2 * (in_len - hist_len)], - hist_len * 2 * sizeof(float)); - } - return out_len; } bool Resampler::init(float bw) { - size_t hist_len = filt_len - 1; - /* Filterbank filter internals */ if (initFilters(bw) < 0) return false; - /* History buffer */ - history = new float[2 * hist_len]; - memset(history, 0, 2 * hist_len * sizeof(float)); - /* Precompute filterbank paths */ in_index = new size_t[MAX_OUTPUT_LEN]; out_path = new size_t[MAX_OUTPUT_LEN]; @@ -228,14 +207,8 @@ size_t Resampler::len() return filt_len; } -void Resampler::enableHistory(bool on) -{ - history_on = on; -} - Resampler::Resampler(size_t p, size_t q, size_t filt_len) - : in_index(NULL), out_path(NULL), partitions(NULL), - history(NULL), history_on(true) + : in_index(NULL), out_path(NULL), partitions(NULL) { this->p = p; this->q = q; @@ -246,7 +219,6 @@ Resampler::~Resampler() { releaseFilters(); - delete history; delete in_index; delete out_path; } diff --git a/Transceiver52M/Resampler.h b/Transceiver52M/Resampler.h index 072ec928..c9f9787b 100644 --- a/Transceiver52M/Resampler.h +++ b/Transceiver52M/Resampler.h @@ -52,18 +52,13 @@ public: * Input and output vector lengths must of be equal multiples of the * rational conversion rate denominator and numerator respectively. */ - int rotate(float *in, size_t in_len, float *out, size_t out_len); + int rotate(const float *in, size_t in_len, float *out, size_t out_len); /* Get filter length * @return number of taps in each filter partition */ size_t len(); - /* - * Enable/disable history - */ - void enableHistory(bool on); - private: size_t p; size_t q; @@ -72,8 +67,6 @@ private: size_t *out_path; float **partitions; - float *history; - bool history_on; bool initFilters(float bw); void releaseFilters(); diff --git a/Transceiver52M/radioBuffer.cpp b/Transceiver52M/radioBuffer.cpp new file mode 100644 index 00000000..9e6f0799 --- /dev/null +++ b/Transceiver52M/radioBuffer.cpp @@ -0,0 +1,228 @@ +/* + * Segmented Ring Buffer + * + * Copyright (C) 2015 Ettus Research LLC + * + * Author: Tom Tsou + * + * 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 +#include "radioBuffer.h" + +RadioBuffer::RadioBuffer(size_t numSegments, size_t segmentLen, + size_t hLen, bool outDirection) + : writeIndex(0), readIndex(0), availSamples(0) +{ + if (!outDirection) + hLen = 0; + + buffer = new float[2 * (hLen + numSegments * segmentLen)]; + bufferLen = numSegments * segmentLen; + + segments.resize(numSegments); + + for (size_t i = 0; i < numSegments; i++) + segments[i] = &buffer[2 * (hLen + i * segmentLen)]; + + this->outDirection = outDirection; + this->numSegments = numSegments; + this->segmentLen = segmentLen; + this->hLen = hLen; +} + +RadioBuffer::~RadioBuffer() +{ + delete buffer; +} + +void RadioBuffer::reset() +{ + writeIndex = 0; + readIndex = 0; + availSamples = 0; +} + +/* + * Output direction + * + * Return a pointer to the oldest segment or NULL if a complete segment is not + * available. + */ +const float *RadioBuffer::getReadSegment() +{ + if (!outDirection) { + std::cout << "Invalid direction" << std::endl; + return NULL; + } + if (availSamples < segmentLen) { + std::cout << "Not enough samples " << std::endl; + std::cout << availSamples << " available per segment " + << segmentLen << std::endl; + return NULL; + } + + size_t num = readIndex / segmentLen; + + if (num >= numSegments) { + std::cout << "Invalid segment" << std::endl; + return NULL; + } else if (!num) { + memcpy(buffer, + &buffer[2 * bufferLen], + hLen * 2 * sizeof(float)); + } + + availSamples -= segmentLen; + readIndex = (readIndex + segmentLen) % bufferLen; + + return segments[num]; +} + +/* + * Output direction + * + * Write a non-segment length of samples to the buffer. + */ +bool RadioBuffer::write(const float *wr, size_t len) +{ + if (!outDirection) { + std::cout << "Invalid direction" << std::endl; + return false; + } + if (availSamples + len > bufferLen) { + std::cout << "Insufficient space" << std::endl; + std::cout << bufferLen - availSamples << " available per write " + << len << std::endl; + return false; + } + + if (writeIndex + len <= bufferLen) { + memcpy(&buffer[2 * (writeIndex + hLen)], + wr, len * 2 * sizeof(float)); + } else { + size_t len0 = bufferLen - writeIndex; + size_t len1 = len - len0; + memcpy(&buffer[2 * (writeIndex + hLen)], wr, len0 * 2 * sizeof(float)); + memcpy(&buffer[2 * hLen], &wr[2 * len0], len1 * 2 * sizeof(float)); + } + + availSamples += len; + writeIndex = (writeIndex + len) % bufferLen; + + return true; +} + +bool RadioBuffer::zero(size_t len) +{ + if (!outDirection) { + std::cout << "Invalid direction" << std::endl; + return false; + } + if (availSamples + len > bufferLen) { + std::cout << "Insufficient space" << std::endl; + std::cout << bufferLen - availSamples << " available per zero " + << len << std::endl; + return false; + } + + if (writeIndex + len <= bufferLen) { + memset(&buffer[2 * (writeIndex + hLen)], + 0, len * 2 * sizeof(float)); + } else { + size_t len0 = bufferLen - writeIndex; + size_t len1 = len - len0; + memset(&buffer[2 * (writeIndex + hLen)], 0, len0 * 2 * sizeof(float)); + memset(&buffer[2 * hLen], 0, len1 * 2 * sizeof(float)); + } + + availSamples += len; + writeIndex = (writeIndex + len) % bufferLen; + + return true; +} + +/* + * Input direction + */ +float *RadioBuffer::getWriteSegment() +{ + if (outDirection) { + std::cout << "Invalid direction" << std::endl; + return NULL; + } + if (bufferLen - availSamples < segmentLen) { + std::cout << "Insufficient samples" << std::endl; + std::cout << bufferLen - availSamples + << " available for segment " << segmentLen + << std::endl; + return NULL; + } + if (writeIndex % segmentLen) { + std::cout << "Internal segment error" << std::endl; + return NULL; + } + + size_t num = writeIndex / segmentLen; + + if (num >= numSegments) + return NULL; + + availSamples += segmentLen; + writeIndex = (writeIndex + segmentLen) % bufferLen; + + return segments[num]; +} + +bool RadioBuffer::zeroWriteSegment() +{ + float *segment = getWriteSegment(); + if (!segment) + return false; + + memset(segment, 0, segmentLen * 2 * sizeof(float)); + + return true; +} + +bool RadioBuffer::read(float *rd, size_t len) +{ + if (outDirection) { + std::cout << "Invalid direction" << std::endl; + return false; + } + if (availSamples < len) { + std::cout << "Insufficient samples" << std::endl; + std::cout << availSamples << " available for " + << len << std::endl; + return false; + } + + if (readIndex + len <= bufferLen) { + memcpy(rd, &buffer[2 * readIndex], len * 2 * sizeof(float)); + } else { + size_t len0 = bufferLen - readIndex; + size_t len1 = len - len0; + memcpy(rd, &buffer[2 * readIndex], len0 * 2 * sizeof(float)); + memcpy(&rd[2 * len0], buffer, len1 * 2 * sizeof(float)); + } + + availSamples -= len; + readIndex = (readIndex + len) % bufferLen; + + return true; +} diff --git a/Transceiver52M/radioBuffer.h b/Transceiver52M/radioBuffer.h new file mode 100644 index 00000000..afb6e637 --- /dev/null +++ b/Transceiver52M/radioBuffer.h @@ -0,0 +1,45 @@ +#include +#include +#include + +class RadioBuffer { +public: + RadioBuffer(size_t numSegments, size_t segmentLen, + size_t hLen, bool outDirection); + + ~RadioBuffer(); + + const size_t getSegmentLen() { return segmentLen; }; + const size_t getNumSegments() { return numSegments; }; + const size_t getAvailSamples() { return availSamples; }; + const size_t getAvailSegments() { return availSamples / segmentLen; }; + + const size_t getFreeSamples() + { + return bufferLen - availSamples; + } + + const size_t getFreeSegments() + { + return getFreeSamples() / segmentLen; + } + + void reset(); + + /* Output direction */ + const float *getReadSegment(); + bool write(const float *wr, size_t len); + bool zero(size_t len); + + /* Input direction */ + float *getWriteSegment(); + bool zeroWriteSegment(); + bool read(float *rd, size_t len); + +private: + size_t writeIndex, readIndex, availSamples; + size_t bufferLen, numSegments, segmentLen, hLen; + float *buffer; + std::vector segments; + bool outDirection; +}; diff --git a/Transceiver52M/radioInterface.cpp b/Transceiver52M/radioInterface.cpp index b719c946..052b4390 100644 --- a/Transceiver52M/radioInterface.cpp +++ b/Transceiver52M/radioInterface.cpp @@ -1,26 +1,23 @@ /* -* Copyright 2008, 2009 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. -* -* This use of this software may be subject to additional restrictions. -* See the LEGAL file in the main directory for details. - - 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 . - -*/ + * Radio device interface + * + * Copyright (C) 2008-2014 Free Software Foundation, Inc. + * Copyright (C) 2015 Ettus Research LLC + * + * 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 "radioInterface.h" #include "Resampler.h" @@ -37,8 +34,8 @@ RadioInterface::RadioInterface(RadioDevice *wRadio, size_t tx_sps, size_t rx_sps, size_t chans, size_t diversity, int wReceiveOffset, GSM::Time wStartTime) : mRadio(wRadio), mSPSTx(tx_sps), mSPSRx(rx_sps), mChans(chans), - mMIMO(diversity), sendCursor(0), recvCursor(0), underrun(false), - overrun(false), receiveOffset(wReceiveOffset), mOn(false) + mMIMO(diversity), underrun(false), overrun(false), + receiveOffset(wReceiveOffset), mOn(false) { mClock.set(wStartTime); } @@ -65,35 +62,20 @@ bool RadioInterface::init(int type) powerScaling.resize(mChans); for (size_t i = 0; i < mChans; i++) { - sendBuffer[i] = new signalVector(CHUNK * mSPSTx); - recvBuffer[i] = new signalVector(NUMCHUNKS * CHUNK * mSPSRx); + sendBuffer[i] = new RadioBuffer(NUMCHUNKS, CHUNK * mSPSTx, 0, true); + recvBuffer[i] = new RadioBuffer(NUMCHUNKS, CHUNK * mSPSRx, 0, false); - convertSendBuffer[i] = new short[sendBuffer[i]->size() * 2]; - convertRecvBuffer[i] = new short[recvBuffer[i]->size() * 2]; + convertSendBuffer[i] = new short[CHUNK * mSPSTx * 2]; + convertRecvBuffer[i] = new short[CHUNK * mSPSRx * 2]; powerScaling[i] = 1.0; } - sendCursor = 0; - recvCursor = 0; - return true; } void RadioInterface::close() { - for (size_t i = 0; i < sendBuffer.size(); i++) - delete sendBuffer[i]; - - for (size_t i = 0; i < recvBuffer.size(); i++) - delete recvBuffer[i]; - - for (size_t i = 0; i < convertSendBuffer.size(); i++) - delete convertSendBuffer[i]; - - for (size_t i = 0; i < convertRecvBuffer.size(); i++) - delete convertRecvBuffer[i]; - sendBuffer.resize(0); recvBuffer.resize(0); convertSendBuffer.resize(0); @@ -132,35 +114,26 @@ int RadioInterface::setPowerAttenuation(int atten, size_t chan) } int RadioInterface::radioifyVector(signalVector &wVector, - float *retVector, - bool zero) + size_t chan, bool zero) { - if (zero) { - memset(retVector, 0, wVector.size() * 2 * sizeof(float)); - return wVector.size(); - } - - memcpy(retVector, wVector.begin(), wVector.size() * 2 * sizeof(float)); + if (zero) + sendBuffer[chan]->zero(wVector.size()); + else + sendBuffer[chan]->write((float *) wVector.begin(), wVector.size()); return wVector.size(); } -int RadioInterface::unRadioifyVector(float *floatVector, - signalVector& newVector) +int RadioInterface::unRadioifyVector(signalVector *newVector, size_t chan) { - signalVector::iterator itr = newVector.begin(); - - if (newVector.size() > recvCursor) { + if (newVector->size() > recvBuffer[chan]->getAvailSamples()) { LOG(ALERT) << "Insufficient number of samples in receive buffer"; return -1; } - for (size_t i = 0; i < newVector.size(); i++) { - *itr++ = Complex(floatVector[2 * i + 0], - floatVector[2 * i + 1]); - } + recvBuffer[chan]->read((float *) newVector->begin(), newVector->size()); - return newVector.size(); + return newVector->size(); } bool RadioInterface::tuneTx(double freq, size_t chan) @@ -187,8 +160,10 @@ bool RadioInterface::start() if (!mRadio->start()) return false; - recvCursor = 0; - sendCursor = 0; + for (size_t i = 0; i < mChans; i++) { + sendBuffer[i]->reset(); + recvBuffer[i]->reset(); + } writeTimestamp = mRadio->initialWriteTimestamp(); readTimestamp = mRadio->initialReadTimestamp(); @@ -239,14 +214,10 @@ void RadioInterface::driveTransmitRadio(std::vector &bursts, if (!mOn) return; - for (size_t i = 0; i < mChans; i++) { - radioifyVector(*bursts[i], - (float *) (sendBuffer[i]->begin() + sendCursor), zeros[i]); - } + for (size_t i = 0; i < mChans; i++) + radioifyVector(*bursts[i], i, zeros[i]); - sendCursor += bursts[0]->size(); - - pushBuffer(); + while (pushBuffer()); } bool RadioInterface::driveReceiveRadio() @@ -261,8 +232,7 @@ bool RadioInterface::driveReceiveRadio() GSM::Time rcvClock = mClock.get(); rcvClock.decTN(receiveOffset); unsigned tN = rcvClock.TN(); - int recvSz = recvCursor; - int readSz = 0; + int recvSz = recvBuffer[0]->getAvailSamples(); const int symbolsPerSlot = gSlotLen + 8; int burstSize; @@ -285,11 +255,8 @@ bool RadioInterface::driveReceiveRadio() for (size_t i = 0; i < mChans; i++) { burst = new radioVector(rcvClock, burstSize, head, mMIMO); - for (size_t n = 0; n < mMIMO; n++) { - unRadioifyVector((float *) - (recvBuffer[mMIMO * i + n]->begin() + readSz), - *burst->getVector(n)); - } + for (size_t n = 0; n < mMIMO; n++) + unRadioifyVector(burst->getVector(n), i); if (mReceiveFIFO[i].size() < 32) mReceiveFIFO[i].write(burst); @@ -299,7 +266,6 @@ bool RadioInterface::driveReceiveRadio() mClock.incTN(); rcvClock.incTN(); - readSz += burstSize; recvSz -= burstSize; tN = rcvClock.TN(); @@ -308,16 +274,6 @@ bool RadioInterface::driveReceiveRadio() burstSize = (symbolsPerSlot + (tN % 4 == 0)) * mSPSRx; } - if (readSz > 0) { - for (size_t i = 0; i < recvBuffer.size(); i++) { - memmove(recvBuffer[i]->begin(), - recvBuffer[i]->begin() + readSz, - (recvCursor - readSz) * 2 * sizeof(float)); - } - - recvCursor -= readSz; - } - return true; } @@ -339,74 +295,66 @@ VectorFIFO* RadioInterface::receiveFIFO(size_t chan) double RadioInterface::setRxGain(double dB, size_t chan) { - if (mRadio) - return mRadio->setRxGain(dB, chan); - else - return -1; + return mRadio->setRxGain(dB, chan); } double RadioInterface::getRxGain(size_t chan) { - if (mRadio) - return mRadio->getRxGain(chan); - else - return -1; + return mRadio->getRxGain(chan); } /* Receive a timestamped chunk from the device */ void RadioInterface::pullBuffer() { bool local_underrun; - int num_recv; - float *output; + size_t numRecv, segmentLen = recvBuffer[0]->getSegmentLen(); - if (recvCursor > recvBuffer[0]->size() - CHUNK) + if (recvBuffer[0]->getFreeSegments() <= 0) return; /* Outer buffer access size is fixed */ - num_recv = mRadio->readSamples(convertRecvBuffer, - CHUNK, - &overrun, - readTimestamp, - &local_underrun); - if (num_recv != CHUNK) { - LOG(ALERT) << "Receive error " << num_recv; + numRecv = mRadio->readSamples(convertRecvBuffer, + segmentLen, + &overrun, + readTimestamp, + &local_underrun); + + if (numRecv != segmentLen) { + LOG(ALERT) << "Receive error " << numRecv; return; } for (size_t i = 0; i < mChans; i++) { - output = (float *) (recvBuffer[i]->begin() + recvCursor); - convert_short_float(output, convertRecvBuffer[i], 2 * num_recv); + convert_short_float(recvBuffer[i]->getWriteSegment(), + convertRecvBuffer[i], + segmentLen * 2); } underrun |= local_underrun; - - readTimestamp += num_recv; - recvCursor += num_recv; + readTimestamp += numRecv; } /* Send timestamped chunk to the device with arbitrary size */ -void RadioInterface::pushBuffer() +bool RadioInterface::pushBuffer() { - int num_sent; + size_t numSent, segmentLen = sendBuffer[0]->getSegmentLen(); - if (sendCursor < CHUNK) - return; - - if (sendCursor > sendBuffer[0]->size()) - LOG(ALERT) << "Send buffer overflow"; + if (sendBuffer[0]->getAvailSegments() < 1) + return false; for (size_t i = 0; i < mChans; i++) { convert_float_short(convertSendBuffer[i], - (float *) sendBuffer[i]->begin(), - powerScaling[i], 2 * sendCursor); + (float *) sendBuffer[0]->getReadSegment(), + powerScaling[i], + segmentLen * 2); } - /* Send the all samples in the send buffer */ - num_sent = mRadio->writeSamples(convertSendBuffer, - sendCursor, - &underrun, - writeTimestamp); - writeTimestamp += num_sent; - sendCursor = 0; + /* Send the all samples in the send buffer */ + numSent = mRadio->writeSamples(convertSendBuffer, + segmentLen, + &underrun, + writeTimestamp); + writeTimestamp += numSent; + + return true; } diff --git a/Transceiver52M/radioInterface.h b/Transceiver52M/radioInterface.h index ce06578a..1f225a22 100644 --- a/Transceiver52M/radioInterface.h +++ b/Transceiver52M/radioInterface.h @@ -20,6 +20,7 @@ #include "radioDevice.h" #include "radioVector.h" #include "radioClock.h" +#include "radioBuffer.h" #include "Resampler.h" static const unsigned gSlotLen = 148; ///< number of symbols per slot, not counting guard periods @@ -40,10 +41,8 @@ protected: size_t mChans; size_t mMIMO; - std::vector sendBuffer; - std::vector recvBuffer; - unsigned sendCursor; - unsigned recvCursor; + std::vector sendBuffer; + std::vector recvBuffer; std::vector convertRecvBuffer; std::vector convertSendBuffer; @@ -61,16 +60,14 @@ protected: private: - /** format samples to USRP */ - int radioifyVector(signalVector &wVector, - float *floatVector, - bool zero); + /** format samples to USRP */ + int radioifyVector(signalVector &wVector, size_t chan, bool zero); /** format samples from USRP */ - int unRadioifyVector(float *floatVector, signalVector &wVector); + int unRadioifyVector(signalVector *wVector, size_t chan); /** push GSM bursts into the transmit buffer */ - virtual void pushBuffer(void); + virtual bool pushBuffer(void); /** pull GSM bursts from the receive buffer */ virtual void pullBuffer(void); @@ -152,20 +149,15 @@ void *AlignRadioServiceLoopAdapter(RadioInterface*); #endif class RadioInterfaceResamp : public RadioInterface { - private: - signalVector *innerSendBuffer; signalVector *outerSendBuffer; - signalVector *innerRecvBuffer; signalVector *outerRecvBuffer; - void pushBuffer(); + bool pushBuffer(); void pullBuffer(); public: - RadioInterfaceResamp(RadioDevice* wRadio, size_t wSPS = 4, size_t chans = 1); - ~RadioInterfaceResamp(); bool init(int type); @@ -184,7 +176,7 @@ public: bool tuneRx(double freq, size_t chan); private: - std::vector dnsamplers; + Resampler *dnsampler; std::vector phases; signalVector *outerRecvBuffer; diff --git a/Transceiver52M/radioInterfaceDiversity.cpp b/Transceiver52M/radioInterfaceDiversity.cpp index 8e921b15..b3973e55 100644 --- a/Transceiver52M/radioInterfaceDiversity.cpp +++ b/Transceiver52M/radioInterfaceDiversity.cpp @@ -65,14 +65,11 @@ RadioInterfaceDiversity::~RadioInterfaceDiversity() void RadioInterfaceDiversity::close() { delete outerRecvBuffer; + delete dnsampler; + dnsampler = NULL; outerRecvBuffer = NULL; - for (size_t i = 0; i < dnsamplers.size(); i++) { - delete dnsamplers[i]; - dnsamplers[i] = NULL; - } - if (recvBuffer.size()) recvBuffer[0] = NULL; @@ -98,15 +95,16 @@ bool RadioInterfaceDiversity::setupDiversityChannels() return false; } + dnsampler = new Resampler(resamp_inrate, resamp_outrate); + if (!dnsampler->init()) { + LOG(ALERT) << "Rx resampler failed to initialize"; + return false; + } + /* One Receive buffer and downsampler per diversity channel */ for (size_t i = 0; i < mMIMO * mChans; i++) { - dnsamplers[i] = new Resampler(resamp_inrate, resamp_outrate); - if (!dnsamplers[i]->init()) { - LOG(ALERT) << "Rx resampler failed to initialize"; - return false; - } - - recvBuffer[i] = new signalVector(inner_rx_len); + recvBuffer[i] = new RadioBuffer(NUMCHUNKS, + resamp_inchunk, 0, false); } return true; @@ -115,7 +113,7 @@ bool RadioInterfaceDiversity::setupDiversityChannels() /* Initialize I/O specific objects */ bool RadioInterfaceDiversity::init(int type) { - int tx_len, outer_rx_len; + int outer_rx_len; if ((mMIMO != 2) || (mChans != 2)) { LOG(ALERT) << "Unsupported channel configuration " << mChans; @@ -128,13 +126,11 @@ bool RadioInterfaceDiversity::init(int type) convertSendBuffer.resize(mChans); convertRecvBuffer.resize(mChans); mReceiveFIFO.resize(mChans); - dnsamplers.resize(mChans * mMIMO); phases.resize(mChans); if (!setupDiversityChannels()) return false; - tx_len = CHUNK * mSPSTx; outer_rx_len = resamp_outchunk; for (size_t i = 0; i < mChans; i++) { @@ -142,11 +138,11 @@ bool RadioInterfaceDiversity::init(int type) convertRecvBuffer[i] = new short[outer_rx_len * 2]; /* Send buffers (not-resampled) */ - sendBuffer[i] = new signalVector(tx_len); - convertSendBuffer[i] = new short[tx_len * 2]; + sendBuffer[i] = new RadioBuffer(NUMCHUNKS, CHUNK * mSPSTx, 0, true); + convertSendBuffer[i] = new short[CHUNK * mSPSTx * 2]; } - outerRecvBuffer = new signalVector(outer_rx_len, dnsamplers[0]->len()); + outerRecvBuffer = new signalVector(outer_rx_len, dnsampler->len()); return true; } @@ -182,7 +178,7 @@ void RadioInterfaceDiversity::pullBuffer() signalVector *shift, *base; float *in, *out, rate = -mFreqSpacing * 2.0 * M_PI / 1.08333333e6; - if (recvCursor > recvBuffer[0]->size() - resamp_inchunk) + if (recvBuffer[0]->getFreeSegments() <= 0) return; /* Outer buffer access size is fixed */ @@ -211,10 +207,10 @@ void RadioInterfaceDiversity::pullBuffer() /* Diversity path 1 */ base = outerRecvBuffer; in = (float *) base->begin(); - out = (float *) (recvBuffer[path0]->begin() + recvCursor); + out = (float *) recvBuffer[path0]->getWriteSegment(); - rc = dnsamplers[2 * i + 0]->rotate(in, resamp_outchunk, - out, resamp_inchunk); + rc = dnsampler->rotate(in, resamp_outchunk, + out, resamp_inchunk); if (rc < 0) { LOG(ALERT) << "Sample rate downsampling error"; } @@ -226,15 +222,15 @@ void RadioInterfaceDiversity::pullBuffer() /* Diversity path 2 */ shift = new signalVector(base->size(), base->getStart()); in = (float *) shift->begin(); - out = (float *) (recvBuffer[path1]->begin() + recvCursor); + out = (float *) recvBuffer[path1]->getWriteSegment(); rate = i ? -rate : rate; if (!frequencyShift(shift, base, rate, phases[i], &phases[i])) { LOG(ALERT) << "Frequency shift failed"; } - rc = dnsamplers[2 * i + 1]->rotate(in, resamp_outchunk, - out, resamp_inchunk); + rc = dnsampler->rotate(in, resamp_outchunk, + out, resamp_inchunk); if (rc < 0) { LOG(ALERT) << "Sample rate downsampling error"; } @@ -244,5 +240,4 @@ void RadioInterfaceDiversity::pullBuffer() underrun |= local_underrun; readTimestamp += (TIMESTAMP) resamp_outchunk; - recvCursor += resamp_inchunk; } diff --git a/Transceiver52M/radioInterfaceResamp.cpp b/Transceiver52M/radioInterfaceResamp.cpp index f898d65e..26dd40be 100644 --- a/Transceiver52M/radioInterfaceResamp.cpp +++ b/Transceiver52M/radioInterfaceResamp.cpp @@ -1,8 +1,10 @@ /* * Radio device interface with sample rate conversion - * Written by Thomas Tsou * - * Copyright 2011, 2012, 2013 Free Software Foundation, Inc. + * Copyright (C) 2011-2014 Free Software Foundation, Inc. + * Copyright (C) 2015 Ettus Research LLC + * + * Author: Tom Tsou * * 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 @@ -58,8 +60,8 @@ static size_t resamp_outchunk = 0; RadioInterfaceResamp::RadioInterfaceResamp(RadioDevice *wRadio, size_t sps, size_t chans) : RadioInterface(wRadio, sps, chans), - innerSendBuffer(NULL), outerSendBuffer(NULL), - innerRecvBuffer(NULL), outerRecvBuffer(NULL) + outerSendBuffer(NULL), + outerRecvBuffer(NULL) { } @@ -70,17 +72,13 @@ RadioInterfaceResamp::~RadioInterfaceResamp() void RadioInterfaceResamp::close() { - delete innerSendBuffer; delete outerSendBuffer; - delete innerRecvBuffer; delete outerRecvBuffer; delete upsampler; delete dnsampler; - innerSendBuffer = NULL; outerSendBuffer = NULL; - innerRecvBuffer = NULL; outerRecvBuffer = NULL; upsampler = NULL; @@ -157,21 +155,18 @@ bool RadioInterfaceResamp::init(int type) * and requires headroom equivalent to the filter length. Low * rate buffers are allocated in the main radio interface code. */ - innerSendBuffer = - new signalVector(NUMCHUNKS * resamp_inchunk, upsampler->len()); + sendBuffer[0] = new RadioBuffer(NUMCHUNKS, resamp_inchunk, + upsampler->len(), true); + recvBuffer[0] = new RadioBuffer(NUMCHUNKS * 20, resamp_inchunk, 0, false); + outerSendBuffer = new signalVector(NUMCHUNKS * resamp_outchunk); outerRecvBuffer = new signalVector(resamp_outchunk, dnsampler->len()); - innerRecvBuffer = - new signalVector(NUMCHUNKS * resamp_inchunk / mSPSTx); convertSendBuffer[0] = new short[outerSendBuffer->size() * 2]; convertRecvBuffer[0] = new short[outerRecvBuffer->size() * 2]; - sendBuffer[0] = innerSendBuffer; - recvBuffer[0] = innerRecvBuffer; - return true; } @@ -181,7 +176,7 @@ void RadioInterfaceResamp::pullBuffer() bool local_underrun; int rc, num_recv; - if (recvCursor > innerRecvBuffer->size() - resamp_inchunk) + if (recvBuffer[0]->getFreeSegments() <= 0) return; /* Outer buffer access size is fixed */ @@ -204,57 +199,47 @@ void RadioInterfaceResamp::pullBuffer() /* Write to the end of the inner receive buffer */ rc = dnsampler->rotate((float *) outerRecvBuffer->begin(), resamp_outchunk, - (float *) (innerRecvBuffer->begin() + recvCursor), + recvBuffer[0]->getWriteSegment(), resamp_inchunk); if (rc < 0) { LOG(ALERT) << "Sample rate upsampling error"; } - recvCursor += resamp_inchunk; + /* Set history for the next chunk */ + outerRecvBuffer->updateHistory(); } /* Send a timestamped chunk to the device */ -void RadioInterfaceResamp::pushBuffer() +bool RadioInterfaceResamp::pushBuffer() { - int rc, chunks, num_sent; - int inner_len, outer_len; + int rc; + size_t numSent; - if (sendCursor < resamp_inchunk) - return; - - if (sendCursor > innerSendBuffer->size()) - LOG(ALERT) << "Send buffer overflow"; - - chunks = sendCursor / resamp_inchunk; - - inner_len = chunks * resamp_inchunk; - outer_len = chunks * resamp_outchunk; + if (sendBuffer[0]->getAvailSegments() <= 0) + return false; /* Always send from the beginning of the buffer */ - rc = upsampler->rotate((float *) innerSendBuffer->begin(), inner_len, - (float *) outerSendBuffer->begin(), outer_len); + rc = upsampler->rotate(sendBuffer[0]->getReadSegment(), + resamp_inchunk, + (float *) outerSendBuffer->begin(), + resamp_outchunk); if (rc < 0) { LOG(ALERT) << "Sample rate downsampling error"; } convert_float_short(convertSendBuffer[0], (float *) outerSendBuffer->begin(), - powerScaling[0], 2 * outer_len); + powerScaling[0], 2 * resamp_outchunk); - num_sent = mRadio->writeSamples(convertSendBuffer, - outer_len, - &underrun, - writeTimestamp); - if (num_sent != outer_len) { - LOG(ALERT) << "Transmit error " << num_sent; + numSent = mRadio->writeSamples(convertSendBuffer, + resamp_outchunk, + &underrun, + writeTimestamp); + if (numSent != resamp_outchunk) { + LOG(ALERT) << "Transmit error " << numSent; } - /* Shift remaining samples to beginning of buffer */ - memmove(innerSendBuffer->begin(), - innerSendBuffer->begin() + inner_len, - (sendCursor - inner_len) * 2 * sizeof(float)); + writeTimestamp += resamp_outchunk; - writeTimestamp += outer_len; - sendCursor -= inner_len; - assert(sendCursor >= 0); + return true; } diff --git a/Transceiver52M/sigProcLib.cpp b/Transceiver52M/sigProcLib.cpp index 477449f0..7a032b39 100644 --- a/Transceiver52M/sigProcLib.cpp +++ b/Transceiver52M/sigProcLib.cpp @@ -2128,7 +2128,6 @@ bool sigProcLibSetup() goto fail; } - dnsampler->enableHistory(false); dnsampler_in = new signalVector(DOWNSAMPLE_IN_LEN, dnsampler->len()); return true; diff --git a/Transceiver52M/signalVector.cpp b/Transceiver52M/signalVector.cpp index 4b4099eb..798a3c70 100644 --- a/Transceiver52M/signalVector.cpp +++ b/Transceiver52M/signalVector.cpp @@ -50,6 +50,15 @@ size_t signalVector::getStart() const return mStart - mData; } +size_t signalVector::updateHistory() +{ + size_t num = getStart(); + + memmove(mData, mStart + this->size() - num, num * sizeof(complex)); + + return num; +} + Symmetry signalVector::getSymmetry() const { return symmetry; diff --git a/Transceiver52M/signalVector.h b/Transceiver52M/signalVector.h index c9cb1050..38541fec 100644 --- a/Transceiver52M/signalVector.h +++ b/Transceiver52M/signalVector.h @@ -32,6 +32,7 @@ public: /** Return head room */ size_t getStart() const; + size_t updateHistory(); Symmetry getSymmetry() const; void setSymmetry(Symmetry symmetry);