1
0
mirror of https://github.com/f4exb/sdrangel.git synced 2024-11-26 17:58:43 -05:00

SDRdaemon plugin: implemented reset buffer indexes and auto balance buffer reads/writes

This commit is contained in:
Edouard Griffiths 2016-03-18 14:03:34 +01:00
parent f7e3db53fe
commit c1c64b7051
9 changed files with 195 additions and 46 deletions

View File

@ -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)

View File

@ -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
};

View File

@ -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);
}

View File

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

View File

@ -187,7 +187,7 @@
</size>
</property>
<property name="toolTip">
<string>Main buffer gauge: write leads read lags</string>
<string>Main buffer pointer positions: write leads read lags</string>
</property>
<property name="minimum">
<number>0</number>
@ -218,7 +218,7 @@
</size>
</property>
<property name="toolTip">
<string>Main buffer gauge: read leads write lags</string>
<string>Main buffer pointer positions: read leads write lags</string>
</property>
<property name="maximum">
<number>50</number>
@ -243,12 +243,19 @@
<item>
<layout class="QHBoxLayout" name="streamLayout">
<item>
<widget class="ButtonSwitch" name="autoFollowRate">
<widget class="QToolButton" name="streamLocked">
<property name="enabled">
<bool>false</bool>
</property>
<property name="toolTip">
<string>Follow stream sample rate automatically</string>
<string>Stream locked status i.e. synced with meta data</string>
</property>
<property name="text">
<string>Auto</string>
<string>...</string>
</property>
<property name="icon">
<iconset resource="../../../sdrbase/resources/res.qrc">
<normaloff>:/locked.png</normaloff>:/locked.png</iconset>
</property>
</widget>
</item>
@ -380,23 +387,6 @@
</item>
<item>
<layout class="QHBoxLayout" name="lz4Layout">
<item>
<widget class="QToolButton" name="streamLocked">
<property name="enabled">
<bool>false</bool>
</property>
<property name="toolTip">
<string>Stream locked status i.e. synced with meta data</string>
</property>
<property name="text">
<string>...</string>
</property>
<property name="icon">
<iconset resource="../../../sdrbase/resources/res.qrc">
<normaloff>:/locked.png</normaloff>:/locked.png</iconset>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="lz4Compressed">
<property name="enabled">
@ -505,6 +495,46 @@
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="resetIndexes">
<property name="maximumSize">
<size>
<width>22</width>
<height>20</height>
</size>
</property>
<property name="toolTip">
<string>Reset buffer indexes</string>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="../../../sdrbase/resources/res.qrc">
<normaloff>:/recycle.png</normaloff>:/recycle.png</iconset>
</property>
</widget>
</item>
<item>
<widget class="ButtonSwitch" name="autoCorrBuffer">
<property name="toolTip">
<string>Auto maintain buffer read / write balance</string>
</property>
<property name="text">
<string>B</string>
</property>
</widget>
</item>
<item>
<widget class="ButtonSwitch" name="autoFollowRate">
<property name="toolTip">
<string>Auto follow actual stream sample rate</string>
</property>
<property name="text">
<string>R</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
@ -619,6 +649,20 @@
</customwidgets>
<resources>
<include location="../../../sdrbase/resources/res.qrc"/>
<include location="../../../sdrbase/resources/res.qrc"/>
<include location="../../../sdrbase/resources/res.qrc"/>
<include location="../../../sdrbase/resources/res.qrc"/>
<include location="../../../sdrbase/resources/res.qrc"/>
<include location="../../../sdrbase/resources/res.qrc"/>
<include location="../../../sdrbase/resources/res.qrc"/>
<include location="../../../sdrbase/resources/res.qrc"/>
<include location="../../../sdrbase/resources/res.qrc"/>
<include location="../../../sdrbase/resources/res.qrc"/>
<include location="../../../sdrbase/resources/res.qrc"/>
<include location="../../../sdrbase/resources/res.qrc"/>
<include location="../../../sdrbase/resources/res.qrc"/>
<include location="../../../sdrbase/resources/res.qrc"/>
<include location="../../../sdrbase/resources/res.qrc"/>
</resources>
<connections/>
</ui>

View File

@ -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,11 +117,24 @@ 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();
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))

View File

@ -93,23 +93,40 @@ 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()
{ }
};
@ -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

View File

@ -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;
}

View File

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