1
0
mirror of https://github.com/f4exb/sdrangel.git synced 2024-11-15 12:51:49 -05:00

DaemonSrc: implemented status report to the GUI

This commit is contained in:
f4exb 2018-09-02 19:12:03 +02:00
parent 472a9b2532
commit b306aa8aa7
8 changed files with 607 additions and 30 deletions

View File

@ -35,6 +35,8 @@
MESSAGE_CLASS_DEFINITION(DaemonSrc::MsgSampleRateNotification, Message)
MESSAGE_CLASS_DEFINITION(DaemonSrc::MsgConfigureDaemonSrc, Message)
MESSAGE_CLASS_DEFINITION(DaemonSrc::MsgQueryStreamData, Message)
MESSAGE_CLASS_DEFINITION(DaemonSrc::MsgReportStreamData, Message)
const QString DaemonSrc::m_channelIdURI = "sdrangel.channeltx.daemonsrc";
const QString DaemonSrc::m_channelId ="DaemonSrc";
@ -140,6 +142,30 @@ bool DaemonSrc::handleMessage(const Message& cmd)
return true;
}
else if (MsgQueryStreamData::match(cmd))
{
if (m_guiMessageQueue)
{
struct timeval tv;
gettimeofday(&tv, 0);
MsgReportStreamData *msg = MsgReportStreamData::create(
tv.tv_sec,
tv.tv_usec,
m_dataReadQueue.size(),
m_dataReadQueue.length(),
m_dataReadQueue.readSampleCount(),
m_nbCorrectableErrors,
m_nbUncorrectableErrors,
m_currentMeta.m_nbOriginalBlocks,
m_currentMeta.m_nbFECBlocks,
m_currentMeta.m_centerFrequency,
m_currentMeta.m_sampleRate);
m_guiMessageQueue->push(msg);
}
return true;
}
return false;
}
@ -422,3 +448,4 @@ void DaemonSrc::webapiFormatChannelReport(SWGSDRangel::SWGChannelReport& respons
response.getSdrDaemonChannelSourceReport()->setCorrectableErrorsCount(m_nbCorrectableErrors);
response.getSdrDaemonChannelSourceReport()->setUncorrectableErrorsCount(m_nbUncorrectableErrors);
}

View File

@ -83,6 +83,99 @@ public:
int m_sampleRate;
};
class MsgQueryStreamData : public Message {
MESSAGE_CLASS_DECLARATION
public:
static MsgQueryStreamData* create() {
return new MsgQueryStreamData();
}
private:
MsgQueryStreamData() : Message() {}
};
class MsgReportStreamData : public Message {
MESSAGE_CLASS_DECLARATION
public:
uint32_t get_tv_sec() const { return m_tv_sec; }
uint32_t get_tv_usec() const { return m_tv_usec; }
uint32_t get_queueSize() const { return m_queueSize; }
uint32_t get_queueLength() const { return m_queueLength; }
uint32_t get_readSamplesCount() const { return m_readSamplesCount; }
uint32_t get_nbCorrectableErrors() const { return m_nbCorrectableErrors; }
uint32_t get_nbUncorrectableErrors() const { return m_nbUncorrectableErrors; }
uint32_t get_nbOriginalBlocks() const { return m_nbOriginalBlocks; }
uint32_t get_nbFECBlocks() const { return m_nbFECBlocks; }
uint32_t get_centerFreq() const { return m_centerFreq; }
uint32_t get_sampleRate() const { return m_sampleRate; }
static MsgReportStreamData* create(
uint32_t tv_sec,
uint32_t tv_usec,
uint32_t queueSize,
uint32_t queueLength,
uint32_t readSamplesCount,
uint32_t nbCorrectableErrors,
uint32_t nbUncorrectableErrors,
uint32_t nbOriginalBlocks,
uint32_t nbFECBlocks,
uint32_t centerFreq,
uint32_t sampleRate)
{
return new MsgReportStreamData(
tv_sec,
tv_usec,
queueSize,
queueLength,
readSamplesCount,
nbCorrectableErrors,
nbUncorrectableErrors,
nbOriginalBlocks,
nbFECBlocks,
centerFreq,
sampleRate);
}
protected:
uint32_t m_tv_sec;
uint32_t m_tv_usec;
uint32_t m_queueSize;
uint32_t m_queueLength;
uint32_t m_readSamplesCount;
uint32_t m_nbCorrectableErrors;
uint32_t m_nbUncorrectableErrors;
uint32_t m_nbOriginalBlocks;
uint32_t m_nbFECBlocks;
uint32_t m_centerFreq;
uint32_t m_sampleRate;
MsgReportStreamData(
uint32_t tv_sec,
uint32_t tv_usec,
uint32_t queueSize,
uint32_t queueLength,
uint32_t readSamplesCount,
uint32_t nbCorrectableErrors,
uint32_t nbUncorrectableErrors,
uint32_t nbOriginalBlocks,
uint32_t nbFECBlocks,
uint32_t centerFreq,
uint32_t sampleRate) :
Message(),
m_tv_sec(tv_sec),
m_tv_usec(tv_usec),
m_queueSize(queueSize),
m_queueLength(queueLength),
m_readSamplesCount(readSamplesCount),
m_nbCorrectableErrors(nbCorrectableErrors),
m_nbUncorrectableErrors(nbUncorrectableErrors),
m_nbOriginalBlocks(nbOriginalBlocks),
m_nbFECBlocks(nbFECBlocks),
m_centerFreq(centerFreq),
m_sampleRate(sampleRate)
{ }
};
DaemonSrc(DeviceSinkAPI *deviceAPI);
~DaemonSrc();

