1
0
mirror of https://github.com/f4exb/sdrangel.git synced 2026-06-29 06:55:56 -04:00

SDRDaemonSink GUI: sample rate active feedback

This commit is contained in:
f4exb
2018-08-31 07:38:30 +02:00
parent 90fb223b01
commit f8383f8cff
11 changed files with 142 additions and 99 deletions
@@ -58,6 +58,7 @@ SDRdaemonSinkGui::SDRdaemonSinkGui(DeviceUISet *deviceUISet, QWidget* parent) :
m_lastCountUnrecoverable = 0;
m_lastCountRecovered = 0;
m_lastSampleCount = 0;
m_lastTimestampRateCorrection = 0;
m_resetCounts = true;
m_paletteGreenText.setColor(QPalette::WindowText, Qt::green);
@@ -176,12 +177,6 @@ bool SDRdaemonSinkGui::handleMessage(const Message& message)
blockApplySettings(false);
return true;
}
else if (SDRdaemonSinkOutput::MsgReportSDRdaemonSinkStreamTiming::match(message))
{
m_samplesCount = ((SDRdaemonSinkOutput::MsgReportSDRdaemonSinkStreamTiming&)message).getSamplesCount();
updateWithStreamTime();
return true;
}
else if (SDRdaemonSinkOutput::MsgStartStop::match(message))
{
SDRdaemonSinkOutput::MsgStartStop& notif = (SDRdaemonSinkOutput::MsgStartStop&) message;
@@ -339,7 +334,7 @@ void SDRdaemonSinkGui::on_apiAddress_returnPressed()
QString infoURL = QString("http://%1:%2/sdrdaemon").arg(m_settings.m_apiAddress).arg(m_settings.m_apiPort);
m_networkRequest.setUrl(QUrl(infoURL));
m_networkManager->get(m_networkRequest);
m_networkManager->get(m_networkRequest);
}
void SDRdaemonSinkGui::on_apiPort_returnPressed()
@@ -360,7 +355,7 @@ void SDRdaemonSinkGui::on_apiPort_returnPressed()
QString infoURL = QString("http://%1:%2/sdrdaemon").arg(m_settings.m_apiAddress).arg(m_settings.m_apiPort);
m_networkRequest.setUrl(QUrl(infoURL));
m_networkManager->get(m_networkRequest);
m_networkManager->get(m_networkRequest);
}
void SDRdaemonSinkGui::on_dataAddress_returnPressed()
@@ -472,35 +467,17 @@ void SDRdaemonSinkGui::displayEventTimer()
ui->eventCountsTimeText->setText(s_time);
}
void SDRdaemonSinkGui::updateWithStreamTime()
{
int t_sec = 0;
int t_msec = 0;
if (m_settings.m_sampleRate > 0){
t_msec = ((m_samplesCount * 1000) / m_settings.m_sampleRate) % 1000;
t_sec = m_samplesCount / m_settings.m_sampleRate;
}
QTime t(0, 0, 0, 0);
t = t.addSecs(t_sec);
t = t.addMSecs(t_msec);
QString s_timems = t.toString("HH:mm:ss.zzz");
//ui->relTimeText->setText(s_timems); TODO with absolute time
}
void SDRdaemonSinkGui::tick()
{
if ((++m_tickCount & 0xf) == 0) // 16*50ms ~800ms
if (++m_tickCount == 20) // once per second
{
QString reportURL = QString("http://%1:%2/sdrdaemon/channel/report").arg(m_settings.m_apiAddress).arg(m_settings.m_apiPort);
m_networkRequest.setUrl(QUrl(reportURL));
m_networkManager->get(m_networkRequest);
// SDRdaemonSinkOutput::MsgConfigureSDRdaemonSinkStreamTiming* message = SDRdaemonSinkOutput::MsgConfigureSDRdaemonSinkStreamTiming::create();
// m_deviceSampleSink->getInputMessageQueue()->push(message);
displayEventTimer();
m_tickCount = 0;
}
}
@@ -556,12 +533,22 @@ void SDRdaemonSinkGui::analyzeApiReply(const QJsonObject& jsonObject)
int queueLength = report["queueLength"].toInt();
QString queueLengthText = QString("%1/%2").arg(queueLength).arg(queueSize);
ui->queueLengthText->setText(queueLengthText);
ui->queueLengthGauge->setValue((queueLength*100)/queueSize);
int queueLengthPercent = (queueLength*100)/queueSize;
ui->queueLengthGauge->setValue(queueLengthPercent);
int unrecoverableCount = report["uncorrectableErrorsCount"].toInt();
int recoverableCount = report["correctableErrorsCount"].toInt();
int sampleCount = report["samplesCount"].toInt();
LimitedCounter<uint32_t, 2000000000> sampleCount(report["samplesCount"].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;
@@ -572,12 +559,19 @@ void SDRdaemonSinkGui::analyzeApiReply(const QJsonObject& jsonObject)
displayEventCounts();
}
if ((sampleCount - m_lastSampleCount) == 0) {
LimitedCounter<uint32_t, 2000000000> sampleCountDelta = sampleCount - m_lastSampleCount;
if (sampleCountDelta.value() == 0) {
ui->allFramesDecoded->setStyleSheet("QToolButton { background-color : blue; }");
}
double remoteStreamRate = (sampleCount - m_lastSampleCount) / (double) (timestampUs - m_lastTimestampUs);
ui->remoteStreamRateText->setText(QString("%1").arg(remoteStreamRate * 1e6, 0, 'f', 0));
double remoteStreamRate = sampleCountDelta.value()*1e6 / (double) (timestampUs - m_lastTimestampUs);
if (remoteStreamRate != 0)
{
m_rateMovingAverage(remoteStreamRate);
ui->remoteStreamRateText->setText(QString("%1").arg(m_rateMovingAverage.instantAverage(), 0, 'f', 0));
}
m_resetCounts = false;
m_lastCountRecovered = recoverableCount;
@@ -610,3 +604,16 @@ void SDRdaemonSinkGui::analyzeApiReply(const QJsonObject& jsonObject)
ui->infoText->setText(infoLine);
}
}
void SDRdaemonSinkGui::sampleRateCorrection(int queueLength, int queueSize, int64_t timeDelta)
{
int nbBlocksDiff = queueLength - (queueSize/2);
int nbSamplesDiff = nbBlocksDiff * 127 * 127;
float sampleCorr = (nbSamplesDiff * 50000.0) / timeDelta;
int chunkCorr = roundf(sampleCorr);
qDebug("SDRdaemonSinkGui::sampleRateCorrection: %d samples", -chunkCorr);
SDRdaemonSinkOutput::MsgConfigureSDRdaemonSinkChunkCorrection* message = SDRdaemonSinkOutput::MsgConfigureSDRdaemonSinkChunkCorrection::create(-chunkCorr);
m_deviceSampleSink->getInputMessageQueue()->push(message);
}
@@ -24,6 +24,8 @@
#include <QNetworkRequest>
#include "util/messagequeue.h"
#include "util/limitedcounter.h"
#include "util/movingaverage.h"
#include "sdrdaemonsinksettings.h"
#include "sdrdaemonsinkoutput.h"
@@ -69,7 +71,8 @@ private:
int m_sampleRate;
quint64 m_deviceCenterFrequency; //!< Center frequency in device
int m_samplesCount;
std::size_t m_tickCount;
MovingAverageUtil<double, double, 120> m_rateMovingAverage; // ~2mn average
uint32_t m_tickCount;
std::size_t m_nbSinceLastFlowCheck;
int m_lastEngineState;
bool m_doApplySettings;
@@ -79,8 +82,9 @@ private:
uint32_t m_countRecovered;
uint32_t m_lastCountUnrecoverable;
uint32_t m_lastCountRecovered;
uint32_t m_lastSampleCount;
uint64_t m_lastTimestampUs;
LimitedCounter<uint32_t, 2000000000> m_lastSampleCount;
uint64_t m_lastTimestampUs;
uint64_t m_lastTimestampRateCorrection;
bool m_resetCounts;
QTime m_time;
@@ -98,13 +102,13 @@ private:
void displayTime();
void sendControl(bool force = false);
void sendSettings();
void updateWithStreamTime();
void updateSampleRateAndFrequency();
void updateTxDelayTooltip();
void displayEventCounts();
void displayEventStatus(int recoverableCount, int unrecoverableCount);
void displayEventTimer();
void analyzeApiReply(const QJsonObject& jsonObject);
void sampleRateCorrection(int queueLength, int queueSize, int64_t timeDelta);
private slots:
void handleInputMessages();
@@ -36,9 +36,7 @@
MESSAGE_CLASS_DEFINITION(SDRdaemonSinkOutput::MsgConfigureSDRdaemonSink, Message)
MESSAGE_CLASS_DEFINITION(SDRdaemonSinkOutput::MsgConfigureSDRdaemonSinkWork, Message)
MESSAGE_CLASS_DEFINITION(SDRdaemonSinkOutput::MsgStartStop, Message)
MESSAGE_CLASS_DEFINITION(SDRdaemonSinkOutput::MsgConfigureSDRdaemonSinkStreamTiming, Message)
MESSAGE_CLASS_DEFINITION(SDRdaemonSinkOutput::MsgConfigureSDRdaemonSinkChunkCorrection, Message)
MESSAGE_CLASS_DEFINITION(SDRdaemonSinkOutput::MsgReportSDRdaemonSinkStreamTiming, Message)
SDRdaemonSinkOutput::SDRdaemonSinkOutput(DeviceSinkAPI *deviceAPI) :
m_deviceAPI(deviceAPI),
@@ -211,18 +209,6 @@ bool SDRdaemonSinkOutput::handleMessage(const Message& message)
return true;
}
else if (MsgConfigureSDRdaemonSinkStreamTiming::match(message))
{
MsgReportSDRdaemonSinkStreamTiming *report;
if (m_sdrDaemonSinkThread != 0 && getMessageQueueToGUI())
{
report = MsgReportSDRdaemonSinkStreamTiming::create(m_sdrDaemonSinkThread->getSamplesCount());
getMessageQueueToGUI()->push(report);
}
return true;
}
else if (MsgConfigureSDRdaemonSinkChunkCorrection::match(message))
{
MsgConfigureSDRdaemonSinkChunkCorrection& conf = (MsgConfigureSDRdaemonSinkChunkCorrection&) message;
@@ -114,43 +114,6 @@ public:
{ }
};
class MsgConfigureSDRdaemonSinkStreamTiming : public Message {
MESSAGE_CLASS_DECLARATION
public:
static MsgConfigureSDRdaemonSinkStreamTiming* create()
{
return new MsgConfigureSDRdaemonSinkStreamTiming();
}
private:
MsgConfigureSDRdaemonSinkStreamTiming() :
Message()
{ }
};
class MsgReportSDRdaemonSinkStreamTiming : public Message {
MESSAGE_CLASS_DECLARATION
public:
std::size_t getSamplesCount() const { return m_samplesCount; }
static MsgReportSDRdaemonSinkStreamTiming* create(std::size_t samplesCount)
{
return new MsgReportSDRdaemonSinkStreamTiming(samplesCount);
}
protected:
std::size_t m_samplesCount;
MsgReportSDRdaemonSinkStreamTiming(std::size_t samplesCount) :
Message(),
m_samplesCount(samplesCount)
{ }
};
SDRdaemonSinkOutput(DeviceSinkAPI *deviceAPI);
virtual ~SDRdaemonSinkOutput();
virtual void destroy();
@@ -67,7 +67,7 @@ private:
int m_samplesChunkSize;
SampleSourceFifo* m_sampleFifo;
std::size_t m_samplesCount;
uint32_t m_samplesCount;
int m_chunkCorrection;
int m_samplerate;