From c1c64b70510a7253bedd7fd8efada93cfaf8ea15 Mon Sep 17 00:00:00 2001 From: Edouard Griffiths Date: Fri, 18 Mar 2016 14:03:34 +0100 Subject: [PATCH] SDRdaemon plugin: implemented reset buffer indexes and auto balance buffer reads/writes --- .../sdrdaemon/sdrdaemonbuffer.cpp | 43 +++++++-- .../samplesource/sdrdaemon/sdrdaemonbuffer.h | 17 +++- .../samplesource/sdrdaemon/sdrdaemongui.cpp | 30 +++++-- plugins/samplesource/sdrdaemon/sdrdaemongui.h | 5 +- .../samplesource/sdrdaemon/sdrdaemongui.ui | 88 ++++++++++++++----- .../samplesource/sdrdaemon/sdrdaemoninput.cpp | 26 ++++-- .../samplesource/sdrdaemon/sdrdaemoninput.h | 29 ++++-- .../sdrdaemon/sdrdaemonudphandler.cpp | 1 + .../sdrdaemon/sdrdaemonudphandler.h | 2 + 9 files changed, 195 insertions(+), 46 deletions(-) diff --git a/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.cpp b/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.cpp index 8304090ce..b542b8fc5 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.cpp +++ b/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.cpp @@ -57,11 +57,16 @@ SDRdaemonBuffer::SDRdaemonBuffer(uint32_t throttlems) : m_readSize(0), m_readBuffer(0), m_autoFollowRate(false), + m_autoCorrBuffer(false), m_skewTest(false), m_skewCorrection(false), + m_resetIndexes(false), m_readCount(0), m_writeCount(0), - m_nbCycles(0) + m_nbCycles(0), + m_readCountBal(0), + m_writeCountBal(0), + m_nbReadsBal(0) { m_currentMeta.init(); } @@ -191,6 +196,13 @@ bool SDRdaemonBuffer::readMeta(char *array, uint32_t length) m_sampleRate = sampleRate; } + // Reset indexes if requested + if (m_resetIndexes) + { + resetIndexes(); + m_resetIndexes = false; + } + if (metaData->m_sampleBytes & 0x10) { m_lz4 = true; @@ -240,15 +252,33 @@ void SDRdaemonBuffer::writeData(char *array, uint32_t length) uint8_t *SDRdaemonBuffer::readData(int32_t length) { + // auto compensation calculations if (m_skewTest && ((m_readIndex + length) > (m_rawSize / 2))) { + // auto follow sample rate calculation int dIndex = (m_readIndex - m_writeIndex > 0 ? m_readIndex - m_writeIndex : m_writeIndex - m_readIndex); // absolute delta m_skewCorrection = (dIndex < m_rawSize / 10); // close by 10% m_nbCycles++; + // auto R/W balance calculation + if (m_nbReadsBal && m_autoCorrBuffer) + { + int32_t dBytes = (m_writeCountBal - m_readCountBal) / m_nbReadsBal; + m_balCorrection += dBytes / (int32_t) m_iqSampleSize; + m_readCountBal = 0; + m_writeCountBal = 0; + m_nbReadsBal = 0; + } + else + { + m_balCorrection = 0; + } + // un-arm m_skewTest = false; } m_readCount += length; + m_readCountBal += length; + m_nbReadsBal++; if (m_readIndex + length < m_rawSize) { @@ -260,13 +290,11 @@ uint8_t *SDRdaemonBuffer::readData(int32_t length) { uint32_t readIndex = m_readIndex; m_readIndex = 0; - m_skewTest = true; + m_skewTest = true; // re-arm return &m_rawBuffer[readIndex]; } else { - // TODO: implement auto skew rate compensation calculation - if (length > m_readSize) { updateReadBufferSize(length); @@ -277,7 +305,7 @@ uint8_t *SDRdaemonBuffer::readData(int32_t length) length -= m_rawSize - m_readIndex; std::memcpy((void *) &m_readBuffer[m_rawSize - m_readIndex], (const void *) m_rawBuffer, length); m_readIndex = length; - m_skewTest = true; + m_skewTest = true; // re-arm return m_readBuffer; } } @@ -361,6 +389,7 @@ void SDRdaemonBuffer::writeToRawBufferUncompressed(const char *array, uint32_t l } m_writeCount += length; + m_writeCountBal += length; } void SDRdaemonBuffer::resetIndexes() @@ -372,6 +401,10 @@ void SDRdaemonBuffer::resetIndexes() m_nbCycles = 0; m_skewTest = false; m_skewCorrection = false; + m_readCountBal = 0; + m_writeCountBal = 0; + m_nbReadsBal = 0; + m_balCorrection = 0; } void SDRdaemonBuffer::updateBlockCounts(uint32_t nbBytesReceived) diff --git a/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h b/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h index 912c88e38..c594f1915 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h +++ b/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h @@ -79,6 +79,9 @@ public: uint32_t getLz4DataCRCOK() const { return m_nbLastLz4CRCOK; } uint32_t getLz4SuccessfulDecodes() const { return m_nbLastLz4SuccessfulDecodes; } void setAutoFollowRate(bool autoFollowRate) { m_autoFollowRate = autoFollowRate; } + void setAutoCorrBuffer(bool autoCorrBuffer) { m_autoCorrBuffer = autoCorrBuffer; } + void setResetIndexes() { m_resetIndexes = true; } + int32_t getRWBalanceCorrection() const { return m_balCorrection; } /** Get buffer gauge value in % of buffer size ([-50:50]) * [-50:0] : write leads or read lags @@ -154,11 +157,19 @@ private: uint8_t *m_readBuffer; //!< Read buffer to hold samples when looping back to beginning of raw buffer bool m_autoFollowRate; //!< Auto follow stream sample rate else stick with meta data sample rate + bool m_autoCorrBuffer; //!< Auto correct buffer read / write balance (attempt to ...) bool m_skewTest; bool m_skewCorrection; //!< Do a skew rate correction at next meta data reception - int64_t m_readCount; - int64_t m_writeCount; - uint32_t m_nbCycles; //!< Number of buffer cycles since start of byte counting + bool m_resetIndexes; //!< Do a reset indexes at next meta data reception + + int64_t m_readCount; //!< Number of bytes read for auto skew compensation + int64_t m_writeCount; //!< Number of bytes written for auto skew compensation + uint32_t m_nbCycles; //!< Number of buffer cycles since start of auto skew compensation byte counting + + int64_t m_readCountBal; //!< Number of bytes read for auto R/W balance + int64_t m_writeCountBal; //!< Number of bytes written for auto R/W balance + uint32_t m_nbReadsBal; //!< Number of buffer reads since start of auto R/W balance byte counting + int32_t m_balCorrection; //!< R/W balance correction in number of samples }; diff --git a/plugins/samplesource/sdrdaemon/sdrdaemongui.cpp b/plugins/samplesource/sdrdaemon/sdrdaemongui.cpp index eb11fa5f2..079860a63 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemongui.cpp +++ b/plugins/samplesource/sdrdaemon/sdrdaemongui.cpp @@ -116,6 +116,7 @@ QByteArray SDRdaemonGui::serialize() const s.writeBool(3, m_dcBlock); s.writeBool(4, m_iqCorrection); s.writeBool(5, m_autoFollowRate); + s.writeBool(6, m_autoCorrBuffer); return s.final(); } @@ -129,6 +130,7 @@ bool SDRdaemonGui::deserialize(const QByteArray& data) bool dcBlock; bool iqCorrection; bool autoFollowRate; + bool autoCorrBuffer; if (!d.isValid()) { @@ -152,6 +154,7 @@ bool SDRdaemonGui::deserialize(const QByteArray& data) d.readBool(3, &dcBlock, false); d.readBool(4, &iqCorrection, false); d.readBool(5, &autoFollowRate, false); + d.readBool(5, &autoCorrBuffer, false); if ((address != m_address) || (port != m_port)) { @@ -167,9 +170,11 @@ bool SDRdaemonGui::deserialize(const QByteArray& data) configureAutoCorrections(); } - if (m_autoFollowRate != autoFollowRate) { + if ((m_autoFollowRate != autoFollowRate) || (m_autoCorrBuffer != autoCorrBuffer)) + { m_autoFollowRate = autoFollowRate; - configureAutoFollowRate(); + m_autoCorrBuffer = autoCorrBuffer; + configureAutoFollowPolicy(); } displaySettings(); @@ -261,6 +266,7 @@ void SDRdaemonGui::displaySettings() ui->dcOffset->setChecked(m_dcBlock); ui->iqImbalance->setChecked(m_iqCorrection); ui->autoFollowRate->setChecked(m_autoFollowRate); + ui->autoCorrBuffer->setChecked(m_autoCorrBuffer); } void SDRdaemonGui::on_applyButton_clicked(bool checked) @@ -314,10 +320,24 @@ void SDRdaemonGui::on_autoFollowRate_toggled(bool checked) { if (m_autoFollowRate != checked) { m_autoFollowRate = checked; - configureAutoFollowRate(); + configureAutoFollowPolicy(); } } +void SDRdaemonGui::on_autoCorrBuffer_toggled(bool checked) +{ + if (m_autoCorrBuffer != checked) { + m_autoCorrBuffer = checked; + configureAutoFollowPolicy(); + } +} + +void SDRdaemonGui::on_resetIndexes_clicked(bool checked) +{ + SDRdaemonInput::MsgConfigureSDRdaemonResetIndexes* message = SDRdaemonInput::MsgConfigureSDRdaemonResetIndexes::create(); + m_sampleSource->getInputMessageQueue()->push(message); +} + void SDRdaemonGui::configureUDPLink() { qDebug() << "SDRdaemonGui::configureUDPLink: " << m_address.toStdString().c_str() @@ -333,9 +353,9 @@ void SDRdaemonGui::configureAutoCorrections() m_sampleSource->getInputMessageQueue()->push(message); } -void SDRdaemonGui::configureAutoFollowRate() +void SDRdaemonGui::configureAutoFollowPolicy() { - SDRdaemonInput::MsgConfigureSDRdaemonAutoFollowRate* message = SDRdaemonInput::MsgConfigureSDRdaemonAutoFollowRate::create(m_autoFollowRate); + SDRdaemonInput::MsgConfigureSDRdaemonAutoFollowPolicy* message = SDRdaemonInput::MsgConfigureSDRdaemonAutoFollowPolicy::create(m_autoFollowRate, m_autoCorrBuffer); m_sampleSource->getInputMessageQueue()->push(message); } diff --git a/plugins/samplesource/sdrdaemon/sdrdaemongui.h b/plugins/samplesource/sdrdaemon/sdrdaemongui.h index 28688e97a..3684c1006 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemongui.h +++ b/plugins/samplesource/sdrdaemon/sdrdaemongui.h @@ -75,12 +75,13 @@ private: bool m_dcBlock; bool m_iqCorrection; bool m_autoFollowRate; + bool m_autoCorrBuffer; void displaySettings(); void displayTime(); void configureUDPLink(); void configureAutoCorrections(); - void configureAutoFollowRate(); + void configureAutoFollowPolicy(); void updateWithAcquisition(); void updateWithStreamData(); void updateWithStreamTime(); @@ -91,6 +92,8 @@ private slots: void on_dcOffset_toggled(bool checked); void on_iqImbalance_toggled(bool checked); void on_autoFollowRate_toggled(bool checked); + void on_autoCorrBuffer_toggled(bool checked); + void on_resetIndexes_clicked(bool checked); void on_address_textEdited(const QString& arg1); void on_port_textEdited(const QString& arg1); void tick(); diff --git a/plugins/samplesource/sdrdaemon/sdrdaemongui.ui b/plugins/samplesource/sdrdaemon/sdrdaemongui.ui index d0a11ea89..858db5ba4 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemongui.ui +++ b/plugins/samplesource/sdrdaemon/sdrdaemongui.ui @@ -187,7 +187,7 @@ - Main buffer gauge: write leads read lags + Main buffer pointer positions: write leads read lags 0 @@ -218,7 +218,7 @@ - Main buffer gauge: read leads write lags + Main buffer pointer positions: read leads write lags 50 @@ -243,12 +243,19 @@ - + + + false + - Follow stream sample rate automatically + Stream locked status i.e. synced with meta data - Auto + ... + + + + :/locked.png:/locked.png @@ -380,23 +387,6 @@ - - - - false - - - Stream locked status i.e. synced with meta data - - - ... - - - - :/locked.png:/locked.png - - - @@ -505,6 +495,46 @@ + + + + + 22 + 20 + + + + Reset buffer indexes + + + + + + + :/recycle.png:/recycle.png + + + + + + + Auto maintain buffer read / write balance + + + B + + + + + + + Auto follow actual stream sample rate + + + R + + + @@ -619,6 +649,20 @@ + + + + + + + + + + + + + + diff --git a/plugins/samplesource/sdrdaemon/sdrdaemoninput.cpp b/plugins/samplesource/sdrdaemon/sdrdaemoninput.cpp index 043b93c81..ae0ce0cec 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemoninput.cpp +++ b/plugins/samplesource/sdrdaemon/sdrdaemoninput.cpp @@ -30,7 +30,8 @@ MESSAGE_CLASS_DEFINITION(SDRdaemonInput::MsgConfigureSDRdaemonUDPLink, Message) MESSAGE_CLASS_DEFINITION(SDRdaemonInput::MsgConfigureSDRdaemonAutoCorr, Message) MESSAGE_CLASS_DEFINITION(SDRdaemonInput::MsgConfigureSDRdaemonWork, Message) -MESSAGE_CLASS_DEFINITION(SDRdaemonInput::MsgConfigureSDRdaemonAutoFollowRate, Message) +MESSAGE_CLASS_DEFINITION(SDRdaemonInput::MsgConfigureSDRdaemonAutoFollowPolicy, Message) +MESSAGE_CLASS_DEFINITION(SDRdaemonInput::MsgConfigureSDRdaemonResetIndexes, Message) MESSAGE_CLASS_DEFINITION(SDRdaemonInput::MsgConfigureSDRdaemonStreamTiming, Message) MESSAGE_CLASS_DEFINITION(SDRdaemonInput::MsgReportSDRdaemonAcquisition, Message) MESSAGE_CLASS_DEFINITION(SDRdaemonInput::MsgReportSDRdaemonStreamData, Message) @@ -44,7 +45,9 @@ SDRdaemonInput::SDRdaemonInput(const QTimer& masterTimer) : m_sampleRate(0), m_centerFrequency(0), m_startingTimeStamp(0), - m_masterTimer(masterTimer) + m_masterTimer(masterTimer), + m_autoFollowRate(false), + m_autoCorrBuffer(false) { m_sampleFifo.setSize(96000 * 4); m_SDRdaemonUDPHandler = new SDRdaemonUDPHandler(&m_sampleFifo, getOutputMessageQueueToGUI()); @@ -114,13 +117,26 @@ bool SDRdaemonInput::handleMessage(const Message& message) DSPEngine::instance()->configureCorrections(dcBlock, iqImbalance); return true; } - else if (MsgConfigureSDRdaemonAutoFollowRate::match(message)) + else if (MsgConfigureSDRdaemonAutoFollowPolicy::match(message)) { - MsgConfigureSDRdaemonAutoFollowRate& conf = (MsgConfigureSDRdaemonAutoFollowRate&) message; + MsgConfigureSDRdaemonAutoFollowPolicy& conf = (MsgConfigureSDRdaemonAutoFollowPolicy&) message; bool autoFollowRate = conf.autoFollowRate(); - m_SDRdaemonUDPHandler->setAutoFollowRate(autoFollowRate); + bool autoCorrBuffer = conf.autoCorrBuffer(); + if (autoFollowRate != m_autoFollowRate) { + m_SDRdaemonUDPHandler->setAutoFollowRate(autoFollowRate); + m_autoFollowRate = autoFollowRate; + } + if (autoCorrBuffer != m_autoCorrBuffer) { + m_SDRdaemonUDPHandler->setAutoCorrBuffer(autoCorrBuffer); + m_autoCorrBuffer = autoCorrBuffer; + } return true; } + else if (MsgConfigureSDRdaemonResetIndexes::match(message)) + { + m_SDRdaemonUDPHandler->resetIndexes(); + return true; + } else if (MsgConfigureSDRdaemonWork::match(message)) { MsgConfigureSDRdaemonWork& conf = (MsgConfigureSDRdaemonWork&) message; diff --git a/plugins/samplesource/sdrdaemon/sdrdaemoninput.h b/plugins/samplesource/sdrdaemon/sdrdaemoninput.h index 5985d000a..a8dbe1084 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemoninput.h +++ b/plugins/samplesource/sdrdaemon/sdrdaemoninput.h @@ -93,26 +93,43 @@ public: { } }; - class MsgConfigureSDRdaemonAutoFollowRate : public Message { + class MsgConfigureSDRdaemonAutoFollowPolicy : public Message { MESSAGE_CLASS_DECLARATION public: bool autoFollowRate() const { return m_autoFollowRate; } + bool autoCorrBuffer() const { return m_autoCorrBuffer; } - static MsgConfigureSDRdaemonAutoFollowRate* create(bool autoFollowRate) + static MsgConfigureSDRdaemonAutoFollowPolicy* create(bool autoFollowRate, bool autoCorrBuffer) { - return new MsgConfigureSDRdaemonAutoFollowRate(autoFollowRate); + return new MsgConfigureSDRdaemonAutoFollowPolicy(autoFollowRate, autoCorrBuffer); } private: bool m_autoFollowRate; + bool m_autoCorrBuffer; - MsgConfigureSDRdaemonAutoFollowRate(bool autoFollowRate) : + MsgConfigureSDRdaemonAutoFollowPolicy(bool autoFollowRate, bool autoCorrBuffer) : Message(), - m_autoFollowRate(autoFollowRate) + m_autoFollowRate(autoFollowRate), + m_autoCorrBuffer(autoCorrBuffer) { } }; + class MsgConfigureSDRdaemonResetIndexes : public Message { + MESSAGE_CLASS_DECLARATION + public: + static MsgConfigureSDRdaemonResetIndexes* create() + { + return new MsgConfigureSDRdaemonResetIndexes(); + } + + private: + MsgConfigureSDRdaemonResetIndexes() : + Message() + { } + }; + class MsgConfigureSDRdaemonStreamTiming : public Message { MESSAGE_CLASS_DECLARATION @@ -274,6 +291,8 @@ private: quint64 m_centerFrequency; std::time_t m_startingTimeStamp; const QTimer& m_masterTimer; + bool m_autoFollowRate; + bool m_autoCorrBuffer; }; #endif // INCLUDE_SDRDAEMONINPUT_H diff --git a/plugins/samplesource/sdrdaemon/sdrdaemonudphandler.cpp b/plugins/samplesource/sdrdaemon/sdrdaemonudphandler.cpp index 15afcdbc2..ed1ea3d62 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemonudphandler.cpp +++ b/plugins/samplesource/sdrdaemon/sdrdaemonudphandler.cpp @@ -218,6 +218,7 @@ void SDRdaemonUDPHandler::tick() { m_throttlems = throttlems; m_readLengthSamples = (m_sdrDaemonBuffer.getSampleRate() * (m_throttlems+(m_throttleToggle ? 1 : 0))) / 1000; + m_readLengthSamples += m_sdrDaemonBuffer.getRWBalanceCorrection(); m_readLength = m_readLengthSamples * SDRdaemonBuffer::m_iqSampleSize; m_throttleToggle = !m_throttleToggle; } diff --git a/plugins/samplesource/sdrdaemon/sdrdaemonudphandler.h b/plugins/samplesource/sdrdaemon/sdrdaemonudphandler.h index d94199807..36cecbbb5 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemonudphandler.h +++ b/plugins/samplesource/sdrdaemon/sdrdaemonudphandler.h @@ -42,6 +42,8 @@ public: void stop(); void configureUDPLink(const QString& address, quint16 port); void setAutoFollowRate(bool autoFollowRate) { m_sdrDaemonBuffer.setAutoFollowRate(autoFollowRate); } + void setAutoCorrBuffer(bool autoCorrBuffer) { m_sdrDaemonBuffer.setAutoCorrBuffer(autoCorrBuffer); } + void resetIndexes() { m_sdrDaemonBuffer.setResetIndexes(); } public slots: void dataReadyRead();