From db67e07ab94d9b1f6e6df96d234ea52c52f26fae Mon Sep 17 00:00:00 2001 From: f4exb Date: Wed, 19 Apr 2017 18:41:55 +0200 Subject: [PATCH] LimeSDR input: implemented basic stream reporting --- .../limesdrinput/limesdrinput.cpp | 49 +++ .../samplesource/limesdrinput/limesdrinput.h | 364 +++++++++++------- .../limesdrinput/limesdrinputgui.cpp | 37 +- .../limesdrinput/limesdrinputgui.h | 1 + .../limesdrinput/limesdrinputgui.ui | 83 ++++ sdrbase/resources/res.qrc | 1 + sdrbase/resources/stream.png | Bin 0 -> 487 bytes 7 files changed, 399 insertions(+), 136 deletions(-) create mode 100644 sdrbase/resources/stream.png diff --git a/plugins/samplesource/limesdrinput/limesdrinput.cpp b/plugins/samplesource/limesdrinput/limesdrinput.cpp index 93e303307..4c121104f 100644 --- a/plugins/samplesource/limesdrinput/limesdrinput.cpp +++ b/plugins/samplesource/limesdrinput/limesdrinput.cpp @@ -28,8 +28,10 @@ #include "limesdr/devicelimesdrparam.h" MESSAGE_CLASS_DEFINITION(LimeSDRInput::MsgConfigureLimeSDR, Message) +MESSAGE_CLASS_DEFINITION(LimeSDRInput::MsgGetStreamInfo, Message) MESSAGE_CLASS_DEFINITION(LimeSDRInput::MsgSetReferenceConfig, Message) MESSAGE_CLASS_DEFINITION(LimeSDRInput::MsgReportLimeSDRToGUI, Message) +MESSAGE_CLASS_DEFINITION(LimeSDRInput::MsgReportStreamInfo, Message) LimeSDRInput::LimeSDRInput(DeviceSourceAPI *deviceAPI) : @@ -333,6 +335,53 @@ bool LimeSDRInput::handleMessage(const Message& message) m_settings = conf.getSettings(); return true; } + else if (MsgGetStreamInfo::match(message)) + { + qDebug() << "LimeSDRInput::handleMessage: MsgGetStreamInfo"; + lms_stream_status_t status; + + if (LMS_GetStreamStatus(&m_streamId, &status) < 0) + { + qDebug("LimeSDRInput::handleMessage: canot get stream status"); + MsgReportStreamInfo *report = MsgReportStreamInfo::create( + false, // Success + status.active, + status.fifoFilledCount, + status.fifoSize, + status.underrun, + status.overrun, + status.droppedPackets, + status.sampleRate, + status.linkRate, + status.timestamp); + m_deviceAPI->getDeviceOutputMessageQueue()->push(report); + } + else + { + qDebug() << "LimeSDRInput::handleMessage: got stream status at %llu" << status.timestamp + << " fifoFilledCount: " << status.fifoFilledCount + << " fifoSize: " << status.fifoSize + << " underrun: " << status.underrun + << " overrun: " << status.overrun + << " droppedPackets: " << status.droppedPackets + << " sampleRate: " << status.sampleRate + << " linkRate: " << status.linkRate; + MsgReportStreamInfo *report = MsgReportStreamInfo::create( + true, // Success + status.active, + status.fifoFilledCount, + status.fifoSize, + status.underrun, + status.overrun, + status.droppedPackets, + status.sampleRate, + status.linkRate, + status.timestamp); + m_deviceAPI->getDeviceOutputMessageQueue()->push(report); + } + + return true; + } else { return false; diff --git a/plugins/samplesource/limesdrinput/limesdrinput.h b/plugins/samplesource/limesdrinput/limesdrinput.h index a49d1dc62..9256d4256 100644 --- a/plugins/samplesource/limesdrinput/limesdrinput.h +++ b/plugins/samplesource/limesdrinput/limesdrinput.h @@ -1,135 +1,229 @@ -/////////////////////////////////////////////////////////////////////////////////// -// Copyright (C) 2017 Edouard Griffiths, F4EXB // -// // -// This program is free software; you can redistribute it and/or modify // -// it under the terms of the GNU General Public License as published by // -// the Free Software Foundation as version 3 of the License, or // -// // -// This program is distributed in the hope that it will be useful, // -// but WITHOUT ANY WARRANTY; without even the implied warranty of // -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // -// GNU General Public License V3 for more details. // -// // -// You should have received a copy of the GNU General Public License // -// along with this program. If not, see . // -/////////////////////////////////////////////////////////////////////////////////// - -#ifndef PLUGINS_SAMPLESOURCE_LIMESDRINPUT_LIMESDRINPUT_H_ -#define PLUGINS_SAMPLESOURCE_LIMESDRINPUT_LIMESDRINPUT_H_ - -#include -#include - -#include "dsp/devicesamplesource.h" -#include "limesdr/devicelimesdrshared.h" -#include "limesdrinputsettings.h" - -class DeviceSourceAPI; -class LimeSDRInputThread; -struct DeviceLimeSDRParams; - -class LimeSDRInput : public DeviceSampleSource -{ -public: - class MsgConfigureLimeSDR : public Message { - MESSAGE_CLASS_DECLARATION - - public: - const LimeSDRInputSettings& getSettings() const { return m_settings; } - - static MsgConfigureLimeSDR* create(const LimeSDRInputSettings& settings) - { - return new MsgConfigureLimeSDR(settings); - } - - private: - LimeSDRInputSettings m_settings; - - MsgConfigureLimeSDR(const LimeSDRInputSettings& settings) : - Message(), - m_settings(settings) - { } - }; - - class MsgSetReferenceConfig : public Message { - MESSAGE_CLASS_DECLARATION - - public: - const LimeSDRInputSettings& getSettings() const { return m_settings; } - - static MsgSetReferenceConfig* create(const LimeSDRInputSettings& settings) - { - return new MsgSetReferenceConfig(settings); - } - - private: - LimeSDRInputSettings m_settings; - - MsgSetReferenceConfig(const LimeSDRInputSettings& settings) : - Message(), - m_settings(settings) - { } - }; - - class MsgReportLimeSDRToGUI : public Message { - MESSAGE_CLASS_DECLARATION - - public: - float getCenterFrequency() const { return m_centerFrequency; } - int getSampleRate() const { return m_sampleRate; } - uint32_t getLog2HardDecim() const { return m_log2HardDecim; } - - static MsgReportLimeSDRToGUI* create(float centerFrequency, int sampleRate, uint32_t log2HardDecim) - { - return new MsgReportLimeSDRToGUI(centerFrequency, sampleRate, log2HardDecim); - } - - private: - float m_centerFrequency; - int m_sampleRate; - uint32_t m_log2HardDecim; - - MsgReportLimeSDRToGUI(float centerFrequency, int sampleRate, uint32_t log2HardDecim) : - Message(), - m_centerFrequency(centerFrequency), - m_sampleRate(sampleRate), - m_log2HardDecim(log2HardDecim) - { } - }; - - LimeSDRInput(DeviceSourceAPI *deviceAPI); - virtual ~LimeSDRInput(); - - virtual bool start(); - virtual void stop(); - - virtual const QString& getDeviceDescription() const; - virtual int getSampleRate() const; - virtual quint64 getCenterFrequency() const; - - virtual bool handleMessage(const Message& message); - - std::size_t getChannelIndex(); - void getLORange(float& minF, float& maxF, float& stepF) const; - void getSRRange(float& minF, float& maxF, float& stepF) const; - void getLPRange(float& minF, float& maxF, float& stepF) const; - uint32_t getHWLog2Decim() const; - -private: - DeviceSourceAPI *m_deviceAPI; - QMutex m_mutex; - LimeSDRInputSettings m_settings; - LimeSDRInputThread* m_limeSDRInputThread; - QString m_deviceDescription; - bool m_running; - DeviceLimeSDRShared m_deviceShared; - bool m_firstConfig; - - lms_stream_t m_streamId; - - bool openDevice(); - void closeDevice(); - bool applySettings(const LimeSDRInputSettings& settings, bool force); -}; - -#endif /* PLUGINS_SAMPLESOURCE_LIMESDRINPUT_LIMESDRINPUT_H_ */ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2017 Edouard Griffiths, F4EXB // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////// + +#ifndef PLUGINS_SAMPLESOURCE_LIMESDRINPUT_LIMESDRINPUT_H_ +#define PLUGINS_SAMPLESOURCE_LIMESDRINPUT_LIMESDRINPUT_H_ + +#include +#include + +#include "dsp/devicesamplesource.h" +#include "limesdr/devicelimesdrshared.h" +#include "limesdrinputsettings.h" + +class DeviceSourceAPI; +class LimeSDRInputThread; +struct DeviceLimeSDRParams; + +class LimeSDRInput : public DeviceSampleSource +{ +public: + class MsgConfigureLimeSDR : public Message { + MESSAGE_CLASS_DECLARATION + + public: + const LimeSDRInputSettings& getSettings() const { return m_settings; } + + static MsgConfigureLimeSDR* create(const LimeSDRInputSettings& settings) + { + return new MsgConfigureLimeSDR(settings); + } + + private: + LimeSDRInputSettings m_settings; + + MsgConfigureLimeSDR(const LimeSDRInputSettings& settings) : + Message(), + m_settings(settings) + { } + }; + + class MsgSetReferenceConfig : public Message { + MESSAGE_CLASS_DECLARATION + + public: + const LimeSDRInputSettings& getSettings() const { return m_settings; } + + static MsgSetReferenceConfig* create(const LimeSDRInputSettings& settings) + { + return new MsgSetReferenceConfig(settings); + } + + private: + LimeSDRInputSettings m_settings; + + MsgSetReferenceConfig(const LimeSDRInputSettings& settings) : + Message(), + m_settings(settings) + { } + }; + + class MsgGetStreamInfo : public Message { + MESSAGE_CLASS_DECLARATION + + public: + static MsgGetStreamInfo* create() + { + return new MsgGetStreamInfo(); + } + + private: + MsgGetStreamInfo() : + Message() + { } + }; + + class MsgReportLimeSDRToGUI : public Message { + MESSAGE_CLASS_DECLARATION + + public: + float getCenterFrequency() const { return m_centerFrequency; } + int getSampleRate() const { return m_sampleRate; } + uint32_t getLog2HardDecim() const { return m_log2HardDecim; } + + static MsgReportLimeSDRToGUI* create(float centerFrequency, int sampleRate, uint32_t log2HardDecim) + { + return new MsgReportLimeSDRToGUI(centerFrequency, sampleRate, log2HardDecim); + } + + private: + float m_centerFrequency; + int m_sampleRate; + uint32_t m_log2HardDecim; + + MsgReportLimeSDRToGUI(float centerFrequency, int sampleRate, uint32_t log2HardDecim) : + Message(), + m_centerFrequency(centerFrequency), + m_sampleRate(sampleRate), + m_log2HardDecim(log2HardDecim) + { } + }; + + class MsgReportStreamInfo : public Message { + MESSAGE_CLASS_DECLARATION + + public: + bool getSuccess() const { return m_success; } + bool getActive() const { return m_active; } + uint32_t getFifoFilledCount() const { return m_fifoFilledCount; } + uint32_t getFifoSize() const { return m_fifoSize; } + uint32_t getUnderrun() const { return m_underrun; } + uint32_t getOverrun() const { return m_overrun; } + uint32_t getDroppedPackets() const { return m_droppedPackets; } + float getSampleRate() const { return m_sampleRate; } + float getLinkRate() const { return m_linkRate; } + uint64_t getTimestamp() const { return m_timestamp; } + + static MsgReportStreamInfo* create( + bool active, + uint32_t fifoFilledCount, + uint32_t fifoSize, + uint32_t underrun, + uint32_t overrun, + uint32_t droppedPackets, + float sampleRate, + float linkRate, + uint64_t timestamp + ) + { + return new MsgReportStreamInfo( + active, + fifoFilledCount, + fifoSize, + underrun, + overrun, + droppedPackets, + sampleRate, + linkRate, + timestamp + ); + } + + private: + bool m_success; + // everything from lms_stream_status_t + bool m_active; //!< Indicates whether the stream is currently active + uint32_t m_fifoFilledCount; //!< Number of samples in FIFO buffer + uint32_t m_fifoSize; //!< Size of FIFO buffer + uint32_t m_underrun; //!< FIFO underrun count + uint32_t m_overrun; //!< FIFO overrun count + uint32_t m_droppedPackets; //!< Number of dropped packets by HW + float m_sampleRate; //!< Sampling rate of the stream + float m_linkRate; //!< Combined data rate of all stream of the same direction (TX or RX) + uint64_t m_timestamp; //!< Current HW timestamp + + MsgReportStreamInfo( + bool success, + bool active, + uint32_t fifoFilledCount, + uint32_t fifoSize, + uint32_t underrun, + uint32_t overrun, + uint32_t droppedPackets, + float sampleRate, + float linkRate, + uint64_t timestamp + ) : + Message(), + m_success(success), + m_active(active), + m_fifoFilledCount(fifoFilledCount), + m_fifoSize(fifoSize), + m_underrun(underrun), + m_overrun(overrun), + m_droppedPackets(droppedPackets), + m_sampleRate(sampleRate), + m_linkRate(linkRate), + m_timestamp(timestamp) + { } + }; + + LimeSDRInput(DeviceSourceAPI *deviceAPI); + virtual ~LimeSDRInput(); + + virtual bool start(); + virtual void stop(); + + virtual const QString& getDeviceDescription() const; + virtual int getSampleRate() const; + virtual quint64 getCenterFrequency() const; + + virtual bool handleMessage(const Message& message); + + std::size_t getChannelIndex(); + void getLORange(float& minF, float& maxF, float& stepF) const; + void getSRRange(float& minF, float& maxF, float& stepF) const; + void getLPRange(float& minF, float& maxF, float& stepF) const; + uint32_t getHWLog2Decim() const; + +private: + DeviceSourceAPI *m_deviceAPI; + QMutex m_mutex; + LimeSDRInputSettings m_settings; + LimeSDRInputThread* m_limeSDRInputThread; + QString m_deviceDescription; + bool m_running; + DeviceLimeSDRShared m_deviceShared; + bool m_firstConfig; + + lms_stream_t m_streamId; + + bool openDevice(); + void closeDevice(); + bool applySettings(const LimeSDRInputSettings& settings, bool force); +}; + +#endif /* PLUGINS_SAMPLESOURCE_LIMESDRINPUT_LIMESDRINPUT_H_ */ diff --git a/plugins/samplesource/limesdrinput/limesdrinputgui.cpp b/plugins/samplesource/limesdrinput/limesdrinputgui.cpp index c794c0d04..6e38962a9 100644 --- a/plugins/samplesource/limesdrinput/limesdrinputgui.cpp +++ b/plugins/samplesource/limesdrinput/limesdrinputgui.cpp @@ -35,7 +35,8 @@ LimeSDRInputGUI::LimeSDRInputGUI(DeviceSourceAPI *deviceAPI, QWidget* parent) : m_sampleSource(0), m_sampleRate(0), m_lastEngineState((DSPDeviceSourceEngine::State)-1), - m_doApplySettings(true) + m_doApplySettings(true), + m_statusCounter(0) { m_limeSDRInput = new LimeSDRInput(m_deviceAPI); m_sampleSource = (DeviceSampleSource *) m_limeSDRInput; @@ -179,6 +180,29 @@ void LimeSDRInputGUI::handleMessagesToGUI() delete message; } + else if (LimeSDRInput::MsgReportStreamInfo::match(*message)) + { + LimeSDRInput::MsgReportStreamInfo *report = (LimeSDRInput::MsgReportStreamInfo *) message; + + if (report->getSuccess()) + { + if (report->getActive()) + { + ui->streamStatusLabel->setStyleSheet("QLabel { background-color : green; }"); + } + else + { + ui->streamStatusLabel->setStyleSheet("QLabel { background:rgb(79,79,79); }"); + } + + ui->streamSampleRateText->setText(tr("%1kS").arg(QString::number(report->getSampleRate() / 1000.0f, 'f', 0))); + ui->streamLinkRateText->setText(tr("%1kB").arg(QString::number(report->getLinkRate() / 1000.0f, 'f', 0))); + } + else + { + ui->streamStatusLabel->setStyleSheet("QLabel { background-color : red; }"); + } + } } } @@ -253,6 +277,17 @@ void LimeSDRInputGUI::updateStatus() m_lastEngineState = state; } + + if (m_statusCounter < 1) + { + m_statusCounter++; + } + else + { + LimeSDRInput::MsgGetStreamInfo* message = LimeSDRInput::MsgGetStreamInfo::create(); + m_sampleSource->getInputMessageQueue()->push(message); + m_statusCounter = 0; + } } void LimeSDRInputGUI::blockApplySettings(bool block) diff --git a/plugins/samplesource/limesdrinput/limesdrinputgui.h b/plugins/samplesource/limesdrinput/limesdrinputgui.h index d8848bc88..28fa87a6c 100644 --- a/plugins/samplesource/limesdrinput/limesdrinputgui.h +++ b/plugins/samplesource/limesdrinput/limesdrinputgui.h @@ -61,6 +61,7 @@ private: quint64 m_deviceCenterFrequency; //!< Center frequency in device int m_lastEngineState; bool m_doApplySettings; + int m_statusCounter; void displaySettings(); void sendSettings(); diff --git a/plugins/samplesource/limesdrinput/limesdrinputgui.ui b/plugins/samplesource/limesdrinput/limesdrinputgui.ui index 9655e14d4..eb4740af8 100644 --- a/plugins/samplesource/limesdrinput/limesdrinputgui.ui +++ b/plugins/samplesource/limesdrinput/limesdrinputgui.ui @@ -591,6 +591,89 @@ + + + + 6 + + + 6 + + + 6 + + + 6 + + + + + + 24 + 24 + + + + + 24 + 24 + + + + + + + :/stream.png + + + + + + + + 50 + 0 + + + + 00000kS + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 50 + 0 + + + + 00000kB + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + diff --git a/sdrbase/resources/res.qrc b/sdrbase/resources/res.qrc index af6b107e1..0385793de 100644 --- a/sdrbase/resources/res.qrc +++ b/sdrbase/resources/res.qrc @@ -76,5 +76,6 @@ picture.png camera.png filter_bandpass.png + stream.png diff --git a/sdrbase/resources/stream.png b/sdrbase/resources/stream.png new file mode 100644 index 0000000000000000000000000000000000000000..5832a47063a5686b45bb70e4196aaa937c566c59 GIT binary patch literal 487 zcmVM+^Oav=?K@c%EA#ahwK6!vxYiDm`8bKU< zfB_2|6Hq=2*T~If{E5zVZa8etI&1B{&$;L93-9()Q~&WpjZs^eRkzjZe-f!gv#riP zTBv&Ay=}ar`i*EW9wY39&{d~`l@|mq@l(;N?lnpC>XrIeT?@9TepAb!?dDiYIE%s7 z65~ppuakF^`K*TZf~`JL{pWCcHS8?dEFWJy$;fGr%=)8hmTO3H7nl zaA%@D4?YQul~F(70^9(Xna@>Kbqn->31A`k_W{~Iwh(SF+PUDDz)b=E0NsEq@jv6& z)sMgtung>HECWYbTW@IkF}jKUrfd4?xobL%hxYZ^hc@z7F`(IP4z<}e+V##z+Vx0( dIPdn9-2vSNBMef`*RB8n002ovPDHLkV1lla*oOcB literal 0 HcmV?d00001