Files
osmo-trx/Transceiver52M/radioBuffer.cpp
Eric 5561f1129d clean up mutex, scopedlock, and signal classes
This also uncovers very interesting design decisions like the copying of
mutexes and condition vars depending on recursive locks that were
previously hidden by shady c function calls..
We have perfectly good c++11 versions for all of that.

While we're at it, also use the initialization list for the other (still
copy constructable) vectors, which cleans up the radio interfaces.

Change-Id: Idc9e3b1144c5b93f5dad2f8e0e30f1058477aa52
2022-12-23 13:41:30 +00:00

230 lines
5.4 KiB
C++

/*
* Segmented Ring Buffer
*
* Copyright (C) 2015 Ettus Research LLC
*
* Author: Tom Tsou <tom@tsou.cc>
*
* SPDX-License-Identifier: AGPL-3.0+
*
* 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 <string.h>
#include <iostream>
#include "radioBuffer.h"
RadioBuffer::RadioBuffer(size_t numSegments, size_t segmentLen,
size_t hLen, bool outDirection)
: writeIndex(0), readIndex(0), availSamples(0), segments(numSegments)
{
if (!outDirection)
hLen = 0;
buffer = new float[2 * (hLen + numSegments * segmentLen)];
bufferLen = numSegments * segmentLen;
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;
}