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();