View File

@ -93,6 +93,60 @@ bool DaemonSrcGUI::handleMessage(const Message& message)
blockApplySettings(false);
return true;
}
else if (DaemonSrc::MsgReportStreamData::match(message))
{
const DaemonSrc::MsgReportStreamData& report = (DaemonSrc::MsgReportStreamData&) message;
ui->centerFrequency->setText(QString("%1").arg(report.get_centerFreq()));
ui->sampleRate->setText(QString("%1").arg(report.get_sampleRate()));
QString nominalNbBlocksText = QString("%1/%2")
.arg(report.get_nbOriginalBlocks() + report.get_nbFECBlocks())
.arg(report.get_nbFECBlocks());
ui->nominalNbBlocksText->setText(nominalNbBlocksText);
QString queueLengthText = QString("%1/%2").arg(report.get_queueLength()).arg(report.get_queueSize());
ui->queueLengthText->setText(queueLengthText);
int queueLengthPercent = (report.get_queueLength()*100)/report.get_queueSize();
ui->queueLengthGauge->setValue(queueLengthPercent);
int unrecoverableCount = report.get_nbUncorrectableErrors();
int recoverableCount = report.get_nbCorrectableErrors();
uint64_t timestampUs = report.get_tv_sec()*1000000ULL + report.get_tv_usec();
if (!m_resetCounts)
{
int recoverableCountDelta = recoverableCount - m_lastCountRecovered;
int unrecoverableCountDelta = unrecoverableCount - m_lastCountUnrecoverable;
displayEventStatus(recoverableCountDelta, unrecoverableCountDelta);
m_countRecovered += recoverableCountDelta;
m_countUnrecoverable += unrecoverableCountDelta;
displayEventCounts();
}
uint32_t sampleCountDelta, sampleCount;
sampleCount = report.get_readSamplesCount();
if (sampleCount < m_lastSampleCount) {
sampleCountDelta = (0xFFFFFFFFU - sampleCount) + m_lastSampleCount + 1;
} else {
sampleCountDelta = sampleCount - m_lastSampleCount;
}
if (sampleCountDelta == 0) {
ui->allFramesDecoded->setStyleSheet("QToolButton { background-color : blue; }");
}
double remoteStreamRate = sampleCountDelta*1e6 / (double) (timestampUs - m_lastTimestampUs);
if (remoteStreamRate != 0) {
ui->streamRateText->setText(QString("%1").arg(remoteStreamRate, 0, 'f', 0));
}
m_resetCounts = false;
m_lastCountRecovered = recoverableCount;
m_lastCountUnrecoverable = unrecoverableCount;
m_lastSampleCount = sampleCount;
m_lastTimestampUs = timestampUs;
return true;
}
else
{
return false;
@ -103,7 +157,15 @@ DaemonSrcGUI::DaemonSrcGUI(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, Baseb
RollupWidget(parent),
ui(new Ui::DaemonSrcGUI),
m_pluginAPI(pluginAPI),
m_deviceUISet(deviceUISet)
m_deviceUISet(deviceUISet),
m_countUnrecoverable(0),
m_countRecovered(0),
m_lastCountUnrecoverable(0),
m_lastCountRecovered(0),
m_lastSampleCount(0),
m_lastTimestampUs(0),
m_resetCounts(true),
m_tickCount(0)
{
ui->setupUi(this);
setAttribute(Qt::WA_DeleteOnClose, true);
@ -126,6 +188,9 @@ DaemonSrcGUI::DaemonSrcGUI(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, Baseb
m_deviceUISet->addRollupWidget(this);
connect(getInputMessageQueue(), SIGNAL(messageEnqueued()), this, SLOT(handleSourceMessages()));
connect(&(m_deviceUISet->m_deviceSinkAPI->getMasterTimer()), SIGNAL(timeout()), this, SLOT(tick()));
m_time.start();
displaySettings();
applySettings(true);
@ -250,3 +315,59 @@ void DaemonSrcGUI::on_dataApplyButton_clicked(bool checked __attribute__((unused
applySettings();
}
void DaemonSrcGUI::on_eventCountsReset_clicked(bool checked __attribute__((unused)))
{
m_countUnrecoverable = 0;
m_countRecovered = 0;
m_time.start();
displayEventCounts();
displayEventTimer();
}
void DaemonSrcGUI::displayEventCounts()
{
QString nstr = QString("%1").arg(m_countUnrecoverable, 3, 10, QChar('0'));
ui->eventUnrecText->setText(nstr);
nstr = QString("%1").arg(m_countRecovered, 3, 10, QChar('0'));
ui->eventRecText->setText(nstr);
}
void DaemonSrcGUI::displayEventStatus(int recoverableCount, int unrecoverableCount)
{
if (unrecoverableCount == 0)
{
if (recoverableCount == 0) {
ui->allFramesDecoded->setStyleSheet("QToolButton { background-color : green; }");
} else {
ui->allFramesDecoded->setStyleSheet("QToolButton { background:rgb(79,79,79); }");
}
}
else
{
ui->allFramesDecoded->setStyleSheet("QToolButton { background-color : red; }");
}
}
void DaemonSrcGUI::displayEventTimer()
{
int elapsedTimeMillis = m_time.elapsed();
QTime recordLength(0, 0, 0, 0);
recordLength = recordLength.addSecs(elapsedTimeMillis/1000);
QString s_time = recordLength.toString("HH:mm:ss");
ui->eventCountsTimeText->setText(s_time);
}
void DaemonSrcGUI::tick()
{
if (++m_tickCount == 20) // once per second
{
DaemonSrc::MsgQueryStreamData *msg = DaemonSrc::MsgQueryStreamData::create();
m_daemonSrc->getInputMessageQueue()->push(msg);
displayEventTimer();
m_tickCount = 0;
}
}

View File

@ -17,10 +17,12 @@
#ifndef PLUGINS_CHANNELTX_DAEMONSRC_DAEMONSRCGUI_H_
#define PLUGINS_CHANNELTX_DAEMONSRC_DAEMONSRCGUI_H_
#include <QTime>
#include "plugin/plugininstancegui.h"
#include "dsp/channelmarker.h"
#include "gui/rollupwidget.h"
#include "util/messagequeue.h"
#include "dsp/channelmarker.h"
#include "daemonsrcsettings.h"
@ -62,6 +64,16 @@ private:
DaemonSrc* m_daemonSrc;
MessageQueue m_inputMessageQueue;
uint32_t m_countUnrecoverable;
uint32_t m_countRecovered;
uint32_t m_lastCountUnrecoverable;
uint32_t m_lastCountRecovered;
uint32_t m_lastSampleCount;
uint64_t m_lastTimestampUs;
bool m_resetCounts;
QTime m_time;
uint32_t m_tickCount;
explicit DaemonSrcGUI(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, BasebandSampleSource *channelTx, QWidget* parent = 0);
virtual ~DaemonSrcGUI();
@ -72,6 +84,10 @@ private:
void leaveEvent(QEvent*);
void enterEvent(QEvent*);
void displayEventCounts();
void displayEventStatus(int recoverableCount, int unrecoverableCount);
void displayEventTimer();
private slots:
void handleSourceMessages();
void on_dataAddress_returnPressed();
@ -79,6 +95,8 @@ private slots:
void on_dataApplyButton_clicked(bool checked);
void onWidgetRolled(QWidget* widget, bool rollDown);
void onMenuDialogCalled(const QPoint& p);
void on_eventCountsReset_clicked(bool checked);
void tick();
};

View File

@ -7,7 +7,7 @@
<x>0</x>
<y>0</y>
<width>320</width>
<height>90</height>
<height>140</height>
</rect>
</property>
<property name="sizePolicy">
@ -19,7 +19,13 @@
<property name="minimumSize">
<size>
<width>320</width>
<height>90</height>
<height>140</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>320</width>
<height>16777215</height>
</size>
</property>
<property name="font">
@ -37,7 +43,7 @@
<x>10</x>
<y>10</y>
<width>301</width>
<height>61</height>
<height>121</height>
</rect>
</property>
<property name="windowTitle">
@ -150,6 +156,272 @@
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="nominalValuesLayout">
<item>
<widget class="QLabel" name="centerFrequencyLabel">
<property name="text">
<string>Freq</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="centerFrequency">
<property name="minimumSize">
<size>
<width>60</width>
<height>0</height>
</size>
</property>
<property name="toolTip">
<string>Stream center frequency setting</string>
</property>
<property name="text">
<string>00000000</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="centerFrequencyUnits">
<property name="text">
<string>kHz</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="sampleRateLabel">
<property name="text">
<string> SR</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="sampleRate">
<property name="minimumSize">
<size>
<width>60</width>
<height>0</height>
</size>
</property>
<property name="toolTip">
<string>Stream nominal sample rate</string>
</property>
<property name="text">
<string>0000000</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="sampleRateUnits">
<property name="text">
<string>S/s</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="monitorLayout">
<item>
<widget class="QLabel" name="nominalNbBlocksText">
<property name="minimumSize">
<size>
<width>50</width>
<height>0</height>
</size>
</property>
<property name="toolTip">
<string>Nb total blocks / Nb FEC blocks</string>
</property>
<property name="text">
<string>000/00</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="allFramesDecoded">
<property name="enabled">
<bool>false</bool>
</property>
<property name="toolTip">
<string>Frames status: green = all original received, none = some recovered by FEC, red = some lost, blue = remote not streaming</string>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="../../../sdrgui/resources/res.qrc">
<normaloff>:/locked.png</normaloff>:/locked.png</iconset>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="streamRateText">
<property name="minimumSize">
<size>
<width>50</width>
<height>0</height>
</size>
</property>
<property name="toolTip">
<string>Stream actual sample rate</string>
</property>
<property name="text">
<string>0000000</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="streamRateUnits">
<property name="minimumSize">
<size>
<width>20</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>S/s</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="eventCountsReset">
<property name="maximumSize">
<size>
<width>22</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>0</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="eventUnrecText">
<property name="minimumSize">
<size>
<width>25</width>
<height>0</height>
</size>
</property>
<property name="toolTip">
<string>Number of unrecoverable errors since event counts reset</string>
</property>
<property name="text">
<string>000</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="eventRecText">
<property name="minimumSize">
<size>
<width>25</width>
<height>0</height>
</size>
</property>
<property name="toolTip">
<string>Number of correctable errors since event counts reset</string>
</property>
<property name="text">
<string>000</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="eventCountsTimeText">
<property name="toolTip">
<string>Time since last event counts reset</string>
</property>
<property name="text">
<string>00:00:00</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="queueLengthLayout">
<item>
<widget class="QLabel" name="queueLengthLabel">
<property name="text">
<string>QL</string>
</property>
</widget>
</item>
<item>
<widget class="QProgressBar" name="queueLengthGauge">
<property name="maximumSize">
<size>
<width>16777215</width>
<height>14</height>
</size>
</property>
<property name="toolTip">
<string>Queue length gauge</string>
</property>
<property name="value">
<number>24</number>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="queueLengthText">
<property name="minimumSize">
<size>
<width>50</width>
<height>0</height>
</size>
</property>
<property name="toolTip">
<string>Queued data blocks / Queue size in data blocks</string>
</property>
<property name="text">
<string>000/000</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
@ -174,6 +446,8 @@
<container>1</container>
</customwidget>
</customwidgets>
<resources/>
<resources>
<include location="../../../sdrgui/resources/res.qrc"/>
</resources>
<connections/>
</ui>

View File

@ -59,6 +59,8 @@ SDRdaemonSinkGui::SDRdaemonSinkGui(DeviceUISet *deviceUISet, QWidget* parent) :
m_lastCountRecovered = 0;
m_lastSampleCount = 0;
m_lastTimestampRateCorrection = 0;
m_nbSamplesSinceRateCorrection = 0;
m_chunkSizeCorrection = 0;
m_resetCounts = true;
m_paletteGreenText.setColor(QPalette::WindowText, Qt::green);
@ -242,6 +244,9 @@ void SDRdaemonSinkGui::displaySettings()
QString s1 = QString::number(m_settings.m_nbFECBlocks, 'f', 0);
ui->nominalNbBlocksText->setText(tr("%1/%2").arg(s0).arg(s1));
ui->serverType->setCurrentIndex((int) m_settings.m_serverType);
ui->deviceIndex->setText(tr("%1").arg(m_settings.m_deviceIndex));
ui->channelIndex->setText(tr("%1").arg(m_settings.m_channelIndex));
ui->apiAddress->setText(m_settings.m_apiAddress);
ui->apiPort->setText(tr("%1").arg(m_settings.m_apiPort));
ui->dataAddress->setText(m_settings.m_dataAddress);
@ -455,6 +460,9 @@ void SDRdaemonSinkGui::on_startStop_toggled(bool checked)
{
if (m_doApplySettings)
{
m_nbSamplesSinceRateCorrection = 0;
m_lastTimestampRateCorrection = 0;
SDRdaemonSinkOutput::MsgStartStop *message = SDRdaemonSinkOutput::MsgStartStop::create(checked);
m_deviceSampleSink->getInputMessageQueue()->push(message);
}
@ -590,15 +598,6 @@ void SDRdaemonSinkGui::analyzeApiReply(const QJsonObject& jsonObject)
int recoverableCount = report["correctableErrorsCount"].toInt();
uint64_t timestampUs = report["tvSec"].toInt()*1000000ULL + report["tvUSec"].toInt();
if (m_lastTimestampRateCorrection == 0) {
m_lastTimestampRateCorrection = timestampUs;
}
if ((timestampUs - m_lastTimestampRateCorrection > 600e6) && ((queueLengthPercent > 60) || (queueLengthPercent < 40)))
{
m_lastTimestampRateCorrection = timestampUs;
}
if (!m_resetCounts)
{
int recoverableCountDelta = recoverableCount - m_lastCountRecovered;
@ -618,16 +617,31 @@ void SDRdaemonSinkGui::analyzeApiReply(const QJsonObject& jsonObject)
sampleCountDelta = sampleCount - m_lastSampleCount;
}
if (sampleCountDelta == 0) {
if (sampleCountDelta == 0)
{
ui->allFramesDecoded->setStyleSheet("QToolButton { background-color : blue; }");
}
else
{
if (m_lastTimestampRateCorrection == 0) {
m_lastTimestampRateCorrection = timestampUs;
}
//if ((timestampUs - m_lastTimestampRateCorrection > 300e6) && ((queueLengthPercent > 60) || (queueLengthPercent < 40)))
if ((m_nbSamplesSinceRateCorrection > 20000000) && ((queueLengthPercent > 60) || (queueLengthPercent < 40)))
{
sampleRateCorrection(queueLength, queueSize, timestampUs - m_lastTimestampRateCorrection);
m_lastTimestampRateCorrection = timestampUs;
m_nbSamplesSinceRateCorrection = 0;
}
m_nbSamplesSinceRateCorrection += sampleCountDelta;
}
double remoteStreamRate = sampleCountDelta*1e6 / (double) (timestampUs - m_lastTimestampUs);
if (remoteStreamRate != 0)
{
m_rateMovingAverage(remoteStreamRate);
ui->remoteStreamRateText->setText(QString("%1").arg(m_rateMovingAverage.instantAverage(), 0, 'f', 0));
if (remoteStreamRate != 0) {
ui->remoteStreamRateText->setText(QString("%1").arg(remoteStreamRate, 0, 'f', 0));
}
m_resetCounts = false;
@ -662,15 +676,16 @@ void SDRdaemonSinkGui::analyzeApiReply(const QJsonObject& jsonObject)
}
}
void SDRdaemonSinkGui::sampleRateCorrection(int queueLength, int queueSize, int64_t timeDelta)
void SDRdaemonSinkGui::sampleRateCorrection(int queueLength, int queueSize, int64_t timeDeltaUs)
{
int nbBlocksDiff = queueLength - (queueSize/2);
int nbSamplesDiff = nbBlocksDiff * 127 * 127;
float sampleCorr = (nbSamplesDiff * 50000.0) / timeDelta;
int chunkCorr = roundf(sampleCorr);
float sampleCorr = (nbSamplesDiff * 50000.0) / timeDeltaUs; // correction for ~50ms chunks (50000 us)
int chunkCorr = -roundf(sampleCorr);
m_chunkSizeCorrection += chunkCorr;
qDebug("SDRdaemonSinkGui::sampleRateCorrection: %d samples", -chunkCorr);
qDebug("SDRdaemonSinkGui::sampleRateCorrection: %d (%d) samples", m_chunkSizeCorrection, chunkCorr);
SDRdaemonSinkOutput::MsgConfigureSDRdaemonSinkChunkCorrection* message = SDRdaemonSinkOutput::MsgConfigureSDRdaemonSinkChunkCorrection::create(-chunkCorr);
SDRdaemonSinkOutput::MsgConfigureSDRdaemonSinkChunkCorrection* message = SDRdaemonSinkOutput::MsgConfigureSDRdaemonSinkChunkCorrection::create(m_chunkSizeCorrection);
m_deviceSampleSink->getInputMessageQueue()->push(message);
}

View File

@ -17,15 +17,16 @@
#ifndef INCLUDE_SDRDAEMONSINKGUI_H
#define INCLUDE_SDRDAEMONSINKGUI_H
#include <plugin/plugininstancegui.h>
#include <stdint.h>
#include <QTimer>
#include <QTime>
#include <QWidget>
#include <QNetworkRequest>
#include "plugin/plugininstancegui.h"
#include "util/messagequeue.h"
#include "util/limitedcounter.h"
#include "util/movingaverage.h"
#include "sdrdaemonsinksettings.h"
#include "sdrdaemonsinkoutput.h"
@ -40,6 +41,33 @@ namespace Ui {
class SDRdaemonSinkGui;
}
class SDRdaemonSinkExpAvg {
public:
SDRdaemonSinkExpAvg(float alpha) :
m_alpha(alpha),
m_start(true),
m_s(0)
{}
int put(int y)
{
if (m_start) {
m_start = false;
m_s = y;
} else {
m_s = m_alpha*y + (1.0-m_alpha)*m_s;
}
return roundf(m_s);
}
void reset() {
m_start = true;
}
private:
float m_alpha;
bool m_start;
float m_s;
};
class SDRdaemonSinkGui : public QWidget, public PluginInstanceGUI {
Q_OBJECT
@ -71,7 +99,6 @@ private:
int m_sampleRate;
quint64 m_deviceCenterFrequency; //!< Center frequency in device
int m_samplesCount;
MovingAverageUtil<double, double, 30> m_rateMovingAverage; // ~30s average
uint32_t m_tickCount;
std::size_t m_nbSinceLastFlowCheck;
int m_lastEngineState;
@ -85,6 +112,8 @@ private:
uint32_t m_lastSampleCount;
uint64_t m_lastTimestampUs;
uint64_t m_lastTimestampRateCorrection;
uint32_t m_nbSamplesSinceRateCorrection;
int m_chunkSizeCorrection;
bool m_resetCounts;
QTime m_time;
@ -108,7 +137,7 @@ private:
void displayEventStatus(int recoverableCount, int unrecoverableCount);
void displayEventTimer();
void analyzeApiReply(const QJsonObject& jsonObject);
void sampleRateCorrection(int queueLength, int queueSize, int64_t timeDelta);
void sampleRateCorrection(int queueLength, int queueSize, int64_t timeDeltaUs);
private slots:
void handleInputMessages();

View File

@ -54,7 +54,7 @@ public:
bool isRunning() const { return m_running; }
std::size_t getSamplesCount() const { return m_samplesCount; }
uint32_t getSamplesCount() const { return m_samplesCount; }
void setSamplesCount(int samplesCount) { m_samplesCount = samplesCount; }
void setChunkCorrection(int chunkCorrection) { m_chunkCorrection = chunkCorrection; }