diff --git a/sdrbase/CMakeLists.txt b/sdrbase/CMakeLists.txt index 6153dd488..e54e5e454 100644 --- a/sdrbase/CMakeLists.txt +++ b/sdrbase/CMakeLists.txt @@ -98,6 +98,7 @@ set(sdrbase_SOURCES dsp/phaselockcomplex.cpp dsp/projector.cpp dsp/samplemififo.cpp + dsp/samplemofifo.cpp dsp/samplesinkfifo.cpp dsp/samplesourcefifo.cpp dsp/basebandsamplesink.cpp @@ -236,6 +237,7 @@ set(sdrbase_HEADERS dsp/projector.h dsp/recursivefilters.h dsp/samplemififo.h + dsp/samplemofifo.h dsp/samplesinkfifo.h dsp/samplesourcefifo.h dsp/basebandsamplesink.h diff --git a/sdrbase/dsp/samplemofifo.cpp b/sdrbase/dsp/samplemofifo.cpp new file mode 100644 index 000000000..ddee4aa19 --- /dev/null +++ b/sdrbase/dsp/samplemofifo.cpp @@ -0,0 +1,188 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2019 Edouard Griffiths, F4EXB // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as 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 General Public License V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////// + +#include "samplemofifo.h" + +void SampleMOFifo::init(unsigned int nbStreams, unsigned int size) +{ + m_nbStreams = nbStreams; + m_size = size; + m_readCount = 0; + m_readHead = size/2; + m_writeHead = 0; + m_data.resize(nbStreams); + m_vReadCount.clear(); + m_vReadHead.clear(); + m_vWriteHead.clear(); + + for (unsigned int stream = 0; stream < nbStreams; stream++) + { + m_data[stream].resize(size); + m_vReadCount.push_back(0); + m_vReadHead.push_back(size/2); + m_vWriteHead.push_back(0); + } +} + +SampleMOFifo::SampleMOFifo(QObject *parent) : + QObject(parent), + m_nbStreams(0), + m_size(0), + m_readCount(0) +{} + +SampleMOFifo::SampleMOFifo(unsigned int nbStreams, unsigned int size, QObject *parent) : + QObject(parent) +{ + init(nbStreams, size); +} + +SampleMOFifo::~SampleMOFifo() +{} + +void SampleMOFifo::reset() +{ + m_readCount = 0; + m_readHead = m_size/2; + m_writeHead = 0; + + for (unsigned int stream = 0; stream < m_nbStreams; stream++) + { + m_data[stream].resize(m_size); + m_vReadCount[stream] = 0; + m_vReadHead[stream] = m_size/2; + m_vWriteHead[stream] = 0; + } +} + +void SampleMOFifo::readSync( + unsigned int amount, + unsigned int& ipart1Begin, unsigned int& ipart1End, + unsigned int& ipart2Begin, unsigned int& ipart2End +) +{ + QMutexLocker mutexLocker(&m_mutex); + unsigned int spaceLeft = m_size - m_readHead; + m_readCount += amount; + + if (amount <= spaceLeft) + { + ipart1Begin = m_readHead; + ipart1End = m_readHead + amount; + ipart2Begin = m_size; + ipart2End = m_size; + m_readHead += amount; + } + else + { + unsigned int remaining = amount - spaceLeft; + ipart1Begin = m_readHead; + ipart1End = m_size; + ipart2Begin = 0; + ipart2End = remaining; + m_readHead = remaining; + } + + emit dataSyncRead(); +} + +void SampleMOFifo::writeSync(const std::vector& vbegin, unsigned int amount) +{ + QMutexLocker mutexLocker(&m_mutex); + unsigned int spaceLeft = m_size - m_writeHead; + m_readCount = amount < m_readCount ? m_readCount - amount : 0; + + if (amount <= spaceLeft) + { + for (unsigned int stream = 0; stream < m_nbStreams; stream++) + { + std::copy(vbegin[stream], vbegin[stream] + amount, m_data[stream].begin() + m_writeHead); + m_writeHead += amount; + } + } + else + { + unsigned int remaining = amount - spaceLeft; + + for (unsigned int stream = 0; stream < m_nbStreams; stream++) + { + std::copy(vbegin[stream], vbegin[stream] + spaceLeft, m_data[stream].begin() + m_writeHead); + std::copy(vbegin[stream] + spaceLeft, vbegin[stream] + amount, m_data[stream].begin()); + m_writeHead = remaining; + } + } +} + +void SampleMOFifo::readAsync( + unsigned int amount, + unsigned int& ipart1Begin, unsigned int& ipart1End, + unsigned int& ipart2Begin, unsigned int& ipart2End, + unsigned int stream +) +{ + if (stream >= m_nbStreams) { + return; + } + + QMutexLocker mutexLocker(&m_mutex); + unsigned int spaceLeft = m_size - m_vReadHead[stream]; + m_vReadCount[stream] += amount; + + if (amount <= spaceLeft) + { + ipart1Begin = m_vReadHead[stream]; + ipart1End = m_vReadHead[stream] + amount; + ipart2Begin = m_size; + ipart2End = m_size; + m_vReadHead[stream] += amount; + } + else + { + unsigned int remaining = amount - spaceLeft; + ipart1Begin = m_vReadHead[stream]; + ipart1End = m_size; + ipart2Begin = 0; + ipart2End = remaining; + m_readHead = remaining; + } + + emit dataAsyncRead(stream); +} + +void SampleMOFifo::writeAsync(const SampleVector::const_iterator& begin, unsigned int amount, unsigned int stream) +{ + QMutexLocker mutexLocker(&m_mutex); + unsigned int spaceLeft = m_size - m_vWriteHead[stream]; + m_vReadCount[stream] = amount < m_vReadCount[stream] ? m_vReadCount[stream] - amount : 0; + + if (amount <= spaceLeft) + { + std::copy(begin, begin + amount, m_data[stream].begin() + m_vWriteHead[stream]); + m_vWriteHead[stream] += amount; + } + else + { + unsigned int remaining = amount - spaceLeft; + + for (unsigned int stream = 0; stream < m_nbStreams; stream++) + { + std::copy(begin, begin + spaceLeft, m_data[stream].begin() + m_vWriteHead[stream]); + std::copy(begin + spaceLeft, begin + amount, m_data[stream].begin()); + m_vWriteHead[stream] = remaining; + } + } +} diff --git a/sdrbase/dsp/samplemofifo.h b/sdrbase/dsp/samplemofifo.h new file mode 100644 index 000000000..3382d6d89 --- /dev/null +++ b/sdrbase/dsp/samplemofifo.h @@ -0,0 +1,83 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2019 Edouard Griffiths, F4EXB // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as 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 General Public License V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////// + +#ifndef INCLUDE_SAMPLEMOFIFO_H +#define INCLUDE_SAMPLEMOFIFO_H + +#include +#include +#include "dsp/dsptypes.h" +#include "export.h" + +class SDRBASE_API SampleMOFifo : public QObject { + Q_OBJECT + +public: + SampleMOFifo(QObject *parent = nullptr); + SampleMOFifo(unsigned int nbStreams, unsigned int size, QObject *parent = nullptr); + ~SampleMOFifo(); + void init(unsigned int nbStreams, unsigned int size); + void reset(); + + void readSync( + unsigned int amount, + unsigned int& ipart1Begin, unsigned int& ipart1End, + unsigned int& ipart2Begin, unsigned int& ipart2End + ); + void writeSync(const std::vector& vbegin, unsigned int amount); + + void readAsync( + unsigned int amount, + unsigned int& ipart1Begin, unsigned int& ipart1End, + unsigned int& ipart2Begin, unsigned int& ipart2End, + unsigned int stream + ); + void writeAsync(const SampleVector::const_iterator& begin, unsigned int amount, unsigned int stream); + + unsigned int remainderSync() + { + QMutexLocker mutexLocker(&m_mutex); + return m_readCount; + } + unsigned int remainderAsync(unsigned int stream) + { + if (stream >= m_nbStreams) { + return 0; + } + + QMutexLocker mutexLocker(&m_mutex); + return m_vReadCount[stream]; + } + +signals: + void dataSyncRead(); + void dataAsyncRead(int streamIndex); + +private: + std::vector m_data; + unsigned int m_nbStreams; + unsigned int m_size; + unsigned int m_readCount; + unsigned int m_readHead; + unsigned int m_writeHead; + std::vector m_vReadCount; + std::vector m_vReadHead; + std::vector m_vWriteHead; + QMutex m_mutex; +}; + +#endif // INCLUDE_SAMPLEMOFIFO_H \ No newline at end of file