From e4f97e1a1b9b45c82976a74f34c26b35e63acd8d Mon Sep 17 00:00:00 2001 From: f4exb Date: Sun, 24 Jan 2016 19:21:21 +0100 Subject: [PATCH 01/51] Copied filesource plugin folder to new sdrdaemon --- plugins/samplesource/CMakeLists.txt | 1 + plugins/samplesource/sdrdaemon/CMakeLists.txt | 49 +++ .../samplesource/sdrdaemon/sdrdaemongui.cpp | 241 ++++++++++++ plugins/samplesource/sdrdaemon/sdrdaemongui.h | 82 +++++ .../samplesource/sdrdaemon/sdrdaemongui.ui | 346 ++++++++++++++++++ .../samplesource/sdrdaemon/sdrdaemoninput.cpp | 290 +++++++++++++++ .../samplesource/sdrdaemon/sdrdaemoninput.h | 213 +++++++++++ .../sdrdaemon/sdrdaemonplugin.cpp | 82 +++++ .../samplesource/sdrdaemon/sdrdaemonplugin.h | 47 +++ .../sdrdaemon/sdrdaemonthread.cpp | 153 ++++++++ .../samplesource/sdrdaemon/sdrdaemonthread.h | 67 ++++ 11 files changed, 1571 insertions(+) create mode 100644 plugins/samplesource/sdrdaemon/CMakeLists.txt create mode 100644 plugins/samplesource/sdrdaemon/sdrdaemongui.cpp create mode 100644 plugins/samplesource/sdrdaemon/sdrdaemongui.h create mode 100644 plugins/samplesource/sdrdaemon/sdrdaemongui.ui create mode 100644 plugins/samplesource/sdrdaemon/sdrdaemoninput.cpp create mode 100644 plugins/samplesource/sdrdaemon/sdrdaemoninput.h create mode 100644 plugins/samplesource/sdrdaemon/sdrdaemonplugin.cpp create mode 100644 plugins/samplesource/sdrdaemon/sdrdaemonplugin.h create mode 100644 plugins/samplesource/sdrdaemon/sdrdaemonthread.cpp create mode 100644 plugins/samplesource/sdrdaemon/sdrdaemonthread.h diff --git a/plugins/samplesource/CMakeLists.txt b/plugins/samplesource/CMakeLists.txt index 032b0b2eb..5e1ec48eb 100644 --- a/plugins/samplesource/CMakeLists.txt +++ b/plugins/samplesource/CMakeLists.txt @@ -43,3 +43,4 @@ if(LIBUSB_FOUND AND LIBHACKRF_FOUND) endif(LIBUSB_FOUND AND LIBHACKRF_FOUND) add_subdirectory(filesource) +add_subdirectory(sdrdaemon) diff --git a/plugins/samplesource/sdrdaemon/CMakeLists.txt b/plugins/samplesource/sdrdaemon/CMakeLists.txt new file mode 100644 index 000000000..f693b6adb --- /dev/null +++ b/plugins/samplesource/sdrdaemon/CMakeLists.txt @@ -0,0 +1,49 @@ +project(sdrdaemon) + +set(sdrdaemon_SOURCES + sdrdaemongui.cpp + sdrdaemoninput.cpp + sdrdaemonplugin.cpp + sdrdaemonthread.cpp +) + +set(sdrdaemon_HEADERS + sdrdaemongui.h + sdrdaemoninput.h + sdrdaemonplugin.h + sdrdaemonthread.h +) + +set(sdrdaemon_FORMS + sdrdaemongui.ui +) + +include_directories( + . + ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_SOURCE_DIR}/include + ${CMAKE_SOURCE_DIR}/include-gpl + ${LIBRTLSDR_INCLUDE_DIR} +) + +#include(${QT_USE_FILE}) +add_definitions(${QT_DEFINITIONS}) +add_definitions(-DQT_PLUGIN) +add_definitions(-DQT_SHARED) + +#qt4_wrap_cpp(sdrdaemon_HEADERS_MOC ${sdrdaemon_HEADERS}) +qt5_wrap_ui(sdrdaemon_FORMS_HEADERS ${sdrdaemon_FORMS}) + +add_library(inputsdrdaemon SHARED + ${sdrdaemon_SOURCES} + ${sdrdaemon_HEADERS_MOC} + ${sdrdaemon_FORMS_HEADERS} +) + +target_link_libraries(inputsdrdaemon + ${QT_LIBRARIES} + ${LIBUSB_LIBRARIES} + sdrbase +) + +qt5_use_modules(inputsdrdaemon Core Widgets OpenGL Multimedia) diff --git a/plugins/samplesource/sdrdaemon/sdrdaemongui.cpp b/plugins/samplesource/sdrdaemon/sdrdaemongui.cpp new file mode 100644 index 000000000..b8dd917e3 --- /dev/null +++ b/plugins/samplesource/sdrdaemon/sdrdaemongui.cpp @@ -0,0 +1,241 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2015 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 . // +/////////////////////////////////////////////////////////////////////////////////// + +#include + +#include +#include +#include +#include +#include "ui_sdrdaemongui.h" +#include "plugin/pluginapi.h" +#include "gui/colormapper.h" +#include "dsp/dspengine.h" +#include "mainwindow.h" + +#include "sdrdaemongui.h" + +SDRdaemonGui::SDRdaemonGui(PluginAPI* pluginAPI, QWidget* parent) : + QWidget(parent), + ui(new Ui::SDRdaemonGui), + m_pluginAPI(pluginAPI), + m_settings(), + m_sampleSource(NULL), + m_acquisition(false), + m_fileName("..."), + m_sampleRate(0), + m_centerFrequency(0), + m_startingTimeStamp(0), + m_samplesCount(0), + m_tickCount(0) +{ + ui->setupUi(this); + ui->centerFrequency->setColorMapper(ColorMapper(ColorMapper::ReverseGold)); + ui->centerFrequency->setValueRange(7, 0, pow(10,7)); + ui->fileNameText->setText(m_fileName); + connect(&m_updateTimer, SIGNAL(timeout()), this, SLOT(updateHardware())); + connect(&(m_pluginAPI->getMainWindow()->getMasterTimer()), SIGNAL(timeout()), this, SLOT(tick())); + displaySettings(); + + m_sampleSource = new SDRdaemonInput(m_pluginAPI->getMainWindow()->getMasterTimer()); + connect(m_sampleSource->getOutputMessageQueueToGUI(), SIGNAL(messageEnqueued()), this, SLOT(handleSourceMessages())); + DSPEngine::instance()->setSource(m_sampleSource); +} + +SDRdaemonGui::~SDRdaemonGui() +{ + delete ui; +} + +void SDRdaemonGui::destroy() +{ + delete this; +} + +void SDRdaemonGui::setName(const QString& name) +{ + setObjectName(name); +} + +QString SDRdaemonGui::getName() const +{ + return objectName(); +} + +void SDRdaemonGui::resetToDefaults() +{ + m_settings.resetToDefaults(); + displaySettings(); + sendSettings(); +} + +qint64 SDRdaemonGui::getCenterFrequency() const +{ + return m_centerFrequency; +} + +void SDRdaemonGui::setCenterFrequency(qint64 centerFrequency) +{ + m_centerFrequency = centerFrequency; + displaySettings(); + sendSettings(); +} + +QByteArray SDRdaemonGui::serialize() const +{ + return m_settings.serialize(); +} + +bool SDRdaemonGui::deserialize(const QByteArray& data) +{ + if(m_settings.deserialize(data)) { + displaySettings(); + sendSettings(); + return true; + } else { + resetToDefaults(); + return false; + } +} + +bool SDRdaemonGui::handleMessage(const Message& message) +{ + if (SDRdaemonInput::MsgReportSDRdaemonAcquisition::match(message)) + { + m_acquisition = ((SDRdaemonInput::MsgReportSDRdaemonAcquisition&)message).getAcquisition(); + updateWithAcquisition(); + return true; + } + else if (SDRdaemonInput::MsgReportSDRdaemonStreamData::match(message)) + { + m_sampleRate = ((SDRdaemonInput::MsgReportSDRdaemonStreamData&)message).getSampleRate(); + m_centerFrequency = ((SDRdaemonInput::MsgReportSDRdaemonStreamData&)message).getCenterFrequency(); + m_startingTimeStamp = ((SDRdaemonInput::MsgReportSDRdaemonStreamData&)message).getStartingTimeStamp(); + updateWithStreamData(); + return true; + } + else if (SDRdaemonInput::MsgReportSDRdaemonStreamTiming::match(message)) + { + m_samplesCount = ((SDRdaemonInput::MsgReportSDRdaemonStreamTiming&)message).getSamplesCount(); + updateWithStreamTime(); + return true; + } + else + { + return false; + } +} + +void SDRdaemonGui::handleSourceMessages() +{ + Message* message; + + while ((message = m_sampleSource->getOutputMessageQueueToGUI()->pop()) != 0) + { + qDebug("SDRdaemonGui::handleSourceMessages: message: %s", message->getIdentifier()); + + if (handleMessage(*message)) + { + delete message; + } + } +} + +void SDRdaemonGui::displaySettings() +{ +} + +void SDRdaemonGui::sendSettings() +{ +} + +void SDRdaemonGui::updateHardware() +{ +} + +void SDRdaemonGui::on_play_toggled(bool checked) +{ + SDRdaemonInput::MsgConfigureSDRdaemonWork* message = SDRdaemonInput::MsgConfigureSDRdaemonWork::create(checked); + m_sampleSource->getInputMessageQueue()->push(message); +} + +void SDRdaemonGui::on_showFileDialog_clicked(bool checked) +{ + QString fileName = QFileDialog::getOpenFileName(this, + tr("Open I/Q record file"), ".", tr("SDR I/Q Files (*.sdriq)")); + + if (fileName != "") + { + m_fileName = fileName; + ui->fileNameText->setText(m_fileName); + configureFileName(); + } +} + +void SDRdaemonGui::configureFileName() +{ + qDebug() << "SDRdaemonGui::configureFileName: " << m_fileName.toStdString().c_str(); + SDRdaemonInput::MsgConfigureSDRdaemonName* message = SDRdaemonInput::MsgConfigureSDRdaemonName::create(m_fileName); + m_sampleSource->getInputMessageQueue()->push(message); +} + +void SDRdaemonGui::updateWithAcquisition() +{ + ui->play->setEnabled(m_acquisition); + ui->play->setChecked(m_acquisition); + ui->showFileDialog->setEnabled(!m_acquisition); +} + +void SDRdaemonGui::updateWithStreamData() +{ + ui->centerFrequency->setValue(m_centerFrequency/1000); + QString s = QString::number(m_sampleRate/1000.0, 'f', 0); + ui->sampleRateText->setText(tr("%1k").arg(s)); + ui->play->setEnabled(m_acquisition); + updateWithStreamTime(); // TODO: remove when time data is implemented +} + +void SDRdaemonGui::updateWithStreamTime() +{ + int t_sec = 0; + int t_msec = 0; + + if (m_sampleRate > 0){ + t_msec = ((m_samplesCount * 1000) / m_sampleRate) % 1000; + t_sec = m_samplesCount / m_sampleRate; + } + + QTime t(0, 0, 0, 0); + t = t.addSecs(t_sec); + t = t.addMSecs(t_msec); + QString s_time = t.toString("hh:mm:ss.zzz"); + ui->relTimeText->setText(s_time); + + quint64 startingTimeStampMsec = m_startingTimeStamp * 1000; + QDateTime dt = QDateTime::fromMSecsSinceEpoch(startingTimeStampMsec); + dt = dt.addSecs(t_sec); + dt = dt.addMSecs(t_msec); + QString s_date = dt.toString("yyyyMMdd hh.mm.ss.zzz"); + ui->absTimeText->setText(s_date); +} + +void SDRdaemonGui::tick() +{ + if ((++m_tickCount & 0xf) == 0) { + SDRdaemonInput::MsgConfigureSDRdaemonStreamTiming* message = SDRdaemonInput::MsgConfigureSDRdaemonStreamTiming::create(); + m_sampleSource->getInputMessageQueue()->push(message); + } +} diff --git a/plugins/samplesource/sdrdaemon/sdrdaemongui.h b/plugins/samplesource/sdrdaemon/sdrdaemongui.h new file mode 100644 index 000000000..b9216f9b0 --- /dev/null +++ b/plugins/samplesource/sdrdaemon/sdrdaemongui.h @@ -0,0 +1,82 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2016 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 INCLUDE_SDRDAEMONGUI_H +#define INCLUDE_SDRDAEMONGUI_H + +#include +#include "plugin/plugingui.h" + +#include "sdrdaemoninput.h" + +class PluginAPI; + +namespace Ui { + class SDRdaemonGui; +} + +class SDRdaemonGui : public QWidget, public PluginGUI { + Q_OBJECT + +public: + explicit SDRdaemonGui(PluginAPI* pluginAPI, QWidget* parent = NULL); + virtual ~SDRdaemonGui(); + void destroy(); + + void setName(const QString& name); + QString getName() const; + + void resetToDefaults(); + virtual qint64 getCenterFrequency() const; + virtual void setCenterFrequency(qint64 centerFrequency); + QByteArray serialize() const; + bool deserialize(const QByteArray& data); + virtual bool handleMessage(const Message& message); + +private: + Ui::SDRdaemonGui* ui; + + PluginAPI* m_pluginAPI; + SDRdaemonInput::Settings m_settings; + QTimer m_updateTimer; + std::vector m_gains; + SampleSource* m_sampleSource; + bool m_acquisition; + QString m_fileName; + int m_sampleRate; + quint64 m_centerFrequency; + std::time_t m_startingTimeStamp; + int m_samplesCount; + std::size_t m_tickCount; + + void displaySettings(); + void displayTime(); + void sendSettings(); + void updateHardware(); + void configureFileName(); + void updateWithAcquisition(); + void updateWithStreamData(); + void updateWithStreamTime(); + +private slots: + void handleSourceMessages(); + void on_playLoop_toggled(bool checked); + void on_play_toggled(bool checked); + void on_showFileDialog_clicked(bool checked); + void tick(); +}; + +#endif // INCLUDE_SDRDAEMONGUI_H diff --git a/plugins/samplesource/sdrdaemon/sdrdaemongui.ui b/plugins/samplesource/sdrdaemon/sdrdaemongui.ui new file mode 100644 index 000000000..9dcf1e942 --- /dev/null +++ b/plugins/samplesource/sdrdaemon/sdrdaemongui.ui @@ -0,0 +1,346 @@ + + + SDRdaemonGui + + + + 0 + 0 + 198 + 133 + + + + + 0 + 0 + + + + + Sans Serif + 9 + + + + BladeRF + + + + 3 + + + 2 + + + 2 + + + 2 + + + 2 + + + + + + + Qt::Horizontal + + + + 0 + 0 + + + + + + + + false + + + + 0 + 0 + + + + + 32 + 16 + + + + + Monospace + 20 + + + + SizeVerCursor + + + Qt::StrongFocus + + + Record center frequency in kHz + + + + + + + kHz + + + + + + + Qt::Horizontal + + + + 0 + 0 + + + + + + + + + + Qt::Horizontal + + + + + + + + + + 24 + 24 + + + + + 24 + 24 + + + + Open file + + + + + + + :/preset-load.png:/preset-load.png + + + + + + + false + + + File currently opened + + + ... + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + + Qt::Horizontal + + + + + + + + + + 8 + + + + Record sample rate + + + 0k + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Qt::Vertical + + + + + + + false + + + Record absolute time + + + 20150101 00:00:00.000 + + + + + + + + + Qt::Horizontal + + + + + + + + + Play in a loop + + + + + + + :/playloop.png:/playloop.png + + + + 16 + 16 + + + + true + + + + + + + Stopped / Play / Pause + + + + + + + :/play.png + :/pause.png + :/stop.png + :/stop.png + :/play.png + :/pause.png + :/play.png + :/pause.png:/play.png + + + + 16 + 16 + + + + true + + + false + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Qt::Vertical + + + + + + + false + + + Record time from start + + + 00:00:00.000 + + + + + + + + + + ValueDial + QWidget +
gui/valuedial.h
+ 1 +
+ + ButtonSwitch + QToolButton +
gui/buttonswitch.h
+
+
+ + + + +
diff --git a/plugins/samplesource/sdrdaemon/sdrdaemoninput.cpp b/plugins/samplesource/sdrdaemon/sdrdaemoninput.cpp new file mode 100644 index 000000000..896972e64 --- /dev/null +++ b/plugins/samplesource/sdrdaemon/sdrdaemoninput.cpp @@ -0,0 +1,290 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2015 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 . // +/////////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include + +#include "util/simpleserializer.h" +#include "dsp/dspcommands.h" +#include "dsp/dspengine.h" +#include "dsp/filesink.h" + +#include "sdrdaemongui.h" +#include "sdrdaemoninput.h" +#include "sdrdaemonthread.h" + +MESSAGE_CLASS_DEFINITION(SDRdaemonInput::MsgConfigureSDRdaemon, Message) +MESSAGE_CLASS_DEFINITION(SDRdaemonInput::MsgConfigureSDRdaemonName, Message) +MESSAGE_CLASS_DEFINITION(SDRdaemonInput::MsgConfigureSDRdaemonWork, Message) +MESSAGE_CLASS_DEFINITION(SDRdaemonInput::MsgConfigureSDRdaemonStreamTiming, Message) +MESSAGE_CLASS_DEFINITION(SDRdaemonInput::MsgReportSDRdaemonAcquisition, Message) +MESSAGE_CLASS_DEFINITION(SDRdaemonInput::MsgReportSDRdaemonStreamData, Message) +MESSAGE_CLASS_DEFINITION(SDRdaemonInput::MsgReportSDRdaemonStreamTiming, Message) + +SDRdaemonInput::Settings::Settings() : + m_fileName("./test.sdriq") +{ +} + +void SDRdaemonInput::Settings::resetToDefaults() +{ + m_fileName = "./test.sdriq"; +} + +QByteArray SDRdaemonInput::Settings::serialize() const +{ + SimpleSerializer s(1); + s.writeString(1, m_fileName); + return s.final(); +} + +bool SDRdaemonInput::Settings::deserialize(const QByteArray& data) +{ + SimpleDeserializer d(data); + + if(!d.isValid()) { + resetToDefaults(); + return false; + } + + if(d.getVersion() == 1) { + int intval; + d.readString(1, &m_fileName, "./test.sdriq"); + return true; + } else { + resetToDefaults(); + return false; + } +} + +SDRdaemonInput::SDRdaemonInput(const QTimer& masterTimer) : + m_settings(), + m_SDRdaemonThread(NULL), + m_deviceDescription(), + m_fileName("..."), + m_sampleRate(0), + m_centerFrequency(0), + m_startingTimeStamp(0), + m_masterTimer(masterTimer) +{ +} + +SDRdaemonInput::~SDRdaemonInput() +{ + stop(); +} + +void SDRdaemonInput::openFileStream() +{ + qDebug() << "SDRdaemonInput::openFileStream: " << m_fileName.toStdString().c_str(); + + //stopInput(); + + if (m_ifstream.is_open()) { + m_ifstream.close(); + } + + m_ifstream.open(m_fileName.toStdString().c_str(), std::ios::binary); + FileSink::Header header; + FileSink::readHeader(m_ifstream, header); + + m_sampleRate = header.sampleRate; + m_centerFrequency = header.centerFrequency; + m_startingTimeStamp = header.startTimeStamp; + + MsgReportSDRdaemonStreamData *report = MsgReportSDRdaemonStreamData::create(m_sampleRate, m_centerFrequency, m_startingTimeStamp); // file stream data + getOutputMessageQueueToGUI()->push(report); +} + +bool SDRdaemonInput::init(const Message& message) +{ + return false; +} + +bool SDRdaemonInput::start(int device) +{ + QMutexLocker mutexLocker(&m_mutex); + qDebug() << "SDRdaemonInput::startInput"; + + if (m_ifstream.tellg() != 0) { + m_ifstream.clear(); + m_ifstream.seekg(0, std::ios::beg); + } + + if(!m_sampleFifo.setSize(96000 * 4)) { + qCritical("Could not allocate SampleFifo"); + return false; + } + + //openFileStream(); + + if((m_SDRdaemonThread = new SDRdaemonThread(&m_ifstream, &m_sampleFifo)) == NULL) { + qFatal("out of memory"); + stop(); + return false; + } + + m_SDRdaemonThread->setSamplerate(m_sampleRate); + m_SDRdaemonThread->connectTimer(m_masterTimer); + m_SDRdaemonThread->startWork(); + m_deviceDescription = "SDRdaemon"; + + mutexLocker.unlock(); + //applySettings(m_generalSettings, m_settings, true); + qDebug("SDRdaemonInput::startInput: started"); + + MsgReportSDRdaemonAcquisition *report = MsgReportSDRdaemonAcquisition::create(true); // acquisition on + getOutputMessageQueueToGUI()->push(report); + + return true; +} + +void SDRdaemonInput::stop() +{ + qDebug() << "SDRdaemonInput::stop"; + QMutexLocker mutexLocker(&m_mutex); + + if(m_SDRdaemonThread != 0) + { + m_SDRdaemonThread->stopWork(); + delete m_SDRdaemonThread; + m_SDRdaemonThread = 0; + } + + m_deviceDescription.clear(); + + MsgReportSDRdaemonAcquisition *report = MsgReportSDRdaemonAcquisition::create(false); // acquisition off + getOutputMessageQueueToGUI()->push(report); +} + +const QString& SDRdaemonInput::getDeviceDescription() const +{ + return m_deviceDescription; +} + +int SDRdaemonInput::getSampleRate() const +{ + return m_sampleRate; +} + +quint64 SDRdaemonInput::getCenterFrequency() const +{ + return m_centerFrequency; +} + +std::time_t SDRdaemonInput::getStartingTimeStamp() const +{ + return m_startingTimeStamp; +} + +bool SDRdaemonInput::handleMessage(const Message& message) +{ + if (MsgConfigureSDRdaemonName::match(message)) + { + MsgConfigureSDRdaemonName& conf = (MsgConfigureSDRdaemonName&) message; + m_fileName = conf.getFileName(); + openFileStream(); + return true; + } + else if (MsgConfigureSDRdaemonWork::match(message)) + { + MsgConfigureSDRdaemonWork& conf = (MsgConfigureSDRdaemonWork&) message; + bool working = conf.isWorking(); + + if (m_SDRdaemonThread != 0) + { + if (working) + { + m_SDRdaemonThread->startWork(); + MsgReportSDRdaemonStreamTiming *report = + MsgReportSDRdaemonStreamTiming::create(m_SDRdaemonThread->getSamplesCount()); + getOutputMessageQueueToGUI()->push(report); + } + else + { + m_SDRdaemonThread->stopWork(); + } + } + + return true; + } + else if (MsgConfigureSDRdaemonStreamTiming::match(message)) + { + MsgReportSDRdaemonStreamTiming *report; + + if (m_SDRdaemonThread != 0) + { + report = MsgReportSDRdaemonStreamTiming::create(m_SDRdaemonThread->getSamplesCount()); + getOutputMessageQueueToGUI()->push(report); + } + + return true; + } + else + { + return false; + } +} + +bool SDRdaemonInput::applySettings(const Settings& settings, bool force) +{ + QMutexLocker mutexLocker(&m_mutex); + bool wasRunning = false; + + if((m_settings.m_fileName != settings.m_fileName) || force) + { + m_settings.m_fileName = settings.m_fileName; + + if (m_SDRdaemonThread != 0) + { + wasRunning = m_SDRdaemonThread->isRunning(); + + if (wasRunning) + { + m_SDRdaemonThread->stopWork(); + } + } + + if (m_ifstream.is_open()) + { + m_ifstream.close(); + } + + openFileStream(); + + if (m_SDRdaemonThread != 0) + { + m_SDRdaemonThread->setSamplerate(m_sampleRate); + + if (wasRunning) + { + m_SDRdaemonThread->startWork(); + } + } + + DSPSignalNotification *notif = new DSPSignalNotification(m_sampleRate, m_centerFrequency); + DSPEngine::instance()->getInputMessageQueue()->push(notif); + + qDebug() << "SDRdaemonInput::applySettings:" + << " file name: " << settings.m_fileName.toStdString().c_str() + << " center freq: " << m_centerFrequency << " Hz" + << " sample rate: " << m_sampleRate + << " Unix timestamp: " << m_startingTimeStamp; + } + + return true; +} diff --git a/plugins/samplesource/sdrdaemon/sdrdaemoninput.h b/plugins/samplesource/sdrdaemon/sdrdaemoninput.h new file mode 100644 index 000000000..e0c180b20 --- /dev/null +++ b/plugins/samplesource/sdrdaemon/sdrdaemoninput.h @@ -0,0 +1,213 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2016 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 INCLUDE_SDRDAEMONINPUT_H +#define INCLUDE_SDRDAEMONINPUT_H + +#include "dsp/samplesource.h" +#include +#include +#include +#include +#include + +class SDRdaemonThread; + +class SDRdaemonInput : public SampleSource { +public: + struct Settings { + QString m_fileName; + + Settings(); + void resetToDefaults(); + QByteArray serialize() const; + bool deserialize(const QByteArray& data); + }; + + class MsgConfigureSDRdaemon : public Message { + MESSAGE_CLASS_DECLARATION + + public: + const Settings& getSettings() const { return m_settings; } + + static MsgConfigureSDRdaemon* create(const Settings& settings) + { + return new MsgConfigureSDRdaemon(settings); + } + + private: + Settings m_settings; + + MsgConfigureSDRdaemon(const Settings& settings) : + Message(), + m_settings(settings) + { } + }; + + class MsgConfigureSDRdaemonName : public Message { + MESSAGE_CLASS_DECLARATION + + public: + const QString& getFileName() const { return m_fileName; } + + static MsgConfigureSDRdaemonName* create(const QString& fileName) + { + return new MsgConfigureSDRdaemonName(fileName); + } + + private: + QString m_fileName; + + MsgConfigureSDRdaemonName(const QString& fileName) : + Message(), + m_fileName(fileName) + { } + }; + + class MsgConfigureSDRdaemonWork : public Message { + MESSAGE_CLASS_DECLARATION + + public: + bool isWorking() const { return m_working; } + + static MsgConfigureSDRdaemonWork* create(bool working) + { + return new MsgConfigureSDRdaemonWork(working); + } + + private: + bool m_working; + + MsgConfigureSDRdaemonWork(bool working) : + Message(), + m_working(working) + { } + }; + + class MsgConfigureSDRdaemonStreamTiming : public Message { + MESSAGE_CLASS_DECLARATION + + public: + + static MsgConfigureSDRdaemonStreamTiming* create() + { + return new MsgConfigureSDRdaemonStreamTiming(); + } + + private: + + MsgConfigureSDRdaemonStreamTiming() : + Message() + { } + }; + + class MsgReportSDRdaemonAcquisition : public Message { + MESSAGE_CLASS_DECLARATION + + public: + bool getAcquisition() const { return m_acquisition; } + + static MsgReportSDRdaemonAcquisition* create(bool acquisition) + { + return new MsgReportSDRdaemonAcquisition(acquisition); + } + + protected: + bool m_acquisition; + + MsgReportSDRdaemonAcquisition(bool acquisition) : + Message(), + m_acquisition(acquisition) + { } + }; + + class MsgReportSDRdaemonStreamData : public Message { + MESSAGE_CLASS_DECLARATION + + public: + int getSampleRate() const { return m_sampleRate; } + quint64 getCenterFrequency() const { return m_centerFrequency; } + std::time_t getStartingTimeStamp() const { return m_startingTimeStamp; } + + static MsgReportSDRdaemonStreamData* create(int sampleRate, quint64 centerFrequency, std::time_t startingTimeStamp) + { + return new MsgReportSDRdaemonStreamData(sampleRate, centerFrequency, startingTimeStamp); + } + + protected: + int m_sampleRate; + quint64 m_centerFrequency; + std::time_t m_startingTimeStamp; + + MsgReportSDRdaemonStreamData(int sampleRate, quint64 centerFrequency, std::time_t startingTimeStamp) : + Message(), + m_sampleRate(sampleRate), + m_centerFrequency(centerFrequency), + m_startingTimeStamp(startingTimeStamp) + { } + }; + + class MsgReportSDRdaemonStreamTiming : public Message { + MESSAGE_CLASS_DECLARATION + + public: + std::size_t getSamplesCount() const { return m_samplesCount; } + + static MsgReportSDRdaemonStreamTiming* create(std::size_t samplesCount) + { + return new MsgReportSDRdaemonStreamTiming(samplesCount); + } + + protected: + std::size_t m_samplesCount; + + MsgReportSDRdaemonStreamTiming(std::size_t samplesCount) : + Message(), + m_samplesCount(samplesCount) + { } + }; + + SDRdaemonInput(const QTimer& masterTimer); + virtual ~SDRdaemonInput(); + + virtual bool init(const Message& message); + virtual bool start(int device); + virtual void stop(); + + virtual const QString& getDeviceDescription() const; + virtual int getSampleRate() const; + virtual quint64 getCenterFrequency() const; + std::time_t getStartingTimeStamp() const; + + virtual bool handleMessage(const Message& message); + +private: + QMutex m_mutex; + Settings m_settings; + std::ifstream m_ifstream; + SDRdaemonThread* m_SDRdaemonThread; + QString m_deviceDescription; + QString m_fileName; + int m_sampleRate; + quint64 m_centerFrequency; + std::time_t m_startingTimeStamp; + const QTimer& m_masterTimer; + + bool applySettings(const Settings& settings, bool force); + void openFileStream(); +}; + +#endif // INCLUDE_SDRDAEMONINPUT_H diff --git a/plugins/samplesource/sdrdaemon/sdrdaemonplugin.cpp b/plugins/samplesource/sdrdaemon/sdrdaemonplugin.cpp new file mode 100644 index 000000000..5bdf64780 --- /dev/null +++ b/plugins/samplesource/sdrdaemon/sdrdaemonplugin.cpp @@ -0,0 +1,82 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2015 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 . // +/////////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include "plugin/pluginapi.h" +#include "util/simpleserializer.h" + +#include "sdrdaemongui.h" +#include "sdrdaemonplugin.h" + +const PluginDescriptor SDRdaemonPlugin::m_pluginDescriptor = { + QString("File source input"), + QString("---"), + QString("(c) Edouard Griffiths, F4EXB"), + QString("https://github.com/f4exb/sdrangel"), + true, + QString("https://github.com/f4exb/sdrangel") +}; + +const QString SDRdaemonPlugin::m_deviceTypeID = SDRDAEMON_DEVICE_TYPE_ID; + +SDRdaemonPlugin::SDRdaemonPlugin(QObject* parent) : + QObject(parent) +{ +} + +const PluginDescriptor& SDRdaemonPlugin::getPluginDescriptor() const +{ + return m_pluginDescriptor; +} + +void SDRdaemonPlugin::initPlugin(PluginAPI* pluginAPI) +{ + m_pluginAPI = pluginAPI; + m_pluginAPI->registerSampleSource(m_deviceTypeID, this); +} + +PluginInterface::SampleSourceDevices SDRdaemonPlugin::enumSampleSources() +{ + SampleSourceDevices result; + int count = 1; + + for(int i = 0; i < count; i++) + { + QString displayedName(QString("SDRdaemon[%1]").arg(i)); + + result.append(SampleSourceDevice(displayedName, + m_deviceTypeID, + QString::null, + i)); + } + + return result; +} + +PluginGUI* SDRdaemonPlugin::createSampleSourcePluginGUI(const QString& sourceId) +{ + if(sourceId == m_deviceTypeID) + { + SDRdaemonGui* gui = new SDRdaemonGui(m_pluginAPI); + m_pluginAPI->setInputGUI(gui); + return gui; + } + else + { + return NULL; + } +} diff --git a/plugins/samplesource/sdrdaemon/sdrdaemonplugin.h b/plugins/samplesource/sdrdaemon/sdrdaemonplugin.h new file mode 100644 index 000000000..3dd77313f --- /dev/null +++ b/plugins/samplesource/sdrdaemon/sdrdaemonplugin.h @@ -0,0 +1,47 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2016 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 INCLUDE_SDRDAEMONPLUGIN_H +#define INCLUDE_SDRDAEMONPLUGIN_H + +#include +#include "plugin/plugininterface.h" + +#define SDRDAEMON_DEVICE_TYPE_ID "sdrangel.samplesource.sdrdaemon" + +class SDRdaemonPlugin : public QObject, public PluginInterface { + Q_OBJECT + Q_INTERFACES(PluginInterface) + Q_PLUGIN_METADATA(IID SDRDAEMON_DEVICE_TYPE_ID) + +public: + explicit SDRdaemonPlugin(QObject* parent = NULL); + + const PluginDescriptor& getPluginDescriptor() const; + void initPlugin(PluginAPI* pluginAPI); + + virtual SampleSourceDevices enumSampleSources(); + virtual PluginGUI* createSampleSourcePluginGUI(const QString& sourceId); + + static const QString m_deviceTypeID; + +private: + static const PluginDescriptor m_pluginDescriptor; + + PluginAPI* m_pluginAPI; +}; + +#endif // INCLUDE_SDRDAEMONPLUGIN_H diff --git a/plugins/samplesource/sdrdaemon/sdrdaemonthread.cpp b/plugins/samplesource/sdrdaemon/sdrdaemonthread.cpp new file mode 100644 index 000000000..4a261a2f9 --- /dev/null +++ b/plugins/samplesource/sdrdaemon/sdrdaemonthread.cpp @@ -0,0 +1,153 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2015 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 . // +/////////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include "dsp/samplefifo.h" +#include + +#include "sdrdaemonthread.h" + +const int SDRdaemonThread::m_rateDivider = 1000/SDRDAEMON_THROTTLE_MS; + +SDRdaemonThread::SDRdaemonThread(std::ifstream *samplesStream, SampleFifo* sampleFifo, QObject* parent) : + QThread(parent), + m_running(false), + m_ifstream(samplesStream), + m_buf(0), + m_bufsize(0), + m_chunksize(0), + m_sampleFifo(sampleFifo), + m_samplesCount(0), + m_samplerate(0) +{ + assert(m_ifstream != 0); +} + +SDRdaemonThread::~SDRdaemonThread() +{ + if (m_running) { + stopWork(); + } + + if (m_buf != 0) { + free(m_buf); + } +} + +void SDRdaemonThread::startWork() +{ + qDebug() << "SDRdaemonThread::startWork: "; + + if (m_ifstream->is_open()) + { + qDebug() << " - file stream open, starting..."; + m_startWaitMutex.lock(); + start(); + while(!m_running) + m_startWaiter.wait(&m_startWaitMutex, 100); + m_startWaitMutex.unlock(); + } + else + { + qDebug() << " - file stream closed, not starting."; + } +} + +void SDRdaemonThread::stopWork() +{ + qDebug() << "SDRdaemonThread::stopWork"; + m_running = false; + wait(); +} + +void SDRdaemonThread::setSamplerate(int samplerate) +{ + qDebug() << "SDRdaemonThread::setSamplerate:" + << " new:" << samplerate + << " old:" << m_samplerate; + + if (samplerate != m_samplerate) + { + if (m_running) { + stopWork(); + } + + m_samplerate = samplerate; + m_chunksize = (m_samplerate / m_rateDivider)*4; // TODO: implement FF and slow motion here. 4 corresponds to live. 2 is half speed, 8 is doulbe speed + m_bufsize = m_chunksize; + + if (m_buf == 0) { + qDebug() << " - Allocate buffer"; + m_buf = (quint8*) malloc(m_bufsize); + } else { + qDebug() << " - Re-allocate buffer"; + m_buf = (quint8*) realloc((void*) m_buf, m_bufsize); + } + + qDebug() << " - size: " << m_bufsize + << " #samples: " << (m_bufsize/4); + } + + //m_samplerate = samplerate; +} + +void SDRdaemonThread::run() +{ + int res; + + m_running = true; + m_startWaiter.wakeAll(); + + while(m_running) // actual work is in the tick() function + { + sleep(1); + } + + m_running = false; +} + +void SDRdaemonThread::connectTimer(const QTimer& timer) +{ + qDebug() << "SDRdaemonThread::connectTimer"; + connect(&timer, SIGNAL(timeout()), this, SLOT(tick())); +} + +void SDRdaemonThread::tick() +{ + if (m_running) + { + // read samples directly feeding the SampleFifo (no callback) + m_ifstream->read(reinterpret_cast(m_buf), m_chunksize); + + if (m_ifstream->eof()) + { + m_sampleFifo->write(m_buf, m_ifstream->gcount()); + // TODO: handle loop playback situation + m_ifstream->clear(); + m_ifstream->seekg(0, std::ios::beg); + m_samplesCount = 0; + //stopWork(); + //m_ifstream->close(); + } + else + { + m_sampleFifo->write(m_buf, m_chunksize); + m_samplesCount += m_chunksize / 4; + } + } +} diff --git a/plugins/samplesource/sdrdaemon/sdrdaemonthread.h b/plugins/samplesource/sdrdaemon/sdrdaemonthread.h new file mode 100644 index 000000000..9d3ff1d3a --- /dev/null +++ b/plugins/samplesource/sdrdaemon/sdrdaemonthread.h @@ -0,0 +1,67 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2016 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 INCLUDE_SDRDAEMONTHREAD_H +#define INCLUDE_SDRDAEMONTHREAD_H + +#include +#include +#include +#include +#include +#include +#include +#include "dsp/samplefifo.h" +#include "dsp/inthalfbandfilter.h" + +#define SDRDAEMON_THROTTLE_MS 50 + +class SDRdaemonThread : public QThread { + Q_OBJECT + +public: + SDRdaemonThread(std::ifstream *samplesStream, SampleFifo* sampleFifo, QObject* parent = NULL); + ~SDRdaemonThread(); + + void startWork(); + void stopWork(); + void setSamplerate(int samplerate); + bool isRunning() const { return m_running; } + std::size_t getSamplesCount() const { return m_samplesCount; } + + void connectTimer(const QTimer& timer); + +private: + QMutex m_startWaitMutex; + QWaitCondition m_startWaiter; + bool m_running; + + std::ifstream* m_ifstream; + quint8 *m_buf; + std::size_t m_bufsize; + std::size_t m_chunksize; + SampleFifo* m_sampleFifo; + std::size_t m_samplesCount; + + int m_samplerate; + static const int m_rateDivider; + + void run(); +private slots: + void tick(); +}; + +#endif // INCLUDE_SDRDAEMONTHREAD_H From 1850452601f82e242b3ccfa1dc35ec19b8a90dac Mon Sep 17 00:00:00 2001 From: f4exb Date: Sun, 24 Jan 2016 19:26:42 +0100 Subject: [PATCH 02/51] Add liblz4 dependency for sdrdaemon plugin --- cmake/Modules/FindLZ4.cmake | 27 +++++++++++++++++++ plugins/samplesource/sdrdaemon/CMakeLists.txt | 7 +++++ 2 files changed, 34 insertions(+) create mode 100644 cmake/Modules/FindLZ4.cmake diff --git a/cmake/Modules/FindLZ4.cmake b/cmake/Modules/FindLZ4.cmake new file mode 100644 index 000000000..51f133840 --- /dev/null +++ b/cmake/Modules/FindLZ4.cmake @@ -0,0 +1,27 @@ +INCLUDE(FindPkgConfig) +PKG_CHECK_MODULES(PC_LZ4 "liblz4") + +FIND_PATH(LZ4_INCLUDE_DIRS + NAMES lz4.h + HINTS ${PC_LZ4_INCLUDE_DIR} + ${CMAKE_INSTALL_PREFIX}/include + ${LIBLZ4_INSTALL_PREFIX}/include + PATHS + /usr/local/include + /usr/include +) + +FIND_LIBRARY(LZ4_LIBRARIES + NAMES lz4 liblz4 + HINTS ${PC_LZ4_LIBDIR} + ${CMAKE_INSTALL_PREFIX}/lib + ${CMAKE_INSTALL_PREFIX}/lib64 + PATHS + ${LZ4_INCLUDE_DIRS}/../lib + /usr/local/lib + /usr/lib +) + +INCLUDE(FindPackageHandleStandardArgs) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(LZ4 DEFAULT_MSG LZ4_LIBRARIES LZ4_INCLUDE_DIRS) +MARK_AS_ADVANCED(LZ4_LIBRARIES LZ4_INCLUDE_DIRS) diff --git a/plugins/samplesource/sdrdaemon/CMakeLists.txt b/plugins/samplesource/sdrdaemon/CMakeLists.txt index f693b6adb..0ae1cb3b0 100644 --- a/plugins/samplesource/sdrdaemon/CMakeLists.txt +++ b/plugins/samplesource/sdrdaemon/CMakeLists.txt @@ -1,5 +1,7 @@ project(sdrdaemon) +find_package(LZ4) + set(sdrdaemon_SOURCES sdrdaemongui.cpp sdrdaemoninput.cpp @@ -40,9 +42,14 @@ add_library(inputsdrdaemon SHARED ${sdrdaemon_FORMS_HEADERS} ) +target_include_directories(inputsdrdaemon PUBLIC + ${LZ4_INCLUDE_DIRS} +) + target_link_libraries(inputsdrdaemon ${QT_LIBRARIES} ${LIBUSB_LIBRARIES} + ${LZ4_LIBRARIES} sdrbase ) From 7a6882829a681554e88a385a480bb1faa968ac40 Mon Sep 17 00:00:00 2001 From: f4exb Date: Sun, 24 Jan 2016 23:38:55 +0100 Subject: [PATCH 03/51] SDRdaemon plugin: new classes --- CMakeLists.txt | 4 +- include/util/CRC64.h | 38 +++ plugins/samplesource/sdrdaemon/CMakeLists.txt | 2 + .../sdrdaemon/sdrdaemonbuffer.cpp | 232 ++++++++++++++++ .../samplesource/sdrdaemon/sdrdaemonbuffer.h | 94 +++++++ .../samplesource/sdrdaemon/sdrdaemongui.ui | 250 +++++++++++++----- .../samplesource/sdrdaemon/sdrdaemonthread.h | 4 + sdrbase/util/CRC64.cpp | 159 +++++++++++ 8 files changed, 717 insertions(+), 66 deletions(-) create mode 100644 include/util/CRC64.h create mode 100644 plugins/samplesource/sdrdaemon/sdrdaemonbuffer.cpp create mode 100644 plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h create mode 100644 sdrbase/util/CRC64.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index c1d4e5687..9ce27a3db 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -126,6 +126,7 @@ set(sdrbase_SOURCES sdrbase/settings/preset.cpp sdrbase/settings/mainsettings.cpp + sdrbase/util/CRC64.cpp sdrbase/util/db.cpp sdrbase/util/message.cpp sdrbase/util/messagequeue.cpp @@ -208,7 +209,8 @@ set(sdrbase_HEADERS include/settings/preset.h include/settings/mainsettings.h - include/util/db.h + include/util/CRC64.h + include/util/db.h include/util/export.h include/util/message.h include/util/messagequeue.h diff --git a/include/util/CRC64.h b/include/util/CRC64.h new file mode 100644 index 000000000..bede1df55 --- /dev/null +++ b/include/util/CRC64.h @@ -0,0 +1,38 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2016 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 INCLUDE_CRC64_H_ +#define INCLUDE_CRC64_H_ + +#include + +class CRC64 +{ +public: + CRC64(); + ~CRC64(); + uint64_t calculate_crc(uint8_t *stream, int length); + +private: + void build_crc_table(); + + uint64_t m_crcTable[256]; + static const uint64_t m_poly; +}; + + + +#endif /* INCLUDE_CRC64_H_ */ diff --git a/plugins/samplesource/sdrdaemon/CMakeLists.txt b/plugins/samplesource/sdrdaemon/CMakeLists.txt index 0ae1cb3b0..2fc7bb122 100644 --- a/plugins/samplesource/sdrdaemon/CMakeLists.txt +++ b/plugins/samplesource/sdrdaemon/CMakeLists.txt @@ -3,6 +3,7 @@ project(sdrdaemon) find_package(LZ4) set(sdrdaemon_SOURCES + sdrdaemonbuffer.cpp sdrdaemongui.cpp sdrdaemoninput.cpp sdrdaemonplugin.cpp @@ -10,6 +11,7 @@ set(sdrdaemon_SOURCES ) set(sdrdaemon_HEADERS + sdrdaemonbuffer.h sdrdaemongui.h sdrdaemoninput.h sdrdaemonplugin.h diff --git a/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.cpp b/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.cpp new file mode 100644 index 000000000..a468eaa1f --- /dev/null +++ b/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.cpp @@ -0,0 +1,232 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2016 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 . // +/////////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include "sdrdaemonbuffer.h" + +SDRdaemonBuffer::SDRdaemonBuffer(std::size_t blockSize) : + m_blockSize(blockSize), + m_sync(false), + m_lz4(false), + m_lz4InBuffer(0), + m_lz4InCount(0), + m_lz4InSize(0), + m_lz4OutBuffer(0), + m_lz4OutSize(0), + m_nbDecodes(0), + m_nbSuccessfulDecodes(0), + m_nbCRCOK(0), + m_dataCRC(0) +{ + m_buf = new uint8_t[blockSize]; + m_currentMeta.init(); +} + +SDRdaemonBuffer::~SDRdaemonBuffer() +{ + delete[] m_buf; +} + +bool SDRdaemonBuffer::writeAndRead(uint8_t *array, std::size_t length, uint8_t *data, std::size_t& dataLength) +{ + assert(length == m_blockSize); // TODO: allow fragmented blocks with larger size + MetaData *metaData = (MetaData *) array; + + if (m_crc64.calculate_crc(array, sizeof(MetaData) - 8) == metaData->m_crc) + { + dataLength = 0; + memcpy((void *) &m_dataCRC, (const void *) &array[sizeof(MetaData)], 8); + + if (!(m_currentMeta == *metaData)) + { + std::cerr << "SDRdaemonBuffer::writeAndRead: "; + printMeta(metaData); + } + + m_currentMeta = *metaData; + + // sanity checks + if (metaData->m_blockSize == m_blockSize) // sent blocksize matches given blocksize + { + if (metaData->m_sampleBytes & 0x10) + { + m_lz4 = true; + updateSizes(metaData); + } + else + { + m_lz4 = false; + } + + m_sync = true; + } + else + { + m_sync = false; + } + + return false; + } + else + { + if (m_sync) + { + if (m_lz4) + { + return writeAndReadLZ4(array, length, data, dataLength); + } + else + { + std::memcpy((void *) data, (const void *) array, length); + dataLength = length; + return true; + } + } + else + { + dataLength = 0; + return false; + } + } +} + +bool SDRdaemonBuffer::writeAndReadLZ4(uint8_t *array, std::size_t length, uint8_t *data, std::size_t& dataLength) +{ + if (m_lz4InCount + length < m_lz4InSize) + { + std::memcpy((void *) &m_lz4InBuffer[m_lz4InCount], (const void *) array, length); // copy data in compressed Buffer + dataLength = 0; + m_lz4InCount += length; + } + else + { + std::memcpy((void *) &m_lz4InBuffer[m_lz4InCount], (const void *) array, m_lz4InSize - m_lz4InCount); // copy rest of data in compressed Buffer + m_lz4InCount += length; + } + + if (m_lz4InCount >= m_lz4InSize) // full input compressed block retrieved + { + if (m_nbDecodes == 100) + { + std::cerr << "SDRdaemonBuffer::writeAndReadLZ4:" + << " decoding: " << m_nbCRCOK + << ":" << m_nbSuccessfulDecodes + << "/" << m_nbDecodes + << std::endl; + + m_nbDecodes = 0; + m_nbSuccessfulDecodes = 0; + m_nbCRCOK = 0; + } + + uint64_t crc64 = m_crc64.calculate_crc(m_lz4InBuffer, m_lz4InSize); + //uint64_t crc64 = 0x0123456789ABCDEF; + + if (memcmp(&crc64, &m_dataCRC, 8) == 0) + { + m_nbCRCOK++; + } + + int compressedSize = LZ4_decompress_fast((const char*) m_lz4InBuffer, (char*) m_lz4OutBuffer, m_lz4OutSize); + m_nbDecodes++; + + if (compressedSize == m_lz4InSize) + { + /* + std::cerr << "SDRdaemonBuffer::writeAndReadLZ4: decoding OK:" + << " read: " << compressedSize + << " expected: " << m_lz4InSize + << " out: " << m_lz4OutSize + << std::endl; + */ + std::memcpy((void *) data, (const void *) m_lz4OutBuffer, m_lz4OutSize); // send what is in buffer + dataLength = m_lz4OutSize; + m_nbSuccessfulDecodes++; + } + else + { +// std::cerr << "SDRdaemonBuffer::writeAndReadLZ4: decoding error:" +// << " read: " << compressedSize +// << " expected: " << m_lz4InSize +// << " out: " << m_lz4OutSize +// << std::endl; + + //if (compressedSize > 0) + //{ + std::memcpy((void *) data, (const void *) m_lz4OutBuffer, m_lz4OutSize); // send what is in buffer + dataLength = m_lz4OutSize; + //} + //else + //{ + // dataLength = 0; + //} + } + + m_lz4InCount = 0; + } + + return dataLength != 0; +} + +void SDRdaemonBuffer::updateSizes(MetaData *metaData) +{ + m_lz4InSize = metaData->m_nbBytes; // compressed input size + uint32_t sampleBytes = metaData->m_sampleBytes & 0x0F; + uint32_t originalSize = sampleBytes * 2 * metaData->m_nbSamples * metaData->m_nbBlocks; + + if (originalSize != m_lz4OutSize) + { + uint32_t masInputSize = LZ4_compressBound(originalSize); + + if (m_lz4InBuffer) { + delete[] m_lz4InBuffer; + } + + m_lz4InBuffer = new uint8_t[m_lz4InSize]; // provide extra space for a full UDP block + + if (m_lz4OutBuffer) { + delete[] m_lz4OutBuffer; + } + + m_lz4OutBuffer = new uint8_t[originalSize]; + m_lz4OutSize = originalSize; + } + + m_lz4InCount = 0; +} + + +void SDRdaemonBuffer::printMeta(MetaData *metaData) +{ + std::cerr + << "|" << metaData->m_centerFrequency + << ":" << metaData->m_sampleRate + << ":" << (int) (metaData->m_sampleBytes & 0xF) + << ":" << (int) metaData->m_sampleBits + << ":" << metaData->m_blockSize + << ":" << metaData->m_nbSamples + << "||" << metaData->m_nbBlocks + << ":" << metaData->m_nbBytes + << "|" << metaData->m_tv_sec + << ":" << metaData->m_tv_usec + << std::endl; +} + + + + diff --git a/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h b/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h new file mode 100644 index 000000000..4a8e0de6a --- /dev/null +++ b/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h @@ -0,0 +1,94 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2016 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_SDRDAEMON_SDRDAEMONBUFFER_H_ +#define PLUGINS_SAMPLESOURCE_SDRDAEMON_SDRDAEMONBUFFER_H_ + +#include +#include +#include +#include +#include "util/CRC64.h" + +class SDRdaemonBuffer +{ +public: +#pragma pack(push, 1) + struct MetaData + { + // critical data + uint64_t m_centerFrequency; //!< center frequency in Hz + uint32_t m_sampleRate; //!< sample rate in Hz + uint8_t m_sampleBytes; //!< MSB(4): indicators, LSB(4) number of bytes per sample + uint8_t m_sampleBits; //!< number of effective bits per sample + uint16_t m_blockSize; //!< payload size + uint32_t m_nbSamples; //!< number of samples in a hardware block + // end of critical data + uint16_t m_nbBlocks; //!< number of hardware blocks in the frame + uint32_t m_nbBytes; //!< total number of bytes in the frame + uint32_t m_tv_sec; //!< seconds of timestamp at start time of frame processing + uint32_t m_tv_usec; //!< microseconds of timestamp at start time of frame processing + uint64_t m_crc; //!< 64 bit CRC of the above + + bool operator==(const MetaData& rhs) + { + return (memcmp((const void *) this, (const void *) &rhs, 20) == 0); // Only the 20 first bytes are relevant (critical) + } + + void init() + { + memset((void *) this, 0, sizeof(MetaData)); + } + + void operator=(const MetaData& rhs) + { + memcpy((void *) this, (const void *) &rhs, sizeof(MetaData)); + } + }; +#pragma pack(pop) + + SDRdaemonBuffer(std::size_t blockSize); + ~SDRdaemonBuffer(); + bool writeAndRead(uint8_t *array, std::size_t length, uint8_t *data, std::size_t& dataLength); + const MetaData& getCurrentMeta() const { return m_currentMeta; } + +private: + bool writeAndReadLZ4(uint8_t *array, std::size_t length, uint8_t *data, std::size_t& dataLength); + void updateSizes(MetaData *metaData); + void printMeta(MetaData *metaData); + + std::size_t m_blockSize; //!< UDP block (payload) size + bool m_sync; //!< Meta data acquired (Stream synchronized) + bool m_lz4; //!< Stream is compressed with LZ4 + MetaData m_currentMeta; //!< Stored current meta data + CRC64 m_crc64; //!< CRC64 calculator + uint8_t *m_buf; //!< UDP block buffer + + uint8_t *m_lz4InBuffer; //!< Buffer for LZ4 compressed input + uint32_t m_lz4InCount; //!< Current position in LZ4 input buffer + uint32_t m_lz4InSize; //!< Size in bytes of the LZ4 input data + uint8_t *m_lz4OutBuffer; //!< Buffer for LZ4 uncompressed output + uint32_t m_lz4OutSize; //!< Size in bytes of the LZ4 output data (original uncomressed data) + uint32_t m_nbDecodes; + uint32_t m_nbSuccessfulDecodes; + uint32_t m_nbCRCOK; + uint64_t m_dataCRC; + +}; + + + +#endif /* PLUGINS_SAMPLESOURCE_SDRDAEMON_SDRDAEMONBUFFER_H_ */ diff --git a/plugins/samplesource/sdrdaemon/sdrdaemongui.ui b/plugins/samplesource/sdrdaemon/sdrdaemongui.ui index 9dcf1e942..228619b6a 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemongui.ui +++ b/plugins/samplesource/sdrdaemon/sdrdaemongui.ui @@ -6,8 +6,8 @@ 0 0 - 198 - 133 + 343 + 207 @@ -23,22 +23,13 @@ - BladeRF + SDRdaemon 3 - - 2 - - - 2 - - - 2 - - + 2 @@ -119,6 +110,187 @@ + + + + + + Addr: + + + + + + + + 120 + 0 + + + + + + + + Port: + + + + + + + + 50 + 0 + + + + + + + + + 30 + 16777215 + + + + OK + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + + 50 + 0 + + + + + 8 + + + + Record sample rate + + + 0k + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Qt::Vertical + + + + + + + false + + + Record absolute time + + + 20150101 00:00:00.000 + + + + + + + + + + + Dec. + + + + + + + Decimation factor + + + 6 + + + 1 + + + 0 + + + Qt::Horizontal + + + + + + + 1 + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 50 + 0 + + + + 0k + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + @@ -172,58 +344,6 @@ - - - - - - - 8 - - - - Record sample rate - - - 0k - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - Qt::Vertical - - - - - - - false - - - Record absolute time - - - 20150101 00:00:00.000 - - - - - diff --git a/plugins/samplesource/sdrdaemon/sdrdaemonthread.h b/plugins/samplesource/sdrdaemon/sdrdaemonthread.h index 9d3ff1d3a..3464a095e 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemonthread.h +++ b/plugins/samplesource/sdrdaemon/sdrdaemonthread.h @@ -21,6 +21,7 @@ #include #include #include + #include #include #include @@ -29,6 +30,8 @@ #define SDRDAEMON_THROTTLE_MS 50 +class QUdpSocket; + class SDRdaemonThread : public QThread { Q_OBJECT @@ -50,6 +53,7 @@ private: bool m_running; std::ifstream* m_ifstream; + QUdpSocket *m_dataSocket; quint8 *m_buf; std::size_t m_bufsize; std::size_t m_chunksize; diff --git a/sdrbase/util/CRC64.cpp b/sdrbase/util/CRC64.cpp new file mode 100644 index 000000000..e07cf0d14 --- /dev/null +++ b/sdrbase/util/CRC64.cpp @@ -0,0 +1,159 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2016 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 . // +/////////////////////////////////////////////////////////////////////////////////// + +#include "util/CRC64.h" + +/** +* poly is: x^64 + x^62 + x^57 + x^55 + x^54 + x^53 + x^52 + x^47 + x^46 + x^45 + x^40 + x^39 + +* x^38 + x^37 + x^35 + x^33 + x^32 + x^31 + x^29 + x^27 + x^24 + x^23 + x^22 + x^21 + +* x^19 + x^17 + x^13 + x^12 + x^10 + x^9 + x^7 + x^4 + x^1 + 1 +* +* represented here with lsb = highest degree term +* +* 1100100101101100010101111001010111010111100001110000111101000010_ +* || | | || || | | |||| | | ||| | |||| ||| |||| | | | +* || | | || || | | |||| | | ||| | |||| ||| |||| | | +- x^64 (implied) +* || | | || || | | |||| | | ||| | |||| ||| |||| | | +* || | | || || | | |||| | | ||| | |||| ||| |||| | +--- x^62 +* || | | || || | | |||| | | ||| | |||| ||| |||| +-------- x^57 +* ....................................................................... +* || +* |+---------------------------------------------------------------- x^1 +* +----------------------------------------------------------------- x^0 (1) +*/ +const uint64_t CRC64::m_poly = 0xC96C5795D7870F42ull; + +CRC64::CRC64() +{ + build_crc_table(); +} + +CRC64::~CRC64() +{} + +/** +* input is dividend: as 0000000000000000000000000000000000000000000000000000000000000000<8-bit byte> +* where the lsb of the 8-bit byte is the coefficient of the highest degree term (x^71) of the dividend +* so division is really for input byte * x^64 +* +* you may wonder how 72 bits will fit in 64-bit data type... well as the shift-right occurs, 0's are supplied +* on the left (most significant) side ... when the 8 shifts are done, the right side (where the input +* byte was placed) is discarded +* +* when done, table[XX] (where XX is a byte) is equal to the CRC of 00 00 00 00 00 00 00 00 XX +*/ +void CRC64::build_crc_table() +{ + for(int i = 0; i < 256; ++i) + { + uint64_t crc = i; + + for(unsigned int j = 0; j < 8; ++j) + { + if(crc & 1) // is current coefficient set? + { + crc >>= 1; // yes, then assume it gets zero'd (by implied x^64 coefficient of dividend) + crc ^= m_poly; // and add rest of the divisor + } + else // no? then move to next coefficient + { + crc >>= 1; + } + } + + m_crcTable[i] = crc; + } +} + +/** +* will give an example CRC calculation for input array {0xDE, 0xAD} +* +* each byte represents a group of 8 coefficients for 8 dividend terms +* +* the actual polynomial dividend is: +* +* = DE AD 00 00 00 00 00 00 00 00 (hex) +* = 11011110 10101101 0000000000000000000...0 (binary) +* || |||| | | || | +* || |||| | | || +------------------------ x^71 +* || |||| | | |+-------------------------- x^69 +* || |||| | | +--------------------------- x^68 +* || |||| | +----------------------------- x^66 +* || |||| +------------------------------- x^64 +* || |||| +* || |||+---------------------------------- x^78 +* || ||+----------------------------------- x^77 +* || |+------------------------------------ x^76 +* || +------------------------------------- x^75 +* |+--------------------------------------- x^73 +* +---------------------------------------- x^72 +* +* +* the basic idea behind how the table lookup results can be used with one +* another is that: +* +* Mod(A * x^n, P(x)) = Mod(x^n * Mod(A, P(X)), P(X)) +* +* in other words, an input data shifted towards the higher degree terms +* changes the pre-computed crc of the input data by shifting it also +* the same amount towards higher degree terms (mod the polynomial) +* +* here is an example: +* +* 1) input: +* +* 00 00 00 00 00 00 00 00 AD DE +* +* 2) index crc table for byte DE (really for dividend 00 00 00 00 00 00 00 00 DE) +* +* we get A8B4AFBDC5A6ACA4 +* +* 3) apply that to the input stream: +* +* 00 00 00 00 00 00 00 00 AD DE +* A8 B4 AF BD C5 A6 AC A4 +* ----------------------------- +* 00 A8 B4 AF BD C5 A6 AC 09 +* +* 4) index crc table for byte 09 (really for dividend 00 00 00 00 00 00 00 00 09) +* +* we get 448FCBB7FCB9E309 +* +* 5) apply that to the input stream +* +* 00 A8 B4 AF BD C5 A6 AC 09 +* 44 8F CB B7 FC B9 E3 09 +* -------------------------- +* 44 27 7F 18 41 7C 45 A5 +* +*/ +uint64_t CRC64::calculate_crc(uint8_t *stream, int length) +{ + uint64_t crc = 0; + + for (int i = 0 ; i < length; ++i) + { + uint8_t index = stream[i] ^ crc; + uint64_t lookup = m_crcTable[index]; + + crc >>= 8; + crc ^= lookup; + } + + return crc; +} + + From fd8c9c41ebab634a03c2915b3e4271a0556609af Mon Sep 17 00:00:00 2001 From: f4exb Date: Mon, 25 Jan 2016 08:40:44 +0100 Subject: [PATCH 04/51] SDRdaemon plugin: added samples buffer to the SDRdaemon buffer class --- plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h b/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h index 4a8e0de6a..01757f8ac 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h +++ b/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h @@ -22,6 +22,7 @@ #include #include #include "util/CRC64.h" +#include "dsp/samplefifo.h" class SDRdaemonBuffer { @@ -87,6 +88,7 @@ private: uint32_t m_nbCRCOK; uint64_t m_dataCRC; + SampleVector m_convertBuffer; }; From 458767aa45c1783e269609dd61230a7f5262ccab Mon Sep 17 00:00:00 2001 From: f4exb Date: Tue, 26 Jan 2016 08:27:45 +0100 Subject: [PATCH 05/51] SDRdaemon plugin: changed sample buffer to raw format (uint8_t) --- .../sdrdaemon/sdrdaemonbuffer.cpp | 21 +++++++++++++++---- .../samplesource/sdrdaemon/sdrdaemonbuffer.h | 17 +++++++++------ 2 files changed, 28 insertions(+), 10 deletions(-) diff --git a/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.cpp b/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.cpp index a468eaa1f..8017e630f 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.cpp +++ b/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.cpp @@ -31,7 +31,11 @@ SDRdaemonBuffer::SDRdaemonBuffer(std::size_t blockSize) : m_nbDecodes(0), m_nbSuccessfulDecodes(0), m_nbCRCOK(0), - m_dataCRC(0) + m_dataCRC(0), + m_sampleRate(1000000), + m_sampleBytes(2), + m_sampleBits(12), + m_rawBuffer(0) { m_buf = new uint8_t[blockSize]; m_currentMeta.init(); @@ -39,6 +43,10 @@ SDRdaemonBuffer::SDRdaemonBuffer(std::size_t blockSize) : SDRdaemonBuffer::~SDRdaemonBuffer() { + if (m_rawBuffer) { + delete[] m_rawBuffer; + } + delete[] m_buf; } @@ -210,6 +218,14 @@ void SDRdaemonBuffer::updateSizes(MetaData *metaData) m_lz4InCount = 0; } +void SDRdaemonBuffer::updateBufferSize() +{ + if (m_rawBuffer) { + delete[] m_rawBuffer; + } + + m_rawBuffer = new uint8_t[m_sampleRate * 2 * m_sampleBytes]; // store 1 second of samples +} void SDRdaemonBuffer::printMeta(MetaData *metaData) { @@ -227,6 +243,3 @@ void SDRdaemonBuffer::printMeta(MetaData *metaData) << std::endl; } - - - diff --git a/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h b/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h index 01757f8ac..7f90e2168 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h +++ b/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h @@ -69,6 +69,7 @@ public: private: bool writeAndReadLZ4(uint8_t *array, std::size_t length, uint8_t *data, std::size_t& dataLength); void updateSizes(MetaData *metaData); + void updateBufferSize(); void printMeta(MetaData *metaData); std::size_t m_blockSize; //!< UDP block (payload) size @@ -78,17 +79,21 @@ private: CRC64 m_crc64; //!< CRC64 calculator uint8_t *m_buf; //!< UDP block buffer - uint8_t *m_lz4InBuffer; //!< Buffer for LZ4 compressed input - uint32_t m_lz4InCount; //!< Current position in LZ4 input buffer - uint32_t m_lz4InSize; //!< Size in bytes of the LZ4 input data - uint8_t *m_lz4OutBuffer; //!< Buffer for LZ4 uncompressed output - uint32_t m_lz4OutSize; //!< Size in bytes of the LZ4 output data (original uncomressed data) + uint8_t *m_lz4InBuffer; //!< Buffer for LZ4 compressed input + uint32_t m_lz4InCount; //!< Current position in LZ4 input buffer + uint32_t m_lz4InSize; //!< Size in bytes of the LZ4 input data + uint8_t *m_lz4OutBuffer; //!< Buffer for LZ4 uncompressed output + uint32_t m_lz4OutSize; //!< Size in bytes of the LZ4 output data (original uncomressed data) uint32_t m_nbDecodes; uint32_t m_nbSuccessfulDecodes; uint32_t m_nbCRCOK; uint64_t m_dataCRC; - SampleVector m_convertBuffer; + uint32_t m_sampleRate; //!< Current sample rate in Hz + uint8_t m_sampleBytes; //!< Current number of bytes per I or Q sample + uint8_t m_sampleBits; //!< Current number of effective bits per sample + + uint8_t *m_rawBuffer; //!< Buffer for raw samples obtained from UDP (I/Q not in a formal I/Q structure) }; From 34138dc1c45802f6d93b2ba5002fa13facb48b68 Mon Sep 17 00:00:00 2001 From: f4exb Date: Tue, 26 Jan 2016 23:48:52 +0100 Subject: [PATCH 06/51] Removed methods taken from gd-sdmnsource --- .../sdrdaemon/sdrdaemonbuffer.cpp | 50 +++++------- .../samplesource/sdrdaemon/sdrdaemonbuffer.h | 8 +- .../sdrdaemon/sdrdaemonthread.cpp | 78 ++++++++++++++++--- .../samplesource/sdrdaemon/sdrdaemonthread.h | 18 ++++- 4 files changed, 105 insertions(+), 49 deletions(-) diff --git a/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.cpp b/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.cpp index 8017e630f..e81b4863e 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.cpp +++ b/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.cpp @@ -38,6 +38,7 @@ SDRdaemonBuffer::SDRdaemonBuffer(std::size_t blockSize) : m_rawBuffer(0) { m_buf = new uint8_t[blockSize]; + updateBufferSize(); m_currentMeta.init(); } @@ -50,19 +51,18 @@ SDRdaemonBuffer::~SDRdaemonBuffer() delete[] m_buf; } -bool SDRdaemonBuffer::writeAndRead(uint8_t *array, std::size_t length, uint8_t *data, std::size_t& dataLength) +bool SDRdaemonBuffer::readMeta(char *array, std::size_t length) { - assert(length == m_blockSize); // TODO: allow fragmented blocks with larger size + assert(length >= sizeof(MetaData) + 8); MetaData *metaData = (MetaData *) array; - if (m_crc64.calculate_crc(array, sizeof(MetaData) - 8) == metaData->m_crc) + if (m_crc64.calculate_crc((uint8_t *)array, sizeof(MetaData) - 8) == metaData->m_crc) { - dataLength = 0; memcpy((void *) &m_dataCRC, (const void *) &array[sizeof(MetaData)], 8); if (!(m_currentMeta == *metaData)) { - std::cerr << "SDRdaemonBuffer::writeAndRead: "; + std::cerr << "SDRdaemonBuffer::readMeta: "; printMeta(metaData); } @@ -74,7 +74,7 @@ bool SDRdaemonBuffer::writeAndRead(uint8_t *array, std::size_t length, uint8_t * if (metaData->m_sampleBytes & 0x10) { m_lz4 = true; - updateSizes(metaData); + updateLZ4Sizes(metaData); } else { @@ -87,38 +87,30 @@ bool SDRdaemonBuffer::writeAndRead(uint8_t *array, std::size_t length, uint8_t * { m_sync = false; } - - return false; } - else + + return m_sync; +} + +void SDRdaemonBuffer::writeData(char *array, std::size_t length) +{ + if (m_sync) { - if (m_sync) + if (m_lz4) { - if (m_lz4) - { - return writeAndReadLZ4(array, length, data, dataLength); - } - else - { - std::memcpy((void *) data, (const void *) array, length); - dataLength = length; - return true; - } + writeDataLZ4(array, length); } else { - dataLength = 0; - return false; + // TODO: uncompressed case } } } -bool SDRdaemonBuffer::writeAndReadLZ4(uint8_t *array, std::size_t length, uint8_t *data, std::size_t& dataLength) +void SDRdaemonBuffer::writeDataLZ4(char *array, std::size_t length) { if (m_lz4InCount + length < m_lz4InSize) { - std::memcpy((void *) &m_lz4InBuffer[m_lz4InCount], (const void *) array, length); // copy data in compressed Buffer - dataLength = 0; m_lz4InCount += length; } else @@ -162,8 +154,6 @@ bool SDRdaemonBuffer::writeAndReadLZ4(uint8_t *array, std::size_t length, uint8_ << " out: " << m_lz4OutSize << std::endl; */ - std::memcpy((void *) data, (const void *) m_lz4OutBuffer, m_lz4OutSize); // send what is in buffer - dataLength = m_lz4OutSize; m_nbSuccessfulDecodes++; } else @@ -176,8 +166,6 @@ bool SDRdaemonBuffer::writeAndReadLZ4(uint8_t *array, std::size_t length, uint8_ //if (compressedSize > 0) //{ - std::memcpy((void *) data, (const void *) m_lz4OutBuffer, m_lz4OutSize); // send what is in buffer - dataLength = m_lz4OutSize; //} //else //{ @@ -187,11 +175,9 @@ bool SDRdaemonBuffer::writeAndReadLZ4(uint8_t *array, std::size_t length, uint8_ m_lz4InCount = 0; } - - return dataLength != 0; } -void SDRdaemonBuffer::updateSizes(MetaData *metaData) +void SDRdaemonBuffer::updateLZ4Sizes(MetaData *metaData) { m_lz4InSize = metaData->m_nbBytes; // compressed input size uint32_t sampleBytes = metaData->m_sampleBytes & 0x0F; diff --git a/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h b/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h index 7f90e2168..38f53f9f1 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h +++ b/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h @@ -63,12 +63,14 @@ public: SDRdaemonBuffer(std::size_t blockSize); ~SDRdaemonBuffer(); - bool writeAndRead(uint8_t *array, std::size_t length, uint8_t *data, std::size_t& dataLength); + bool readMeta(char *array, std::size_t length); //!< Attempt to read meta. Returns true if meta block + void writeData(char *array, std::size_t length); //!< Write data into buffer. const MetaData& getCurrentMeta() const { return m_currentMeta; } + bool isSync() const { return m_sync; } private: - bool writeAndReadLZ4(uint8_t *array, std::size_t length, uint8_t *data, std::size_t& dataLength); - void updateSizes(MetaData *metaData); + void updateLZ4Sizes(MetaData *metaData); + void writeDataLZ4(char *array, std::size_t length); void updateBufferSize(); void printMeta(MetaData *metaData); diff --git a/plugins/samplesource/sdrdaemon/sdrdaemonthread.cpp b/plugins/samplesource/sdrdaemon/sdrdaemonthread.cpp index 4a261a2f9..91cc84ba6 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemonthread.cpp +++ b/plugins/samplesource/sdrdaemon/sdrdaemonthread.cpp @@ -18,24 +18,33 @@ #include #include #include "dsp/samplefifo.h" +#include #include #include "sdrdaemonthread.h" const int SDRdaemonThread::m_rateDivider = 1000/SDRDAEMON_THROTTLE_MS; +const int SDRdaemonThread::m_udpPayloadSize = 512; SDRdaemonThread::SDRdaemonThread(std::ifstream *samplesStream, SampleFifo* sampleFifo, QObject* parent) : QThread(parent), m_running(false), + m_dataSocket(0), + m_dataAddress(QHostAddress::LocalHost), + m_dataPort(9090), + m_dataConnected(false), m_ifstream(samplesStream), m_buf(0), + m_udpBuf(0), m_bufsize(0), m_chunksize(0), m_sampleFifo(sampleFifo), m_samplesCount(0), + m_sdrDaemonBuffer(m_udpPayloadSize), m_samplerate(0) { assert(m_ifstream != 0); + m_udpBuf = new char[m_udpPayloadSize]; } SDRdaemonThread::~SDRdaemonThread() @@ -44,6 +53,10 @@ SDRdaemonThread::~SDRdaemonThread() stopWork(); } + if (m_udpBuf != 0) { + free(m_udpBuf); + } + if (m_buf != 0) { free(m_buf); } @@ -52,30 +65,48 @@ SDRdaemonThread::~SDRdaemonThread() void SDRdaemonThread::startWork() { qDebug() << "SDRdaemonThread::startWork: "; + + if (!m_dataSocket) { + m_dataSocket = new QUdpSocket(this); + } - if (m_ifstream->is_open()) - { - qDebug() << " - file stream open, starting..."; - m_startWaitMutex.lock(); - start(); - while(!m_running) - m_startWaiter.wait(&m_startWaitMutex, 100); - m_startWaitMutex.unlock(); - } + if (m_dataSocket->bind(m_dataAddress, m_dataPort)) + { + qDebug("SDRdaemonThread::startWork: bind data socket to port %d", m_dataPort); + connect(m_dataSocket, SIGNAL(readyRead()), this, SLOT(dataReadyRead())); + + m_startWaitMutex.lock(); + start(); + while(!m_running) + m_startWaiter.wait(&m_startWaitMutex, 100); + m_startWaitMutex.unlock(); + m_dataConnected = true; + } else { - qDebug() << " - file stream closed, not starting."; + qWarning("SDRdaemonThread::startWork: cannot bind data port %d", m_dataPort); + m_dataConnected = false; } } void SDRdaemonThread::stopWork() { qDebug() << "SDRdaemonThread::stopWork"; + + if (m_dataConnected) { + disconnect(m_dataSocket, SIGNAL(readyRead()), this, SLOT(dataReadyRead())); + } + + if (m_dataSocket) { + delete m_dataSocket; + m_dataSocket = 0; + } + m_running = false; wait(); } -void SDRdaemonThread::setSamplerate(int samplerate) +void SDRdaemonThread::setSamplerate(uint32_t samplerate) { qDebug() << "SDRdaemonThread::setSamplerate:" << " new:" << samplerate @@ -151,3 +182,28 @@ void SDRdaemonThread::tick() } } } + +void SDRdaemonThread::dataReadyRead() +{ + while (m_dataSocket->hasPendingDatagrams()) + { + qint64 pendingDataSize = m_dataSocket->pendingDatagramSize(); + qint64 readBytes = m_dataSocket->readDatagram(m_udpBuf, pendingDataSize, 0, 0); + + if (readBytes < 0) + { + qDebug() << "SDRdaemonThread::dataReadyRead: read failed"; + } + else if (readBytes > 0) + { + if (m_sdrDaemonBuffer.readMeta(m_udpBuf, readBytes)) + { + setSamplerate(m_sdrDaemonBuffer.getCurrentMeta().m_sampleRate); + } + else if (m_sdrDaemonBuffer.isSync()) + { + m_sdrDaemonBuffer.writeData(m_udpBuf, readBytes); + } + } + } +} diff --git a/plugins/samplesource/sdrdaemon/sdrdaemonthread.h b/plugins/samplesource/sdrdaemon/sdrdaemonthread.h index 3464a095e..c1b1d1b30 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemonthread.h +++ b/plugins/samplesource/sdrdaemon/sdrdaemonthread.h @@ -21,12 +21,14 @@ #include #include #include +#include #include #include #include #include "dsp/samplefifo.h" #include "dsp/inthalfbandfilter.h" +#include "sdrdaemonbuffer.h" #define SDRDAEMON_THROTTLE_MS 50 @@ -41,12 +43,15 @@ public: void startWork(); void stopWork(); - void setSamplerate(int samplerate); + void setSamplerate(uint32_t samplerate); bool isRunning() const { return m_running; } std::size_t getSamplesCount() const { return m_samplesCount; } void connectTimer(const QTimer& timer); +public slots: + void dataReadyRead(); + private: QMutex m_startWaitMutex; QWaitCondition m_startWaiter; @@ -54,14 +59,21 @@ private: std::ifstream* m_ifstream; QUdpSocket *m_dataSocket; - quint8 *m_buf; + QHostAddress m_dataAddress; + int m_dataPort; + bool m_dataConnected; + quint8 *m_buf; + char *m_udpBuf; std::size_t m_bufsize; std::size_t m_chunksize; SampleFifo* m_sampleFifo; std::size_t m_samplesCount; - int m_samplerate; + SDRdaemonBuffer m_sdrDaemonBuffer; + + uint32_t m_samplerate; static const int m_rateDivider; + static const int m_udpPayloadSize; void run(); private slots: From 2fe57dabaecc4b461fdc41ca976d730027b6c43b Mon Sep 17 00:00:00 2001 From: f4exb Date: Wed, 27 Jan 2016 08:24:00 +0100 Subject: [PATCH 07/51] SDRdaemon: revised buffers allocation --- .../sdrdaemon/sdrdaemonbuffer.cpp | 70 +++++++++++-------- .../samplesource/sdrdaemon/sdrdaemonbuffer.h | 7 +- 2 files changed, 44 insertions(+), 33 deletions(-) diff --git a/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.cpp b/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.cpp index e81b4863e..6e4ee3e1e 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.cpp +++ b/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.cpp @@ -27,7 +27,7 @@ SDRdaemonBuffer::SDRdaemonBuffer(std::size_t blockSize) : m_lz4InCount(0), m_lz4InSize(0), m_lz4OutBuffer(0), - m_lz4OutSize(0), + m_frameSize(0), m_nbDecodes(0), m_nbSuccessfulDecodes(0), m_nbCRCOK(0), @@ -37,8 +37,6 @@ SDRdaemonBuffer::SDRdaemonBuffer(std::size_t blockSize) : m_sampleBits(12), m_rawBuffer(0) { - m_buf = new uint8_t[blockSize]; - updateBufferSize(); m_currentMeta.init(); } @@ -48,7 +46,9 @@ SDRdaemonBuffer::~SDRdaemonBuffer() delete[] m_rawBuffer; } - delete[] m_buf; + if (m_lz4InBuffer) { + delete[] m_lz4InBuffer; + } } bool SDRdaemonBuffer::readMeta(char *array, std::size_t length) @@ -71,16 +71,31 @@ bool SDRdaemonBuffer::readMeta(char *array, std::size_t length) // sanity checks if (metaData->m_blockSize == m_blockSize) // sent blocksize matches given blocksize { + uint32_t sampleBytes = metaData->m_sampleBytes & 0x0F; + uint32_t frameSize = sampleBytes * 2 * metaData->m_nbSamples * metaData->m_nbBlocks; + if (metaData->m_sampleBytes & 0x10) { m_lz4 = true; - updateLZ4Sizes(metaData); + m_lz4InSize = metaData->m_nbBytes; // compressed input size + m_lz4InCount = 0; + + if (frameSize != m_frameSize) + { + updateLZ4Sizes(frameSize); + } } else { m_lz4 = false; } + if (frameSize != m_frameSize) + { + updateBufferSize(frameSize); + } + + m_frameSize = frameSize; m_sync = true; } else @@ -142,7 +157,7 @@ void SDRdaemonBuffer::writeDataLZ4(char *array, std::size_t length) m_nbCRCOK++; } - int compressedSize = LZ4_decompress_fast((const char*) m_lz4InBuffer, (char*) m_lz4OutBuffer, m_lz4OutSize); + int compressedSize = LZ4_decompress_fast((const char*) m_lz4InBuffer, (char*) m_lz4OutBuffer, m_frameSize); m_nbDecodes++; if (compressedSize == m_lz4InSize) @@ -177,40 +192,37 @@ void SDRdaemonBuffer::writeDataLZ4(char *array, std::size_t length) } } -void SDRdaemonBuffer::updateLZ4Sizes(MetaData *metaData) +void SDRdaemonBuffer::updateLZ4Sizes(uint32_t frameSize) { - m_lz4InSize = metaData->m_nbBytes; // compressed input size - uint32_t sampleBytes = metaData->m_sampleBytes & 0x0F; - uint32_t originalSize = sampleBytes * 2 * metaData->m_nbSamples * metaData->m_nbBlocks; + uint32_t masInputSize = LZ4_compressBound(frameSize); - if (originalSize != m_lz4OutSize) - { - uint32_t masInputSize = LZ4_compressBound(originalSize); - - if (m_lz4InBuffer) { - delete[] m_lz4InBuffer; - } - - m_lz4InBuffer = new uint8_t[m_lz4InSize]; // provide extra space for a full UDP block - - if (m_lz4OutBuffer) { - delete[] m_lz4OutBuffer; - } - - m_lz4OutBuffer = new uint8_t[originalSize]; - m_lz4OutSize = originalSize; + if (m_lz4InBuffer) { + delete[] m_lz4InBuffer; } - m_lz4InCount = 0; + m_lz4InBuffer = new uint8_t[m_lz4InSize]; // provide extra space for a full UDP block + + if (m_lz4OutBuffer) { + delete[] m_lz4OutBuffer; + } + + m_lz4OutBuffer = new uint8_t[frameSize]; } -void SDRdaemonBuffer::updateBufferSize() +void SDRdaemonBuffer::updateBufferSize(uint32_t frameSize) { + uint32_t nbFrames = ((m_sampleRate * 2 * m_sampleBytes) / frameSize) + 1; // store at least 1 second of samples + + std::cerr << "SDRdaemonBuffer::updateBufferSize:" + << " frameSize: " << frameSize + << " nbFrames: " << nbFrames + << std::endl; + if (m_rawBuffer) { delete[] m_rawBuffer; } - m_rawBuffer = new uint8_t[m_sampleRate * 2 * m_sampleBytes]; // store 1 second of samples + m_rawBuffer = new uint8_t[nbFrames * frameSize]; } void SDRdaemonBuffer::printMeta(MetaData *metaData) diff --git a/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h b/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h index 38f53f9f1..5aa80202a 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h +++ b/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h @@ -69,9 +69,9 @@ public: bool isSync() const { return m_sync; } private: - void updateLZ4Sizes(MetaData *metaData); + void updateLZ4Sizes(uint32_t frameSize); void writeDataLZ4(char *array, std::size_t length); - void updateBufferSize(); + void updateBufferSize(uint32_t frameSize); void printMeta(MetaData *metaData); std::size_t m_blockSize; //!< UDP block (payload) size @@ -79,13 +79,12 @@ private: bool m_lz4; //!< Stream is compressed with LZ4 MetaData m_currentMeta; //!< Stored current meta data CRC64 m_crc64; //!< CRC64 calculator - uint8_t *m_buf; //!< UDP block buffer uint8_t *m_lz4InBuffer; //!< Buffer for LZ4 compressed input uint32_t m_lz4InCount; //!< Current position in LZ4 input buffer uint32_t m_lz4InSize; //!< Size in bytes of the LZ4 input data uint8_t *m_lz4OutBuffer; //!< Buffer for LZ4 uncompressed output - uint32_t m_lz4OutSize; //!< Size in bytes of the LZ4 output data (original uncomressed data) + uint32_t m_frameSize; //!< Size in bytes of one uncompressed frame uint32_t m_nbDecodes; uint32_t m_nbSuccessfulDecodes; uint32_t m_nbCRCOK; From 13d698a9401c26192ce66178faecba90161b2077 Mon Sep 17 00:00:00 2001 From: f4exb Date: Wed, 27 Jan 2016 08:40:54 +0100 Subject: [PATCH 08/51] SDRdaemon: updated write data to raw buffer methods --- .../sdrdaemon/sdrdaemonbuffer.cpp | 45 +++++++++---------- .../samplesource/sdrdaemon/sdrdaemonbuffer.h | 3 ++ 2 files changed, 24 insertions(+), 24 deletions(-) diff --git a/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.cpp b/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.cpp index 6e4ee3e1e..7d1db9254 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.cpp +++ b/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.cpp @@ -117,15 +117,35 @@ void SDRdaemonBuffer::writeData(char *array, std::size_t length) } else { - // TODO: uncompressed case + writeDataUncompressed(array, length); } } } +void SDRdaemonBuffer::writeDataUncompressed(char *array, std::size_t length) +{ + if (m_inCount + length < m_frameSize) + { + std::memcpy((void *) &m_rawBuffer[m_inCount], (const void *) array, length); + m_inCount += length; + } + else + { + std::memcpy((void *) &m_rawBuffer[m_inCount], (const void *) array, m_frameSize - m_inCount); // copy rest of data in compressed Buffer + m_inCount += length; + } + + if (m_inCount >= m_frameSize) // full block retrieved + { + // TODO: to do? + } +} + void SDRdaemonBuffer::writeDataLZ4(char *array, std::size_t length) { if (m_lz4InCount + length < m_lz4InSize) { + std::memcpy((void *) &m_lz4InBuffer[m_lz4InCount], (const void *) array, length); m_lz4InCount += length; } else @@ -162,31 +182,8 @@ void SDRdaemonBuffer::writeDataLZ4(char *array, std::size_t length) if (compressedSize == m_lz4InSize) { - /* - std::cerr << "SDRdaemonBuffer::writeAndReadLZ4: decoding OK:" - << " read: " << compressedSize - << " expected: " << m_lz4InSize - << " out: " << m_lz4OutSize - << std::endl; - */ m_nbSuccessfulDecodes++; } - else - { -// std::cerr << "SDRdaemonBuffer::writeAndReadLZ4: decoding error:" -// << " read: " << compressedSize -// << " expected: " << m_lz4InSize -// << " out: " << m_lz4OutSize -// << std::endl; - - //if (compressedSize > 0) - //{ - //} - //else - //{ - // dataLength = 0; - //} - } m_lz4InCount = 0; } diff --git a/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h b/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h index 5aa80202a..b88dc0ace 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h +++ b/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h @@ -71,6 +71,7 @@ public: private: void updateLZ4Sizes(uint32_t frameSize); void writeDataLZ4(char *array, std::size_t length); + void writeDataUncompressed(char *array, std::size_t length); void updateBufferSize(uint32_t frameSize); void printMeta(MetaData *metaData); @@ -80,6 +81,7 @@ private: MetaData m_currentMeta; //!< Stored current meta data CRC64 m_crc64; //!< CRC64 calculator + uint32_t m_inCount; //!< Current position of uncompressed input uint8_t *m_lz4InBuffer; //!< Buffer for LZ4 compressed input uint32_t m_lz4InCount; //!< Current position in LZ4 input buffer uint32_t m_lz4InSize; //!< Size in bytes of the LZ4 input data @@ -94,6 +96,7 @@ private: uint8_t m_sampleBytes; //!< Current number of bytes per I or Q sample uint8_t m_sampleBits; //!< Current number of effective bits per sample + uint32_t m_rawCount; //!< Current position in the raw samples buffer uint8_t *m_rawBuffer; //!< Buffer for raw samples obtained from UDP (I/Q not in a formal I/Q structure) }; From ca7d8de81e32d781cedb8f19348688b4eebb605e Mon Sep 17 00:00:00 2001 From: f4exb Date: Thu, 28 Jan 2016 03:30:36 +0100 Subject: [PATCH 09/51] SDRdaemon plugin: added counters for data received from UDP --- include/gui/scopewindow.h | 67 ------ .../sdrdaemon/sdrdaemonbuffer.cpp | 12 +- .../samplesource/sdrdaemon/sdrdaemonbuffer.h | 3 + sdrbase/gui/scopewindow.cpp | 192 ------------------ 4 files changed, 14 insertions(+), 260 deletions(-) delete mode 100644 include/gui/scopewindow.h delete mode 100644 sdrbase/gui/scopewindow.cpp diff --git a/include/gui/scopewindow.h b/include/gui/scopewindow.h deleted file mode 100644 index 59c2d7d6e..000000000 --- a/include/gui/scopewindow.h +++ /dev/null @@ -1,67 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////////// -// Copyright (C) 2012 maintech GmbH, Otto-Hahn-Str. 15, 97204 Hoechberg, Germany // -// written by Christian Daniel // -// // -// 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 INCLUDE_SCOPEWINDOW_H -#define INCLUDE_SCOPEWINDOW_H - -#include -#include "dsp/dsptypes.h" -#include "util/export.h" - -class DSPEngine; - -namespace Ui { - class ScopeWindow; -} - -class SDRANGEL_API ScopeWindow : public QWidget { - Q_OBJECT - -public: - explicit ScopeWindow(DSPEngine* dspEngine, QWidget* parent = NULL); - ~ScopeWindow(); - - void setSampleRate(int sampleRate); - - void resetToDefaults(); - QByteArray serialize() const; - bool deserialize(const QByteArray& data); - -private slots: - void on_amp_valueChanged(int value); - void on_scope_traceSizeChanged(int value); - void on_time_valueChanged(int value); - void on_timeOfs_valueChanged(int value); - void on_displayMode_currentIndexChanged(int index); - - void on_horizView_clicked(); - void on_vertView_clicked(); - -private: - Ui::ScopeWindow *ui; - int m_sampleRate; - - qint32 m_displayData; - qint32 m_displayOrientation; - qint32 m_timeBase; - qint32 m_timeOffset; - qint32 m_amplification; - - void applySettings(); -}; - -#endif // INCLUDE_SCOPEWINDOW_H diff --git a/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.cpp b/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.cpp index 7d1db9254..d7d9927dd 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.cpp +++ b/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.cpp @@ -35,7 +35,9 @@ SDRdaemonBuffer::SDRdaemonBuffer(std::size_t blockSize) : m_sampleRate(1000000), m_sampleBytes(2), m_sampleBits(12), - m_rawBuffer(0) + m_rawBuffer(0), + m_bytesInBlock(0), + m_nbBlocks(0) { m_currentMeta.init(); } @@ -55,10 +57,12 @@ bool SDRdaemonBuffer::readMeta(char *array, std::size_t length) { assert(length >= sizeof(MetaData) + 8); MetaData *metaData = (MetaData *) array; + updateBlockCounts(length); if (m_crc64.calculate_crc((uint8_t *)array, sizeof(MetaData) - 8) == metaData->m_crc) { memcpy((void *) &m_dataCRC, (const void *) &array[sizeof(MetaData)], 8); + m_nbBlocks = 0; if (!(m_currentMeta == *metaData)) { @@ -222,6 +226,12 @@ void SDRdaemonBuffer::updateBufferSize(uint32_t frameSize) m_rawBuffer = new uint8_t[nbFrames * frameSize]; } +void SDRdaemonBuffer::updateBlockCounts(uint32_t nbBytesReceived) +{ + m_nbBlocks += m_bytesInBlock + nbBytesReceived > m_blockSize ? 1 : 0; + m_bytesInBlock = m_bytesInBlock + nbBytesReceived > m_blockSize ? nbBytesReceived : m_bytesInBlock + nbBytesReceived; +} + void SDRdaemonBuffer::printMeta(MetaData *metaData) { std::cerr diff --git a/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h b/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h index b88dc0ace..2ce6d1daf 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h +++ b/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h @@ -73,6 +73,7 @@ private: void writeDataLZ4(char *array, std::size_t length); void writeDataUncompressed(char *array, std::size_t length); void updateBufferSize(uint32_t frameSize); + void updateBlockCounts(uint32_t nbBytesReceived); void printMeta(MetaData *metaData); std::size_t m_blockSize; //!< UDP block (payload) size @@ -98,6 +99,8 @@ private: uint32_t m_rawCount; //!< Current position in the raw samples buffer uint8_t *m_rawBuffer; //!< Buffer for raw samples obtained from UDP (I/Q not in a formal I/Q structure) + uint32_t m_bytesInBlock; //!< Number of bytes received in the current UDP block + uint32_t m_nbBlocks; //!< Number of UDP blocks received in the current frame }; diff --git a/sdrbase/gui/scopewindow.cpp b/sdrbase/gui/scopewindow.cpp deleted file mode 100644 index 13f90777e..000000000 --- a/sdrbase/gui/scopewindow.cpp +++ /dev/null @@ -1,192 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////////// -// Copyright (C) 2012 maintech GmbH, Otto-Hahn-Str. 15, 97204 Hoechberg, Germany // -// written by Christian Daniel // -// // -// 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 . // -/////////////////////////////////////////////////////////////////////////////////// - -#include "gui/scopewindow.h" -#include "ui_scopewindow.h" -#include "util/simpleserializer.h" - -ScopeWindow::ScopeWindow(DSPEngine* dspEngine, QWidget* parent) : - QWidget(parent), - ui(new Ui::ScopeWindow), - m_sampleRate(0), - m_timeBase(1) -{ - ui->setupUi(this); - ui->scope->setDSPEngine(dspEngine); -} - -ScopeWindow::~ScopeWindow() -{ - delete ui; -} - -void ScopeWindow::setSampleRate(int sampleRate) -{ - m_sampleRate = sampleRate; - on_scope_traceSizeChanged(0); -} - -void ScopeWindow::resetToDefaults() -{ - m_displayData = GLScope::ModeIQ; - m_displayOrientation = Qt::Horizontal; - m_timeBase = 1; - m_timeOffset = 0; - m_amplification = 0; - applySettings(); -} - -QByteArray ScopeWindow::serialize() const -{ - SimpleSerializer s(1); -#if 0 - s.writeS32(1, m_displayData); - s.writeS32(2, m_displayOrientation); - s.writeS32(3, m_timeBase); - s.writeS32(4, m_timeOffset); - s.writeS32(5, m_amplification); -#endif - return s.final(); -} - -bool ScopeWindow::deserialize(const QByteArray& data) -{ -#if 0 - SimpleDeserializer d(data); - - if(!d.isValid()) { - resetToDefaults(); - return false; - } - - if(d.getVersion() == 1) { - d.readS32(1, &m_displayData, GLScope::ModeIQ); - d.readS32(2, &m_displayOrientation, Qt::Horizontal); - d.readS32(3, &m_timeBase, 1); - d.readS32(4, &m_timeOffset, 0); - d.readS32(5, &m_amplification, 0); - if(m_timeBase < 0) - m_timeBase = 1; - applySettings(); - return true; - } else { - resetToDefaults(); - return false; - } -#else - resetToDefaults(); - return false; -#endif -} - -void ScopeWindow::on_amp_valueChanged(int value) -{ - static qreal amps[11] = { 0.2, 0.1, 0.05, 0.02, 0.01, 0.005, 0.002, 0.001, 0.0005, 0.0002, 0.0001 }; - ui->ampText->setText(tr("%1\n/div").arg(amps[value], 0, 'f', 4)); - ui->scope->setAmp(0.2 / amps[value]); - m_amplification = value; -} - -void ScopeWindow::on_scope_traceSizeChanged(int) -{ - qreal t = (ui->scope->getTraceSize() * 0.1 / m_sampleRate) / (qreal)m_timeBase; - if(t < 0.000001) - ui->timeText->setText(tr("%1\nns/div").arg(t * 1000000000.0)); - else if(t < 0.001) - ui->timeText->setText(tr("%1\nµs/div").arg(t * 1000000.0)); - else if(t < 1.0) - ui->timeText->setText(tr("%1\nms/div").arg(t * 1000.0)); - else ui->timeText->setText(tr("%1\ns/div").arg(t * 1.0)); -} - -void ScopeWindow::on_time_valueChanged(int value) -{ - m_timeBase = value; - on_scope_traceSizeChanged(0); - ui->scope->setTimeBase(m_timeBase); -} - -void ScopeWindow::on_timeOfs_valueChanged(int value) -{ - m_timeOffset = value; - ui->scope->setTimeOfsProMill(value); -} - -void ScopeWindow::on_displayMode_currentIndexChanged(int index) -{ - m_displayData = index; - switch(index) { - case 0: // i+q - ui->scope->setMode(GLScope::ModeIQ); - break; - case 1: // mag(lin)+pha - ui->scope->setMode(GLScope::ModeMagLinPha); - break; - case 2: // mag(dB)+pha - ui->scope->setMode(GLScope::ModeMagdBPha); - break; - case 3: // derived1+derived2 - ui->scope->setMode(GLScope::ModeDerived12); - break; - case 4: // clostationary - ui->scope->setMode(GLScope::ModeCyclostationary); - break; - - default: - break; - } -} - -void ScopeWindow::on_horizView_clicked() -{ - m_displayOrientation = Qt::Horizontal; - if(ui->horizView->isChecked()) { - ui->vertView->setChecked(false); - ui->scope->setOrientation(Qt::Horizontal); - } else { - ui->horizView->setChecked(true); - } -} - -void ScopeWindow::on_vertView_clicked() -{ - m_displayOrientation = Qt::Vertical; - if(ui->vertView->isChecked()) { - ui->horizView->setChecked(false); - ui->scope->setOrientation(Qt::Vertical); - } else { - ui->vertView->setChecked(true); - ui->scope->setOrientation(Qt::Vertical); - } -} - -void ScopeWindow::applySettings() -{ - ui->displayMode->setCurrentIndex(m_displayData); - if(m_displayOrientation == Qt::Horizontal) { - ui->scope->setOrientation(Qt::Horizontal); - ui->horizView->setChecked(true); - ui->vertView->setChecked(false); - } else { - ui->scope->setOrientation(Qt::Vertical); - ui->horizView->setChecked(false); - ui->vertView->setChecked(true); - } - ui->time->setValue(m_timeBase); - ui->timeOfs->setValue(m_timeOffset); - ui->amp->setValue(m_amplification); -} From e9058a1c94b072dd56487ada550f346e4c074b18 Mon Sep 17 00:00:00 2001 From: f4exb Date: Thu, 28 Jan 2016 04:54:16 +0100 Subject: [PATCH 10/51] SDRdaemon plugin: handle data writes --- .../sdrdaemon/sdrdaemonbuffer.cpp | 81 +++++++++++++------ .../samplesource/sdrdaemon/sdrdaemonbuffer.h | 18 +++-- .../sdrdaemon/sdrdaemonthread.cpp | 2 + 3 files changed, 71 insertions(+), 30 deletions(-) diff --git a/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.cpp b/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.cpp index d7d9927dd..e850af437 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.cpp +++ b/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.cpp @@ -19,10 +19,11 @@ #include #include "sdrdaemonbuffer.h" -SDRdaemonBuffer::SDRdaemonBuffer(std::size_t blockSize) : +SDRdaemonBuffer::SDRdaemonBuffer(uint32_t blockSize) : m_blockSize(blockSize), m_sync(false), m_lz4(false), + m_inCount(0), m_lz4InBuffer(0), m_lz4InCount(0), m_lz4InSize(0), @@ -35,6 +36,9 @@ SDRdaemonBuffer::SDRdaemonBuffer(std::size_t blockSize) : m_sampleRate(1000000), m_sampleBytes(2), m_sampleBits(12), + m_rawCount(0), + m_readCount(0), + m_rawSize(0), m_rawBuffer(0), m_bytesInBlock(0), m_nbBlocks(0) @@ -51,18 +55,22 @@ SDRdaemonBuffer::~SDRdaemonBuffer() if (m_lz4InBuffer) { delete[] m_lz4InBuffer; } + + if (m_lz4OutBuffer) { + delete[] m_lz4OutBuffer; + } } -bool SDRdaemonBuffer::readMeta(char *array, std::size_t length) +bool SDRdaemonBuffer::readMeta(char *array, uint32_t length) { assert(length >= sizeof(MetaData) + 8); MetaData *metaData = (MetaData *) array; - updateBlockCounts(length); if (m_crc64.calculate_crc((uint8_t *)array, sizeof(MetaData) - 8) == metaData->m_crc) { memcpy((void *) &m_dataCRC, (const void *) &array[sizeof(MetaData)], 8); m_nbBlocks = 0; + m_inCount = 0; if (!(m_currentMeta == *metaData)) { @@ -75,8 +83,8 @@ bool SDRdaemonBuffer::readMeta(char *array, std::size_t length) // sanity checks if (metaData->m_blockSize == m_blockSize) // sent blocksize matches given blocksize { - uint32_t sampleBytes = metaData->m_sampleBytes & 0x0F; - uint32_t frameSize = sampleBytes * 2 * metaData->m_nbSamples * metaData->m_nbBlocks; + m_sampleBytes = metaData->m_sampleBytes & 0x0F; + uint32_t frameSize = 2 * 2 * metaData->m_nbSamples * metaData->m_nbBlocks; if (metaData->m_sampleBytes & 0x10) { @@ -111,9 +119,9 @@ bool SDRdaemonBuffer::readMeta(char *array, std::size_t length) return m_sync; } -void SDRdaemonBuffer::writeData(char *array, std::size_t length) +void SDRdaemonBuffer::writeData(char *array, uint32_t length) { - if (m_sync) + if ((m_sync) && (m_nbBlocks > 0)) { if (m_lz4) { @@ -126,26 +134,21 @@ void SDRdaemonBuffer::writeData(char *array, std::size_t length) } } -void SDRdaemonBuffer::writeDataUncompressed(char *array, std::size_t length) +void SDRdaemonBuffer::writeDataUncompressed(const char *array, uint32_t length) { if (m_inCount + length < m_frameSize) { - std::memcpy((void *) &m_rawBuffer[m_inCount], (const void *) array, length); + std::memcpy((void *) &m_rawBuffer[m_rawCount], (const void *) array, length); m_inCount += length; } - else + else if (m_inCount < m_frameSize) { - std::memcpy((void *) &m_rawBuffer[m_inCount], (const void *) array, m_frameSize - m_inCount); // copy rest of data in compressed Buffer - m_inCount += length; - } - - if (m_inCount >= m_frameSize) // full block retrieved - { - // TODO: to do? + std::memcpy((void *) &m_rawBuffer[m_rawCount], (const void *) array, m_frameSize - m_inCount); // copy rest of data in compressed Buffer + m_inCount += m_frameSize - m_inCount; } } -void SDRdaemonBuffer::writeDataLZ4(char *array, std::size_t length) +void SDRdaemonBuffer::writeDataLZ4(const char *array, uint32_t length) { if (m_lz4InCount + length < m_lz4InSize) { @@ -181,7 +184,7 @@ void SDRdaemonBuffer::writeDataLZ4(char *array, std::size_t length) m_nbCRCOK++; } - int compressedSize = LZ4_decompress_fast((const char*) m_lz4InBuffer, (char*) m_lz4OutBuffer, m_frameSize); + int compressedSize = LZ4_decompress_fast((const char*) m_lz4InBuffer, (char*) &m_rawBuffer[m_rawCount], m_frameSize); m_nbDecodes++; if (compressedSize == m_lz4InSize) @@ -189,19 +192,50 @@ void SDRdaemonBuffer::writeDataLZ4(char *array, std::size_t length) m_nbSuccessfulDecodes++; } + writeToRawBufferLZ4((const char *) m_lz4InBuffer, m_frameSize); + m_lz4InCount = 0; } } +void SDRdaemonBuffer::writeToRawBufferUncompressed(const char *array, uint32_t length) +{ + // TODO: handle the 1 byte per I or Q sample + if (m_rawCount + length < m_rawSize) + { + std::memcpy((void *) &m_rawBuffer[m_rawCount], (const void *) array, length); + m_rawCount += length; + } + else + { + std::memcpy((void *) &m_rawBuffer[m_rawCount], (const void *) array, m_rawSize - m_rawCount); + m_rawCount = length - (m_rawSize - m_rawCount); + std::memcpy((void *) m_rawBuffer, (const void *) array, m_rawCount); + } +} + +void SDRdaemonBuffer::writeToRawBufferLZ4(const char *array, uint32_t length) +{ + int compressedSize = LZ4_decompress_fast((const char*) m_lz4InBuffer, (char*) m_lz4OutBuffer, m_frameSize); + m_nbDecodes++; + + if (compressedSize == m_lz4InSize) + { + m_nbSuccessfulDecodes++; + } + + writeToRawBufferUncompressed((const char *) m_lz4OutBuffer, m_frameSize); +} + void SDRdaemonBuffer::updateLZ4Sizes(uint32_t frameSize) { - uint32_t masInputSize = LZ4_compressBound(frameSize); + uint32_t maxInputSize = LZ4_compressBound(frameSize); if (m_lz4InBuffer) { delete[] m_lz4InBuffer; } - m_lz4InBuffer = new uint8_t[m_lz4InSize]; // provide extra space for a full UDP block + m_lz4InBuffer = new uint8_t[maxInputSize]; if (m_lz4OutBuffer) { delete[] m_lz4OutBuffer; @@ -212,7 +246,7 @@ void SDRdaemonBuffer::updateLZ4Sizes(uint32_t frameSize) void SDRdaemonBuffer::updateBufferSize(uint32_t frameSize) { - uint32_t nbFrames = ((m_sampleRate * 2 * m_sampleBytes) / frameSize) + 1; // store at least 1 second of samples + uint32_t nbFrames = ((m_sampleRate * 2 * 2) / frameSize) + 1; // store at least 1 second of samples std::cerr << "SDRdaemonBuffer::updateBufferSize:" << " frameSize: " << frameSize @@ -223,7 +257,8 @@ void SDRdaemonBuffer::updateBufferSize(uint32_t frameSize) delete[] m_rawBuffer; } - m_rawBuffer = new uint8_t[nbFrames * frameSize]; + m_rawSize = nbFrames * frameSize; + m_rawBuffer = new uint8_t[m_rawSize]; } void SDRdaemonBuffer::updateBlockCounts(uint32_t nbBytesReceived) diff --git a/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h b/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h index 2ce6d1daf..b1a613df7 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h +++ b/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h @@ -61,19 +61,21 @@ public: }; #pragma pack(pop) - SDRdaemonBuffer(std::size_t blockSize); + SDRdaemonBuffer(uint32_t blockSize); ~SDRdaemonBuffer(); - bool readMeta(char *array, std::size_t length); //!< Attempt to read meta. Returns true if meta block - void writeData(char *array, std::size_t length); //!< Write data into buffer. + bool readMeta(char *array, uint32_t length); //!< Attempt to read meta. Returns true if meta block + void writeData(char *array, uint32_t length); //!< Write data into buffer. const MetaData& getCurrentMeta() const { return m_currentMeta; } + void updateBlockCounts(uint32_t nbBytesReceived); bool isSync() const { return m_sync; } private: void updateLZ4Sizes(uint32_t frameSize); - void writeDataLZ4(char *array, std::size_t length); - void writeDataUncompressed(char *array, std::size_t length); + void writeDataLZ4(const char *array, uint32_t length); + void writeDataUncompressed(const char *array, uint32_t length); + void writeToRawBufferLZ4(const char *array, uint32_t originalLength); + void writeToRawBufferUncompressed(const char *array, uint32_t length); void updateBufferSize(uint32_t frameSize); - void updateBlockCounts(uint32_t nbBytesReceived); void printMeta(MetaData *metaData); std::size_t m_blockSize; //!< UDP block (payload) size @@ -97,7 +99,9 @@ private: uint8_t m_sampleBytes; //!< Current number of bytes per I or Q sample uint8_t m_sampleBits; //!< Current number of effective bits per sample - uint32_t m_rawCount; //!< Current position in the raw samples buffer + uint32_t m_rawCount; //!< Current write position in the raw samples buffer + uint32_t m_readCount; //!< Current read position in the raw samples buffer + uint32_t m_rawSize; //!< Size of the raw samples buffer in bytes uint8_t *m_rawBuffer; //!< Buffer for raw samples obtained from UDP (I/Q not in a formal I/Q structure) uint32_t m_bytesInBlock; //!< Number of bytes received in the current UDP block uint32_t m_nbBlocks; //!< Number of UDP blocks received in the current frame diff --git a/plugins/samplesource/sdrdaemon/sdrdaemonthread.cpp b/plugins/samplesource/sdrdaemon/sdrdaemonthread.cpp index 91cc84ba6..934b1c17b 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemonthread.cpp +++ b/plugins/samplesource/sdrdaemon/sdrdaemonthread.cpp @@ -196,6 +196,8 @@ void SDRdaemonThread::dataReadyRead() } else if (readBytes > 0) { + m_sdrDaemonBuffer.updateBlockCounts(readBytes); + if (m_sdrDaemonBuffer.readMeta(m_udpBuf, readBytes)) { setSamplerate(m_sdrDaemonBuffer.getCurrentMeta().m_sampleRate); From becf359db91545d84260469b9ed8849431705653 Mon Sep 17 00:00:00 2001 From: f4exb Date: Fri, 29 Jan 2016 08:17:34 +0100 Subject: [PATCH 11/51] SDRdaemon plugin: handle data reads --- .../sdrdaemon/sdrdaemonbuffer.cpp | 29 ++++++++++++++ .../samplesource/sdrdaemon/sdrdaemonbuffer.h | 2 + .../samplesource/sdrdaemon/sdrdaemoninput.cpp | 40 +------------------ .../samplesource/sdrdaemon/sdrdaemoninput.h | 3 -- .../sdrdaemon/sdrdaemonthread.cpp | 23 ++--------- .../samplesource/sdrdaemon/sdrdaemonthread.h | 4 +- 6 files changed, 36 insertions(+), 65 deletions(-) diff --git a/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.cpp b/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.cpp index e850af437..8aca1add3 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.cpp +++ b/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.cpp @@ -40,6 +40,7 @@ SDRdaemonBuffer::SDRdaemonBuffer(uint32_t blockSize) : m_readCount(0), m_rawSize(0), m_rawBuffer(0), + m_frameBuffer(0), m_bytesInBlock(0), m_nbBlocks(0) { @@ -59,6 +60,10 @@ SDRdaemonBuffer::~SDRdaemonBuffer() if (m_lz4OutBuffer) { delete[] m_lz4OutBuffer; } + + if (m_frameBuffer) { + delete[] m_frameBuffer; + } } bool SDRdaemonBuffer::readMeta(char *array, uint32_t length) @@ -227,6 +232,24 @@ void SDRdaemonBuffer::writeToRawBufferLZ4(const char *array, uint32_t length) writeToRawBufferUncompressed((const char *) m_lz4OutBuffer, m_frameSize); } +uint8_t *SDRdaemonBuffer::readData(uint32_t length) +{ + uint32_t readCount = m_readCount; + + if (m_readCount + length < m_rawSize) + { + m_readCount += length; + return &m_rawBuffer[readCount]; + } + else + { + std::memcpy((void *) m_frameBuffer, (const void *) &m_rawBuffer[readCount], m_rawSize - m_rawCount); + m_readCount = length - (m_rawSize - m_rawCount); + std::memcpy((void *) m_frameBuffer, (const void *) &m_frameBuffer[m_rawSize - m_rawCount], m_readCount); + return m_frameBuffer; + } +} + void SDRdaemonBuffer::updateLZ4Sizes(uint32_t frameSize) { uint32_t maxInputSize = LZ4_compressBound(frameSize); @@ -259,6 +282,12 @@ void SDRdaemonBuffer::updateBufferSize(uint32_t frameSize) m_rawSize = nbFrames * frameSize; m_rawBuffer = new uint8_t[m_rawSize]; + + if (m_frameBuffer) { + delete[] m_frameBuffer; + } + + m_frameBuffer = new uint8_t[frameSize]; } void SDRdaemonBuffer::updateBlockCounts(uint32_t nbBytesReceived) diff --git a/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h b/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h index b1a613df7..37778fba8 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h +++ b/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h @@ -65,6 +65,7 @@ public: ~SDRdaemonBuffer(); bool readMeta(char *array, uint32_t length); //!< Attempt to read meta. Returns true if meta block void writeData(char *array, uint32_t length); //!< Write data into buffer. + uint8_t *readData(uint32_t length); //!< Read data from buffer const MetaData& getCurrentMeta() const { return m_currentMeta; } void updateBlockCounts(uint32_t nbBytesReceived); bool isSync() const { return m_sync; } @@ -103,6 +104,7 @@ private: uint32_t m_readCount; //!< Current read position in the raw samples buffer uint32_t m_rawSize; //!< Size of the raw samples buffer in bytes uint8_t *m_rawBuffer; //!< Buffer for raw samples obtained from UDP (I/Q not in a formal I/Q structure) + uint8_t *m_frameBuffer; //!< Buffer to build a frame length of raw samples uint32_t m_bytesInBlock; //!< Number of bytes received in the current UDP block uint32_t m_nbBlocks; //!< Number of UDP blocks received in the current frame }; diff --git a/plugins/samplesource/sdrdaemon/sdrdaemoninput.cpp b/plugins/samplesource/sdrdaemon/sdrdaemoninput.cpp index 896972e64..55e3b998d 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemoninput.cpp +++ b/plugins/samplesource/sdrdaemon/sdrdaemoninput.cpp @@ -88,28 +88,6 @@ SDRdaemonInput::~SDRdaemonInput() stop(); } -void SDRdaemonInput::openFileStream() -{ - qDebug() << "SDRdaemonInput::openFileStream: " << m_fileName.toStdString().c_str(); - - //stopInput(); - - if (m_ifstream.is_open()) { - m_ifstream.close(); - } - - m_ifstream.open(m_fileName.toStdString().c_str(), std::ios::binary); - FileSink::Header header; - FileSink::readHeader(m_ifstream, header); - - m_sampleRate = header.sampleRate; - m_centerFrequency = header.centerFrequency; - m_startingTimeStamp = header.startTimeStamp; - - MsgReportSDRdaemonStreamData *report = MsgReportSDRdaemonStreamData::create(m_sampleRate, m_centerFrequency, m_startingTimeStamp); // file stream data - getOutputMessageQueueToGUI()->push(report); -} - bool SDRdaemonInput::init(const Message& message) { return false; @@ -120,19 +98,12 @@ bool SDRdaemonInput::start(int device) QMutexLocker mutexLocker(&m_mutex); qDebug() << "SDRdaemonInput::startInput"; - if (m_ifstream.tellg() != 0) { - m_ifstream.clear(); - m_ifstream.seekg(0, std::ios::beg); - } - if(!m_sampleFifo.setSize(96000 * 4)) { qCritical("Could not allocate SampleFifo"); return false; } - //openFileStream(); - - if((m_SDRdaemonThread = new SDRdaemonThread(&m_ifstream, &m_sampleFifo)) == NULL) { + if((m_SDRdaemonThread = new SDRdaemonThread(&m_sampleFifo)) == NULL) { qFatal("out of memory"); stop(); return false; @@ -197,7 +168,6 @@ bool SDRdaemonInput::handleMessage(const Message& message) { MsgConfigureSDRdaemonName& conf = (MsgConfigureSDRdaemonName&) message; m_fileName = conf.getFileName(); - openFileStream(); return true; } else if (MsgConfigureSDRdaemonWork::match(message)) @@ -259,13 +229,6 @@ bool SDRdaemonInput::applySettings(const Settings& settings, bool force) } } - if (m_ifstream.is_open()) - { - m_ifstream.close(); - } - - openFileStream(); - if (m_SDRdaemonThread != 0) { m_SDRdaemonThread->setSamplerate(m_sampleRate); @@ -280,7 +243,6 @@ bool SDRdaemonInput::applySettings(const Settings& settings, bool force) DSPEngine::instance()->getInputMessageQueue()->push(notif); qDebug() << "SDRdaemonInput::applySettings:" - << " file name: " << settings.m_fileName.toStdString().c_str() << " center freq: " << m_centerFrequency << " Hz" << " sample rate: " << m_sampleRate << " Unix timestamp: " << m_startingTimeStamp; diff --git a/plugins/samplesource/sdrdaemon/sdrdaemoninput.h b/plugins/samplesource/sdrdaemon/sdrdaemoninput.h index e0c180b20..01e004b6c 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemoninput.h +++ b/plugins/samplesource/sdrdaemon/sdrdaemoninput.h @@ -22,7 +22,6 @@ #include #include #include -#include class SDRdaemonThread; @@ -197,7 +196,6 @@ public: private: QMutex m_mutex; Settings m_settings; - std::ifstream m_ifstream; SDRdaemonThread* m_SDRdaemonThread; QString m_deviceDescription; QString m_fileName; @@ -207,7 +205,6 @@ private: const QTimer& m_masterTimer; bool applySettings(const Settings& settings, bool force); - void openFileStream(); }; #endif // INCLUDE_SDRDAEMONINPUT_H diff --git a/plugins/samplesource/sdrdaemon/sdrdaemonthread.cpp b/plugins/samplesource/sdrdaemon/sdrdaemonthread.cpp index 934b1c17b..222e5ea5d 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemonthread.cpp +++ b/plugins/samplesource/sdrdaemon/sdrdaemonthread.cpp @@ -26,14 +26,13 @@ const int SDRdaemonThread::m_rateDivider = 1000/SDRDAEMON_THROTTLE_MS; const int SDRdaemonThread::m_udpPayloadSize = 512; -SDRdaemonThread::SDRdaemonThread(std::ifstream *samplesStream, SampleFifo* sampleFifo, QObject* parent) : +SDRdaemonThread::SDRdaemonThread(SampleFifo* sampleFifo, QObject* parent) : QThread(parent), m_running(false), m_dataSocket(0), m_dataAddress(QHostAddress::LocalHost), m_dataPort(9090), m_dataConnected(false), - m_ifstream(samplesStream), m_buf(0), m_udpBuf(0), m_bufsize(0), @@ -43,7 +42,6 @@ SDRdaemonThread::SDRdaemonThread(std::ifstream *samplesStream, SampleFifo* sampl m_sdrDaemonBuffer(m_udpPayloadSize), m_samplerate(0) { - assert(m_ifstream != 0); m_udpBuf = new char[m_udpPayloadSize]; } @@ -163,23 +161,8 @@ void SDRdaemonThread::tick() if (m_running) { // read samples directly feeding the SampleFifo (no callback) - m_ifstream->read(reinterpret_cast(m_buf), m_chunksize); - - if (m_ifstream->eof()) - { - m_sampleFifo->write(m_buf, m_ifstream->gcount()); - // TODO: handle loop playback situation - m_ifstream->clear(); - m_ifstream->seekg(0, std::ios::beg); - m_samplesCount = 0; - //stopWork(); - //m_ifstream->close(); - } - else - { - m_sampleFifo->write(m_buf, m_chunksize); - m_samplesCount += m_chunksize / 4; - } + m_sampleFifo->write(reinterpret_cast(m_sdrDaemonBuffer.readData(m_chunksize)), m_chunksize); + m_samplesCount += m_chunksize / 4; } } diff --git a/plugins/samplesource/sdrdaemon/sdrdaemonthread.h b/plugins/samplesource/sdrdaemon/sdrdaemonthread.h index c1b1d1b30..373348598 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemonthread.h +++ b/plugins/samplesource/sdrdaemon/sdrdaemonthread.h @@ -24,7 +24,6 @@ #include #include -#include #include #include "dsp/samplefifo.h" #include "dsp/inthalfbandfilter.h" @@ -38,7 +37,7 @@ class SDRdaemonThread : public QThread { Q_OBJECT public: - SDRdaemonThread(std::ifstream *samplesStream, SampleFifo* sampleFifo, QObject* parent = NULL); + SDRdaemonThread(SampleFifo* sampleFifo, QObject* parent = NULL); ~SDRdaemonThread(); void startWork(); @@ -57,7 +56,6 @@ private: QWaitCondition m_startWaiter; bool m_running; - std::ifstream* m_ifstream; QUdpSocket *m_dataSocket; QHostAddress m_dataAddress; int m_dataPort; From 1602525e0c13ba379e40b7f022158a338f6e4c35 Mon Sep 17 00:00:00 2001 From: f4exb Date: Mon, 1 Feb 2016 08:24:14 +0100 Subject: [PATCH 12/51] SDRdaemon plugin: removed references to file input --- Readme.md | 3 +- plugins/channel/udpsrc/udpsrcgui.cpp | 2 +- .../samplesource/sdrdaemon/sdrdaemongui.cpp | 115 +++++----- plugins/samplesource/sdrdaemon/sdrdaemongui.h | 13 +- .../samplesource/sdrdaemon/sdrdaemongui.ui | 208 +----------------- .../samplesource/sdrdaemon/sdrdaemoninput.cpp | 99 ++++----- .../samplesource/sdrdaemon/sdrdaemoninput.h | 53 ++--- .../samplesource/sdrdaemon/sdrdaemonthread.h | 1 + 8 files changed, 136 insertions(+), 358 deletions(-) diff --git a/Readme.md b/Readme.md index f2e7e7366..a6ddeed90 100644 --- a/Readme.md +++ b/Readme.md @@ -193,6 +193,7 @@ See the v1.0.1 first official relase [release notes](https://github.com/f4exb/sd

To Do

+ - UDP source plugin: add the possibility to launch an external command that will process the samples like a GNUradio headless flowgraph - Allow the handling of more than one device at the same time. For Rx/Tx devices like the BladeRF Rx and Tx appear as two logical devices with two plugin instances and a common handler for the physical device services both plugins. This effectively opens Tx support. - Tx channels - Possibility to connect channels for example Rx to Tx or single Rx channel to dual Rx channel supporting MI(MO) features like 360 degree polarization detection. @@ -202,7 +203,7 @@ See the v1.0.1 first official relase [release notes](https://github.com/f4exb/sd - Headless mode based on a saved configuration in above human readable form - Allow arbitrary sample rate for channelizers and demodulators (not multiple of 48 kHz). Prerequisite for polyphase channelizer - Implement polyphase channelizer - - Level calibration + - Level calibration - Even more demods ...

Developper's notes

diff --git a/plugins/channel/udpsrc/udpsrcgui.cpp b/plugins/channel/udpsrc/udpsrcgui.cpp index 8d873d263..f7418ad2c 100644 --- a/plugins/channel/udpsrc/udpsrcgui.cpp +++ b/plugins/channel/udpsrc/udpsrcgui.cpp @@ -305,7 +305,7 @@ void UDPSrcGUI::applySettings() int udpPort = ui->udpPort->text().toInt(&ok); - if((!ok) || (udpPort < 1) || (udpPort > 65535)) + if((!ok) || (udpPort < 1024) || (udpPort > 65535)) { udpPort = 9999; } diff --git a/plugins/samplesource/sdrdaemon/sdrdaemongui.cpp b/plugins/samplesource/sdrdaemon/sdrdaemongui.cpp index b8dd917e3..9c7205bc4 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemongui.cpp +++ b/plugins/samplesource/sdrdaemon/sdrdaemongui.cpp @@ -20,11 +20,13 @@ #include #include #include +#include #include "ui_sdrdaemongui.h" #include "plugin/pluginapi.h" #include "gui/colormapper.h" #include "dsp/dspengine.h" #include "mainwindow.h" +#include "util/simpleserializer.h" #include "sdrdaemongui.h" @@ -32,10 +34,8 @@ SDRdaemonGui::SDRdaemonGui(PluginAPI* pluginAPI, QWidget* parent) : QWidget(parent), ui(new Ui::SDRdaemonGui), m_pluginAPI(pluginAPI), - m_settings(), m_sampleSource(NULL), m_acquisition(false), - m_fileName("..."), m_sampleRate(0), m_centerFrequency(0), m_startingTimeStamp(0), @@ -45,14 +45,14 @@ SDRdaemonGui::SDRdaemonGui(PluginAPI* pluginAPI, QWidget* parent) : ui->setupUi(this); ui->centerFrequency->setColorMapper(ColorMapper(ColorMapper::ReverseGold)); ui->centerFrequency->setValueRange(7, 0, pow(10,7)); - ui->fileNameText->setText(m_fileName); connect(&m_updateTimer, SIGNAL(timeout()), this, SLOT(updateHardware())); connect(&(m_pluginAPI->getMainWindow()->getMasterTimer()), SIGNAL(timeout()), this, SLOT(tick())); - displaySettings(); m_sampleSource = new SDRdaemonInput(m_pluginAPI->getMainWindow()->getMasterTimer()); connect(m_sampleSource->getOutputMessageQueueToGUI(), SIGNAL(messageEnqueued()), this, SLOT(handleSourceMessages())); DSPEngine::instance()->setSource(m_sampleSource); + + displaySettings(); } SDRdaemonGui::~SDRdaemonGui() @@ -77,11 +77,54 @@ QString SDRdaemonGui::getName() const void SDRdaemonGui::resetToDefaults() { - m_settings.resetToDefaults(); displaySettings(); - sendSettings(); } +QByteArray SDRdaemonGui::serialize() const +{ + bool ok; + SimpleSerializer s(1); + s.writeString(1, ui->address->text()); + uint32_t uintval = ui->port->text().toInt(&ok); + if((!ok) || (uintval < 1024) || (uintval > 65535)) { + uintval = 9090; + } + s.writeU32(2, uintval); + return s.final(); +} + +bool SDRdaemonGui::deserialize(const QByteArray& data) +{ + SimpleDeserializer d(data); + QString address; + uint32_t uintval; + quint16 port; + + if(!d.isValid()) { + resetToDefaults(); + return false; + } + + if(d.getVersion() == 1) { + uint32_t uintval; + d.readString(1, &address, "127.0.0.1"); + d.readU32(2, &uintval, 9090); + if ((uintval > 1024) && (uintval < 65536)) { + port = uintval; + } else { + port = 9090; + } + return true; + } else { + resetToDefaults(); + return false; + } + + ui->address->setText(address); + ui->port->setText(QString::number(port)); +} + + qint64 SDRdaemonGui::getCenterFrequency() const { return m_centerFrequency; @@ -91,24 +134,6 @@ void SDRdaemonGui::setCenterFrequency(qint64 centerFrequency) { m_centerFrequency = centerFrequency; displaySettings(); - sendSettings(); -} - -QByteArray SDRdaemonGui::serialize() const -{ - return m_settings.serialize(); -} - -bool SDRdaemonGui::deserialize(const QByteArray& data) -{ - if(m_settings.deserialize(data)) { - displaySettings(); - sendSettings(); - return true; - } else { - resetToDefaults(); - return false; - } } bool SDRdaemonGui::handleMessage(const Message& message) @@ -158,45 +183,37 @@ void SDRdaemonGui::displaySettings() { } -void SDRdaemonGui::sendSettings() -{ -} - -void SDRdaemonGui::updateHardware() -{ -} - void SDRdaemonGui::on_play_toggled(bool checked) { SDRdaemonInput::MsgConfigureSDRdaemonWork* message = SDRdaemonInput::MsgConfigureSDRdaemonWork::create(checked); m_sampleSource->getInputMessageQueue()->push(message); } -void SDRdaemonGui::on_showFileDialog_clicked(bool checked) +void SDRdaemonGui::on_applyButton_clicked(bool checked) { - QString fileName = QFileDialog::getOpenFileName(this, - tr("Open I/Q record file"), ".", tr("SDR I/Q Files (*.sdriq)")); - - if (fileName != "") - { - m_fileName = fileName; - ui->fileNameText->setText(m_fileName); - configureFileName(); - } + configureUDPLink(); } -void SDRdaemonGui::configureFileName() +void SDRdaemonGui::configureUDPLink() { - qDebug() << "SDRdaemonGui::configureFileName: " << m_fileName.toStdString().c_str(); - SDRdaemonInput::MsgConfigureSDRdaemonName* message = SDRdaemonInput::MsgConfigureSDRdaemonName::create(m_fileName); + bool ok; + QString udpAddress = ui->address->text(); + int udpPort = ui->port->text().toInt(&ok); + + if((!ok) || (udpPort < 1024) || (udpPort > 65535)) + { + udpPort = 9090; + } + + qDebug() << "SDRdaemonGui::configureUDPLink: " << udpAddress.toStdString().c_str() + << " : " << udpPort; + + SDRdaemonInput::MsgConfigureSDRdaemonUDPLink* message = SDRdaemonInput::MsgConfigureSDRdaemonUDPLink::create(udpAddress, udpPort); m_sampleSource->getInputMessageQueue()->push(message); } void SDRdaemonGui::updateWithAcquisition() { - ui->play->setEnabled(m_acquisition); - ui->play->setChecked(m_acquisition); - ui->showFileDialog->setEnabled(!m_acquisition); } void SDRdaemonGui::updateWithStreamData() @@ -204,7 +221,6 @@ void SDRdaemonGui::updateWithStreamData() ui->centerFrequency->setValue(m_centerFrequency/1000); QString s = QString::number(m_sampleRate/1000.0, 'f', 0); ui->sampleRateText->setText(tr("%1k").arg(s)); - ui->play->setEnabled(m_acquisition); updateWithStreamTime(); // TODO: remove when time data is implemented } @@ -222,7 +238,6 @@ void SDRdaemonGui::updateWithStreamTime() t = t.addSecs(t_sec); t = t.addMSecs(t_msec); QString s_time = t.toString("hh:mm:ss.zzz"); - ui->relTimeText->setText(s_time); quint64 startingTimeStampMsec = m_startingTimeStamp * 1000; QDateTime dt = QDateTime::fromMSecsSinceEpoch(startingTimeStampMsec); diff --git a/plugins/samplesource/sdrdaemon/sdrdaemongui.h b/plugins/samplesource/sdrdaemon/sdrdaemongui.h index b9216f9b0..d192453f7 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemongui.h +++ b/plugins/samplesource/sdrdaemon/sdrdaemongui.h @@ -40,22 +40,19 @@ public: QString getName() const; void resetToDefaults(); - virtual qint64 getCenterFrequency() const; - virtual void setCenterFrequency(qint64 centerFrequency); QByteArray serialize() const; bool deserialize(const QByteArray& data); + virtual qint64 getCenterFrequency() const; + virtual void setCenterFrequency(qint64 centerFrequency); virtual bool handleMessage(const Message& message); private: Ui::SDRdaemonGui* ui; PluginAPI* m_pluginAPI; - SDRdaemonInput::Settings m_settings; QTimer m_updateTimer; - std::vector m_gains; SampleSource* m_sampleSource; bool m_acquisition; - QString m_fileName; int m_sampleRate; quint64 m_centerFrequency; std::time_t m_startingTimeStamp; @@ -64,9 +61,7 @@ private: void displaySettings(); void displayTime(); - void sendSettings(); - void updateHardware(); - void configureFileName(); + void configureUDPLink(); void updateWithAcquisition(); void updateWithStreamData(); void updateWithStreamTime(); @@ -75,7 +70,7 @@ private slots: void handleSourceMessages(); void on_playLoop_toggled(bool checked); void on_play_toggled(bool checked); - void on_showFileDialog_clicked(bool checked); + void on_applyButton_clicked(bool checked); void tick(); }; diff --git a/plugins/samplesource/sdrdaemon/sdrdaemongui.ui b/plugins/samplesource/sdrdaemon/sdrdaemongui.ui index 228619b6a..c6e778eeb 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemongui.ui +++ b/plugins/samplesource/sdrdaemon/sdrdaemongui.ui @@ -147,7 +147,7 @@
- + 30 @@ -235,108 +235,6 @@
- - - - - - Dec. - - - - - - - Decimation factor - - - 6 - - - 1 - - - 0 - - - Qt::Horizontal - - - - - - - 1 - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - 50 - 0 - - - - 0k - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - - - - - 24 - 24 - - - - - 24 - 24 - - - - Open file - - - - - - - :/preset-load.png:/preset-load.png - - - - - - - false - - - File currently opened - - - ... - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - @@ -345,104 +243,7 @@ - - - Qt::Horizontal - - - - - - - - - Play in a loop - - - - - - - :/playloop.png:/playloop.png - - - - 16 - 16 - - - - true - - - - - - - Stopped / Play / Pause - - - - - - - :/play.png - :/pause.png - :/stop.png - :/stop.png - :/play.png - :/pause.png - :/play.png - :/pause.png:/play.png - - - - 16 - 16 - - - - true - - - false - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - Qt::Vertical - - - - - - - false - - - Record time from start - - - 00:00:00.000 - - - - +
@@ -453,11 +254,6 @@
gui/valuedial.h
1 - - ButtonSwitch - QToolButton -
gui/buttonswitch.h
-
diff --git a/plugins/samplesource/sdrdaemon/sdrdaemoninput.cpp b/plugins/samplesource/sdrdaemon/sdrdaemoninput.cpp index 55e3b998d..f5005be78 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemoninput.cpp +++ b/plugins/samplesource/sdrdaemon/sdrdaemoninput.cpp @@ -27,55 +27,18 @@ #include "sdrdaemoninput.h" #include "sdrdaemonthread.h" -MESSAGE_CLASS_DEFINITION(SDRdaemonInput::MsgConfigureSDRdaemon, Message) -MESSAGE_CLASS_DEFINITION(SDRdaemonInput::MsgConfigureSDRdaemonName, Message) +MESSAGE_CLASS_DEFINITION(SDRdaemonInput::MsgConfigureSDRdaemonUDPLink, Message) MESSAGE_CLASS_DEFINITION(SDRdaemonInput::MsgConfigureSDRdaemonWork, Message) MESSAGE_CLASS_DEFINITION(SDRdaemonInput::MsgConfigureSDRdaemonStreamTiming, Message) MESSAGE_CLASS_DEFINITION(SDRdaemonInput::MsgReportSDRdaemonAcquisition, Message) MESSAGE_CLASS_DEFINITION(SDRdaemonInput::MsgReportSDRdaemonStreamData, Message) MESSAGE_CLASS_DEFINITION(SDRdaemonInput::MsgReportSDRdaemonStreamTiming, Message) -SDRdaemonInput::Settings::Settings() : - m_fileName("./test.sdriq") -{ -} - -void SDRdaemonInput::Settings::resetToDefaults() -{ - m_fileName = "./test.sdriq"; -} - -QByteArray SDRdaemonInput::Settings::serialize() const -{ - SimpleSerializer s(1); - s.writeString(1, m_fileName); - return s.final(); -} - -bool SDRdaemonInput::Settings::deserialize(const QByteArray& data) -{ - SimpleDeserializer d(data); - - if(!d.isValid()) { - resetToDefaults(); - return false; - } - - if(d.getVersion() == 1) { - int intval; - d.readString(1, &m_fileName, "./test.sdriq"); - return true; - } else { - resetToDefaults(); - return false; - } -} - SDRdaemonInput::SDRdaemonInput(const QTimer& masterTimer) : - m_settings(), + m_address("127.0.0.1"), + m_port(9090), m_SDRdaemonThread(NULL), m_deviceDescription(), - m_fileName("..."), m_sampleRate(0), m_centerFrequency(0), m_startingTimeStamp(0), @@ -164,10 +127,10 @@ std::time_t SDRdaemonInput::getStartingTimeStamp() const bool SDRdaemonInput::handleMessage(const Message& message) { - if (MsgConfigureSDRdaemonName::match(message)) + if (MsgConfigureSDRdaemonUDPLink::match(message)) { - MsgConfigureSDRdaemonName& conf = (MsgConfigureSDRdaemonName&) message; - m_fileName = conf.getFileName(); + MsgConfigureSDRdaemonUDPLink& conf = (MsgConfigureSDRdaemonUDPLink&) message; + updateLink(conf.getAddress(), conf.getPort()); return true; } else if (MsgConfigureSDRdaemonWork::match(message)) @@ -210,14 +173,50 @@ bool SDRdaemonInput::handleMessage(const Message& message) } } -bool SDRdaemonInput::applySettings(const Settings& settings, bool force) +void SDRdaemonInput::updateLink(const QString& address, quint16 port) { QMutexLocker mutexLocker(&m_mutex); bool wasRunning = false; - if((m_settings.m_fileName != settings.m_fileName) || force) + if ((m_address != address) || (m_port != port)) { - m_settings.m_fileName = settings.m_fileName; + if (m_SDRdaemonThread != 0) + { + wasRunning = m_SDRdaemonThread->isRunning(); + + if (wasRunning) + { + m_SDRdaemonThread->stopWork(); + } + } + + if (m_SDRdaemonThread != 0) + { + m_SDRdaemonThread->updateLink(address, port); + + if (wasRunning) + { + m_SDRdaemonThread->startWork(); + } + } + + m_address = address; + m_port = port; + + qDebug() << "SDRdaemonInput::updateLink:" + << " address: " << m_address.toStdString().c_str() + << "port: " << m_port; + } +} + +void SDRdaemonInput:: updateSampleRate(int sampleRate) +{ + QMutexLocker mutexLocker(&m_mutex); + bool wasRunning = false; + + if (m_sampleRate != sampleRate) + { + m_sampleRate = sampleRate; if (m_SDRdaemonThread != 0) { @@ -242,11 +241,7 @@ bool SDRdaemonInput::applySettings(const Settings& settings, bool force) DSPSignalNotification *notif = new DSPSignalNotification(m_sampleRate, m_centerFrequency); DSPEngine::instance()->getInputMessageQueue()->push(notif); - qDebug() << "SDRdaemonInput::applySettings:" - << " center freq: " << m_centerFrequency << " Hz" - << " sample rate: " << m_sampleRate - << " Unix timestamp: " << m_startingTimeStamp; + qDebug() << "SDRdaemonInput::updateSampleRate:" + << " sample rate: " << m_sampleRate; } - - return true; } diff --git a/plugins/samplesource/sdrdaemon/sdrdaemoninput.h b/plugins/samplesource/sdrdaemon/sdrdaemoninput.h index 01e004b6c..46d0fef0b 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemoninput.h +++ b/plugins/samplesource/sdrdaemon/sdrdaemoninput.h @@ -27,52 +27,26 @@ class SDRdaemonThread; class SDRdaemonInput : public SampleSource { public: - struct Settings { - QString m_fileName; - - Settings(); - void resetToDefaults(); - QByteArray serialize() const; - bool deserialize(const QByteArray& data); - }; - - class MsgConfigureSDRdaemon : public Message { + class MsgConfigureSDRdaemonUDPLink : public Message { MESSAGE_CLASS_DECLARATION public: - const Settings& getSettings() const { return m_settings; } + const QString& getAddress() const { return m_address; } + quint16 getPort() const { return m_port; } - static MsgConfigureSDRdaemon* create(const Settings& settings) + static MsgConfigureSDRdaemonUDPLink* create(const QString& address, quint16 port) { - return new MsgConfigureSDRdaemon(settings); + return new MsgConfigureSDRdaemonUDPLink(address, port); } private: - Settings m_settings; + QString m_address; + quint16 m_port; - MsgConfigureSDRdaemon(const Settings& settings) : + MsgConfigureSDRdaemonUDPLink(const QString& address, quint16 port) : Message(), - m_settings(settings) - { } - }; - - class MsgConfigureSDRdaemonName : public Message { - MESSAGE_CLASS_DECLARATION - - public: - const QString& getFileName() const { return m_fileName; } - - static MsgConfigureSDRdaemonName* create(const QString& fileName) - { - return new MsgConfigureSDRdaemonName(fileName); - } - - private: - QString m_fileName; - - MsgConfigureSDRdaemonName(const QString& fileName) : - Message(), - m_fileName(fileName) + m_address(address), + m_port(port) { } }; @@ -195,16 +169,17 @@ public: private: QMutex m_mutex; - Settings m_settings; + QString m_address; + quint16 m_port; SDRdaemonThread* m_SDRdaemonThread; QString m_deviceDescription; - QString m_fileName; int m_sampleRate; quint64 m_centerFrequency; std::time_t m_startingTimeStamp; const QTimer& m_masterTimer; - bool applySettings(const Settings& settings, bool force); + void updateLink(const QString& address, quint16 port); + void updateSampleRate(int sampleRate); }; #endif // INCLUDE_SDRDAEMONINPUT_H diff --git a/plugins/samplesource/sdrdaemon/sdrdaemonthread.h b/plugins/samplesource/sdrdaemon/sdrdaemonthread.h index 373348598..046d108e7 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemonthread.h +++ b/plugins/samplesource/sdrdaemon/sdrdaemonthread.h @@ -43,6 +43,7 @@ public: void startWork(); void stopWork(); void setSamplerate(uint32_t samplerate); + void updateLink(const QString& address, quint16 port); bool isRunning() const { return m_running; } std::size_t getSamplesCount() const { return m_samplesCount; } From 9213cee156cfbbcbd918495f7be6616314c408cd Mon Sep 17 00:00:00 2001 From: f4exb Date: Tue, 2 Feb 2016 08:21:16 +0100 Subject: [PATCH 13/51] SDRdaemon plugin: change buffer allocation when sample rate changes --- plugins/samplesource/sdrdaemon/sdrdaemonbuffer.cpp | 9 ++++++--- plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h | 2 +- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.cpp b/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.cpp index 8aca1add3..bb66eb41a 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.cpp +++ b/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.cpp @@ -90,6 +90,7 @@ bool SDRdaemonBuffer::readMeta(char *array, uint32_t length) { m_sampleBytes = metaData->m_sampleBytes & 0x0F; uint32_t frameSize = 2 * 2 * metaData->m_nbSamples * metaData->m_nbBlocks; + uint32_t sampleRate = metaData->m_sampleRate; if (metaData->m_sampleBytes & 0x10) { @@ -109,9 +110,10 @@ bool SDRdaemonBuffer::readMeta(char *array, uint32_t length) if (frameSize != m_frameSize) { - updateBufferSize(frameSize); + updateBufferSize(sampleRate, frameSize); } + m_sampleRate = sampleRate; m_frameSize = frameSize; m_sync = true; } @@ -267,11 +269,12 @@ void SDRdaemonBuffer::updateLZ4Sizes(uint32_t frameSize) m_lz4OutBuffer = new uint8_t[frameSize]; } -void SDRdaemonBuffer::updateBufferSize(uint32_t frameSize) +void SDRdaemonBuffer::updateBufferSize(uint32_t sampleRate, uint32_t frameSize) { - uint32_t nbFrames = ((m_sampleRate * 2 * 2) / frameSize) + 1; // store at least 1 second of samples + uint32_t nbFrames = ((sampleRate * 2 * 2) / frameSize) + 1; // store at least 1 second of samples std::cerr << "SDRdaemonBuffer::updateBufferSize:" + << " sampleRate: " << sampleRate << " frameSize: " << frameSize << " nbFrames: " << nbFrames << std::endl; diff --git a/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h b/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h index 37778fba8..1c223b31e 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h +++ b/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h @@ -76,7 +76,7 @@ private: void writeDataUncompressed(const char *array, uint32_t length); void writeToRawBufferLZ4(const char *array, uint32_t originalLength); void writeToRawBufferUncompressed(const char *array, uint32_t length); - void updateBufferSize(uint32_t frameSize); + void updateBufferSize(uint32_t sampleRate, uint32_t frameSize); void printMeta(MetaData *metaData); std::size_t m_blockSize; //!< UDP block (payload) size From 31ef841a9902b6e6681f21a0595694183b6c5a2d Mon Sep 17 00:00:00 2001 From: f4exb Date: Sun, 7 Feb 2016 20:02:13 +0100 Subject: [PATCH 14/51] SDRdaemon plugin. Debug core dump --- .../sdrdaemon/sdrdaemonbuffer.cpp | 8 +- .../samplesource/sdrdaemon/sdrdaemoninput.cpp | 109 +++++---------- .../samplesource/sdrdaemon/sdrdaemoninput.h | 1 - .../sdrdaemon/sdrdaemonthread.cpp | 127 ++++++++++++------ .../samplesource/sdrdaemon/sdrdaemonthread.h | 4 +- 5 files changed, 126 insertions(+), 123 deletions(-) diff --git a/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.cpp b/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.cpp index bb66eb41a..e0822da33 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.cpp +++ b/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.cpp @@ -240,14 +240,14 @@ uint8_t *SDRdaemonBuffer::readData(uint32_t length) if (m_readCount + length < m_rawSize) { - m_readCount += length; return &m_rawBuffer[readCount]; + m_readCount += length; } else { - std::memcpy((void *) m_frameBuffer, (const void *) &m_rawBuffer[readCount], m_rawSize - m_rawCount); - m_readCount = length - (m_rawSize - m_rawCount); - std::memcpy((void *) m_frameBuffer, (const void *) &m_frameBuffer[m_rawSize - m_rawCount], m_readCount); + std::memcpy((void *) m_frameBuffer, (const void *) &m_rawBuffer[readCount], m_rawSize - m_readCount); // read last bit from raw buffer + m_readCount = length - (m_rawSize - m_readCount); + std::memcpy((void *) &m_frameBuffer[m_rawSize - m_readCount], (const void *) m_frameBuffer, m_readCount); // read the rest at start of raw buffer return m_frameBuffer; } } diff --git a/plugins/samplesource/sdrdaemon/sdrdaemoninput.cpp b/plugins/samplesource/sdrdaemon/sdrdaemoninput.cpp index f5005be78..3b172c93e 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemoninput.cpp +++ b/plugins/samplesource/sdrdaemon/sdrdaemoninput.cpp @@ -29,6 +29,42 @@ MESSAGE_CLASS_DEFINITION(SDRdaemonInput::MsgConfigureSDRdaemonUDPLink, Message) MESSAGE_CLASS_DEFINITION(SDRdaemonInput::MsgConfigureSDRdaemonWork, Message) +void SDRdaemonInput::updateLink(const QString& address, quint16 port) +{ + QMutexLocker mutexLocker(&m_mutex); + bool wasRunning = false; + + if ((m_address != address) || (m_port != port)) + { + if (m_SDRdaemonThread != 0) + { + wasRunning = m_SDRdaemonThread->isRunning(); + + if (wasRunning) + { + m_SDRdaemonThread->stopWork(); + } + } + + if (m_SDRdaemonThread != 0) + { + m_SDRdaemonThread->updateLink(address, port); + + if (wasRunning) + { + m_SDRdaemonThread->startWork(); + } + } + + m_address = address; + m_port = port; + + qDebug() << "SDRdaemonInput::updateLink:" + << " address: " << m_address.toStdString().c_str() + << "port: " << m_port; + } +} + MESSAGE_CLASS_DEFINITION(SDRdaemonInput::MsgConfigureSDRdaemonStreamTiming, Message) MESSAGE_CLASS_DEFINITION(SDRdaemonInput::MsgReportSDRdaemonAcquisition, Message) MESSAGE_CLASS_DEFINITION(SDRdaemonInput::MsgReportSDRdaemonStreamData, Message) @@ -72,7 +108,6 @@ bool SDRdaemonInput::start(int device) return false; } - m_SDRdaemonThread->setSamplerate(m_sampleRate); m_SDRdaemonThread->connectTimer(m_masterTimer); m_SDRdaemonThread->startWork(); m_deviceDescription = "SDRdaemon"; @@ -173,75 +208,3 @@ bool SDRdaemonInput::handleMessage(const Message& message) } } -void SDRdaemonInput::updateLink(const QString& address, quint16 port) -{ - QMutexLocker mutexLocker(&m_mutex); - bool wasRunning = false; - - if ((m_address != address) || (m_port != port)) - { - if (m_SDRdaemonThread != 0) - { - wasRunning = m_SDRdaemonThread->isRunning(); - - if (wasRunning) - { - m_SDRdaemonThread->stopWork(); - } - } - - if (m_SDRdaemonThread != 0) - { - m_SDRdaemonThread->updateLink(address, port); - - if (wasRunning) - { - m_SDRdaemonThread->startWork(); - } - } - - m_address = address; - m_port = port; - - qDebug() << "SDRdaemonInput::updateLink:" - << " address: " << m_address.toStdString().c_str() - << "port: " << m_port; - } -} - -void SDRdaemonInput:: updateSampleRate(int sampleRate) -{ - QMutexLocker mutexLocker(&m_mutex); - bool wasRunning = false; - - if (m_sampleRate != sampleRate) - { - m_sampleRate = sampleRate; - - if (m_SDRdaemonThread != 0) - { - wasRunning = m_SDRdaemonThread->isRunning(); - - if (wasRunning) - { - m_SDRdaemonThread->stopWork(); - } - } - - if (m_SDRdaemonThread != 0) - { - m_SDRdaemonThread->setSamplerate(m_sampleRate); - - if (wasRunning) - { - m_SDRdaemonThread->startWork(); - } - } - - DSPSignalNotification *notif = new DSPSignalNotification(m_sampleRate, m_centerFrequency); - DSPEngine::instance()->getInputMessageQueue()->push(notif); - - qDebug() << "SDRdaemonInput::updateSampleRate:" - << " sample rate: " << m_sampleRate; - } -} diff --git a/plugins/samplesource/sdrdaemon/sdrdaemoninput.h b/plugins/samplesource/sdrdaemon/sdrdaemoninput.h index 46d0fef0b..5666ce8e9 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemoninput.h +++ b/plugins/samplesource/sdrdaemon/sdrdaemoninput.h @@ -179,7 +179,6 @@ private: const QTimer& m_masterTimer; void updateLink(const QString& address, quint16 port); - void updateSampleRate(int sampleRate); }; #endif // INCLUDE_SDRDAEMONINPUT_H diff --git a/plugins/samplesource/sdrdaemon/sdrdaemonthread.cpp b/plugins/samplesource/sdrdaemon/sdrdaemonthread.cpp index 222e5ea5d..a3c360cd7 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemonthread.cpp +++ b/plugins/samplesource/sdrdaemon/sdrdaemonthread.cpp @@ -43,6 +43,19 @@ SDRdaemonThread::SDRdaemonThread(SampleFifo* sampleFifo, QObject* parent) : m_samplerate(0) { m_udpBuf = new char[m_udpPayloadSize]; + m_dataSocket = new QUdpSocket(this); + + if (m_dataSocket->bind(m_dataAddress, m_dataPort)) + { + qDebug("SDRdaemonThread::SDRdaemonThread: bind data socket to port %d", m_dataPort); + connect(m_dataSocket, SIGNAL(readyRead()), this, SLOT(dataReadyRead())); + m_dataConnected = true; + } + else + { + qWarning("SDRdaemonThread::SDRdaemonThread: cannot bind data port %d", m_dataPort); + m_dataConnected = false; + } } SDRdaemonThread::~SDRdaemonThread() @@ -64,27 +77,17 @@ void SDRdaemonThread::startWork() { qDebug() << "SDRdaemonThread::startWork: "; - if (!m_dataSocket) { - m_dataSocket = new QUdpSocket(this); - } - - if (m_dataSocket->bind(m_dataAddress, m_dataPort)) + if (!m_dataConnected) { - qDebug("SDRdaemonThread::startWork: bind data socket to port %d", m_dataPort); connect(m_dataSocket, SIGNAL(readyRead()), this, SLOT(dataReadyRead())); - - m_startWaitMutex.lock(); - start(); - while(!m_running) - m_startWaiter.wait(&m_startWaitMutex, 100); - m_startWaitMutex.unlock(); m_dataConnected = true; } - else - { - qWarning("SDRdaemonThread::startWork: cannot bind data port %d", m_dataPort); - m_dataConnected = false; - } + + m_startWaitMutex.lock(); + start(); + while(!m_running) + m_startWaiter.wait(&m_startWaitMutex, 100); + m_startWaitMutex.unlock(); } void SDRdaemonThread::stopWork() @@ -93,11 +96,7 @@ void SDRdaemonThread::stopWork() if (m_dataConnected) { disconnect(m_dataSocket, SIGNAL(readyRead()), this, SLOT(dataReadyRead())); - } - - if (m_dataSocket) { - delete m_dataSocket; - m_dataSocket = 0; + m_dataConnected = false; } m_running = false; @@ -106,33 +105,69 @@ void SDRdaemonThread::stopWork() void SDRdaemonThread::setSamplerate(uint32_t samplerate) { + bool wasRunning = m_running; + qDebug() << "SDRdaemonThread::setSamplerate:" << " new:" << samplerate << " old:" << m_samplerate; - if (samplerate != m_samplerate) + if (m_running) { - if (m_running) { - stopWork(); - } - - m_samplerate = samplerate; - m_chunksize = (m_samplerate / m_rateDivider)*4; // TODO: implement FF and slow motion here. 4 corresponds to live. 2 is half speed, 8 is doulbe speed - m_bufsize = m_chunksize; - - if (m_buf == 0) { - qDebug() << " - Allocate buffer"; - m_buf = (quint8*) malloc(m_bufsize); - } else { - qDebug() << " - Re-allocate buffer"; - m_buf = (quint8*) realloc((void*) m_buf, m_bufsize); - } - - qDebug() << " - size: " << m_bufsize - << " #samples: " << (m_bufsize/4); + stopWork(); + m_running = false; } - //m_samplerate = samplerate; + m_samplerate = samplerate; + m_chunksize = (m_samplerate / m_rateDivider)*4; // TODO: implement FF and slow motion here. 4 corresponds to live. 2 is half speed, 8 is doulbe speed + m_bufsize = m_chunksize; + + if (m_buf == 0) { + qDebug() << " - Allocate buffer"; + m_buf = (quint8*) malloc(m_bufsize); + } else { + qDebug() << " - Re-allocate buffer"; + m_buf = (quint8*) realloc((void*) m_buf, m_bufsize); + } + + qDebug() << " - size: " << m_bufsize + << " #samples: " << (m_bufsize/4); + + if (wasRunning) + { + startWork(); + m_running = true; + } +} + +void SDRdaemonThread::updateLink(const QString& address, quint16 port) +{ + if (m_dataSocket) { + delete m_dataSocket; + m_dataSocket = 0; + } + + m_dataSocket = new QUdpSocket(this); + m_dataPort = port; + + if (m_dataAddress.setAddress(address)) + { + if (m_dataSocket->bind(m_dataAddress, m_dataPort)) + { + qDebug("SDRdaemonThread::startWork: bind data socket to port %d", m_dataPort); + connect(m_dataSocket, SIGNAL(readyRead()), this, SLOT(dataReadyRead())); + m_dataConnected = true; + } + else + { + qWarning("SDRdaemonThread::updateLink: cannot bind data port %d", m_dataPort); + m_dataConnected = false; + } + } + else + { + qWarning("SDRdaemonThread::updateLink: cannot set data address: %s", qPrintable(address)); + m_dataConnected = false; + } } void SDRdaemonThread::run() @@ -183,7 +218,13 @@ void SDRdaemonThread::dataReadyRead() if (m_sdrDaemonBuffer.readMeta(m_udpBuf, readBytes)) { - setSamplerate(m_sdrDaemonBuffer.getCurrentMeta().m_sampleRate); + uint32_t sampleRate = m_sdrDaemonBuffer.getCurrentMeta().m_sampleRate; + + if (m_samplerate != sampleRate) + { + setSamplerate(sampleRate); + m_samplerate = sampleRate; + } } else if (m_sdrDaemonBuffer.isSync()) { diff --git a/plugins/samplesource/sdrdaemon/sdrdaemonthread.h b/plugins/samplesource/sdrdaemon/sdrdaemonthread.h index 046d108e7..35e9fb9ca 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemonthread.h +++ b/plugins/samplesource/sdrdaemon/sdrdaemonthread.h @@ -42,7 +42,6 @@ public: void startWork(); void stopWork(); - void setSamplerate(uint32_t samplerate); void updateLink(const QString& address, quint16 port); bool isRunning() const { return m_running; } std::size_t getSamplesCount() const { return m_samplesCount; } @@ -59,7 +58,7 @@ private: QUdpSocket *m_dataSocket; QHostAddress m_dataAddress; - int m_dataPort; + quint16 m_dataPort; bool m_dataConnected; quint8 *m_buf; char *m_udpBuf; @@ -74,6 +73,7 @@ private: static const int m_rateDivider; static const int m_udpPayloadSize; + void setSamplerate(uint32_t samplerate); void run(); private slots: void tick(); From 4dfc4701e599cad05b50f41204400bf7c851b08f Mon Sep 17 00:00:00 2001 From: f4exb Date: Wed, 10 Feb 2016 22:52:14 +0100 Subject: [PATCH 15/51] Removed useless method in filesource plugin --- .../filesource/filesourceinput.cpp | 49 ------------------- .../samplesource/filesource/filesourceinput.h | 1 - 2 files changed, 50 deletions(-) diff --git a/plugins/samplesource/filesource/filesourceinput.cpp b/plugins/samplesource/filesource/filesourceinput.cpp index d0e03b90c..46d1788a2 100644 --- a/plugins/samplesource/filesource/filesourceinput.cpp +++ b/plugins/samplesource/filesource/filesourceinput.cpp @@ -239,52 +239,3 @@ bool FileSourceInput::handleMessage(const Message& message) return false; } } - -bool FileSourceInput::applySettings(const Settings& settings, bool force) -{ - QMutexLocker mutexLocker(&m_mutex); - bool wasRunning = false; - - if((m_settings.m_fileName != settings.m_fileName) || force) - { - m_settings.m_fileName = settings.m_fileName; - - if (m_fileSourceThread != 0) - { - wasRunning = m_fileSourceThread->isRunning(); - - if (wasRunning) - { - m_fileSourceThread->stopWork(); - } - } - - if (m_ifstream.is_open()) - { - m_ifstream.close(); - } - - openFileStream(); - - if (m_fileSourceThread != 0) - { - m_fileSourceThread->setSamplerate(m_sampleRate); - - if (wasRunning) - { - m_fileSourceThread->startWork(); - } - } - - DSPSignalNotification *notif = new DSPSignalNotification(m_sampleRate, m_centerFrequency); - DSPEngine::instance()->getInputMessageQueue()->push(notif); - - qDebug() << "FileSourceInput::applySettings:" - << " file name: " << settings.m_fileName.toStdString().c_str() - << " center freq: " << m_centerFrequency << " Hz" - << " sample rate: " << m_sampleRate - << " Unix timestamp: " << m_startingTimeStamp; - } - - return true; -} diff --git a/plugins/samplesource/filesource/filesourceinput.h b/plugins/samplesource/filesource/filesourceinput.h index 936035192..fe16d3576 100644 --- a/plugins/samplesource/filesource/filesourceinput.h +++ b/plugins/samplesource/filesource/filesourceinput.h @@ -206,7 +206,6 @@ private: std::time_t m_startingTimeStamp; const QTimer& m_masterTimer; - bool applySettings(const Settings& settings, bool force); void openFileStream(); }; From 42b52a2d2c7e42f009ff625c3f36a1f5db369f9e Mon Sep 17 00:00:00 2001 From: f4exb Date: Sun, 14 Feb 2016 20:01:46 +0100 Subject: [PATCH 16/51] SDRdaemon debug. Frequency now in kHz in the meta data --- .../samplesource/sdrdaemon/sdrdaemonbuffer.h | 2 +- .../samplesource/sdrdaemon/sdrdaemongui.cpp | 18 +++++++--- plugins/samplesource/sdrdaemon/sdrdaemongui.h | 5 ++- .../samplesource/sdrdaemon/sdrdaemongui.ui | 7 ++++ .../samplesource/sdrdaemon/sdrdaemoninput.cpp | 6 ++-- .../samplesource/sdrdaemon/sdrdaemoninput.h | 16 +++++---- .../sdrdaemon/sdrdaemonthread.cpp | 34 +++++++++++++++---- .../samplesource/sdrdaemon/sdrdaemonthread.h | 5 ++- 8 files changed, 68 insertions(+), 25 deletions(-) diff --git a/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h b/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h index 1c223b31e..95c527030 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h +++ b/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h @@ -31,7 +31,7 @@ public: struct MetaData { // critical data - uint64_t m_centerFrequency; //!< center frequency in Hz + uint32_t m_centerFrequency; //!< center frequency in kHz uint32_t m_sampleRate; //!< sample rate in Hz uint8_t m_sampleBytes; //!< MSB(4): indicators, LSB(4) number of bytes per sample uint8_t m_sampleBits; //!< number of effective bits per sample diff --git a/plugins/samplesource/sdrdaemon/sdrdaemongui.cpp b/plugins/samplesource/sdrdaemon/sdrdaemongui.cpp index 9c7205bc4..3f5ebe5ea 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemongui.cpp +++ b/plugins/samplesource/sdrdaemon/sdrdaemongui.cpp @@ -38,10 +38,11 @@ SDRdaemonGui::SDRdaemonGui(PluginAPI* pluginAPI, QWidget* parent) : m_acquisition(false), m_sampleRate(0), m_centerFrequency(0), - m_startingTimeStamp(0), m_samplesCount(0), m_tickCount(0) { + m_startingTimeStamp.tv_sec = 0; + m_startingTimeStamp.tv_usec = 0; ui->setupUi(this); ui->centerFrequency->setColorMapper(ColorMapper(ColorMapper::ReverseGold)); ui->centerFrequency->setValueRange(7, 0, pow(10,7)); @@ -148,7 +149,8 @@ bool SDRdaemonGui::handleMessage(const Message& message) { m_sampleRate = ((SDRdaemonInput::MsgReportSDRdaemonStreamData&)message).getSampleRate(); m_centerFrequency = ((SDRdaemonInput::MsgReportSDRdaemonStreamData&)message).getCenterFrequency(); - m_startingTimeStamp = ((SDRdaemonInput::MsgReportSDRdaemonStreamData&)message).getStartingTimeStamp(); + m_startingTimeStamp.tv_sec = ((SDRdaemonInput::MsgReportSDRdaemonStreamData&)message).get_tv_sec(); + m_startingTimeStamp.tv_usec = ((SDRdaemonInput::MsgReportSDRdaemonStreamData&)message).get_tv_usec(); updateWithStreamData(); return true; } @@ -183,11 +185,12 @@ void SDRdaemonGui::displaySettings() { } +/* void SDRdaemonGui::on_play_toggled(bool checked) { SDRdaemonInput::MsgConfigureSDRdaemonWork* message = SDRdaemonInput::MsgConfigureSDRdaemonWork::create(checked); m_sampleSource->getInputMessageQueue()->push(message); -} +}*/ void SDRdaemonGui::on_applyButton_clicked(bool checked) { @@ -218,7 +221,7 @@ void SDRdaemonGui::updateWithAcquisition() void SDRdaemonGui::updateWithStreamData() { - ui->centerFrequency->setValue(m_centerFrequency/1000); + ui->centerFrequency->setValue(m_centerFrequency); QString s = QString::number(m_sampleRate/1000.0, 'f', 0); ui->sampleRateText->setText(tr("%1k").arg(s)); updateWithStreamTime(); // TODO: remove when time data is implemented @@ -226,6 +229,11 @@ void SDRdaemonGui::updateWithStreamData() void SDRdaemonGui::updateWithStreamTime() { + quint64 startingTimeStampMsec = (m_startingTimeStamp.tv_sec * 1000) + (m_startingTimeStamp.tv_usec / 1000); + QDateTime dt = QDateTime::fromMSecsSinceEpoch(startingTimeStampMsec); + QString s_date = dt.toString("yyyyMMdd hh.mm.ss.zzz"); + ui->absTimeText->setText(s_date); + /* int t_sec = 0; int t_msec = 0; @@ -244,7 +252,7 @@ void SDRdaemonGui::updateWithStreamTime() dt = dt.addSecs(t_sec); dt = dt.addMSecs(t_msec); QString s_date = dt.toString("yyyyMMdd hh.mm.ss.zzz"); - ui->absTimeText->setText(s_date); + ui->absTimeText->setText(s_date);*/ } void SDRdaemonGui::tick() diff --git a/plugins/samplesource/sdrdaemon/sdrdaemongui.h b/plugins/samplesource/sdrdaemon/sdrdaemongui.h index d192453f7..8ed697b8d 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemongui.h +++ b/plugins/samplesource/sdrdaemon/sdrdaemongui.h @@ -18,6 +18,7 @@ #define INCLUDE_SDRDAEMONGUI_H #include +#include #include "plugin/plugingui.h" #include "sdrdaemoninput.h" @@ -55,7 +56,7 @@ private: bool m_acquisition; int m_sampleRate; quint64 m_centerFrequency; - std::time_t m_startingTimeStamp; + struct timeval m_startingTimeStamp; int m_samplesCount; std::size_t m_tickCount; @@ -68,8 +69,6 @@ private: private slots: void handleSourceMessages(); - void on_playLoop_toggled(bool checked); - void on_play_toggled(bool checked); void on_applyButton_clicked(bool checked); void tick(); }; diff --git a/plugins/samplesource/sdrdaemon/sdrdaemongui.ui b/plugins/samplesource/sdrdaemon/sdrdaemongui.ui index c6e778eeb..77943b0a6 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemongui.ui +++ b/plugins/samplesource/sdrdaemon/sdrdaemongui.ui @@ -176,6 +176,13 @@ + + + + Rate: + + + diff --git a/plugins/samplesource/sdrdaemon/sdrdaemoninput.cpp b/plugins/samplesource/sdrdaemon/sdrdaemoninput.cpp index 3b172c93e..5aab189cb 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemoninput.cpp +++ b/plugins/samplesource/sdrdaemon/sdrdaemoninput.cpp @@ -73,7 +73,7 @@ MESSAGE_CLASS_DEFINITION(SDRdaemonInput::MsgReportSDRdaemonStreamTiming, Message SDRdaemonInput::SDRdaemonInput(const QTimer& masterTimer) : m_address("127.0.0.1"), m_port(9090), - m_SDRdaemonThread(NULL), + m_SDRdaemonThread(0), m_deviceDescription(), m_sampleRate(0), m_centerFrequency(0), @@ -97,12 +97,12 @@ bool SDRdaemonInput::start(int device) QMutexLocker mutexLocker(&m_mutex); qDebug() << "SDRdaemonInput::startInput"; - if(!m_sampleFifo.setSize(96000 * 4)) { + if (!m_sampleFifo.setSize(96000 * 4)) { qCritical("Could not allocate SampleFifo"); return false; } - if((m_SDRdaemonThread = new SDRdaemonThread(&m_sampleFifo)) == NULL) { + if ((m_SDRdaemonThread = new SDRdaemonThread(&m_sampleFifo, getOutputMessageQueueToGUI())) == NULL) { qFatal("out of memory"); stop(); return false; diff --git a/plugins/samplesource/sdrdaemon/sdrdaemoninput.h b/plugins/samplesource/sdrdaemon/sdrdaemoninput.h index 5666ce8e9..461a0190f 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemoninput.h +++ b/plugins/samplesource/sdrdaemon/sdrdaemoninput.h @@ -22,6 +22,7 @@ #include #include #include +#include class SDRdaemonThread; @@ -113,23 +114,26 @@ public: public: int getSampleRate() const { return m_sampleRate; } quint64 getCenterFrequency() const { return m_centerFrequency; } - std::time_t getStartingTimeStamp() const { return m_startingTimeStamp; } + uint32_t get_tv_sec() const { return m_tv_sec; } + uint32_t get_tv_usec() const { return m_tv_usec; } - static MsgReportSDRdaemonStreamData* create(int sampleRate, quint64 centerFrequency, std::time_t startingTimeStamp) + static MsgReportSDRdaemonStreamData* create(int sampleRate, quint64 centerFrequency, uint32_t tv_sec, uint32_t tv_usec) { - return new MsgReportSDRdaemonStreamData(sampleRate, centerFrequency, startingTimeStamp); + return new MsgReportSDRdaemonStreamData(sampleRate, centerFrequency, tv_sec, tv_usec); } protected: int m_sampleRate; quint64 m_centerFrequency; - std::time_t m_startingTimeStamp; + uint32_t m_tv_sec; + uint32_t m_tv_usec; - MsgReportSDRdaemonStreamData(int sampleRate, quint64 centerFrequency, std::time_t startingTimeStamp) : + MsgReportSDRdaemonStreamData(int sampleRate, quint64 centerFrequency, uint32_t tv_sec, uint32_t tv_usec) : Message(), m_sampleRate(sampleRate), m_centerFrequency(centerFrequency), - m_startingTimeStamp(startingTimeStamp) + m_tv_sec(tv_sec), + m_tv_usec(tv_usec) { } }; diff --git a/plugins/samplesource/sdrdaemon/sdrdaemonthread.cpp b/plugins/samplesource/sdrdaemon/sdrdaemonthread.cpp index a3c360cd7..f27da2ad3 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemonthread.cpp +++ b/plugins/samplesource/sdrdaemon/sdrdaemonthread.cpp @@ -18,6 +18,8 @@ #include #include #include "dsp/samplefifo.h" +#include "util/messagequeue.h" +#include "sdrdaemoninput.h" #include #include @@ -26,7 +28,7 @@ const int SDRdaemonThread::m_rateDivider = 1000/SDRDAEMON_THROTTLE_MS; const int SDRdaemonThread::m_udpPayloadSize = 512; -SDRdaemonThread::SDRdaemonThread(SampleFifo* sampleFifo, QObject* parent) : +SDRdaemonThread::SDRdaemonThread(SampleFifo* sampleFifo, MessageQueue *outputMessageQueueToGUI, QObject* parent) : QThread(parent), m_running(false), m_dataSocket(0), @@ -40,7 +42,9 @@ SDRdaemonThread::SDRdaemonThread(SampleFifo* sampleFifo, QObject* parent) : m_sampleFifo(sampleFifo), m_samplesCount(0), m_sdrDaemonBuffer(m_udpPayloadSize), - m_samplerate(0) + m_samplerate(0), + m_centerFrequency(0), + m_outputMessageQueueToGUI(outputMessageQueueToGUI) { m_udpBuf = new char[m_udpPayloadSize]; m_dataSocket = new QUdpSocket(this); @@ -218,12 +222,30 @@ void SDRdaemonThread::dataReadyRead() if (m_sdrDaemonBuffer.readMeta(m_udpBuf, readBytes)) { - uint32_t sampleRate = m_sdrDaemonBuffer.getCurrentMeta().m_sampleRate; + const SDRdaemonBuffer::MetaData& metaData = m_sdrDaemonBuffer.getCurrentMeta(); + bool change = false; - if (m_samplerate != sampleRate) + if (m_samplerate != metaData.m_sampleRate) { - setSamplerate(sampleRate); - m_samplerate = sampleRate; + setSamplerate(metaData.m_sampleRate); + m_samplerate = metaData.m_sampleRate; + change = true; + } + + if (m_centerFrequency != metaData.m_centerFrequency) + { + m_centerFrequency = metaData.m_centerFrequency; + change = true; + } + + if (change) + { + SDRdaemonInput::MsgReportSDRdaemonStreamData *report = SDRdaemonInput::MsgReportSDRdaemonStreamData::create( + metaData.m_sampleRate, + metaData.m_centerFrequency, + metaData.m_tv_sec, + metaData.m_tv_usec); + m_outputMessageQueueToGUI->push(report); } } else if (m_sdrDaemonBuffer.isSync()) diff --git a/plugins/samplesource/sdrdaemon/sdrdaemonthread.h b/plugins/samplesource/sdrdaemon/sdrdaemonthread.h index 35e9fb9ca..a3e0fa4c3 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemonthread.h +++ b/plugins/samplesource/sdrdaemon/sdrdaemonthread.h @@ -32,12 +32,13 @@ #define SDRDAEMON_THROTTLE_MS 50 class QUdpSocket; +class MessageQueue; class SDRdaemonThread : public QThread { Q_OBJECT public: - SDRdaemonThread(SampleFifo* sampleFifo, QObject* parent = NULL); + SDRdaemonThread(SampleFifo* sampleFifo, MessageQueue *outputMessageQueueToGUI, QObject* parent = NULL); ~SDRdaemonThread(); void startWork(); @@ -70,6 +71,8 @@ private: SDRdaemonBuffer m_sdrDaemonBuffer; uint32_t m_samplerate; + uint32_t m_centerFrequency; + MessageQueue *m_outputMessageQueueToGUI; static const int m_rateDivider; static const int m_udpPayloadSize; From 8dc05cf578fe86e24be4be90f17336e5d26c0e2d Mon Sep 17 00:00:00 2001 From: f4exb Date: Wed, 17 Feb 2016 02:22:05 +0100 Subject: [PATCH 17/51] SDRdaemon: UDP handler receives data --- plugins/samplesource/sdrdaemon/CMakeLists.txt | 2 + .../samplesource/sdrdaemon/sdrdaemongui.cpp | 3 +- .../samplesource/sdrdaemon/sdrdaemoninput.cpp | 115 ++-------- .../samplesource/sdrdaemon/sdrdaemoninput.h | 21 +- .../sdrdaemon/sdrdaemonudphandler.cpp | 209 ++++++++++++++++++ .../sdrdaemon/sdrdaemonudphandler.h | 81 +++++++ 6 files changed, 321 insertions(+), 110 deletions(-) create mode 100644 plugins/samplesource/sdrdaemon/sdrdaemonudphandler.cpp create mode 100644 plugins/samplesource/sdrdaemon/sdrdaemonudphandler.h diff --git a/plugins/samplesource/sdrdaemon/CMakeLists.txt b/plugins/samplesource/sdrdaemon/CMakeLists.txt index 2fc7bb122..2258a55a1 100644 --- a/plugins/samplesource/sdrdaemon/CMakeLists.txt +++ b/plugins/samplesource/sdrdaemon/CMakeLists.txt @@ -8,6 +8,7 @@ set(sdrdaemon_SOURCES sdrdaemoninput.cpp sdrdaemonplugin.cpp sdrdaemonthread.cpp + sdrdaemonudphandler.cpp ) set(sdrdaemon_HEADERS @@ -16,6 +17,7 @@ set(sdrdaemon_HEADERS sdrdaemoninput.h sdrdaemonplugin.h sdrdaemonthread.h + sdrdaemonudphandler.h ) set(sdrdaemon_FORMS diff --git a/plugins/samplesource/sdrdaemon/sdrdaemongui.cpp b/plugins/samplesource/sdrdaemon/sdrdaemongui.cpp index 3f5ebe5ea..6cccf59ea 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemongui.cpp +++ b/plugins/samplesource/sdrdaemon/sdrdaemongui.cpp @@ -156,7 +156,8 @@ bool SDRdaemonGui::handleMessage(const Message& message) } else if (SDRdaemonInput::MsgReportSDRdaemonStreamTiming::match(message)) { - m_samplesCount = ((SDRdaemonInput::MsgReportSDRdaemonStreamTiming&)message).getSamplesCount(); + m_startingTimeStamp.tv_sec = ((SDRdaemonInput::MsgReportSDRdaemonStreamTiming&)message).get_tv_sec(); + m_startingTimeStamp.tv_usec = ((SDRdaemonInput::MsgReportSDRdaemonStreamTiming&)message).get_tv_usec(); updateWithStreamTime(); return true; } diff --git a/plugins/samplesource/sdrdaemon/sdrdaemoninput.cpp b/plugins/samplesource/sdrdaemon/sdrdaemoninput.cpp index 5aab189cb..e0693390b 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemoninput.cpp +++ b/plugins/samplesource/sdrdaemon/sdrdaemoninput.cpp @@ -25,46 +25,10 @@ #include "sdrdaemongui.h" #include "sdrdaemoninput.h" -#include "sdrdaemonthread.h" +#include "sdrdaemonudphandler.h" MESSAGE_CLASS_DEFINITION(SDRdaemonInput::MsgConfigureSDRdaemonUDPLink, Message) MESSAGE_CLASS_DEFINITION(SDRdaemonInput::MsgConfigureSDRdaemonWork, Message) -void SDRdaemonInput::updateLink(const QString& address, quint16 port) -{ - QMutexLocker mutexLocker(&m_mutex); - bool wasRunning = false; - - if ((m_address != address) || (m_port != port)) - { - if (m_SDRdaemonThread != 0) - { - wasRunning = m_SDRdaemonThread->isRunning(); - - if (wasRunning) - { - m_SDRdaemonThread->stopWork(); - } - } - - if (m_SDRdaemonThread != 0) - { - m_SDRdaemonThread->updateLink(address, port); - - if (wasRunning) - { - m_SDRdaemonThread->startWork(); - } - } - - m_address = address; - m_port = port; - - qDebug() << "SDRdaemonInput::updateLink:" - << " address: " << m_address.toStdString().c_str() - << "port: " << m_port; - } -} - MESSAGE_CLASS_DEFINITION(SDRdaemonInput::MsgConfigureSDRdaemonStreamTiming, Message) MESSAGE_CLASS_DEFINITION(SDRdaemonInput::MsgReportSDRdaemonAcquisition, Message) MESSAGE_CLASS_DEFINITION(SDRdaemonInput::MsgReportSDRdaemonStreamData, Message) @@ -73,71 +37,43 @@ MESSAGE_CLASS_DEFINITION(SDRdaemonInput::MsgReportSDRdaemonStreamTiming, Message SDRdaemonInput::SDRdaemonInput(const QTimer& masterTimer) : m_address("127.0.0.1"), m_port(9090), - m_SDRdaemonThread(0), + m_SDRdaemonUDPHandler(0), m_deviceDescription(), m_sampleRate(0), m_centerFrequency(0), m_startingTimeStamp(0), m_masterTimer(masterTimer) { + m_sampleFifo.setSize(96000 * 4); + m_SDRdaemonUDPHandler = new SDRdaemonUDPHandler(&m_sampleFifo, getOutputMessageQueueToGUI()); + m_SDRdaemonUDPHandler->connectTimer(m_masterTimer); } SDRdaemonInput::~SDRdaemonInput() { stop(); + delete m_SDRdaemonUDPHandler; } bool SDRdaemonInput::init(const Message& message) { + qDebug() << "SDRdaemonInput::init"; return false; } bool SDRdaemonInput::start(int device) { - QMutexLocker mutexLocker(&m_mutex); - qDebug() << "SDRdaemonInput::startInput"; - - if (!m_sampleFifo.setSize(96000 * 4)) { - qCritical("Could not allocate SampleFifo"); - return false; - } - - if ((m_SDRdaemonThread = new SDRdaemonThread(&m_sampleFifo, getOutputMessageQueueToGUI())) == NULL) { - qFatal("out of memory"); - stop(); - return false; - } - - m_SDRdaemonThread->connectTimer(m_masterTimer); - m_SDRdaemonThread->startWork(); - m_deviceDescription = "SDRdaemon"; - - mutexLocker.unlock(); - //applySettings(m_generalSettings, m_settings, true); - qDebug("SDRdaemonInput::startInput: started"); - - MsgReportSDRdaemonAcquisition *report = MsgReportSDRdaemonAcquisition::create(true); // acquisition on - getOutputMessageQueueToGUI()->push(report); - + qDebug() << "SDRdaemonInput::start"; + MsgConfigureSDRdaemonWork *command = MsgConfigureSDRdaemonWork::create(true); + getInputMessageQueue()->push(command); return true; } void SDRdaemonInput::stop() { qDebug() << "SDRdaemonInput::stop"; - QMutexLocker mutexLocker(&m_mutex); - - if(m_SDRdaemonThread != 0) - { - m_SDRdaemonThread->stopWork(); - delete m_SDRdaemonThread; - m_SDRdaemonThread = 0; - } - - m_deviceDescription.clear(); - - MsgReportSDRdaemonAcquisition *report = MsgReportSDRdaemonAcquisition::create(false); // acquisition off - getOutputMessageQueueToGUI()->push(report); + MsgConfigureSDRdaemonWork *command = MsgConfigureSDRdaemonWork::create(false); + getInputMessageQueue()->push(command); } const QString& SDRdaemonInput::getDeviceDescription() const @@ -164,8 +100,6 @@ bool SDRdaemonInput::handleMessage(const Message& message) { if (MsgConfigureSDRdaemonUDPLink::match(message)) { - MsgConfigureSDRdaemonUDPLink& conf = (MsgConfigureSDRdaemonUDPLink&) message; - updateLink(conf.getAddress(), conf.getPort()); return true; } else if (MsgConfigureSDRdaemonWork::match(message)) @@ -173,33 +107,16 @@ bool SDRdaemonInput::handleMessage(const Message& message) MsgConfigureSDRdaemonWork& conf = (MsgConfigureSDRdaemonWork&) message; bool working = conf.isWorking(); - if (m_SDRdaemonThread != 0) - { - if (working) - { - m_SDRdaemonThread->startWork(); - MsgReportSDRdaemonStreamTiming *report = - MsgReportSDRdaemonStreamTiming::create(m_SDRdaemonThread->getSamplesCount()); - getOutputMessageQueueToGUI()->push(report); - } - else - { - m_SDRdaemonThread->stopWork(); - } + if (working) { + m_SDRdaemonUDPHandler->start(); + } else { + m_SDRdaemonUDPHandler->stop(); } return true; } else if (MsgConfigureSDRdaemonStreamTiming::match(message)) { - MsgReportSDRdaemonStreamTiming *report; - - if (m_SDRdaemonThread != 0) - { - report = MsgReportSDRdaemonStreamTiming::create(m_SDRdaemonThread->getSamplesCount()); - getOutputMessageQueueToGUI()->push(report); - } - return true; } else diff --git a/plugins/samplesource/sdrdaemon/sdrdaemoninput.h b/plugins/samplesource/sdrdaemon/sdrdaemoninput.h index 461a0190f..e17c8676c 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemoninput.h +++ b/plugins/samplesource/sdrdaemon/sdrdaemoninput.h @@ -24,7 +24,7 @@ #include #include -class SDRdaemonThread; +class SDRdaemonUDPHandler; class SDRdaemonInput : public SampleSource { public: @@ -141,19 +141,22 @@ public: MESSAGE_CLASS_DECLARATION public: - std::size_t getSamplesCount() const { return m_samplesCount; } + uint32_t get_tv_sec() const { return m_tv_sec; } + uint32_t get_tv_usec() const { return m_tv_usec; } - static MsgReportSDRdaemonStreamTiming* create(std::size_t samplesCount) + static MsgReportSDRdaemonStreamTiming* create(uint32_t tv_sec, uint32_t tv_usec) { - return new MsgReportSDRdaemonStreamTiming(samplesCount); + return new MsgReportSDRdaemonStreamTiming(tv_sec, tv_usec); } protected: - std::size_t m_samplesCount; + uint32_t m_tv_sec; + uint32_t m_tv_usec; - MsgReportSDRdaemonStreamTiming(std::size_t samplesCount) : + MsgReportSDRdaemonStreamTiming(uint32_t tv_sec, uint32_t tv_usec) : Message(), - m_samplesCount(samplesCount) + m_tv_sec(tv_sec), + m_tv_usec(tv_usec) { } }; @@ -175,14 +178,12 @@ private: QMutex m_mutex; QString m_address; quint16 m_port; - SDRdaemonThread* m_SDRdaemonThread; + SDRdaemonUDPHandler* m_SDRdaemonUDPHandler; QString m_deviceDescription; int m_sampleRate; quint64 m_centerFrequency; std::time_t m_startingTimeStamp; const QTimer& m_masterTimer; - - void updateLink(const QString& address, quint16 port); }; #endif // INCLUDE_SDRDAEMONINPUT_H diff --git a/plugins/samplesource/sdrdaemon/sdrdaemonudphandler.cpp b/plugins/samplesource/sdrdaemon/sdrdaemonudphandler.cpp new file mode 100644 index 000000000..f1ce3082c --- /dev/null +++ b/plugins/samplesource/sdrdaemon/sdrdaemonudphandler.cpp @@ -0,0 +1,209 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2015 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 . // +/////////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include "sdrdaemonudphandler.h" +#include "sdrdaemoninput.h" + +const int SDRdaemonUDPHandler::m_rateDivider = 1000/SDRDAEMON_THROTTLE_MS; +const int SDRdaemonUDPHandler::m_udpPayloadSize = 512; + +SDRdaemonUDPHandler::SDRdaemonUDPHandler(SampleFifo *sampleFifo, MessageQueue *outputMessageQueueToGUI) : + m_mutex(QMutex::Recursive), + m_sdrDaemonBuffer(m_udpPayloadSize), + m_dataSocket(0), + m_dataAddress(QHostAddress::LocalHost), + m_dataPort(9090), + m_dataConnected(false), + m_udpBuf(0), + m_udpReadBytes(0), + m_buf(0), + m_bufsize(0), + m_chunksize(0), + m_sampleFifo(sampleFifo), + m_samplerate(0), + m_centerFrequency(0), + m_tv_sec(0), + m_tv_usec(0), + m_outputMessageQueueToGUI(outputMessageQueueToGUI), + m_tickCount(0), + m_samplesCount(0) +{ + m_udpBuf = new char[m_udpPayloadSize]; +} + +SDRdaemonUDPHandler::~SDRdaemonUDPHandler() +{ + stop(); + delete[] m_udpBuf; +} + +void SDRdaemonUDPHandler::start() +{ + if (!m_dataSocket) + { + m_dataSocket = new QUdpSocket(this); + } + + if (!m_dataConnected) + { + if (m_dataSocket->bind(m_dataAddress, m_dataPort)) + { + qDebug("SDRdaemonUDPHandler::start: bind data socket to port %d", m_dataPort); + connect(this, SIGNAL(dataReady()), this, SLOT(processData())); + connect(m_dataSocket, SIGNAL(readyRead()), this, SLOT(dataReadyRead()), Qt::QueuedConnection); // , Qt::QueuedConnection + m_dataConnected = true; + } + else + { + qWarning("SDRdaemonUDPHandler::start: cannot bind data port %d", m_dataPort); + m_dataConnected = false; + } + } +} + +void SDRdaemonUDPHandler::stop() +{ + qDebug("SDRdaemonUDPHandler::stop"); + + if (m_dataConnected) { + disconnect(m_dataSocket, SIGNAL(readyRead()), this, SLOT(dataReadyRead())); + disconnect(this, SIGNAL(dataReady()), this, SLOT(processData)); + m_dataConnected = false; + } + + if (m_dataSocket) + { + delete m_dataSocket; + m_dataSocket = 0; + } +} + +void SDRdaemonUDPHandler::dataReadyRead() +{ + //qDebug() << "SDRdaemonUDPHandler::dataReadyRead"; + + while (m_dataSocket->hasPendingDatagrams()) + { + qint64 pendingDataSize = m_dataSocket->pendingDatagramSize(); + m_udpReadBytes = m_dataSocket->readDatagram(m_udpBuf, pendingDataSize, 0, 0); + emit dataReady(); + } +} + +void SDRdaemonUDPHandler::processData() +{ + if (m_udpReadBytes < 0) + { + qDebug() << "SDRdaemonThread::processData: read failed"; + } + else if (m_udpReadBytes > 0) + { + QMutexLocker ml(&m_mutex); + + m_sdrDaemonBuffer.updateBlockCounts(m_udpReadBytes); + + if (m_sdrDaemonBuffer.readMeta(m_udpBuf, m_udpReadBytes)) + { + const SDRdaemonBuffer::MetaData& metaData = m_sdrDaemonBuffer.getCurrentMeta(); + bool change = false; + m_tv_sec = metaData.m_tv_sec; + m_tv_usec = metaData.m_tv_usec; + + if (m_samplerate != metaData.m_sampleRate) + { + setSamplerate(metaData.m_sampleRate); + m_samplerate = metaData.m_sampleRate; + change = true; + } + + if (m_centerFrequency != metaData.m_centerFrequency) + { + m_centerFrequency = metaData.m_centerFrequency; + change = true; + } + + if (change) + { + SDRdaemonInput::MsgReportSDRdaemonStreamData *report = SDRdaemonInput::MsgReportSDRdaemonStreamData::create( + metaData.m_sampleRate, + metaData.m_centerFrequency, + metaData.m_tv_sec, + metaData.m_tv_usec); + m_outputMessageQueueToGUI->push(report); + } + } + else if (m_sdrDaemonBuffer.isSync()) + { + m_sdrDaemonBuffer.writeData(m_udpBuf, m_udpReadBytes); + } + } +} + +void SDRdaemonUDPHandler::setSamplerate(uint32_t samplerate) +{ + qDebug() << "SDRdaemonUDPHandler::setSamplerate:" + << " new:" << samplerate + << " old:" << m_samplerate; + + QMutexLocker ml(&m_mutex); + + m_samplerate = samplerate; + m_chunksize = (m_samplerate / m_rateDivider)*4; // TODO: implement FF and slow motion here. 4 corresponds to live. 2 is half speed, 8 is doulbe speed + m_bufsize = m_chunksize; + + if (m_buf == 0) { + qDebug() << " - Allocate buffer"; + m_buf = (quint8*) malloc(m_bufsize); + } else { + qDebug() << " - Re-allocate buffer"; + m_buf = (quint8*) realloc((void*) m_buf, m_bufsize); + } + + qDebug() << "SDRdaemonUDPHandler::setSamplerate:" + << " size: " << m_bufsize + << " #samples: " << (m_bufsize/4); +} + +void SDRdaemonUDPHandler::connectTimer(const QTimer& timer) +{ + qDebug() << "SDRdaemonUDPHandler::connectTimer"; + connect(&timer, SIGNAL(timeout()), this, SLOT(tick())); +} + +void SDRdaemonUDPHandler::tick() +{ + // read samples directly feeding the SampleFifo (no callback) + m_sampleFifo->write(reinterpret_cast(m_sdrDaemonBuffer.readData(m_chunksize)), m_chunksize); + m_samplesCount += m_chunksize / 4; + + if (m_tickCount < m_rateDivider) + { + m_tickCount++; + } + else + { + m_tickCount = 0; + SDRdaemonInput::MsgReportSDRdaemonStreamTiming *report = SDRdaemonInput::MsgReportSDRdaemonStreamTiming::create( + m_tv_sec, + m_tv_usec); + m_outputMessageQueueToGUI->push(report); + } +} + + diff --git a/plugins/samplesource/sdrdaemon/sdrdaemonudphandler.h b/plugins/samplesource/sdrdaemon/sdrdaemonudphandler.h new file mode 100644 index 000000000..8f033cf01 --- /dev/null +++ b/plugins/samplesource/sdrdaemon/sdrdaemonudphandler.h @@ -0,0 +1,81 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2015 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_SDRDAEMON_SDRDAEMONUDPHANDLER_H_ +#define PLUGINS_SAMPLESOURCE_SDRDAEMON_SDRDAEMONUDPHANDLER_H_ + +#include +#include +#include +#include +#include "sdrdaemonbuffer.h" + +#define SDRDAEMON_THROTTLE_MS 50 + +class SampleFifo; +class MessageQueue; +class QTimer; + +class SDRdaemonUDPHandler : public QObject +{ + Q_OBJECT +public: + SDRdaemonUDPHandler(SampleFifo* sampleFifo, MessageQueue *outputMessageQueueToGUI); + ~SDRdaemonUDPHandler(); + void connectTimer(const QTimer& timer); + void start(); + void stop(); + +public slots: + void dataReadyRead(); + void processData(); + +signals: + void dataReady(); + +private: + QMutex m_mutex; + SDRdaemonBuffer m_sdrDaemonBuffer; + QUdpSocket *m_dataSocket; + QHostAddress m_dataAddress; + quint16 m_dataPort; + bool m_dataConnected; + char *m_udpBuf; + qint64 m_udpReadBytes; + quint8 *m_buf; + std::size_t m_bufsize; + std::size_t m_chunksize; + SampleFifo *m_sampleFifo; + uint32_t m_samplerate; + uint32_t m_centerFrequency; + uint32_t m_tv_sec; + uint32_t m_tv_usec; + MessageQueue *m_outputMessageQueueToGUI; + uint32_t m_tickCount; + std::size_t m_samplesCount; + + static const int m_rateDivider; + static const int m_udpPayloadSize; + + void setSamplerate(uint32_t samplerate); + +private slots: + void tick(); +}; + + + +#endif /* PLUGINS_SAMPLESOURCE_SDRDAEMON_SDRDAEMONUDPHANDLER_H_ */ From 8d986368bd595711b16fb0227ea81352127c612d Mon Sep 17 00:00:00 2001 From: f4exb Date: Wed, 17 Feb 2016 08:40:10 +0100 Subject: [PATCH 18/51] SDRdaemon: fixed SDRdaemonBuffer returned value for read meta --- plugins/samplesource/sdrdaemon/sdrdaemonbuffer.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.cpp b/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.cpp index e0822da33..1c4856524 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.cpp +++ b/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.cpp @@ -121,9 +121,13 @@ bool SDRdaemonBuffer::readMeta(char *array, uint32_t length) { m_sync = false; } - } - return m_sync; + return m_sync; + } + else + { + return false; + } } void SDRdaemonBuffer::writeData(char *array, uint32_t length) From 05a4a7cb4eddb8683c375ba961cc78aa4d70033c Mon Sep 17 00:00:00 2001 From: f4exb Date: Wed, 17 Feb 2016 19:42:26 +0100 Subject: [PATCH 19/51] SDRdaemon: first working version --- CMakeLists.txt | 8 ++++-- .../samplesource/filesource/CMakeLists.txt | 2 -- plugins/samplesource/sdrdaemon/CMakeLists.txt | 2 -- .../sdrdaemon/sdrdaemonbuffer.cpp | 28 +++++++++++-------- .../samplesource/sdrdaemon/sdrdaemonbuffer.h | 8 ++++-- .../sdrdaemon/sdrdaemonudphandler.cpp | 14 ++++++---- 6 files changed, 35 insertions(+), 27 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9ce27a3db..2f5d9b1b2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -287,7 +287,6 @@ add_library(sdrbase SHARED target_link_libraries(sdrbase ${QT_LIBRARIES} ${OPENGL_LIBRARIES} - ${LIBUSB_LIBRARIES} ) if(FFTW3F_FOUND) @@ -353,5 +352,8 @@ qt5_use_modules(sdrangel Widgets Multimedia) ############################################################################## add_subdirectory(plugins) -add_subdirectory(fcdhid) -add_subdirectory(fcdlib) + +if(LIBUSB_FOUND AND UNIX) + add_subdirectory(fcdhid) + add_subdirectory(fcdlib) +endif(LIBUSB_FOUND AND UNIX) diff --git a/plugins/samplesource/filesource/CMakeLists.txt b/plugins/samplesource/filesource/CMakeLists.txt index 23d26212e..c94ac1a0b 100644 --- a/plugins/samplesource/filesource/CMakeLists.txt +++ b/plugins/samplesource/filesource/CMakeLists.txt @@ -23,7 +23,6 @@ include_directories( ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_SOURCE_DIR}/include ${CMAKE_SOURCE_DIR}/include-gpl - ${LIBRTLSDR_INCLUDE_DIR} ) #include(${QT_USE_FILE}) @@ -42,7 +41,6 @@ add_library(inputfilesource SHARED target_link_libraries(inputfilesource ${QT_LIBRARIES} - ${LIBUSB_LIBRARIES} sdrbase ) diff --git a/plugins/samplesource/sdrdaemon/CMakeLists.txt b/plugins/samplesource/sdrdaemon/CMakeLists.txt index 2258a55a1..082f1bd64 100644 --- a/plugins/samplesource/sdrdaemon/CMakeLists.txt +++ b/plugins/samplesource/sdrdaemon/CMakeLists.txt @@ -7,7 +7,6 @@ set(sdrdaemon_SOURCES sdrdaemongui.cpp sdrdaemoninput.cpp sdrdaemonplugin.cpp - sdrdaemonthread.cpp sdrdaemonudphandler.cpp ) @@ -16,7 +15,6 @@ set(sdrdaemon_HEADERS sdrdaemongui.h sdrdaemoninput.h sdrdaemonplugin.h - sdrdaemonthread.h sdrdaemonudphandler.h ) diff --git a/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.cpp b/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.cpp index 1c4856524..6584de777 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.cpp +++ b/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.cpp @@ -19,8 +19,9 @@ #include #include "sdrdaemonbuffer.h" -SDRdaemonBuffer::SDRdaemonBuffer(uint32_t blockSize) : +SDRdaemonBuffer::SDRdaemonBuffer(uint32_t blockSize, uint32_t rateDivider) : m_blockSize(blockSize), + m_rateDivider(rateDivider), m_sync(false), m_lz4(false), m_inCount(0), @@ -40,7 +41,7 @@ SDRdaemonBuffer::SDRdaemonBuffer(uint32_t blockSize) : m_readCount(0), m_rawSize(0), m_rawBuffer(0), - m_frameBuffer(0), + m_chunkBuffer(0), m_bytesInBlock(0), m_nbBlocks(0) { @@ -61,8 +62,8 @@ SDRdaemonBuffer::~SDRdaemonBuffer() delete[] m_lz4OutBuffer; } - if (m_frameBuffer) { - delete[] m_frameBuffer; + if (m_chunkBuffer) { + delete[] m_chunkBuffer; } } @@ -140,7 +141,8 @@ void SDRdaemonBuffer::writeData(char *array, uint32_t length) } else { - writeDataUncompressed(array, length); + //writeDataUncompressed(array, length); + writeToRawBufferUncompressed(array, length); } } } @@ -249,10 +251,11 @@ uint8_t *SDRdaemonBuffer::readData(uint32_t length) } else { - std::memcpy((void *) m_frameBuffer, (const void *) &m_rawBuffer[readCount], m_rawSize - m_readCount); // read last bit from raw buffer - m_readCount = length - (m_rawSize - m_readCount); - std::memcpy((void *) &m_frameBuffer[m_rawSize - m_readCount], (const void *) m_frameBuffer, m_readCount); // read the rest at start of raw buffer - return m_frameBuffer; + uint32_t retLength = std::min(length, m_chunkSize); + std::memcpy((void *) m_chunkBuffer, (const void *) &m_rawBuffer[readCount], m_rawSize - m_readCount); // read last bit from raw buffer + m_readCount = retLength - (m_rawSize - m_readCount); + std::memcpy((void *) &m_chunkBuffer[m_rawSize - m_readCount], (const void *) m_rawBuffer, m_readCount); // read the rest at start of raw buffer + return m_chunkBuffer; } } @@ -290,11 +293,12 @@ void SDRdaemonBuffer::updateBufferSize(uint32_t sampleRate, uint32_t frameSize) m_rawSize = nbFrames * frameSize; m_rawBuffer = new uint8_t[m_rawSize]; - if (m_frameBuffer) { - delete[] m_frameBuffer; + if (m_chunkBuffer) { + delete[] m_chunkBuffer; } - m_frameBuffer = new uint8_t[frameSize]; + m_chunkSize = (sampleRate * 2 * 2) / m_rateDivider; + m_chunkBuffer = new uint8_t[m_chunkSize]; } void SDRdaemonBuffer::updateBlockCounts(uint32_t nbBytesReceived) diff --git a/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h b/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h index 95c527030..92a7c0d1a 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h +++ b/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h @@ -61,7 +61,7 @@ public: }; #pragma pack(pop) - SDRdaemonBuffer(uint32_t blockSize); + SDRdaemonBuffer(uint32_t blockSize, uint32_t rateDivider); ~SDRdaemonBuffer(); bool readMeta(char *array, uint32_t length); //!< Attempt to read meta. Returns true if meta block void writeData(char *array, uint32_t length); //!< Write data into buffer. @@ -79,7 +79,8 @@ private: void updateBufferSize(uint32_t sampleRate, uint32_t frameSize); void printMeta(MetaData *metaData); - std::size_t m_blockSize; //!< UDP block (payload) size + uint32_t m_blockSize; //!< UDP block (payload) size + uint32_t m_rateDivider; //!< Number of times per seconds the samples are fetched bool m_sync; //!< Meta data acquired (Stream synchronized) bool m_lz4; //!< Stream is compressed with LZ4 MetaData m_currentMeta; //!< Stored current meta data @@ -104,7 +105,8 @@ private: uint32_t m_readCount; //!< Current read position in the raw samples buffer uint32_t m_rawSize; //!< Size of the raw samples buffer in bytes uint8_t *m_rawBuffer; //!< Buffer for raw samples obtained from UDP (I/Q not in a formal I/Q structure) - uint8_t *m_frameBuffer; //!< Buffer to build a frame length of raw samples + uint8_t *m_chunkBuffer; //!< Buffer to build a chunk length of raw samples + uint32_t m_chunkSize; //!< Size of a chunk of samples in bytes uint32_t m_bytesInBlock; //!< Number of bytes received in the current UDP block uint32_t m_nbBlocks; //!< Number of UDP blocks received in the current frame }; diff --git a/plugins/samplesource/sdrdaemon/sdrdaemonudphandler.cpp b/plugins/samplesource/sdrdaemon/sdrdaemonudphandler.cpp index f1ce3082c..769bd447b 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemonudphandler.cpp +++ b/plugins/samplesource/sdrdaemon/sdrdaemonudphandler.cpp @@ -17,6 +17,8 @@ #include #include #include +#include "dsp/dspcommands.h" +#include "dsp/dspengine.h" #include "sdrdaemonudphandler.h" #include "sdrdaemoninput.h" @@ -25,7 +27,7 @@ const int SDRdaemonUDPHandler::m_udpPayloadSize = 512; SDRdaemonUDPHandler::SDRdaemonUDPHandler(SampleFifo *sampleFifo, MessageQueue *outputMessageQueueToGUI) : m_mutex(QMutex::Recursive), - m_sdrDaemonBuffer(m_udpPayloadSize), + m_sdrDaemonBuffer(m_udpPayloadSize, m_rateDivider), m_dataSocket(0), m_dataAddress(QHostAddress::LocalHost), m_dataPort(9090), @@ -140,11 +142,13 @@ void SDRdaemonUDPHandler::processData() if (change) { + DSPSignalNotification *notif = new DSPSignalNotification(m_samplerate, m_centerFrequency); + DSPEngine::instance()->getInputMessageQueue()->push(notif); SDRdaemonInput::MsgReportSDRdaemonStreamData *report = SDRdaemonInput::MsgReportSDRdaemonStreamData::create( - metaData.m_sampleRate, - metaData.m_centerFrequency, - metaData.m_tv_sec, - metaData.m_tv_usec); + m_samplerate, + m_centerFrequency, + m_tv_sec, + m_tv_usec); m_outputMessageQueueToGUI->push(report); } } From f04b6c4dc1f90d4defe83d9f62b8d5c41da77c65 Mon Sep 17 00:00:00 2001 From: f4exb Date: Wed, 17 Feb 2016 23:47:03 +0100 Subject: [PATCH 20/51] SDRdaemon plugin: implement DC offset and IQ imbalance corrections --- plugins/samplesource/sdrdaemon/CMakeLists.txt | 2 - .../samplesource/sdrdaemon/sdrdaemongui.cpp | 50 ++--- plugins/samplesource/sdrdaemon/sdrdaemongui.h | 5 + .../samplesource/sdrdaemon/sdrdaemongui.ui | 188 +++++++++++------- .../samplesource/sdrdaemon/sdrdaemoninput.cpp | 10 + .../samplesource/sdrdaemon/sdrdaemoninput.h | 22 ++ 6 files changed, 183 insertions(+), 94 deletions(-) diff --git a/plugins/samplesource/sdrdaemon/CMakeLists.txt b/plugins/samplesource/sdrdaemon/CMakeLists.txt index 082f1bd64..a191fe0f7 100644 --- a/plugins/samplesource/sdrdaemon/CMakeLists.txt +++ b/plugins/samplesource/sdrdaemon/CMakeLists.txt @@ -27,7 +27,6 @@ include_directories( ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_SOURCE_DIR}/include ${CMAKE_SOURCE_DIR}/include-gpl - ${LIBRTLSDR_INCLUDE_DIR} ) #include(${QT_USE_FILE}) @@ -50,7 +49,6 @@ target_include_directories(inputsdrdaemon PUBLIC target_link_libraries(inputsdrdaemon ${QT_LIBRARIES} - ${LIBUSB_LIBRARIES} ${LZ4_LIBRARIES} sdrbase ) diff --git a/plugins/samplesource/sdrdaemon/sdrdaemongui.cpp b/plugins/samplesource/sdrdaemon/sdrdaemongui.cpp index 6cccf59ea..a9bebf701 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemongui.cpp +++ b/plugins/samplesource/sdrdaemon/sdrdaemongui.cpp @@ -39,7 +39,9 @@ SDRdaemonGui::SDRdaemonGui(PluginAPI* pluginAPI, QWidget* parent) : m_sampleRate(0), m_centerFrequency(0), m_samplesCount(0), - m_tickCount(0) + m_tickCount(0), + m_dcBlock(false), + m_iqCorrection(false) { m_startingTimeStamp.tv_sec = 0; m_startingTimeStamp.tv_usec = 0; @@ -173,7 +175,7 @@ void SDRdaemonGui::handleSourceMessages() while ((message = m_sampleSource->getOutputMessageQueueToGUI()->pop()) != 0) { - qDebug("SDRdaemonGui::handleSourceMessages: message: %s", message->getIdentifier()); + //qDebug("SDRdaemonGui::handleSourceMessages: message: %s", message->getIdentifier()); if (handleMessage(*message)) { @@ -184,6 +186,8 @@ void SDRdaemonGui::handleSourceMessages() void SDRdaemonGui::displaySettings() { + ui->dcOffset->setChecked(m_dcBlock); + ui->iqImbalance->setChecked(m_iqCorrection); } /* @@ -198,6 +202,26 @@ void SDRdaemonGui::on_applyButton_clicked(bool checked) configureUDPLink(); } +void SDRdaemonGui::on_dcOffset_toggled(bool checked) +{ + if (m_dcBlock != checked) + { + m_dcBlock = checked; + SDRdaemonInput::MsgConfigureSDRdaemonAutoCorr* message = SDRdaemonInput::MsgConfigureSDRdaemonAutoCorr::create(m_dcBlock, m_iqCorrection); + m_sampleSource->getInputMessageQueue()->push(message); + } +} + +void SDRdaemonGui::on_iqImbalance_toggled(bool checked) +{ + if (m_iqCorrection != checked) + { + m_iqCorrection = checked; + SDRdaemonInput::MsgConfigureSDRdaemonAutoCorr* message = SDRdaemonInput::MsgConfigureSDRdaemonAutoCorr::create(m_dcBlock, m_iqCorrection); + m_sampleSource->getInputMessageQueue()->push(message); + } +} + void SDRdaemonGui::configureUDPLink() { bool ok; @@ -232,28 +256,8 @@ void SDRdaemonGui::updateWithStreamTime() { quint64 startingTimeStampMsec = (m_startingTimeStamp.tv_sec * 1000) + (m_startingTimeStamp.tv_usec / 1000); QDateTime dt = QDateTime::fromMSecsSinceEpoch(startingTimeStampMsec); - QString s_date = dt.toString("yyyyMMdd hh.mm.ss.zzz"); + QString s_date = dt.toString("yyyy-MM-dd hh:mm:ss.zzz"); ui->absTimeText->setText(s_date); - /* - int t_sec = 0; - int t_msec = 0; - - if (m_sampleRate > 0){ - t_msec = ((m_samplesCount * 1000) / m_sampleRate) % 1000; - t_sec = m_samplesCount / m_sampleRate; - } - - QTime t(0, 0, 0, 0); - t = t.addSecs(t_sec); - t = t.addMSecs(t_msec); - QString s_time = t.toString("hh:mm:ss.zzz"); - - quint64 startingTimeStampMsec = m_startingTimeStamp * 1000; - QDateTime dt = QDateTime::fromMSecsSinceEpoch(startingTimeStampMsec); - dt = dt.addSecs(t_sec); - dt = dt.addMSecs(t_msec); - QString s_date = dt.toString("yyyyMMdd hh.mm.ss.zzz"); - ui->absTimeText->setText(s_date);*/ } void SDRdaemonGui::tick() diff --git a/plugins/samplesource/sdrdaemon/sdrdaemongui.h b/plugins/samplesource/sdrdaemon/sdrdaemongui.h index 8ed697b8d..baa640374 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemongui.h +++ b/plugins/samplesource/sdrdaemon/sdrdaemongui.h @@ -60,6 +60,9 @@ private: int m_samplesCount; std::size_t m_tickCount; + bool m_dcBlock; + bool m_iqCorrection; + void displaySettings(); void displayTime(); void configureUDPLink(); @@ -70,6 +73,8 @@ private: private slots: void handleSourceMessages(); void on_applyButton_clicked(bool checked); + void on_dcOffset_toggled(bool checked); + void on_iqImbalance_toggled(bool checked); void tick(); }; diff --git a/plugins/samplesource/sdrdaemon/sdrdaemongui.ui b/plugins/samplesource/sdrdaemon/sdrdaemongui.ui index 77943b0a6..f19d28026 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemongui.ui +++ b/plugins/samplesource/sdrdaemon/sdrdaemongui.ui @@ -103,6 +103,119 @@ + + + + Qt::Horizontal + + + + + + + + + Rate: + + + + + + + + 50 + 0 + + + + + 8 + + + + Record sample rate + + + 0k + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Qt::Vertical + + + + + + + false + + + Record absolute time + + + 20150101 00:00:00.000 + + + + + + + + + Qt::Horizontal + + + + + + + + + Auto corr + + + + + + + DC Offset auto correction + + + DC Offset + + + + + + + IQ Imbalance auto correction + + + IQ Imbalance + + + + + @@ -175,75 +288,7 @@ - - - - - Rate: - - - - - - - - 50 - 0 - - - - - 8 - - - - Record sample rate - - - 0k - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - Qt::Vertical - - - - - - - false - - - Record absolute time - - - 20150101 00:00:00.000 - - - - - - - + Qt::Horizontal @@ -261,6 +306,11 @@
gui/valuedial.h
1 + + ButtonSwitch + QToolButton +
gui/buttonswitch.h
+
diff --git a/plugins/samplesource/sdrdaemon/sdrdaemoninput.cpp b/plugins/samplesource/sdrdaemon/sdrdaemoninput.cpp index e0693390b..4ce93a06f 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemoninput.cpp +++ b/plugins/samplesource/sdrdaemon/sdrdaemoninput.cpp @@ -28,6 +28,7 @@ #include "sdrdaemonudphandler.h" MESSAGE_CLASS_DEFINITION(SDRdaemonInput::MsgConfigureSDRdaemonUDPLink, Message) +MESSAGE_CLASS_DEFINITION(SDRdaemonInput::MsgConfigureSDRdaemonAutoCorr, Message) MESSAGE_CLASS_DEFINITION(SDRdaemonInput::MsgConfigureSDRdaemonWork, Message) MESSAGE_CLASS_DEFINITION(SDRdaemonInput::MsgConfigureSDRdaemonStreamTiming, Message) MESSAGE_CLASS_DEFINITION(SDRdaemonInput::MsgReportSDRdaemonAcquisition, Message) @@ -100,6 +101,15 @@ bool SDRdaemonInput::handleMessage(const Message& message) { if (MsgConfigureSDRdaemonUDPLink::match(message)) { + // TODO: change UDP settings + return true; + } + else if (MsgConfigureSDRdaemonAutoCorr::match(message)) + { + MsgConfigureSDRdaemonAutoCorr& conf = (MsgConfigureSDRdaemonAutoCorr&) message; + bool dcBlock = conf.getDCBlock(); + bool iqImbalance = conf.getIQImbalance(); + DSPEngine::instance()->configureCorrections(dcBlock, iqImbalance); return true; } else if (MsgConfigureSDRdaemonWork::match(message)) diff --git a/plugins/samplesource/sdrdaemon/sdrdaemoninput.h b/plugins/samplesource/sdrdaemon/sdrdaemoninput.h index e17c8676c..f89be1e81 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemoninput.h +++ b/plugins/samplesource/sdrdaemon/sdrdaemoninput.h @@ -51,6 +51,28 @@ public: { } }; + class MsgConfigureSDRdaemonAutoCorr : public Message { + MESSAGE_CLASS_DECLARATION + public: + bool getDCBlock() const { return m_dcBlock; } + bool getIQImbalance() const { return m_iqCorrection; } + + static MsgConfigureSDRdaemonAutoCorr* create(bool dcBlock, bool iqImbalance) + { + return new MsgConfigureSDRdaemonAutoCorr(dcBlock, iqImbalance); + } + + private: + bool m_dcBlock; + bool m_iqCorrection; + + MsgConfigureSDRdaemonAutoCorr(bool dcBlock, bool iqImbalance) : + Message(), + m_dcBlock(dcBlock), + m_iqCorrection(iqImbalance) + { } + }; + class MsgConfigureSDRdaemonWork : public Message { MESSAGE_CLASS_DECLARATION From 0b0d57724cfd5e39a64279dde1ef0e4c8a55918c Mon Sep 17 00:00:00 2001 From: f4exb Date: Thu, 18 Feb 2016 00:33:04 +0100 Subject: [PATCH 21/51] SDRdaemon plugin: corrected main spectrum frequency display --- plugins/samplesource/sdrdaemon/sdrdaemongui.ui | 8 +++++++- plugins/samplesource/sdrdaemon/sdrdaemonudphandler.cpp | 4 ++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/plugins/samplesource/sdrdaemon/sdrdaemongui.ui b/plugins/samplesource/sdrdaemon/sdrdaemongui.ui index f19d28026..3f35fd068 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemongui.ui +++ b/plugins/samplesource/sdrdaemon/sdrdaemongui.ui @@ -172,7 +172,7 @@ Record absolute time - 20150101 00:00:00.000 + 2015-01-01 00:00:00.000
@@ -240,6 +240,9 @@ 0 + + 127.0.0.1 + @@ -257,6 +260,9 @@ 0 + + 9090 + diff --git a/plugins/samplesource/sdrdaemon/sdrdaemonudphandler.cpp b/plugins/samplesource/sdrdaemon/sdrdaemonudphandler.cpp index 769bd447b..ff6c2f3f1 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemonudphandler.cpp +++ b/plugins/samplesource/sdrdaemon/sdrdaemonudphandler.cpp @@ -142,11 +142,11 @@ void SDRdaemonUDPHandler::processData() if (change) { - DSPSignalNotification *notif = new DSPSignalNotification(m_samplerate, m_centerFrequency); + DSPSignalNotification *notif = new DSPSignalNotification(m_samplerate, m_centerFrequency * 1000); // Frequency in Hz for the DSP engine DSPEngine::instance()->getInputMessageQueue()->push(notif); SDRdaemonInput::MsgReportSDRdaemonStreamData *report = SDRdaemonInput::MsgReportSDRdaemonStreamData::create( m_samplerate, - m_centerFrequency, + m_centerFrequency, // Frequency in kHz for the GUI m_tv_sec, m_tv_usec); m_outputMessageQueueToGUI->push(report); From 07bfcb04dc37218f00c59ba61afb0ee68c64e688 Mon Sep 17 00:00:00 2001 From: f4exb Date: Thu, 18 Feb 2016 01:24:58 +0100 Subject: [PATCH 22/51] SDRdaemo: serialize auto corrections --- Readme.md | 16 ++++++ .../sdrdaemon/sdrdaemonbuffer.cpp | 2 +- .../samplesource/sdrdaemon/sdrdaemongui.cpp | 49 ++++++++++++------- plugins/samplesource/sdrdaemon/sdrdaemongui.h | 3 ++ 4 files changed, 52 insertions(+), 18 deletions(-) diff --git a/Readme.md b/Readme.md index a6ddeed90..b3d437675 100644 --- a/Readme.md +++ b/Readme.md @@ -99,6 +99,22 @@ If you use your own location for librtlsdr install directory you need to specify `-DLIBRTLSDR_LIBRARIES=/opt/install/librtlsdr/lib/librtlsdr.so -DLIBRTLSDR_INCLUDE_DIR=/opt/install/librtlsdr/include` +

Plugins for special devices

+ +

File input

+ +The file input plugin allows the playback of a recorded IQ file. Such a file is obtained using the recording feature. Press F7 to start recording and F8 to stop. The file has a fixed name `test.sdriq` created in the current directory. + +Note that this plugin does not require any of the hardware support libraries nor the libusb library. It is alwasys available in the list of devices as `FileSource[0]` even if no physical device is connected. + +

SDRdaemon input

+ +Warning: this is experimental is buggy (algorithm to retrieve samples is flawed). + +This is the client side of the SDRdaemon server. See the [SDRdaemon](https://github.com/f4exb/sdrdaemon) project in this Github repository. You must specify the address and UDP port to which the server connects and samples will flow into the SDRangel application (default is `127.0.0.1`port `9090`). It uses the meta data to retrieve the sample flow characteristics such as sample rate and receiveng center frequency. + +Note that this plugin does not require any of the hardware support libraries nor the libusb library. It is alwasys available in the list of devices as `SDRdaemon[0]` even if no physical device is connected. +

Software build

Ubuntu

diff --git a/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.cpp b/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.cpp index 6584de777..1e1198d61 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.cpp +++ b/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.cpp @@ -223,7 +223,7 @@ void SDRdaemonBuffer::writeToRawBufferUncompressed(const char *array, uint32_t l { std::memcpy((void *) &m_rawBuffer[m_rawCount], (const void *) array, m_rawSize - m_rawCount); m_rawCount = length - (m_rawSize - m_rawCount); - std::memcpy((void *) m_rawBuffer, (const void *) array, m_rawCount); + std::memcpy((void *) m_rawBuffer, (const void *) &array[m_rawSize - m_rawCount], m_rawCount); } } diff --git a/plugins/samplesource/sdrdaemon/sdrdaemongui.cpp b/plugins/samplesource/sdrdaemon/sdrdaemongui.cpp index a9bebf701..93dbfbfc7 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemongui.cpp +++ b/plugins/samplesource/sdrdaemon/sdrdaemongui.cpp @@ -40,6 +40,8 @@ SDRdaemonGui::SDRdaemonGui(PluginAPI* pluginAPI, QWidget* parent) : m_centerFrequency(0), m_samplesCount(0), m_tickCount(0), + m_address("127.0.0.1"), + m_port(9090), m_dcBlock(false), m_iqCorrection(false) { @@ -80,6 +82,10 @@ QString SDRdaemonGui::getName() const void SDRdaemonGui::resetToDefaults() { + m_address = "127.0.0.1"; + m_port = 9090; + m_dcBlock = false; + m_iqCorrection = false; displaySettings(); } @@ -87,12 +93,18 @@ QByteArray SDRdaemonGui::serialize() const { bool ok; SimpleSerializer s(1); + s.writeString(1, ui->address->text()); uint32_t uintval = ui->port->text().toInt(&ok); + if((!ok) || (uintval < 1024) || (uintval > 65535)) { uintval = 9090; } + s.writeU32(2, uintval); + s.writeBool(3, m_dcBlock); + s.writeBool(4, m_iqCorrection); + return s.final(); } @@ -110,24 +122,27 @@ bool SDRdaemonGui::deserialize(const QByteArray& data) if(d.getVersion() == 1) { uint32_t uintval; - d.readString(1, &address, "127.0.0.1"); + d.readString(1, &m_address, "127.0.0.1"); d.readU32(2, &uintval, 9090); + if ((uintval > 1024) && (uintval < 65536)) { - port = uintval; + m_port = uintval; } else { - port = 9090; + m_port = 9090; } + + d.readBool(3, &m_dcBlock, false); + d.readBool(4, &m_iqCorrection, false); + return true; } else { resetToDefaults(); return false; } - ui->address->setText(address); - ui->port->setText(QString::number(port)); + displaySettings(); } - qint64 SDRdaemonGui::getCenterFrequency() const { return m_centerFrequency; @@ -186,17 +201,12 @@ void SDRdaemonGui::handleSourceMessages() void SDRdaemonGui::displaySettings() { + ui->address->setText(m_address); + ui->port->setText(QString::number(m_port)); ui->dcOffset->setChecked(m_dcBlock); ui->iqImbalance->setChecked(m_iqCorrection); } -/* -void SDRdaemonGui::on_play_toggled(bool checked) -{ - SDRdaemonInput::MsgConfigureSDRdaemonWork* message = SDRdaemonInput::MsgConfigureSDRdaemonWork::create(checked); - m_sampleSource->getInputMessageQueue()->push(message); -}*/ - void SDRdaemonGui::on_applyButton_clicked(bool checked) { configureUDPLink(); @@ -207,8 +217,7 @@ void SDRdaemonGui::on_dcOffset_toggled(bool checked) if (m_dcBlock != checked) { m_dcBlock = checked; - SDRdaemonInput::MsgConfigureSDRdaemonAutoCorr* message = SDRdaemonInput::MsgConfigureSDRdaemonAutoCorr::create(m_dcBlock, m_iqCorrection); - m_sampleSource->getInputMessageQueue()->push(message); + configureAutoCorrections(); } } @@ -217,8 +226,7 @@ void SDRdaemonGui::on_iqImbalance_toggled(bool checked) if (m_iqCorrection != checked) { m_iqCorrection = checked; - SDRdaemonInput::MsgConfigureSDRdaemonAutoCorr* message = SDRdaemonInput::MsgConfigureSDRdaemonAutoCorr::create(m_dcBlock, m_iqCorrection); - m_sampleSource->getInputMessageQueue()->push(message); + configureAutoCorrections(); } } @@ -240,6 +248,12 @@ void SDRdaemonGui::configureUDPLink() m_sampleSource->getInputMessageQueue()->push(message); } +void SDRdaemonGui::configureAutoCorrections() +{ + SDRdaemonInput::MsgConfigureSDRdaemonAutoCorr* message = SDRdaemonInput::MsgConfigureSDRdaemonAutoCorr::create(m_dcBlock, m_iqCorrection); + m_sampleSource->getInputMessageQueue()->push(message); +} + void SDRdaemonGui::updateWithAcquisition() { } @@ -267,3 +281,4 @@ void SDRdaemonGui::tick() m_sampleSource->getInputMessageQueue()->push(message); } } + diff --git a/plugins/samplesource/sdrdaemon/sdrdaemongui.h b/plugins/samplesource/sdrdaemon/sdrdaemongui.h index baa640374..3760f7c12 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemongui.h +++ b/plugins/samplesource/sdrdaemon/sdrdaemongui.h @@ -60,12 +60,15 @@ private: int m_samplesCount; std::size_t m_tickCount; + QString m_address; + quint16 m_port; bool m_dcBlock; bool m_iqCorrection; void displaySettings(); void displayTime(); void configureUDPLink(); + void configureAutoCorrections(); void updateWithAcquisition(); void updateWithStreamData(); void updateWithStreamTime(); From d267d56de56b413c2548d774cc49e00b9fcbe707 Mon Sep 17 00:00:00 2001 From: f4exb Date: Thu, 18 Feb 2016 22:26:47 +0100 Subject: [PATCH 23/51] Sdrdaemon: fixed SDRdaemon buffer read pointer update --- .../sdrdaemon/sdrdaemonbuffer.cpp | 38 ++++++------------- .../samplesource/sdrdaemon/sdrdaemonbuffer.h | 3 +- .../sdrdaemon/sdrdaemonudphandler.cpp | 9 +---- .../sdrdaemon/sdrdaemonudphandler.h | 6 +-- 4 files changed, 14 insertions(+), 42 deletions(-) diff --git a/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.cpp b/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.cpp index 1e1198d61..7fa12bbf5 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.cpp +++ b/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.cpp @@ -37,7 +37,7 @@ SDRdaemonBuffer::SDRdaemonBuffer(uint32_t blockSize, uint32_t rateDivider) : m_sampleRate(1000000), m_sampleBytes(2), m_sampleBits(12), - m_rawCount(0), + m_writeCount(0), m_readCount(0), m_rawSize(0), m_rawBuffer(0), @@ -141,26 +141,11 @@ void SDRdaemonBuffer::writeData(char *array, uint32_t length) } else { - //writeDataUncompressed(array, length); writeToRawBufferUncompressed(array, length); } } } -void SDRdaemonBuffer::writeDataUncompressed(const char *array, uint32_t length) -{ - if (m_inCount + length < m_frameSize) - { - std::memcpy((void *) &m_rawBuffer[m_rawCount], (const void *) array, length); - m_inCount += length; - } - else if (m_inCount < m_frameSize) - { - std::memcpy((void *) &m_rawBuffer[m_rawCount], (const void *) array, m_frameSize - m_inCount); // copy rest of data in compressed Buffer - m_inCount += m_frameSize - m_inCount; - } -} - void SDRdaemonBuffer::writeDataLZ4(const char *array, uint32_t length) { if (m_lz4InCount + length < m_lz4InSize) @@ -197,7 +182,7 @@ void SDRdaemonBuffer::writeDataLZ4(const char *array, uint32_t length) m_nbCRCOK++; } - int compressedSize = LZ4_decompress_fast((const char*) m_lz4InBuffer, (char*) &m_rawBuffer[m_rawCount], m_frameSize); + int compressedSize = LZ4_decompress_fast((const char*) m_lz4InBuffer, (char*) &m_rawBuffer[m_writeCount], m_frameSize); m_nbDecodes++; if (compressedSize == m_lz4InSize) @@ -214,16 +199,16 @@ void SDRdaemonBuffer::writeDataLZ4(const char *array, uint32_t length) void SDRdaemonBuffer::writeToRawBufferUncompressed(const char *array, uint32_t length) { // TODO: handle the 1 byte per I or Q sample - if (m_rawCount + length < m_rawSize) + if (m_writeCount + length < m_rawSize) { - std::memcpy((void *) &m_rawBuffer[m_rawCount], (const void *) array, length); - m_rawCount += length; + std::memcpy((void *) &m_rawBuffer[m_writeCount], (const void *) array, length); + m_writeCount += length; } else { - std::memcpy((void *) &m_rawBuffer[m_rawCount], (const void *) array, m_rawSize - m_rawCount); - m_rawCount = length - (m_rawSize - m_rawCount); - std::memcpy((void *) m_rawBuffer, (const void *) &array[m_rawSize - m_rawCount], m_rawCount); + std::memcpy((void *) &m_rawBuffer[m_writeCount], (const void *) array, m_rawSize - m_writeCount); + m_writeCount = length - (m_rawSize - m_writeCount); + std::memcpy((void *) m_rawBuffer, (const void *) &array[m_rawSize - m_writeCount], m_writeCount); } } @@ -242,17 +227,16 @@ void SDRdaemonBuffer::writeToRawBufferLZ4(const char *array, uint32_t length) uint8_t *SDRdaemonBuffer::readData(uint32_t length) { - uint32_t readCount = m_readCount; - if (m_readCount + length < m_rawSize) { - return &m_rawBuffer[readCount]; + uint32_t readCount = m_readCount; m_readCount += length; + return &m_rawBuffer[readCount]; } else { uint32_t retLength = std::min(length, m_chunkSize); - std::memcpy((void *) m_chunkBuffer, (const void *) &m_rawBuffer[readCount], m_rawSize - m_readCount); // read last bit from raw buffer + std::memcpy((void *) m_chunkBuffer, (const void *) &m_rawBuffer[m_readCount], m_rawSize - m_readCount); // read last bit from raw buffer m_readCount = retLength - (m_rawSize - m_readCount); std::memcpy((void *) &m_chunkBuffer[m_rawSize - m_readCount], (const void *) m_rawBuffer, m_readCount); // read the rest at start of raw buffer return m_chunkBuffer; diff --git a/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h b/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h index 92a7c0d1a..55c6f7ca1 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h +++ b/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h @@ -73,7 +73,6 @@ public: private: void updateLZ4Sizes(uint32_t frameSize); void writeDataLZ4(const char *array, uint32_t length); - void writeDataUncompressed(const char *array, uint32_t length); void writeToRawBufferLZ4(const char *array, uint32_t originalLength); void writeToRawBufferUncompressed(const char *array, uint32_t length); void updateBufferSize(uint32_t sampleRate, uint32_t frameSize); @@ -101,7 +100,7 @@ private: uint8_t m_sampleBytes; //!< Current number of bytes per I or Q sample uint8_t m_sampleBits; //!< Current number of effective bits per sample - uint32_t m_rawCount; //!< Current write position in the raw samples buffer + uint32_t m_writeCount; //!< Current write position in the raw samples buffer uint32_t m_readCount; //!< Current read position in the raw samples buffer uint32_t m_rawSize; //!< Size of the raw samples buffer in bytes uint8_t *m_rawBuffer; //!< Buffer for raw samples obtained from UDP (I/Q not in a formal I/Q structure) diff --git a/plugins/samplesource/sdrdaemon/sdrdaemonudphandler.cpp b/plugins/samplesource/sdrdaemon/sdrdaemonudphandler.cpp index ff6c2f3f1..cf08f181e 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemonudphandler.cpp +++ b/plugins/samplesource/sdrdaemon/sdrdaemonudphandler.cpp @@ -26,7 +26,6 @@ const int SDRdaemonUDPHandler::m_rateDivider = 1000/SDRDAEMON_THROTTLE_MS; const int SDRdaemonUDPHandler::m_udpPayloadSize = 512; SDRdaemonUDPHandler::SDRdaemonUDPHandler(SampleFifo *sampleFifo, MessageQueue *outputMessageQueueToGUI) : - m_mutex(QMutex::Recursive), m_sdrDaemonBuffer(m_udpPayloadSize, m_rateDivider), m_dataSocket(0), m_dataAddress(QHostAddress::LocalHost), @@ -67,7 +66,6 @@ void SDRdaemonUDPHandler::start() if (m_dataSocket->bind(m_dataAddress, m_dataPort)) { qDebug("SDRdaemonUDPHandler::start: bind data socket to port %d", m_dataPort); - connect(this, SIGNAL(dataReady()), this, SLOT(processData())); connect(m_dataSocket, SIGNAL(readyRead()), this, SLOT(dataReadyRead()), Qt::QueuedConnection); // , Qt::QueuedConnection m_dataConnected = true; } @@ -85,7 +83,6 @@ void SDRdaemonUDPHandler::stop() if (m_dataConnected) { disconnect(m_dataSocket, SIGNAL(readyRead()), this, SLOT(dataReadyRead())); - disconnect(this, SIGNAL(dataReady()), this, SLOT(processData)); m_dataConnected = false; } @@ -104,7 +101,7 @@ void SDRdaemonUDPHandler::dataReadyRead() { qint64 pendingDataSize = m_dataSocket->pendingDatagramSize(); m_udpReadBytes = m_dataSocket->readDatagram(m_udpBuf, pendingDataSize, 0, 0); - emit dataReady(); + processData(); } } @@ -116,8 +113,6 @@ void SDRdaemonUDPHandler::processData() } else if (m_udpReadBytes > 0) { - QMutexLocker ml(&m_mutex); - m_sdrDaemonBuffer.updateBlockCounts(m_udpReadBytes); if (m_sdrDaemonBuffer.readMeta(m_udpBuf, m_udpReadBytes)) @@ -165,8 +160,6 @@ void SDRdaemonUDPHandler::setSamplerate(uint32_t samplerate) << " new:" << samplerate << " old:" << m_samplerate; - QMutexLocker ml(&m_mutex); - m_samplerate = samplerate; m_chunksize = (m_samplerate / m_rateDivider)*4; // TODO: implement FF and slow motion here. 4 corresponds to live. 2 is half speed, 8 is doulbe speed m_bufsize = m_chunksize; diff --git a/plugins/samplesource/sdrdaemon/sdrdaemonudphandler.h b/plugins/samplesource/sdrdaemon/sdrdaemonudphandler.h index 8f033cf01..c056f4cfc 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemonudphandler.h +++ b/plugins/samplesource/sdrdaemon/sdrdaemonudphandler.h @@ -41,13 +41,8 @@ public: public slots: void dataReadyRead(); - void processData(); - -signals: - void dataReady(); private: - QMutex m_mutex; SDRdaemonBuffer m_sdrDaemonBuffer; QUdpSocket *m_dataSocket; QHostAddress m_dataAddress; @@ -71,6 +66,7 @@ private: static const int m_udpPayloadSize; void setSamplerate(uint32_t samplerate); + void processData(); private slots: void tick(); From 6b1622279291d7885ee7ba1f0b5bd72425c2cc57 Mon Sep 17 00:00:00 2001 From: f4exb Date: Fri, 19 Feb 2016 08:48:14 +0100 Subject: [PATCH 24/51] SDRdaemon plugin: works with bugs --- Readme.md | 2 +- plugins/samplesource/sdrdaemon/sdrdaemonbuffer.cpp | 5 +++++ plugins/samplesource/sdrdaemon/sdrdaemonudphandler.cpp | 8 ++++++++ plugins/samplesource/sdrdaemon/sdrdaemonudphandler.h | 5 +++++ 4 files changed, 19 insertions(+), 1 deletion(-) diff --git a/Readme.md b/Readme.md index b3d437675..6bd609853 100644 --- a/Readme.md +++ b/Readme.md @@ -109,7 +109,7 @@ Note that this plugin does not require any of the hardware support libraries nor

SDRdaemon input

-Warning: this is experimental is buggy (algorithm to retrieve samples is flawed). +Warning: this is experimental and not fulle debugged yet. This is the client side of the SDRdaemon server. See the [SDRdaemon](https://github.com/f4exb/sdrdaemon) project in this Github repository. You must specify the address and UDP port to which the server connects and samples will flow into the SDRangel application (default is `127.0.0.1`port `9090`). It uses the meta data to retrieve the sample flow characteristics such as sample rate and receiveng center frequency. diff --git a/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.cpp b/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.cpp index 7fa12bbf5..f8afe5e8d 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.cpp +++ b/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.cpp @@ -233,9 +233,14 @@ uint8_t *SDRdaemonBuffer::readData(uint32_t length) m_readCount += length; return &m_rawBuffer[readCount]; } + //else if (m_readCount > 0) else { + if (length > m_chunkSize) { + qDebug("SDRdaemonBuffer::readData: length: %d", length); + } uint32_t retLength = std::min(length, m_chunkSize); + //uint32_t retLength = length; std::memcpy((void *) m_chunkBuffer, (const void *) &m_rawBuffer[m_readCount], m_rawSize - m_readCount); // read last bit from raw buffer m_readCount = retLength - (m_rawSize - m_readCount); std::memcpy((void *) &m_chunkBuffer[m_rawSize - m_readCount], (const void *) m_rawBuffer, m_readCount); // read the rest at start of raw buffer diff --git a/plugins/samplesource/sdrdaemon/sdrdaemonudphandler.cpp b/plugins/samplesource/sdrdaemon/sdrdaemonudphandler.cpp index cf08f181e..9a1c4618a 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemonudphandler.cpp +++ b/plugins/samplesource/sdrdaemon/sdrdaemonudphandler.cpp @@ -26,6 +26,7 @@ const int SDRdaemonUDPHandler::m_rateDivider = 1000/SDRDAEMON_THROTTLE_MS; const int SDRdaemonUDPHandler::m_udpPayloadSize = 512; SDRdaemonUDPHandler::SDRdaemonUDPHandler(SampleFifo *sampleFifo, MessageQueue *outputMessageQueueToGUI) : + //m_mutex(QMutex::Recursive), m_sdrDaemonBuffer(m_udpPayloadSize, m_rateDivider), m_dataSocket(0), m_dataAddress(QHostAddress::LocalHost), @@ -66,6 +67,7 @@ void SDRdaemonUDPHandler::start() if (m_dataSocket->bind(m_dataAddress, m_dataPort)) { qDebug("SDRdaemonUDPHandler::start: bind data socket to port %d", m_dataPort); + //connect(this, SIGNAL(dataReady()), this, SLOT(processData())); connect(m_dataSocket, SIGNAL(readyRead()), this, SLOT(dataReadyRead()), Qt::QueuedConnection); // , Qt::QueuedConnection m_dataConnected = true; } @@ -83,6 +85,7 @@ void SDRdaemonUDPHandler::stop() if (m_dataConnected) { disconnect(m_dataSocket, SIGNAL(readyRead()), this, SLOT(dataReadyRead())); + //disconnect(this, SIGNAL(dataReady()), this, SLOT(processData)); m_dataConnected = false; } @@ -101,6 +104,7 @@ void SDRdaemonUDPHandler::dataReadyRead() { qint64 pendingDataSize = m_dataSocket->pendingDatagramSize(); m_udpReadBytes = m_dataSocket->readDatagram(m_udpBuf, pendingDataSize, 0, 0); + //emit dataReady(); processData(); } } @@ -113,6 +117,8 @@ void SDRdaemonUDPHandler::processData() } else if (m_udpReadBytes > 0) { + //QMutexLocker ml(&m_mutex); + m_sdrDaemonBuffer.updateBlockCounts(m_udpReadBytes); if (m_sdrDaemonBuffer.readMeta(m_udpBuf, m_udpReadBytes)) @@ -160,6 +166,8 @@ void SDRdaemonUDPHandler::setSamplerate(uint32_t samplerate) << " new:" << samplerate << " old:" << m_samplerate; + //QMutexLocker ml(&m_mutex); + m_samplerate = samplerate; m_chunksize = (m_samplerate / m_rateDivider)*4; // TODO: implement FF and slow motion here. 4 corresponds to live. 2 is half speed, 8 is doulbe speed m_bufsize = m_chunksize; diff --git a/plugins/samplesource/sdrdaemon/sdrdaemonudphandler.h b/plugins/samplesource/sdrdaemon/sdrdaemonudphandler.h index c056f4cfc..66becc1a5 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemonudphandler.h +++ b/plugins/samplesource/sdrdaemon/sdrdaemonudphandler.h @@ -41,8 +41,13 @@ public: public slots: void dataReadyRead(); +// void processData(); + +//signals: +// void dataReady(); private: + //QMutex m_mutex; SDRdaemonBuffer m_sdrDaemonBuffer; QUdpSocket *m_dataSocket; QHostAddress m_dataAddress; From 33a196e4aad3bad11a0e2cb79584ec3d93e985da Mon Sep 17 00:00:00 2001 From: f4exb Date: Sat, 20 Feb 2016 03:41:20 +0100 Subject: [PATCH 25/51] SDRdaemon plugin: fixed buffer issues --- .../sdrdaemon/sdrdaemonbuffer.cpp | 101 +++++++++--------- .../samplesource/sdrdaemon/sdrdaemonbuffer.h | 16 +-- .../sdrdaemon/sdrdaemonudphandler.cpp | 26 ++--- .../sdrdaemon/sdrdaemonudphandler.h | 3 - 4 files changed, 65 insertions(+), 81 deletions(-) diff --git a/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.cpp b/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.cpp index f8afe5e8d..75630fcbe 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.cpp +++ b/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.cpp @@ -16,11 +16,15 @@ #include #include +#include #include #include "sdrdaemonbuffer.h" -SDRdaemonBuffer::SDRdaemonBuffer(uint32_t blockSize, uint32_t rateDivider) : - m_blockSize(blockSize), +const int SDRdaemonBuffer::m_udpPayloadSize = 512; +const int SDRdaemonBuffer::m_sampleSize = 2; +const int SDRdaemonBuffer::m_iqSampleSize = 2 * m_sampleSize; + +SDRdaemonBuffer::SDRdaemonBuffer(uint32_t rateDivider) : m_rateDivider(rateDivider), m_sync(false), m_lz4(false), @@ -37,11 +41,10 @@ SDRdaemonBuffer::SDRdaemonBuffer(uint32_t blockSize, uint32_t rateDivider) : m_sampleRate(1000000), m_sampleBytes(2), m_sampleBits(12), - m_writeCount(0), - m_readCount(0), + m_writeIndex(0), + m_readChunkIndex(0), m_rawSize(0), m_rawBuffer(0), - m_chunkBuffer(0), m_bytesInBlock(0), m_nbBlocks(0) { @@ -61,10 +64,6 @@ SDRdaemonBuffer::~SDRdaemonBuffer() if (m_lz4OutBuffer) { delete[] m_lz4OutBuffer; } - - if (m_chunkBuffer) { - delete[] m_chunkBuffer; - } } bool SDRdaemonBuffer::readMeta(char *array, uint32_t length) @@ -87,10 +86,10 @@ bool SDRdaemonBuffer::readMeta(char *array, uint32_t length) m_currentMeta = *metaData; // sanity checks - if (metaData->m_blockSize == m_blockSize) // sent blocksize matches given blocksize + if (metaData->m_blockSize == m_udpPayloadSize) // sent blocksize matches given blocksize { m_sampleBytes = metaData->m_sampleBytes & 0x0F; - uint32_t frameSize = 2 * 2 * metaData->m_nbSamples * metaData->m_nbBlocks; + uint32_t frameSize = m_iqSampleSize * metaData->m_nbSamples * metaData->m_nbBlocks; uint32_t sampleRate = metaData->m_sampleRate; if (metaData->m_sampleBytes & 0x10) @@ -109,9 +108,9 @@ bool SDRdaemonBuffer::readMeta(char *array, uint32_t length) m_lz4 = false; } - if (frameSize != m_frameSize) + if (sampleRate != m_sampleRate) { - updateBufferSize(sampleRate, frameSize); + updateBufferSize(sampleRate); } m_sampleRate = sampleRate; @@ -182,7 +181,7 @@ void SDRdaemonBuffer::writeDataLZ4(const char *array, uint32_t length) m_nbCRCOK++; } - int compressedSize = LZ4_decompress_fast((const char*) m_lz4InBuffer, (char*) &m_rawBuffer[m_writeCount], m_frameSize); + int compressedSize = LZ4_decompress_fast((const char*) m_lz4InBuffer, (char*) &m_rawBuffer[m_writeIndex], m_frameSize); m_nbDecodes++; if (compressedSize == m_lz4InSize) @@ -199,16 +198,16 @@ void SDRdaemonBuffer::writeDataLZ4(const char *array, uint32_t length) void SDRdaemonBuffer::writeToRawBufferUncompressed(const char *array, uint32_t length) { // TODO: handle the 1 byte per I or Q sample - if (m_writeCount + length < m_rawSize) + if (m_writeIndex + length < m_rawSize) { - std::memcpy((void *) &m_rawBuffer[m_writeCount], (const void *) array, length); - m_writeCount += length; + std::memcpy((void *) &m_rawBuffer[m_writeIndex], (const void *) array, length); + m_writeIndex += length; } else { - std::memcpy((void *) &m_rawBuffer[m_writeCount], (const void *) array, m_rawSize - m_writeCount); - m_writeCount = length - (m_rawSize - m_writeCount); - std::memcpy((void *) m_rawBuffer, (const void *) &array[m_rawSize - m_writeCount], m_writeCount); + std::memcpy((void *) &m_rawBuffer[m_writeIndex], (const void *) array, m_rawSize - m_writeIndex); + m_writeIndex = length - (m_rawSize - m_writeIndex); + std::memcpy((void *) m_rawBuffer, (const void *) &array[m_rawSize - m_writeIndex], m_writeIndex); } } @@ -225,27 +224,26 @@ void SDRdaemonBuffer::writeToRawBufferLZ4(const char *array, uint32_t length) writeToRawBufferUncompressed((const char *) m_lz4OutBuffer, m_frameSize); } -uint8_t *SDRdaemonBuffer::readData(uint32_t length) +uint8_t *SDRdaemonBuffer::readDataChunk() { - if (m_readCount + length < m_rawSize) + // relies on the fact that we always have an integer number of chunks in the raw buffer + + if (m_readChunkIndex == m_rateDivider * 2) // go back to start or middle of raw buffer { - uint32_t readCount = m_readCount; - m_readCount += length; - return &m_rawBuffer[readCount]; - } - //else if (m_readCount > 0) - else - { - if (length > m_chunkSize) { - qDebug("SDRdaemonBuffer::readData: length: %d", length); + // make sure the read and write pointers are not in the same half of the raw buffer + if (m_writeIndex < m_rateDivider * m_chunkSize - 1) + { + m_readChunkIndex = m_rateDivider; // go to middle + } + else + { + m_readChunkIndex = 0; // go to start } - uint32_t retLength = std::min(length, m_chunkSize); - //uint32_t retLength = length; - std::memcpy((void *) m_chunkBuffer, (const void *) &m_rawBuffer[m_readCount], m_rawSize - m_readCount); // read last bit from raw buffer - m_readCount = retLength - (m_rawSize - m_readCount); - std::memcpy((void *) &m_chunkBuffer[m_rawSize - m_readCount], (const void *) m_rawBuffer, m_readCount); // read the rest at start of raw buffer - return m_chunkBuffer; } + + uint32_t readIndex = m_readChunkIndex; + m_readChunkIndex++; + return &m_rawBuffer[readIndex * m_chunkSize]; } void SDRdaemonBuffer::updateLZ4Sizes(uint32_t frameSize) @@ -265,35 +263,34 @@ void SDRdaemonBuffer::updateLZ4Sizes(uint32_t frameSize) m_lz4OutBuffer = new uint8_t[frameSize]; } -void SDRdaemonBuffer::updateBufferSize(uint32_t sampleRate, uint32_t frameSize) +void SDRdaemonBuffer::updateBufferSize(uint32_t sampleRate) { - uint32_t nbFrames = ((sampleRate * 2 * 2) / frameSize) + 1; // store at least 1 second of samples + assert(sampleRate % m_rateDivider == 0); // make sure we get an integer number of samples in a chunk - std::cerr << "SDRdaemonBuffer::updateBufferSize:" - << " sampleRate: " << sampleRate - << " frameSize: " << frameSize - << " nbFrames: " << nbFrames - << std::endl; + // Store 2 seconds long of samples so we have two one second long half buffers + m_chunkSize = (sampleRate * m_iqSampleSize) / m_rateDivider; + m_rawSize = m_chunkSize * m_rateDivider * 2; if (m_rawBuffer) { delete[] m_rawBuffer; } - m_rawSize = nbFrames * frameSize; m_rawBuffer = new uint8_t[m_rawSize]; - if (m_chunkBuffer) { - delete[] m_chunkBuffer; - } + m_writeIndex = 0; + m_readChunkIndex = m_rateDivider; - m_chunkSize = (sampleRate * 2 * 2) / m_rateDivider; - m_chunkBuffer = new uint8_t[m_chunkSize]; + std::cerr << "SDRdaemonBuffer::updateBufferSize:" + << " sampleRate: " << sampleRate + << " m_chunkSize: " << m_chunkSize + << " m_rawSize: " << m_rawSize + << std::endl; } void SDRdaemonBuffer::updateBlockCounts(uint32_t nbBytesReceived) { - m_nbBlocks += m_bytesInBlock + nbBytesReceived > m_blockSize ? 1 : 0; - m_bytesInBlock = m_bytesInBlock + nbBytesReceived > m_blockSize ? nbBytesReceived : m_bytesInBlock + nbBytesReceived; + m_nbBlocks += m_bytesInBlock + nbBytesReceived > m_udpPayloadSize ? 1 : 0; + m_bytesInBlock = m_bytesInBlock + nbBytesReceived > m_udpPayloadSize ? nbBytesReceived : m_bytesInBlock + nbBytesReceived; } void SDRdaemonBuffer::printMeta(MetaData *metaData) diff --git a/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h b/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h index 55c6f7ca1..f2abe3346 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h +++ b/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h @@ -61,24 +61,27 @@ public: }; #pragma pack(pop) - SDRdaemonBuffer(uint32_t blockSize, uint32_t rateDivider); + SDRdaemonBuffer(uint32_t rateDivider); ~SDRdaemonBuffer(); bool readMeta(char *array, uint32_t length); //!< Attempt to read meta. Returns true if meta block void writeData(char *array, uint32_t length); //!< Write data into buffer. - uint8_t *readData(uint32_t length); //!< Read data from buffer + uint8_t *readDataChunk(); //!< Read a chunk of data from buffer const MetaData& getCurrentMeta() const { return m_currentMeta; } void updateBlockCounts(uint32_t nbBytesReceived); bool isSync() const { return m_sync; } + static const int m_udpPayloadSize; + static const int m_sampleSize; + static const int m_iqSampleSize; + private: void updateLZ4Sizes(uint32_t frameSize); void writeDataLZ4(const char *array, uint32_t length); void writeToRawBufferLZ4(const char *array, uint32_t originalLength); void writeToRawBufferUncompressed(const char *array, uint32_t length); - void updateBufferSize(uint32_t sampleRate, uint32_t frameSize); + void updateBufferSize(uint32_t sampleRate); void printMeta(MetaData *metaData); - uint32_t m_blockSize; //!< UDP block (payload) size uint32_t m_rateDivider; //!< Number of times per seconds the samples are fetched bool m_sync; //!< Meta data acquired (Stream synchronized) bool m_lz4; //!< Stream is compressed with LZ4 @@ -100,11 +103,10 @@ private: uint8_t m_sampleBytes; //!< Current number of bytes per I or Q sample uint8_t m_sampleBits; //!< Current number of effective bits per sample - uint32_t m_writeCount; //!< Current write position in the raw samples buffer - uint32_t m_readCount; //!< Current read position in the raw samples buffer + uint32_t m_writeIndex; //!< Current write position in the raw samples buffer + uint32_t m_readChunkIndex; //!< Current read chunk index in the raw samples buffer uint32_t m_rawSize; //!< Size of the raw samples buffer in bytes uint8_t *m_rawBuffer; //!< Buffer for raw samples obtained from UDP (I/Q not in a formal I/Q structure) - uint8_t *m_chunkBuffer; //!< Buffer to build a chunk length of raw samples uint32_t m_chunkSize; //!< Size of a chunk of samples in bytes uint32_t m_bytesInBlock; //!< Number of bytes received in the current UDP block uint32_t m_nbBlocks; //!< Number of UDP blocks received in the current frame diff --git a/plugins/samplesource/sdrdaemon/sdrdaemonudphandler.cpp b/plugins/samplesource/sdrdaemon/sdrdaemonudphandler.cpp index 9a1c4618a..e58d509b4 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemonudphandler.cpp +++ b/plugins/samplesource/sdrdaemon/sdrdaemonudphandler.cpp @@ -23,19 +23,16 @@ #include "sdrdaemoninput.h" const int SDRdaemonUDPHandler::m_rateDivider = 1000/SDRDAEMON_THROTTLE_MS; -const int SDRdaemonUDPHandler::m_udpPayloadSize = 512; SDRdaemonUDPHandler::SDRdaemonUDPHandler(SampleFifo *sampleFifo, MessageQueue *outputMessageQueueToGUI) : //m_mutex(QMutex::Recursive), - m_sdrDaemonBuffer(m_udpPayloadSize, m_rateDivider), + m_sdrDaemonBuffer(m_rateDivider), m_dataSocket(0), m_dataAddress(QHostAddress::LocalHost), m_dataPort(9090), m_dataConnected(false), m_udpBuf(0), m_udpReadBytes(0), - m_buf(0), - m_bufsize(0), m_chunksize(0), m_sampleFifo(sampleFifo), m_samplerate(0), @@ -46,7 +43,7 @@ SDRdaemonUDPHandler::SDRdaemonUDPHandler(SampleFifo *sampleFifo, MessageQueue *o m_tickCount(0), m_samplesCount(0) { - m_udpBuf = new char[m_udpPayloadSize]; + m_udpBuf = new char[SDRdaemonBuffer::m_udpPayloadSize]; } SDRdaemonUDPHandler::~SDRdaemonUDPHandler() @@ -169,20 +166,11 @@ void SDRdaemonUDPHandler::setSamplerate(uint32_t samplerate) //QMutexLocker ml(&m_mutex); m_samplerate = samplerate; - m_chunksize = (m_samplerate / m_rateDivider)*4; // TODO: implement FF and slow motion here. 4 corresponds to live. 2 is half speed, 8 is doulbe speed - m_bufsize = m_chunksize; - - if (m_buf == 0) { - qDebug() << " - Allocate buffer"; - m_buf = (quint8*) malloc(m_bufsize); - } else { - qDebug() << " - Re-allocate buffer"; - m_buf = (quint8*) realloc((void*) m_buf, m_bufsize); - } + m_chunksize = (m_samplerate / m_rateDivider) * SDRdaemonBuffer::m_iqSampleSize; qDebug() << "SDRdaemonUDPHandler::setSamplerate:" - << " size: " << m_bufsize - << " #samples: " << (m_bufsize/4); + << " chunk size: " << m_chunksize + << " #samples per chunk: " << (m_chunksize/SDRdaemonBuffer::m_iqSampleSize); } void SDRdaemonUDPHandler::connectTimer(const QTimer& timer) @@ -194,8 +182,8 @@ void SDRdaemonUDPHandler::connectTimer(const QTimer& timer) void SDRdaemonUDPHandler::tick() { // read samples directly feeding the SampleFifo (no callback) - m_sampleFifo->write(reinterpret_cast(m_sdrDaemonBuffer.readData(m_chunksize)), m_chunksize); - m_samplesCount += m_chunksize / 4; + m_sampleFifo->write(reinterpret_cast(m_sdrDaemonBuffer.readDataChunk()), m_chunksize); + m_samplesCount += m_chunksize / SDRdaemonBuffer::m_iqSampleSize; if (m_tickCount < m_rateDivider) { diff --git a/plugins/samplesource/sdrdaemon/sdrdaemonudphandler.h b/plugins/samplesource/sdrdaemon/sdrdaemonudphandler.h index 66becc1a5..f82b2ec62 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemonudphandler.h +++ b/plugins/samplesource/sdrdaemon/sdrdaemonudphandler.h @@ -55,8 +55,6 @@ private: bool m_dataConnected; char *m_udpBuf; qint64 m_udpReadBytes; - quint8 *m_buf; - std::size_t m_bufsize; std::size_t m_chunksize; SampleFifo *m_sampleFifo; uint32_t m_samplerate; @@ -68,7 +66,6 @@ private: std::size_t m_samplesCount; static const int m_rateDivider; - static const int m_udpPayloadSize; void setSamplerate(uint32_t samplerate); void processData(); From b59c28d4c731f75ff51217219c945b1d8d0270f5 Mon Sep 17 00:00:00 2001 From: f4exb Date: Sat, 20 Feb 2016 03:48:04 +0100 Subject: [PATCH 26/51] SDRdaemon plugin: code cleanup --- .../sdrdaemon/sdrdaemonbuffer.cpp | 2 +- .../sdrdaemon/sdrdaemonthread.cpp | 257 ------------------ .../samplesource/sdrdaemon/sdrdaemonthread.h | 85 ------ .../sdrdaemon/sdrdaemonudphandler.cpp | 10 - .../sdrdaemon/sdrdaemonudphandler.h | 5 - 5 files changed, 1 insertion(+), 358 deletions(-) delete mode 100644 plugins/samplesource/sdrdaemon/sdrdaemonthread.cpp delete mode 100644 plugins/samplesource/sdrdaemon/sdrdaemonthread.h diff --git a/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.cpp b/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.cpp index 75630fcbe..43410666a 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.cpp +++ b/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.cpp @@ -45,6 +45,7 @@ SDRdaemonBuffer::SDRdaemonBuffer(uint32_t rateDivider) : m_readChunkIndex(0), m_rawSize(0), m_rawBuffer(0), + m_chunkSize(0), m_bytesInBlock(0), m_nbBlocks(0) { @@ -174,7 +175,6 @@ void SDRdaemonBuffer::writeDataLZ4(const char *array, uint32_t length) } uint64_t crc64 = m_crc64.calculate_crc(m_lz4InBuffer, m_lz4InSize); - //uint64_t crc64 = 0x0123456789ABCDEF; if (memcmp(&crc64, &m_dataCRC, 8) == 0) { diff --git a/plugins/samplesource/sdrdaemon/sdrdaemonthread.cpp b/plugins/samplesource/sdrdaemon/sdrdaemonthread.cpp deleted file mode 100644 index f27da2ad3..000000000 --- a/plugins/samplesource/sdrdaemon/sdrdaemonthread.cpp +++ /dev/null @@ -1,257 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////////// -// Copyright (C) 2015 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 . // -/////////////////////////////////////////////////////////////////////////////////// - -#include -#include -#include -#include "dsp/samplefifo.h" -#include "util/messagequeue.h" -#include "sdrdaemoninput.h" -#include -#include - -#include "sdrdaemonthread.h" - -const int SDRdaemonThread::m_rateDivider = 1000/SDRDAEMON_THROTTLE_MS; -const int SDRdaemonThread::m_udpPayloadSize = 512; - -SDRdaemonThread::SDRdaemonThread(SampleFifo* sampleFifo, MessageQueue *outputMessageQueueToGUI, QObject* parent) : - QThread(parent), - m_running(false), - m_dataSocket(0), - m_dataAddress(QHostAddress::LocalHost), - m_dataPort(9090), - m_dataConnected(false), - m_buf(0), - m_udpBuf(0), - m_bufsize(0), - m_chunksize(0), - m_sampleFifo(sampleFifo), - m_samplesCount(0), - m_sdrDaemonBuffer(m_udpPayloadSize), - m_samplerate(0), - m_centerFrequency(0), - m_outputMessageQueueToGUI(outputMessageQueueToGUI) -{ - m_udpBuf = new char[m_udpPayloadSize]; - m_dataSocket = new QUdpSocket(this); - - if (m_dataSocket->bind(m_dataAddress, m_dataPort)) - { - qDebug("SDRdaemonThread::SDRdaemonThread: bind data socket to port %d", m_dataPort); - connect(m_dataSocket, SIGNAL(readyRead()), this, SLOT(dataReadyRead())); - m_dataConnected = true; - } - else - { - qWarning("SDRdaemonThread::SDRdaemonThread: cannot bind data port %d", m_dataPort); - m_dataConnected = false; - } -} - -SDRdaemonThread::~SDRdaemonThread() -{ - if (m_running) { - stopWork(); - } - - if (m_udpBuf != 0) { - free(m_udpBuf); - } - - if (m_buf != 0) { - free(m_buf); - } -} - -void SDRdaemonThread::startWork() -{ - qDebug() << "SDRdaemonThread::startWork: "; - - if (!m_dataConnected) - { - connect(m_dataSocket, SIGNAL(readyRead()), this, SLOT(dataReadyRead())); - m_dataConnected = true; - } - - m_startWaitMutex.lock(); - start(); - while(!m_running) - m_startWaiter.wait(&m_startWaitMutex, 100); - m_startWaitMutex.unlock(); -} - -void SDRdaemonThread::stopWork() -{ - qDebug() << "SDRdaemonThread::stopWork"; - - if (m_dataConnected) { - disconnect(m_dataSocket, SIGNAL(readyRead()), this, SLOT(dataReadyRead())); - m_dataConnected = false; - } - - m_running = false; - wait(); -} - -void SDRdaemonThread::setSamplerate(uint32_t samplerate) -{ - bool wasRunning = m_running; - - qDebug() << "SDRdaemonThread::setSamplerate:" - << " new:" << samplerate - << " old:" << m_samplerate; - - if (m_running) - { - stopWork(); - m_running = false; - } - - m_samplerate = samplerate; - m_chunksize = (m_samplerate / m_rateDivider)*4; // TODO: implement FF and slow motion here. 4 corresponds to live. 2 is half speed, 8 is doulbe speed - m_bufsize = m_chunksize; - - if (m_buf == 0) { - qDebug() << " - Allocate buffer"; - m_buf = (quint8*) malloc(m_bufsize); - } else { - qDebug() << " - Re-allocate buffer"; - m_buf = (quint8*) realloc((void*) m_buf, m_bufsize); - } - - qDebug() << " - size: " << m_bufsize - << " #samples: " << (m_bufsize/4); - - if (wasRunning) - { - startWork(); - m_running = true; - } -} - -void SDRdaemonThread::updateLink(const QString& address, quint16 port) -{ - if (m_dataSocket) { - delete m_dataSocket; - m_dataSocket = 0; - } - - m_dataSocket = new QUdpSocket(this); - m_dataPort = port; - - if (m_dataAddress.setAddress(address)) - { - if (m_dataSocket->bind(m_dataAddress, m_dataPort)) - { - qDebug("SDRdaemonThread::startWork: bind data socket to port %d", m_dataPort); - connect(m_dataSocket, SIGNAL(readyRead()), this, SLOT(dataReadyRead())); - m_dataConnected = true; - } - else - { - qWarning("SDRdaemonThread::updateLink: cannot bind data port %d", m_dataPort); - m_dataConnected = false; - } - } - else - { - qWarning("SDRdaemonThread::updateLink: cannot set data address: %s", qPrintable(address)); - m_dataConnected = false; - } -} - -void SDRdaemonThread::run() -{ - int res; - - m_running = true; - m_startWaiter.wakeAll(); - - while(m_running) // actual work is in the tick() function - { - sleep(1); - } - - m_running = false; -} - -void SDRdaemonThread::connectTimer(const QTimer& timer) -{ - qDebug() << "SDRdaemonThread::connectTimer"; - connect(&timer, SIGNAL(timeout()), this, SLOT(tick())); -} - -void SDRdaemonThread::tick() -{ - if (m_running) - { - // read samples directly feeding the SampleFifo (no callback) - m_sampleFifo->write(reinterpret_cast(m_sdrDaemonBuffer.readData(m_chunksize)), m_chunksize); - m_samplesCount += m_chunksize / 4; - } -} - -void SDRdaemonThread::dataReadyRead() -{ - while (m_dataSocket->hasPendingDatagrams()) - { - qint64 pendingDataSize = m_dataSocket->pendingDatagramSize(); - qint64 readBytes = m_dataSocket->readDatagram(m_udpBuf, pendingDataSize, 0, 0); - - if (readBytes < 0) - { - qDebug() << "SDRdaemonThread::dataReadyRead: read failed"; - } - else if (readBytes > 0) - { - m_sdrDaemonBuffer.updateBlockCounts(readBytes); - - if (m_sdrDaemonBuffer.readMeta(m_udpBuf, readBytes)) - { - const SDRdaemonBuffer::MetaData& metaData = m_sdrDaemonBuffer.getCurrentMeta(); - bool change = false; - - if (m_samplerate != metaData.m_sampleRate) - { - setSamplerate(metaData.m_sampleRate); - m_samplerate = metaData.m_sampleRate; - change = true; - } - - if (m_centerFrequency != metaData.m_centerFrequency) - { - m_centerFrequency = metaData.m_centerFrequency; - change = true; - } - - if (change) - { - SDRdaemonInput::MsgReportSDRdaemonStreamData *report = SDRdaemonInput::MsgReportSDRdaemonStreamData::create( - metaData.m_sampleRate, - metaData.m_centerFrequency, - metaData.m_tv_sec, - metaData.m_tv_usec); - m_outputMessageQueueToGUI->push(report); - } - } - else if (m_sdrDaemonBuffer.isSync()) - { - m_sdrDaemonBuffer.writeData(m_udpBuf, readBytes); - } - } - } -} diff --git a/plugins/samplesource/sdrdaemon/sdrdaemonthread.h b/plugins/samplesource/sdrdaemon/sdrdaemonthread.h deleted file mode 100644 index a3e0fa4c3..000000000 --- a/plugins/samplesource/sdrdaemon/sdrdaemonthread.h +++ /dev/null @@ -1,85 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////////// -// Copyright (C) 2016 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 INCLUDE_SDRDAEMONTHREAD_H -#define INCLUDE_SDRDAEMONTHREAD_H - -#include -#include -#include -#include -#include - -#include -#include -#include "dsp/samplefifo.h" -#include "dsp/inthalfbandfilter.h" -#include "sdrdaemonbuffer.h" - -#define SDRDAEMON_THROTTLE_MS 50 - -class QUdpSocket; -class MessageQueue; - -class SDRdaemonThread : public QThread { - Q_OBJECT - -public: - SDRdaemonThread(SampleFifo* sampleFifo, MessageQueue *outputMessageQueueToGUI, QObject* parent = NULL); - ~SDRdaemonThread(); - - void startWork(); - void stopWork(); - void updateLink(const QString& address, quint16 port); - bool isRunning() const { return m_running; } - std::size_t getSamplesCount() const { return m_samplesCount; } - - void connectTimer(const QTimer& timer); - -public slots: - void dataReadyRead(); - -private: - QMutex m_startWaitMutex; - QWaitCondition m_startWaiter; - bool m_running; - - QUdpSocket *m_dataSocket; - QHostAddress m_dataAddress; - quint16 m_dataPort; - bool m_dataConnected; - quint8 *m_buf; - char *m_udpBuf; - std::size_t m_bufsize; - std::size_t m_chunksize; - SampleFifo* m_sampleFifo; - std::size_t m_samplesCount; - - SDRdaemonBuffer m_sdrDaemonBuffer; - - uint32_t m_samplerate; - uint32_t m_centerFrequency; - MessageQueue *m_outputMessageQueueToGUI; - static const int m_rateDivider; - static const int m_udpPayloadSize; - - void setSamplerate(uint32_t samplerate); - void run(); -private slots: - void tick(); -}; - -#endif // INCLUDE_SDRDAEMONTHREAD_H diff --git a/plugins/samplesource/sdrdaemon/sdrdaemonudphandler.cpp b/plugins/samplesource/sdrdaemon/sdrdaemonudphandler.cpp index e58d509b4..4cbefe34d 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemonudphandler.cpp +++ b/plugins/samplesource/sdrdaemon/sdrdaemonudphandler.cpp @@ -25,7 +25,6 @@ const int SDRdaemonUDPHandler::m_rateDivider = 1000/SDRDAEMON_THROTTLE_MS; SDRdaemonUDPHandler::SDRdaemonUDPHandler(SampleFifo *sampleFifo, MessageQueue *outputMessageQueueToGUI) : - //m_mutex(QMutex::Recursive), m_sdrDaemonBuffer(m_rateDivider), m_dataSocket(0), m_dataAddress(QHostAddress::LocalHost), @@ -64,7 +63,6 @@ void SDRdaemonUDPHandler::start() if (m_dataSocket->bind(m_dataAddress, m_dataPort)) { qDebug("SDRdaemonUDPHandler::start: bind data socket to port %d", m_dataPort); - //connect(this, SIGNAL(dataReady()), this, SLOT(processData())); connect(m_dataSocket, SIGNAL(readyRead()), this, SLOT(dataReadyRead()), Qt::QueuedConnection); // , Qt::QueuedConnection m_dataConnected = true; } @@ -82,7 +80,6 @@ void SDRdaemonUDPHandler::stop() if (m_dataConnected) { disconnect(m_dataSocket, SIGNAL(readyRead()), this, SLOT(dataReadyRead())); - //disconnect(this, SIGNAL(dataReady()), this, SLOT(processData)); m_dataConnected = false; } @@ -95,13 +92,10 @@ void SDRdaemonUDPHandler::stop() void SDRdaemonUDPHandler::dataReadyRead() { - //qDebug() << "SDRdaemonUDPHandler::dataReadyRead"; - while (m_dataSocket->hasPendingDatagrams()) { qint64 pendingDataSize = m_dataSocket->pendingDatagramSize(); m_udpReadBytes = m_dataSocket->readDatagram(m_udpBuf, pendingDataSize, 0, 0); - //emit dataReady(); processData(); } } @@ -114,8 +108,6 @@ void SDRdaemonUDPHandler::processData() } else if (m_udpReadBytes > 0) { - //QMutexLocker ml(&m_mutex); - m_sdrDaemonBuffer.updateBlockCounts(m_udpReadBytes); if (m_sdrDaemonBuffer.readMeta(m_udpBuf, m_udpReadBytes)) @@ -163,8 +155,6 @@ void SDRdaemonUDPHandler::setSamplerate(uint32_t samplerate) << " new:" << samplerate << " old:" << m_samplerate; - //QMutexLocker ml(&m_mutex); - m_samplerate = samplerate; m_chunksize = (m_samplerate / m_rateDivider) * SDRdaemonBuffer::m_iqSampleSize; diff --git a/plugins/samplesource/sdrdaemon/sdrdaemonudphandler.h b/plugins/samplesource/sdrdaemon/sdrdaemonudphandler.h index f82b2ec62..f7fe0adfc 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemonudphandler.h +++ b/plugins/samplesource/sdrdaemon/sdrdaemonudphandler.h @@ -41,13 +41,8 @@ public: public slots: void dataReadyRead(); -// void processData(); - -//signals: -// void dataReady(); private: - //QMutex m_mutex; SDRdaemonBuffer m_sdrDaemonBuffer; QUdpSocket *m_dataSocket; QHostAddress m_dataAddress; From 952a32172da8c4eacd4c2bde67dcb5ad2e757bbb Mon Sep 17 00:00:00 2001 From: f4exb Date: Sat, 20 Feb 2016 10:10:11 +0100 Subject: [PATCH 27/51] SDRdaemon plugin: update settings after deserialization --- Readme.md | 2 - .../samplesource/sdrdaemon/sdrdaemongui.cpp | 43 ++++++++++++++----- .../sdrdaemon/sdrdaemonudphandler.cpp | 2 +- 3 files changed, 33 insertions(+), 14 deletions(-) diff --git a/Readme.md b/Readme.md index 6bd609853..3ee82d939 100644 --- a/Readme.md +++ b/Readme.md @@ -109,8 +109,6 @@ Note that this plugin does not require any of the hardware support libraries nor

SDRdaemon input

-Warning: this is experimental and not fulle debugged yet. - This is the client side of the SDRdaemon server. See the [SDRdaemon](https://github.com/f4exb/sdrdaemon) project in this Github repository. You must specify the address and UDP port to which the server connects and samples will flow into the SDRangel application (default is `127.0.0.1`port `9090`). It uses the meta data to retrieve the sample flow characteristics such as sample rate and receiveng center frequency. Note that this plugin does not require any of the hardware support libraries nor the libusb library. It is alwasys available in the list of devices as `SDRdaemon[0]` even if no physical device is connected. diff --git a/plugins/samplesource/sdrdaemon/sdrdaemongui.cpp b/plugins/samplesource/sdrdaemon/sdrdaemongui.cpp index 93dbfbfc7..926fbadff 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemongui.cpp +++ b/plugins/samplesource/sdrdaemon/sdrdaemongui.cpp @@ -114,33 +114,54 @@ bool SDRdaemonGui::deserialize(const QByteArray& data) QString address; uint32_t uintval; quint16 port; + bool dcBlock; + bool iqCorrection; - if(!d.isValid()) { + if (!d.isValid()) + { resetToDefaults(); + displaySettings(); return false; } - if(d.getVersion() == 1) { + if (d.getVersion() == 1) + { uint32_t uintval; - d.readString(1, &m_address, "127.0.0.1"); + d.readString(1, &address, "127.0.0.1"); d.readU32(2, &uintval, 9090); if ((uintval > 1024) && (uintval < 65536)) { - m_port = uintval; + port = uintval; } else { - m_port = 9090; + port = 9090; } - d.readBool(3, &m_dcBlock, false); - d.readBool(4, &m_iqCorrection, false); + d.readBool(3, &dcBlock, false); + d.readBool(4, &iqCorrection, false); + if ((address != m_address) || (port != m_port)) + { + m_address = address; + m_port = port; + configureUDPLink(); + } + + if ((dcBlock != m_dcBlock) || (iqCorrection != m_iqCorrection)) + { + m_dcBlock = dcBlock; + m_iqCorrection = iqCorrection; + configureAutoCorrections(); + } + + displaySettings(); return true; - } else { + } + else + { resetToDefaults(); + displaySettings(); return false; } - - displaySettings(); } qint64 SDRdaemonGui::getCenterFrequency() const @@ -260,7 +281,7 @@ void SDRdaemonGui::updateWithAcquisition() void SDRdaemonGui::updateWithStreamData() { - ui->centerFrequency->setValue(m_centerFrequency); + ui->centerFrequency->setValue(m_centerFrequency / 1000); QString s = QString::number(m_sampleRate/1000.0, 'f', 0); ui->sampleRateText->setText(tr("%1k").arg(s)); updateWithStreamTime(); // TODO: remove when time data is implemented diff --git a/plugins/samplesource/sdrdaemon/sdrdaemonudphandler.cpp b/plugins/samplesource/sdrdaemon/sdrdaemonudphandler.cpp index 4cbefe34d..a1dc0690f 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemonudphandler.cpp +++ b/plugins/samplesource/sdrdaemon/sdrdaemonudphandler.cpp @@ -136,7 +136,7 @@ void SDRdaemonUDPHandler::processData() DSPEngine::instance()->getInputMessageQueue()->push(notif); SDRdaemonInput::MsgReportSDRdaemonStreamData *report = SDRdaemonInput::MsgReportSDRdaemonStreamData::create( m_samplerate, - m_centerFrequency, // Frequency in kHz for the GUI + m_centerFrequency * 1000, // Frequency in Hz for the GUI m_tv_sec, m_tv_usec); m_outputMessageQueueToGUI->push(report); From 48d858ce5dbe8d35885d6c56be4ac2909aef6ff4 Mon Sep 17 00:00:00 2001 From: f4exb Date: Sat, 20 Feb 2016 23:02:34 +0100 Subject: [PATCH 28/51] SDRdaemon plugin: fixes --- .../sdrdaemon/sdrdaemonbuffer.cpp | 30 +++++++++---------- .../samplesource/sdrdaemon/sdrdaemonbuffer.h | 6 ++-- .../samplesource/sdrdaemon/sdrdaemongui.ui | 15 ++++++++++ .../samplesource/sdrdaemon/sdrdaemoninput.cpp | 5 ++-- .../sdrdaemon/sdrdaemonudphandler.cpp | 29 +++++++++++++++--- .../sdrdaemon/sdrdaemonudphandler.h | 4 ++- 6 files changed, 64 insertions(+), 25 deletions(-) diff --git a/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.cpp b/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.cpp index 43410666a..12a0791cf 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.cpp +++ b/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.cpp @@ -34,9 +34,9 @@ SDRdaemonBuffer::SDRdaemonBuffer(uint32_t rateDivider) : m_lz4InSize(0), m_lz4OutBuffer(0), m_frameSize(0), - m_nbDecodes(0), - m_nbSuccessfulDecodes(0), - m_nbCRCOK(0), + m_nbLz4Decodes(0), + m_nbLz4SuccessfulDecodes(0), + m_nbLz4CRCOK(0), m_dataCRC(0), m_sampleRate(1000000), m_sampleBytes(2), @@ -161,32 +161,32 @@ void SDRdaemonBuffer::writeDataLZ4(const char *array, uint32_t length) if (m_lz4InCount >= m_lz4InSize) // full input compressed block retrieved { - if (m_nbDecodes == 100) + if (m_nbLz4Decodes == 100) { std::cerr << "SDRdaemonBuffer::writeAndReadLZ4:" - << " decoding: " << m_nbCRCOK - << ":" << m_nbSuccessfulDecodes - << "/" << m_nbDecodes + << " decoding: " << m_nbLz4CRCOK + << ":" << m_nbLz4SuccessfulDecodes + << "/" << m_nbLz4Decodes << std::endl; - m_nbDecodes = 0; - m_nbSuccessfulDecodes = 0; - m_nbCRCOK = 0; + m_nbLz4Decodes = 0; + m_nbLz4SuccessfulDecodes = 0; + m_nbLz4CRCOK = 0; } uint64_t crc64 = m_crc64.calculate_crc(m_lz4InBuffer, m_lz4InSize); if (memcmp(&crc64, &m_dataCRC, 8) == 0) { - m_nbCRCOK++; + m_nbLz4CRCOK++; } int compressedSize = LZ4_decompress_fast((const char*) m_lz4InBuffer, (char*) &m_rawBuffer[m_writeIndex], m_frameSize); - m_nbDecodes++; + m_nbLz4Decodes++; if (compressedSize == m_lz4InSize) { - m_nbSuccessfulDecodes++; + m_nbLz4SuccessfulDecodes++; } writeToRawBufferLZ4((const char *) m_lz4InBuffer, m_frameSize); @@ -214,11 +214,11 @@ void SDRdaemonBuffer::writeToRawBufferUncompressed(const char *array, uint32_t l void SDRdaemonBuffer::writeToRawBufferLZ4(const char *array, uint32_t length) { int compressedSize = LZ4_decompress_fast((const char*) m_lz4InBuffer, (char*) m_lz4OutBuffer, m_frameSize); - m_nbDecodes++; + m_nbLz4Decodes++; if (compressedSize == m_lz4InSize) { - m_nbSuccessfulDecodes++; + m_nbLz4SuccessfulDecodes++; } writeToRawBufferUncompressed((const char *) m_lz4OutBuffer, m_frameSize); diff --git a/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h b/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h index f2abe3346..89aa0660b 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h +++ b/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h @@ -94,9 +94,9 @@ private: uint32_t m_lz4InSize; //!< Size in bytes of the LZ4 input data uint8_t *m_lz4OutBuffer; //!< Buffer for LZ4 uncompressed output uint32_t m_frameSize; //!< Size in bytes of one uncompressed frame - uint32_t m_nbDecodes; - uint32_t m_nbSuccessfulDecodes; - uint32_t m_nbCRCOK; + uint32_t m_nbLz4Decodes; + uint32_t m_nbLz4SuccessfulDecodes; + uint32_t m_nbLz4CRCOK; uint64_t m_dataCRC; uint32_t m_sampleRate; //!< Current sample rate in Hz diff --git a/plugins/samplesource/sdrdaemon/sdrdaemongui.ui b/plugins/samplesource/sdrdaemon/sdrdaemongui.ui index 3f35fd068..4c8745541 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemongui.ui +++ b/plugins/samplesource/sdrdaemon/sdrdaemongui.ui @@ -234,12 +234,18 @@
+ + false + 120 0 + + Data connection IP address + 127.0.0.1 @@ -254,12 +260,18 @@ + + false + 50 0 + + Data connection port + 9090 @@ -267,6 +279,9 @@ + + false + 30 diff --git a/plugins/samplesource/sdrdaemon/sdrdaemoninput.cpp b/plugins/samplesource/sdrdaemon/sdrdaemoninput.cpp index 4ce93a06f..8e29a77ce 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemoninput.cpp +++ b/plugins/samplesource/sdrdaemon/sdrdaemoninput.cpp @@ -47,7 +47,7 @@ SDRdaemonInput::SDRdaemonInput(const QTimer& masterTimer) : { m_sampleFifo.setSize(96000 * 4); m_SDRdaemonUDPHandler = new SDRdaemonUDPHandler(&m_sampleFifo, getOutputMessageQueueToGUI()); - m_SDRdaemonUDPHandler->connectTimer(m_masterTimer); + m_SDRdaemonUDPHandler->connectTimer(&m_masterTimer); } SDRdaemonInput::~SDRdaemonInput() @@ -101,7 +101,8 @@ bool SDRdaemonInput::handleMessage(const Message& message) { if (MsgConfigureSDRdaemonUDPLink::match(message)) { - // TODO: change UDP settings + MsgConfigureSDRdaemonUDPLink& conf = (MsgConfigureSDRdaemonUDPLink&) message; + m_SDRdaemonUDPHandler->configureUDPLink(conf.getAddress(), conf.getPort()); return true; } else if (MsgConfigureSDRdaemonAutoCorr::match(message)) diff --git a/plugins/samplesource/sdrdaemon/sdrdaemonudphandler.cpp b/plugins/samplesource/sdrdaemon/sdrdaemonudphandler.cpp index a1dc0690f..15f869591 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemonudphandler.cpp +++ b/plugins/samplesource/sdrdaemon/sdrdaemonudphandler.cpp @@ -16,6 +16,7 @@ #include #include +#include #include #include "dsp/dspcommands.h" #include "dsp/dspengine.h" @@ -40,7 +41,8 @@ SDRdaemonUDPHandler::SDRdaemonUDPHandler(SampleFifo *sampleFifo, MessageQueue *o m_tv_usec(0), m_outputMessageQueueToGUI(outputMessageQueueToGUI), m_tickCount(0), - m_samplesCount(0) + m_samplesCount(0), + m_timer(0) { m_udpBuf = new char[SDRdaemonBuffer::m_udpPayloadSize]; } @@ -53,6 +55,8 @@ SDRdaemonUDPHandler::~SDRdaemonUDPHandler() void SDRdaemonUDPHandler::start() { + qDebug("SDRdaemonUDPHandler::start"); + if (!m_dataSocket) { m_dataSocket = new QUdpSocket(this); @@ -62,7 +66,7 @@ void SDRdaemonUDPHandler::start() { if (m_dataSocket->bind(m_dataAddress, m_dataPort)) { - qDebug("SDRdaemonUDPHandler::start: bind data socket to port %d", m_dataPort); + qDebug("SDRdaemonUDPHandler::start: bind data socket to %s:%d", m_dataAddress.toString().toStdString().c_str(), m_dataPort); connect(m_dataSocket, SIGNAL(readyRead()), this, SLOT(dataReadyRead()), Qt::QueuedConnection); // , Qt::QueuedConnection m_dataConnected = true; } @@ -90,6 +94,22 @@ void SDRdaemonUDPHandler::stop() } } +void SDRdaemonUDPHandler::configureUDPLink(const QString& address, quint16 port) +{ + qDebug("SDRdaemonUDPHandler::configureUDPLink: %s:%d", address.toStdString().c_str(), port); + bool addressOK = m_dataAddress.setAddress(address); + + if (!addressOK) + { + qWarning("SDRdaemonUDPHandler::configureUDPLink: invalid address %s. Set to localhost.", address.toStdString().c_str()); + m_dataAddress = QHostAddress::LocalHost; + } + + stop(); + m_dataPort = port; + start(); +} + void SDRdaemonUDPHandler::dataReadyRead() { while (m_dataSocket->hasPendingDatagrams()) @@ -163,10 +183,11 @@ void SDRdaemonUDPHandler::setSamplerate(uint32_t samplerate) << " #samples per chunk: " << (m_chunksize/SDRdaemonBuffer::m_iqSampleSize); } -void SDRdaemonUDPHandler::connectTimer(const QTimer& timer) +void SDRdaemonUDPHandler::connectTimer(const QTimer* timer) { qDebug() << "SDRdaemonUDPHandler::connectTimer"; - connect(&timer, SIGNAL(timeout()), this, SLOT(tick())); + m_timer = timer; + connect(timer, SIGNAL(timeout()), this, SLOT(tick())); } void SDRdaemonUDPHandler::tick() diff --git a/plugins/samplesource/sdrdaemon/sdrdaemonudphandler.h b/plugins/samplesource/sdrdaemon/sdrdaemonudphandler.h index f7fe0adfc..50ed52f2c 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemonudphandler.h +++ b/plugins/samplesource/sdrdaemon/sdrdaemonudphandler.h @@ -35,9 +35,10 @@ class SDRdaemonUDPHandler : public QObject public: SDRdaemonUDPHandler(SampleFifo* sampleFifo, MessageQueue *outputMessageQueueToGUI); ~SDRdaemonUDPHandler(); - void connectTimer(const QTimer& timer); + void connectTimer(const QTimer* timer); void start(); void stop(); + void configureUDPLink(const QString& address, quint16 port); public slots: void dataReadyRead(); @@ -59,6 +60,7 @@ private: MessageQueue *m_outputMessageQueueToGUI; uint32_t m_tickCount; std::size_t m_samplesCount; + const QTimer *m_timer; static const int m_rateDivider; From 2d018f7968366aff99da76b3715cb14a33a90d74 Mon Sep 17 00:00:00 2001 From: f4exb Date: Sun, 21 Feb 2016 11:01:43 +0100 Subject: [PATCH 29/51] SDRdaemon plugin: reactivate address setting in GUI. Put in place a stram locked status. --- plugins/samplesource/sdrdaemon/sdrdaemonbuffer.cpp | 13 +++++++++++++ plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h | 4 +++- plugins/samplesource/sdrdaemon/sdrdaemongui.ui | 8 ++++---- 3 files changed, 20 insertions(+), 5 deletions(-) diff --git a/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.cpp b/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.cpp index 12a0791cf..3b2d80735 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.cpp +++ b/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.cpp @@ -27,6 +27,7 @@ const int SDRdaemonBuffer::m_iqSampleSize = 2 * m_sampleSize; SDRdaemonBuffer::SDRdaemonBuffer(uint32_t rateDivider) : m_rateDivider(rateDivider), m_sync(false), + m_syncLock(false), m_lz4(false), m_inCount(0), m_lz4InBuffer(0), @@ -74,6 +75,18 @@ bool SDRdaemonBuffer::readMeta(char *array, uint32_t length) if (m_crc64.calculate_crc((uint8_t *)array, sizeof(MetaData) - 8) == metaData->m_crc) { + // sync condition: + if (m_currentMeta.m_blockSize > 0) + { + uint32_t nbBlocks = m_currentMeta.m_nbBytes / m_currentMeta.m_blockSize; + m_syncLock = nbBlocks + (m_lz4 ? 2 : 1) == m_nbBlocks; + //qDebug("SDRdaemonBuffer::readMeta: m_nbBlocks: %d:%d %s", nbBlocks, m_nbBlocks, (m_syncLock ? "locked" : "unlocked")); + } + else + { + m_syncLock = false; + } + memcpy((void *) &m_dataCRC, (const void *) &array[sizeof(MetaData)], 8); m_nbBlocks = 0; m_inCount = 0; diff --git a/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h b/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h index 89aa0660b..8e48aaf9d 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h +++ b/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h @@ -69,6 +69,7 @@ public: const MetaData& getCurrentMeta() const { return m_currentMeta; } void updateBlockCounts(uint32_t nbBytesReceived); bool isSync() const { return m_sync; } + bool isSyncLocked() const { return m_syncLock; } static const int m_udpPayloadSize; static const int m_sampleSize; @@ -83,7 +84,8 @@ private: void printMeta(MetaData *metaData); uint32_t m_rateDivider; //!< Number of times per seconds the samples are fetched - bool m_sync; //!< Meta data acquired (Stream synchronized) + bool m_sync; //!< Meta data acquired + bool m_syncLock; //!< Meta data expected (Stream synchronized) bool m_lz4; //!< Stream is compressed with LZ4 MetaData m_currentMeta; //!< Stored current meta data CRC64 m_crc64; //!< CRC64 calculator diff --git a/plugins/samplesource/sdrdaemon/sdrdaemongui.ui b/plugins/samplesource/sdrdaemon/sdrdaemongui.ui index 4c8745541..d4e5132d0 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemongui.ui +++ b/plugins/samplesource/sdrdaemon/sdrdaemongui.ui @@ -235,7 +235,7 @@ - false + true @@ -261,7 +261,7 @@ - false + true @@ -280,7 +280,7 @@ - false + true @@ -289,7 +289,7 @@ - OK + Set From 898178bd1203a0963eeaaf47dba304e2b9481f92 Mon Sep 17 00:00:00 2001 From: f4exb Date: Mon, 22 Feb 2016 12:10:13 +0100 Subject: [PATCH 30/51] SDRdaemon plugin: auto skew correction #1 --- .../sdrdaemon/sdrdaemonbuffer.cpp | 46 +++++++++++++++---- .../samplesource/sdrdaemon/sdrdaemonbuffer.h | 13 ++++-- .../sdrdaemon/sdrdaemonudphandler.cpp | 8 ++-- 3 files changed, 52 insertions(+), 15 deletions(-) diff --git a/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.cpp b/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.cpp index 3b2d80735..504467dac 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.cpp +++ b/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.cpp @@ -39,7 +39,8 @@ SDRdaemonBuffer::SDRdaemonBuffer(uint32_t rateDivider) : m_nbLz4SuccessfulDecodes(0), m_nbLz4CRCOK(0), m_dataCRC(0), - m_sampleRate(1000000), + m_sampleRateStream(0), + m_sampleRate(0), m_sampleBytes(2), m_sampleBits(12), m_writeIndex(0), @@ -48,7 +49,11 @@ SDRdaemonBuffer::SDRdaemonBuffer(uint32_t rateDivider) : m_rawBuffer(0), m_chunkSize(0), m_bytesInBlock(0), - m_nbBlocks(0) + m_nbBlocks(0), + m_readCycles(0), + m_lastWriteIndex(0), + m_skewRateSum(0.0), + m_skewRate(0.0) { m_currentMeta.init(); } @@ -106,6 +111,13 @@ bool SDRdaemonBuffer::readMeta(char *array, uint32_t length) uint32_t frameSize = m_iqSampleSize * metaData->m_nbSamples * metaData->m_nbBlocks; uint32_t sampleRate = metaData->m_sampleRate; + if (sampleRate != m_sampleRateStream) + { + m_sampleRateStream = sampleRate; + } + + sampleRate += (((int) (sampleRate * m_skewRate)) / m_rateDivider) * m_rateDivider; + if (metaData->m_sampleBytes & 0x10) { m_lz4 = true; @@ -240,18 +252,32 @@ void SDRdaemonBuffer::writeToRawBufferLZ4(const char *array, uint32_t length) uint8_t *SDRdaemonBuffer::readDataChunk() { // relies on the fact that we always have an integer number of chunks in the raw buffer - - if (m_readChunkIndex == m_rateDivider * 2) // go back to start or middle of raw buffer + if (m_readChunkIndex == m_rateDivider * 2) // go back to start of raw buffer { - // make sure the read and write pointers are not in the same half of the raw buffer - if (m_writeIndex < m_rateDivider * m_chunkSize - 1) + double oneCycleSkew = 0; + + if (m_readCycles > 0) { - m_readChunkIndex = m_rateDivider; // go to middle + oneCycleSkew = (double) ((int) m_writeIndex - (int) m_lastWriteIndex) / (double) m_rawSize; + m_skewRateSum += oneCycleSkew; } - else + + //qDebug("SDRdaemonBuffer::readDataChunk: %d / %d (%lf)", m_writeIndex, m_rawSize, oneCycleSkew); + + if (m_readCycles && ((m_writeIndex < m_rawSize / 10) || (m_rawSize - m_writeIndex < m_rawSize / 10))) { - m_readChunkIndex = 0; // go to start + m_skewRate = m_skewRateSum / m_readCycles; + if (m_skewRate > 0.04) { + m_skewRate = 0.04; + } else if (m_skewRate < -0.04) { + m_skewRate = -0.04; + } + qDebug("SDRdaemonBuffer::readDataChunk: m_skewRate: %lf", m_skewRate); } + + m_readChunkIndex = 0; // go to start + m_lastWriteIndex = m_writeIndex; + m_readCycles++; } uint32_t readIndex = m_readChunkIndex; @@ -292,6 +318,8 @@ void SDRdaemonBuffer::updateBufferSize(uint32_t sampleRate) m_writeIndex = 0; m_readChunkIndex = m_rateDivider; + m_readCycles = 0; + m_skewRateSum = 0; std::cerr << "SDRdaemonBuffer::updateBufferSize:" << " sampleRate: " << sampleRate diff --git a/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h b/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h index 8e48aaf9d..e3c9a4bae 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h +++ b/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h @@ -67,6 +67,7 @@ public: void writeData(char *array, uint32_t length); //!< Write data into buffer. uint8_t *readDataChunk(); //!< Read a chunk of data from buffer const MetaData& getCurrentMeta() const { return m_currentMeta; } + uint32_t getSampleRate() const { return m_sampleRate; } void updateBlockCounts(uint32_t nbBytesReceived); bool isSync() const { return m_sync; } bool isSyncLocked() const { return m_syncLock; } @@ -101,9 +102,10 @@ private: uint32_t m_nbLz4CRCOK; uint64_t m_dataCRC; - uint32_t m_sampleRate; //!< Current sample rate in Hz - uint8_t m_sampleBytes; //!< Current number of bytes per I or Q sample - uint8_t m_sampleBits; //!< Current number of effective bits per sample + uint32_t m_sampleRateStream; //!< Current sample rate from the stream + uint32_t m_sampleRate; //!< Current actual sample rate in Hz + uint8_t m_sampleBytes; //!< Current number of bytes per I or Q sample + uint8_t m_sampleBits; //!< Current number of effective bits per sample uint32_t m_writeIndex; //!< Current write position in the raw samples buffer uint32_t m_readChunkIndex; //!< Current read chunk index in the raw samples buffer @@ -112,6 +114,11 @@ private: uint32_t m_chunkSize; //!< Size of a chunk of samples in bytes uint32_t m_bytesInBlock; //!< Number of bytes received in the current UDP block uint32_t m_nbBlocks; //!< Number of UDP blocks received in the current frame + + uint32_t m_readCycles; //!< Count of read cycles over raw buiffer + uint32_t m_lastWriteIndex; //!< Write index at last skew estimation + double m_skewRateSum; + double m_skewRate; }; diff --git a/plugins/samplesource/sdrdaemon/sdrdaemonudphandler.cpp b/plugins/samplesource/sdrdaemon/sdrdaemonudphandler.cpp index 15f869591..231006c54 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemonudphandler.cpp +++ b/plugins/samplesource/sdrdaemon/sdrdaemonudphandler.cpp @@ -137,10 +137,12 @@ void SDRdaemonUDPHandler::processData() m_tv_sec = metaData.m_tv_sec; m_tv_usec = metaData.m_tv_usec; - if (m_samplerate != metaData.m_sampleRate) + uint32_t sampleRate = m_sdrDaemonBuffer.getSampleRate(); + + if (m_samplerate != sampleRate) { - setSamplerate(metaData.m_sampleRate); - m_samplerate = metaData.m_sampleRate; + setSamplerate(sampleRate); + m_samplerate = sampleRate; change = true; } From bf78fa016eb063e07245095a05c13cebbf2d8a6d Mon Sep 17 00:00:00 2001 From: f4exb Date: Mon, 22 Feb 2016 14:18:41 +0100 Subject: [PATCH 31/51] SDRdaemon plugin: auto skew correction fixed --- plugins/samplesource/sdrdaemon/sdrdaemonbuffer.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.cpp b/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.cpp index 504467dac..e05811d57 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.cpp +++ b/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.cpp @@ -115,6 +115,10 @@ bool SDRdaemonBuffer::readMeta(char *array, uint32_t length) { m_sampleRateStream = sampleRate; } + else + { + sampleRate = m_sampleRate; + } sampleRate += (((int) (sampleRate * m_skewRate)) / m_rateDivider) * m_rateDivider; @@ -320,6 +324,7 @@ void SDRdaemonBuffer::updateBufferSize(uint32_t sampleRate) m_readChunkIndex = m_rateDivider; m_readCycles = 0; m_skewRateSum = 0; + m_skewRate = 0; std::cerr << "SDRdaemonBuffer::updateBufferSize:" << " sampleRate: " << sampleRate From aa709b9d5c42bd1d1b790386843a94bd6a638fd2 Mon Sep 17 00:00:00 2001 From: f4exb Date: Mon, 22 Feb 2016 15:03:16 +0100 Subject: [PATCH 32/51] SDRdaemon plugin: report stream skew data on the GUI --- .../samplesource/sdrdaemon/sdrdaemonbuffer.h | 1 + .../samplesource/sdrdaemon/sdrdaemongui.cpp | 13 +++- plugins/samplesource/sdrdaemon/sdrdaemongui.h | 1 + .../samplesource/sdrdaemon/sdrdaemongui.ui | 78 ++++++++++++++++--- .../samplesource/sdrdaemon/sdrdaemoninput.h | 9 ++- .../sdrdaemon/sdrdaemonudphandler.cpp | 1 + 6 files changed, 87 insertions(+), 16 deletions(-) diff --git a/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h b/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h index e3c9a4bae..31cf04494 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h +++ b/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h @@ -67,6 +67,7 @@ public: void writeData(char *array, uint32_t length); //!< Write data into buffer. uint8_t *readDataChunk(); //!< Read a chunk of data from buffer const MetaData& getCurrentMeta() const { return m_currentMeta; } + uint32_t getSampleRateStream() const { return m_sampleRateStream; } uint32_t getSampleRate() const { return m_sampleRate; } void updateBlockCounts(uint32_t nbBytesReceived); bool isSync() const { return m_sync; } diff --git a/plugins/samplesource/sdrdaemon/sdrdaemongui.cpp b/plugins/samplesource/sdrdaemon/sdrdaemongui.cpp index 926fbadff..7514836aa 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemongui.cpp +++ b/plugins/samplesource/sdrdaemon/sdrdaemongui.cpp @@ -37,6 +37,7 @@ SDRdaemonGui::SDRdaemonGui(PluginAPI* pluginAPI, QWidget* parent) : m_sampleSource(NULL), m_acquisition(false), m_sampleRate(0), + m_sampleRateStream(0), m_centerFrequency(0), m_samplesCount(0), m_tickCount(0), @@ -185,6 +186,7 @@ bool SDRdaemonGui::handleMessage(const Message& message) } else if (SDRdaemonInput::MsgReportSDRdaemonStreamData::match(message)) { + m_sampleRateStream = ((SDRdaemonInput::MsgReportSDRdaemonStreamData&)message).getSampleRateStream(); m_sampleRate = ((SDRdaemonInput::MsgReportSDRdaemonStreamData&)message).getSampleRate(); m_centerFrequency = ((SDRdaemonInput::MsgReportSDRdaemonStreamData&)message).getCenterFrequency(); m_startingTimeStamp.tv_sec = ((SDRdaemonInput::MsgReportSDRdaemonStreamData&)message).get_tv_sec(); @@ -282,9 +284,14 @@ void SDRdaemonGui::updateWithAcquisition() void SDRdaemonGui::updateWithStreamData() { ui->centerFrequency->setValue(m_centerFrequency / 1000); - QString s = QString::number(m_sampleRate/1000.0, 'f', 0); - ui->sampleRateText->setText(tr("%1k").arg(s)); - updateWithStreamTime(); // TODO: remove when time data is implemented + QString s0 = QString::number(m_sampleRateStream/1000.0, 'f', 0); + ui->sampleRateStreamText->setText(tr("%1").arg(s0)); + QString s1 = QString::number(m_sampleRate/1000.0, 'f', 3); + ui->sampleRateText->setText(tr("%1").arg(s1)); + float skewPerCent = (float) ((m_sampleRate - m_sampleRateStream) * 100) / (float) m_sampleRateStream; + QString s2 = QString::number(skewPerCent, 'f', 2); + ui->skewRateText->setText(tr("%1").arg(s2)); + updateWithStreamTime(); } void SDRdaemonGui::updateWithStreamTime() diff --git a/plugins/samplesource/sdrdaemon/sdrdaemongui.h b/plugins/samplesource/sdrdaemon/sdrdaemongui.h index 3760f7c12..346e134c2 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemongui.h +++ b/plugins/samplesource/sdrdaemon/sdrdaemongui.h @@ -55,6 +55,7 @@ private: SampleSource* m_sampleSource; bool m_acquisition; int m_sampleRate; + int m_sampleRateStream; quint64 m_centerFrequency; struct timeval m_startingTimeStamp; int m_samplesCount; diff --git a/plugins/samplesource/sdrdaemon/sdrdaemongui.ui b/plugins/samplesource/sdrdaemon/sdrdaemongui.ui index d4e5132d0..c57d99dd5 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemongui.ui +++ b/plugins/samplesource/sdrdaemon/sdrdaemongui.ui @@ -113,14 +113,7 @@ - - - Rate: - - - - - + 50 @@ -133,10 +126,62 @@ - Record sample rate + Nominal sample rate from stream data (kS/s) - 0k + 00000 + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Qt::Vertical + + + + + + + + 70 + 0 + + + + Actual sample rate (kS/s) + + + 0000.000 + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Qt::Vertical + + + + + + + + 40 + 0 + + + + Sample rate skew from stream nominal rate (%) + + + -00.00 Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter @@ -214,6 +259,19 @@ + + + + Qt::Horizontal + + + + 40 + 20 + + + + diff --git a/plugins/samplesource/sdrdaemon/sdrdaemoninput.h b/plugins/samplesource/sdrdaemon/sdrdaemoninput.h index f89be1e81..0bad392ec 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemoninput.h +++ b/plugins/samplesource/sdrdaemon/sdrdaemoninput.h @@ -134,24 +134,27 @@ public: MESSAGE_CLASS_DECLARATION public: + int getSampleRateStream() const { return m_sampleRateStream; } int getSampleRate() const { return m_sampleRate; } quint64 getCenterFrequency() const { return m_centerFrequency; } uint32_t get_tv_sec() const { return m_tv_sec; } uint32_t get_tv_usec() const { return m_tv_usec; } - static MsgReportSDRdaemonStreamData* create(int sampleRate, quint64 centerFrequency, uint32_t tv_sec, uint32_t tv_usec) + static MsgReportSDRdaemonStreamData* create(int sampleRateStream, int sampleRate, quint64 centerFrequency, uint32_t tv_sec, uint32_t tv_usec) { - return new MsgReportSDRdaemonStreamData(sampleRate, centerFrequency, tv_sec, tv_usec); + return new MsgReportSDRdaemonStreamData(sampleRateStream, sampleRate, centerFrequency, tv_sec, tv_usec); } protected: + int m_sampleRateStream; int m_sampleRate; quint64 m_centerFrequency; uint32_t m_tv_sec; uint32_t m_tv_usec; - MsgReportSDRdaemonStreamData(int sampleRate, quint64 centerFrequency, uint32_t tv_sec, uint32_t tv_usec) : + MsgReportSDRdaemonStreamData(int sampleRateStream, int sampleRate, quint64 centerFrequency, uint32_t tv_sec, uint32_t tv_usec) : Message(), + m_sampleRateStream(sampleRateStream), m_sampleRate(sampleRate), m_centerFrequency(centerFrequency), m_tv_sec(tv_sec), diff --git a/plugins/samplesource/sdrdaemon/sdrdaemonudphandler.cpp b/plugins/samplesource/sdrdaemon/sdrdaemonudphandler.cpp index 231006c54..3342882d4 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemonudphandler.cpp +++ b/plugins/samplesource/sdrdaemon/sdrdaemonudphandler.cpp @@ -157,6 +157,7 @@ void SDRdaemonUDPHandler::processData() DSPSignalNotification *notif = new DSPSignalNotification(m_samplerate, m_centerFrequency * 1000); // Frequency in Hz for the DSP engine DSPEngine::instance()->getInputMessageQueue()->push(notif); SDRdaemonInput::MsgReportSDRdaemonStreamData *report = SDRdaemonInput::MsgReportSDRdaemonStreamData::create( + m_sdrDaemonBuffer.getSampleRateStream(), m_samplerate, m_centerFrequency * 1000, // Frequency in Hz for the GUI m_tv_sec, From 501b14d1e747d77c9e072c97da72c639e65a9e7a Mon Sep 17 00:00:00 2001 From: f4exb Date: Mon, 22 Feb 2016 15:17:44 +0100 Subject: [PATCH 33/51] SDRdaemon plugin: widen auto skew rate compensation to +/-20% --- Readme.md | 4 ++++ plugins/samplesource/sdrdaemon/sdrdaemonbuffer.cpp | 8 ++++---- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/Readme.md b/Readme.md index 3ee82d939..0b5f2e422 100644 --- a/Readme.md +++ b/Readme.md @@ -109,8 +109,12 @@ Note that this plugin does not require any of the hardware support libraries nor

SDRdaemon input

+Warning: this is experimental and not fully debugged yet. + This is the client side of the SDRdaemon server. See the [SDRdaemon](https://github.com/f4exb/sdrdaemon) project in this Github repository. You must specify the address and UDP port to which the server connects and samples will flow into the SDRangel application (default is `127.0.0.1`port `9090`). It uses the meta data to retrieve the sample flow characteristics such as sample rate and receiveng center frequency. +There is an automated skew rate compensation in place. During rate readjustemnt streaming is suspended for about one second. + Note that this plugin does not require any of the hardware support libraries nor the libusb library. It is alwasys available in the list of devices as `SDRdaemon[0]` even if no physical device is connected.

Software build

diff --git a/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.cpp b/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.cpp index e05811d57..5804f806e 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.cpp +++ b/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.cpp @@ -271,10 +271,10 @@ uint8_t *SDRdaemonBuffer::readDataChunk() if (m_readCycles && ((m_writeIndex < m_rawSize / 10) || (m_rawSize - m_writeIndex < m_rawSize / 10))) { m_skewRate = m_skewRateSum / m_readCycles; - if (m_skewRate > 0.04) { - m_skewRate = 0.04; - } else if (m_skewRate < -0.04) { - m_skewRate = -0.04; + if (m_skewRate > 0.2) { + m_skewRate = 0.2; + } else if (m_skewRate < -0.2) { + m_skewRate = -0.2; } qDebug("SDRdaemonBuffer::readDataChunk: m_skewRate: %lf", m_skewRate); } From 942a7ca8033c4eca2065d2c6ef9cb96d9e85e19a Mon Sep 17 00:00:00 2001 From: f4exb Date: Tue, 23 Feb 2016 01:29:03 +0100 Subject: [PATCH 34/51] SDRdaemon plugin: fixed LZ4 writes and uncompressed writes --- .../sdrdaemon/sdrdaemonbuffer.cpp | 41 ++++++++----------- .../samplesource/sdrdaemon/sdrdaemonbuffer.h | 2 +- 2 files changed, 19 insertions(+), 24 deletions(-) diff --git a/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.cpp b/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.cpp index 5804f806e..8e999f7d0 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.cpp +++ b/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.cpp @@ -96,7 +96,7 @@ bool SDRdaemonBuffer::readMeta(char *array, uint32_t length) m_nbBlocks = 0; m_inCount = 0; - if (!(m_currentMeta == *metaData)) + if (!m_lz4 && !(m_currentMeta == *metaData)) { std::cerr << "SDRdaemonBuffer::readMeta: "; printMeta(metaData); @@ -203,23 +203,7 @@ void SDRdaemonBuffer::writeDataLZ4(const char *array, uint32_t length) m_nbLz4CRCOK = 0; } - uint64_t crc64 = m_crc64.calculate_crc(m_lz4InBuffer, m_lz4InSize); - - if (memcmp(&crc64, &m_dataCRC, 8) == 0) - { - m_nbLz4CRCOK++; - } - - int compressedSize = LZ4_decompress_fast((const char*) m_lz4InBuffer, (char*) &m_rawBuffer[m_writeIndex], m_frameSize); - m_nbLz4Decodes++; - - if (compressedSize == m_lz4InSize) - { - m_nbLz4SuccessfulDecodes++; - } - - writeToRawBufferLZ4((const char *) m_lz4InBuffer, m_frameSize); - + writeToRawBufferLZ4(); m_lz4InCount = 0; } } @@ -235,22 +219,33 @@ void SDRdaemonBuffer::writeToRawBufferUncompressed(const char *array, uint32_t l else { std::memcpy((void *) &m_rawBuffer[m_writeIndex], (const void *) array, m_rawSize - m_writeIndex); - m_writeIndex = length - (m_rawSize - m_writeIndex); - std::memcpy((void *) m_rawBuffer, (const void *) &array[m_rawSize - m_writeIndex], m_writeIndex); + length -= m_rawSize - m_writeIndex; + std::memcpy((void *) m_rawBuffer, (const void *) &array[m_rawSize - m_writeIndex], length); + m_writeIndex = length; } } -void SDRdaemonBuffer::writeToRawBufferLZ4(const char *array, uint32_t length) +void SDRdaemonBuffer::writeToRawBufferLZ4() { + uint64_t crc64 = m_crc64.calculate_crc(m_lz4InBuffer, m_lz4InSize); + + if (memcmp(&crc64, &m_dataCRC, 8) == 0) + { + m_nbLz4CRCOK++; + } + else + { + return; + } + int compressedSize = LZ4_decompress_fast((const char*) m_lz4InBuffer, (char*) m_lz4OutBuffer, m_frameSize); m_nbLz4Decodes++; if (compressedSize == m_lz4InSize) { m_nbLz4SuccessfulDecodes++; + writeToRawBufferUncompressed((const char *) m_lz4OutBuffer, m_frameSize); } - - writeToRawBufferUncompressed((const char *) m_lz4OutBuffer, m_frameSize); } uint8_t *SDRdaemonBuffer::readDataChunk() diff --git a/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h b/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h index 31cf04494..cb1b5fcf8 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h +++ b/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h @@ -80,7 +80,7 @@ public: private: void updateLZ4Sizes(uint32_t frameSize); void writeDataLZ4(const char *array, uint32_t length); - void writeToRawBufferLZ4(const char *array, uint32_t originalLength); + void writeToRawBufferLZ4(); void writeToRawBufferUncompressed(const char *array, uint32_t length); void updateBufferSize(uint32_t sampleRate); void printMeta(MetaData *metaData); From 248d5ecdbadb15f67e1fe4ec0f1c7ca6770cb82a Mon Sep 17 00:00:00 2001 From: f4exb Date: Tue, 23 Feb 2016 04:50:15 +0100 Subject: [PATCH 35/51] Fixed sample rate recalculation --- Readme.md | 6 +++--- plugins/samplesource/sdrdaemon/sdrdaemonbuffer.cpp | 6 ++++-- plugins/samplesource/sdrdaemon/sdrdaemongui.ui | 9 ++------- 3 files changed, 9 insertions(+), 12 deletions(-) diff --git a/Readme.md b/Readme.md index 0b5f2e422..edb1d8ed9 100644 --- a/Readme.md +++ b/Readme.md @@ -47,7 +47,7 @@ If you use your own location for gr.osmocom install directory you need to specif `-DGNURADIO_OSMOSDR_LIBRARIES=/opt/install/gr-osmosdr/lib/libgnuradio-osmosdr.so -DGNURADIO_OSMOSDR_INCLUDE_DIRS=/opt/install/gr-osmosdr/include` -

v4l-\*

+

v4l-*

Use `cmake ../ -DV4L-RTL=ON` to build the Linux kernel driver for RTL-SDR (Experimental). Needs a recent kernel and libv4l2. Will need extra work to support SDRPlay. Needs `cp KERNEL_SOURCE/include/linux/compiler.h /usr/include/linux/` and `cp KERNEL_SOURCE/include/uapi/linux/videodev2.h /usr/include/uapi/linux/` and package `libv4l-dev`. @@ -99,7 +99,7 @@ If you use your own location for librtlsdr install directory you need to specify `-DLIBRTLSDR_LIBRARIES=/opt/install/librtlsdr/lib/librtlsdr.so -DLIBRTLSDR_INCLUDE_DIR=/opt/install/librtlsdr/include` -

Plugins for special devices

+

Plugins for special sample sources

File input

@@ -113,7 +113,7 @@ Warning: this is experimental and not fully debugged yet. This is the client side of the SDRdaemon server. See the [SDRdaemon](https://github.com/f4exb/sdrdaemon) project in this Github repository. You must specify the address and UDP port to which the server connects and samples will flow into the SDRangel application (default is `127.0.0.1`port `9090`). It uses the meta data to retrieve the sample flow characteristics such as sample rate and receiveng center frequency. -There is an automated skew rate compensation in place. During rate readjustemnt streaming is suspended for about one second. +There is an automated skew rate compensation in place. During rate readjustemnt streaming can be suspended or signal glitches can occur for about one second. Note that this plugin does not require any of the hardware support libraries nor the libusb library. It is alwasys available in the list of devices as `SDRdaemon[0]` even if no physical device is connected. diff --git a/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.cpp b/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.cpp index 8e999f7d0..a6dffb8e3 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.cpp +++ b/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.cpp @@ -109,7 +109,7 @@ bool SDRdaemonBuffer::readMeta(char *array, uint32_t length) { m_sampleBytes = metaData->m_sampleBytes & 0x0F; uint32_t frameSize = m_iqSampleSize * metaData->m_nbSamples * metaData->m_nbBlocks; - uint32_t sampleRate = metaData->m_sampleRate; + int sampleRate = metaData->m_sampleRate; if (sampleRate != m_sampleRateStream) { @@ -120,7 +120,9 @@ bool SDRdaemonBuffer::readMeta(char *array, uint32_t length) sampleRate = m_sampleRate; } - sampleRate += (((int) (sampleRate * m_skewRate)) / m_rateDivider) * m_rateDivider; + sampleRate += sampleRate * m_skewRate; + sampleRate = (sampleRate / m_rateDivider) * m_rateDivider; + //sampleRate += (((int) (sampleRate * m_skewRate)) / m_rateDivider) * m_rateDivider; if (metaData->m_sampleBytes & 0x10) { diff --git a/plugins/samplesource/sdrdaemon/sdrdaemongui.ui b/plugins/samplesource/sdrdaemon/sdrdaemongui.ui index c57d99dd5..e15476be9 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemongui.ui +++ b/plugins/samplesource/sdrdaemon/sdrdaemongui.ui @@ -6,7 +6,7 @@ 0 0 - 343 + 375 207
@@ -120,11 +120,6 @@ 0
- - - 8 - - Nominal sample rate from stream data (kS/s) @@ -214,7 +209,7 @@ false
- Record absolute time + Stream timestamp 2015-01-01 00:00:00.000 From 66accbcc5aab036081111d85ff209b203a38b6b9 Mon Sep 17 00:00:00 2001 From: f4exb Date: Tue, 23 Feb 2016 10:37:30 +0100 Subject: [PATCH 36/51] Added locked and unlocked icons --- sdrbase/resources/locked.png | Bin 0 -> 732 bytes sdrbase/resources/res.qrc | 104 +++++++++++++++++---------------- sdrbase/resources/unlocked.png | Bin 0 -> 719 bytes 3 files changed, 53 insertions(+), 51 deletions(-) create mode 100644 sdrbase/resources/locked.png create mode 100644 sdrbase/resources/unlocked.png diff --git a/sdrbase/resources/locked.png b/sdrbase/resources/locked.png new file mode 100644 index 0000000000000000000000000000000000000000..9c7e65dcee019a3de7f1f0ba81f8615a949c709d GIT binary patch literal 732 zcmeAS@N?(olHy`uVBq!ia0vp^5+E$V0wks0X&L}2mUKs7M+SzC{oH>NS%G|oWRD45dJ|uM!v-tY$DUh!@P+6=(yLU`q0KcVS>y)vIg-2?-C@?Ni-cbu=u$OrHy0SlD66X@O(0uZ79|Hs9Bu^K|5Rc;C z3G(v6X9_&r7E4Q*%np8(;&kls>cVMDo2Pj39qsS?^5yBLsx=%pU;1p^D>wD{XW7l) zCyRA6#=l+>c3rY#g4E{y{4IySvDsK$IQx2a?X&0UZ!ONprYih0WW01S?)eG6uqS!C zHe8vJ2X4;XXXty$;F{Kl9}=5)Ud~(<=KXEmx@pOwix19S9rypTXl}-bFD!TNGe7>Q zFA<{UprTY%#3aFHAhRp`fRkg22@}J_GU+|Li!B{Bwp=*1y)K>k%Yl*D?FI;w2+IX#_q&d)5z6~GtYz-{(Bn!k+bE0|Bp2R2`Rt` zQ!R0gC`m~yNwrEYN(E93Mh1pvx&}tNM#dqA23CfaR;Fg!28LD!2AeMAok7u%o1c=I zR*74~;ofTnKn;c<8;Z-)t&$RpQ*}#=G8xh`b5gDJ_4P|~3-ogn(=(H^bq&oejEu@c e+$!Bey}}&b-BVAegaMNw1B0ilpUXO@geCy3jUU+n literal 0 HcmV?d00001 diff --git a/sdrbase/resources/res.qrc b/sdrbase/resources/res.qrc index 8d605b41d..85d65915b 100644 --- a/sdrbase/resources/res.qrc +++ b/sdrbase/resources/res.qrc @@ -1,53 +1,55 @@ - - appicon.png - histogram.png - waterfall.png - preset-load.png - preset-save.png - preset-update.png - preset-delete.png - horizontal.png - vertical.png - maxhold.png - grid.png - invertspectrum.png - preset-last.png - display1.png - display2.png - slopen_icon.png - slopep_icon.png - display1_w.png - display2_w.png - horizontal_w.png - vertical_w.png - current.png - slopeb_icon.png - clear.png - playloop.png - play.png - pause.png - stop.png - sdrangel_logo.png - sdrangel_icon.png - minus.png - plus.png - record_off.png - record_on.png - mem.png - minusw.png - plusw.png - mono.png - stereo.png - sound_off.png - sound_on.png - dsb.png - usb.png - flip_lr.png - flip_rl.png - carrier.png - rds.png - recycle.png - lsb.png - + + locked.png + unlocked.png + appicon.png + histogram.png + waterfall.png + preset-load.png + preset-save.png + preset-update.png + preset-delete.png + horizontal.png + vertical.png + maxhold.png + grid.png + invertspectrum.png + preset-last.png + display1.png + display2.png + slopen_icon.png + slopep_icon.png + display1_w.png + display2_w.png + horizontal_w.png + vertical_w.png + current.png + slopeb_icon.png + clear.png + playloop.png + play.png + pause.png + stop.png + sdrangel_logo.png + sdrangel_icon.png + minus.png + plus.png + record_off.png + record_on.png + mem.png + minusw.png + plusw.png + mono.png + stereo.png + sound_off.png + sound_on.png + dsb.png + usb.png + flip_lr.png + flip_rl.png + carrier.png + rds.png + recycle.png + lsb.png + diff --git a/sdrbase/resources/unlocked.png b/sdrbase/resources/unlocked.png new file mode 100644 index 0000000000000000000000000000000000000000..5d70ba8c0ea48876ffc54dfb48d6fe59406d960e GIT binary patch literal 719 zcmeAS@N?(olHy`uVBq!ia0vp^5+E$V0wks0X&L}2mUKs7M+SzC{oH>NS%G|oWRD45dJ|uM!v-tY$DUh!@P+6=(yLU`q0KcVS>y)vIg-2?-C@?Ni-cbu=u$OrHy0SlD66X@lFz@i@MAigg#0qd?ngc1igK z3T&?!kGLnS>X_Nqv}VD?na2eVy7(tOQ8Wo+4`yATu;5Wozr%+Ayizac#vZSHBf@j} zLjB+P@Y0JeW{gXM9y~VOaF^-(?jL5-2_{VbYHvT;&;DE{ZNL-JwvKu2H1pz`TE_Fs zPxi;Je{g-Z&A`KERJoIdpY4B^ zlVXAIzvy4RW@|>rrKH0mVFQ@*ckQ~bAE zHn~C6;mzJH8)tmxs@TZE)Ba#)Pwm#SXt|du-4l?hFW7iXZ|9(Ou!`55==kq<1zs!kd`3*`NswJ)wB`Jv|saDBFsX&Us z$iUD{*T6{E$T-B%z{<$j%D__Fz|hLTplQdmP81Ef`6-!cmAEy0ei~;A)L;m*p|~vF zDk-rzRkyS#lOZiLC)G+{U%w=`KtDGzJu^95*U;3`(j><@N7pYWG$gDbqH=P}*=C?- N22WQ%mvv4FO#mr}5K;gD literal 0 HcmV?d00001 From d835662932f2383924c1368d279923ed423ed712 Mon Sep 17 00:00:00 2001 From: f4exb Date: Tue, 23 Feb 2016 10:38:08 +0100 Subject: [PATCH 37/51] SDRdaemon plugin: corrected plugin name --- plugins/samplesource/sdrdaemon/sdrdaemonbuffer.cpp | 1 - plugins/samplesource/sdrdaemon/sdrdaemonplugin.cpp | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.cpp b/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.cpp index a6dffb8e3..5d1f476ce 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.cpp +++ b/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.cpp @@ -122,7 +122,6 @@ bool SDRdaemonBuffer::readMeta(char *array, uint32_t length) sampleRate += sampleRate * m_skewRate; sampleRate = (sampleRate / m_rateDivider) * m_rateDivider; - //sampleRate += (((int) (sampleRate * m_skewRate)) / m_rateDivider) * m_rateDivider; if (metaData->m_sampleBytes & 0x10) { diff --git a/plugins/samplesource/sdrdaemon/sdrdaemonplugin.cpp b/plugins/samplesource/sdrdaemon/sdrdaemonplugin.cpp index 5bdf64780..c016d13ce 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemonplugin.cpp +++ b/plugins/samplesource/sdrdaemon/sdrdaemonplugin.cpp @@ -23,7 +23,7 @@ #include "sdrdaemonplugin.h" const PluginDescriptor SDRdaemonPlugin::m_pluginDescriptor = { - QString("File source input"), + QString("SDRdaemon input"), QString("---"), QString("(c) Edouard Griffiths, F4EXB"), QString("https://github.com/f4exb/sdrangel"), From 2938a93ddf9d51a084e5aa65b0097f4a5b592067 Mon Sep 17 00:00:00 2001 From: f4exb Date: Tue, 23 Feb 2016 10:53:30 +0100 Subject: [PATCH 38/51] Added compressed icon. Changed unlocked icon --- sdrbase/resources/compressed.png | Bin 0 -> 755 bytes sdrbase/resources/res.qrc | 3 ++- sdrbase/resources/unlocked.png | Bin 719 -> 385 bytes 3 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 sdrbase/resources/compressed.png diff --git a/sdrbase/resources/compressed.png b/sdrbase/resources/compressed.png new file mode 100644 index 0000000000000000000000000000000000000000..0f098430704c4e8a05d2847a15afe42ccd3f94fc GIT binary patch literal 755 zcmeAS@N?(olHy`uVBq!ia0vp^5+E$V0wks0X&L}2mUKs7M+SzC{oH>NS%G|oWRD45dJ|uM!v-tY$DUh!@P+6=(yLU`q0KcVS>y)vIg-2?-C@?Ni-cbu=u$OrHy0SlD66Z2v{8g6|%D}+5($mE;#N+teP}^)KN0B+a?eYS= zLe>W_9n$+D&N9_|q7n-WH@9xHhm~S)#I2Q6*&WvgE$7S3anjL!qP2K#Ypds$33rwV z*z}*+DeWO_wBhLN+TYLi?%ZqrK%QM8gnzVt3BPO>pIJgYjF zS8r41pQ6Gf$o2Qmg74)!{TLYL&wucGbLvv$I@|iTx!wW=t>TYj-RhoA(BWFj!46X|Y zzDg<0Y*`U<;_fGXeFwet>;!Ln>e^GLWwIz{Z*-MrDyoLxLzZXAlggSIw}wYt`Q|Ei6yC4$wjF^iowXh&`j6BNY}_X#L&RX z)WFKXP}{)J%D|vFnk^4SLvDUbW?Cg~4NPqNE&(+df@~-*OSei&EKb!eEy`p_%gjl& z(%087$t}>&O-#>B&ek=uG_x=W^$Rhw2=yv9GAv2|a^~ebpk@Y7S3j3^P6 + compressed.png locked.png - unlocked.png appicon.png + unlocked.png histogram.png waterfall.png preset-load.png diff --git a/sdrbase/resources/unlocked.png b/sdrbase/resources/unlocked.png index 5d70ba8c0ea48876ffc54dfb48d6fe59406d960e..2f6bbb100f5c3c8234793780e2298f72469fa75e 100644 GIT binary patch delta 370 zcmV-&0ge981%U&Q7=H)^0000=e)V$z0007FOGiWi|A&vvzW@LL32;bRa{vGf6951U z69E94oEQKA00(qQO+^Rb0v8D^1uGOO$^ZZX5=lfsR5;6xk}*m{K@>$#g2Y6y5DQ~r zAqW~bpopE8f+%QZ=Q6}n_h6sOMQ9ZhY;^@z79vTE2}HuN@PDI!lJC#lVi@k+Gw<V9#E18+rI&e9^Y54YvT?wyEm73)#S>st?Zo zI%Qj`UStE0s_q2duBxp+XD0P}!wX+DgI^j9sIZn@Va3((e*j6KfTq=oz<#;p9m3l#I5R5bM)gp%wzs$_DP(pvHaP+SP-8YXEKrUOlfu z1%PsVOXsOG3Mi${C?IY%QmR@2mg9i~I>3A$FdXwI!(qaGKXNyz>)ucD8`~u65#Pb? QmjD0&07*qoM6N<$f?eU8zyJUM literal 719 zcmeAS@N?(olHy`uVBq!ia0vp^5+E$V0wks0X&L}2mUKs7M+SzC{oH>NS%G|oWRD45dJ|uM!v-tY$DUh!@P+6=(yLU`q0KcVS>y)vIg-2?-C@?Ni-cbu=u$OrHy0SlD66X@lFz@i@MAigg#0qd?ngc1igK z3T&?!kGLnS>X_Nqv}VD?na2eVy7(tOQ8Wo+4`yATu;5Wozr%+Ayizac#vZSHBf@j} zLjB+P@Y0JeW{gXM9y~VOaF^-(?jL5-2_{VbYHvT;&;DE{ZNL-JwvKu2H1pz`TE_Fs zPxi;Je{g-Z&A`KERJoIdpY4B^ zlVXAIzvy4RW@|>rrKH0mVFQ@*ckQ~bAE zHn~C6;mzJH8)tmxs@TZE)Ba#)Pwm#SXt|du-4l?hFW7iXZ|9(Ou!`55==kq<1zs!kd`3*`NswJ)wB`Jv|saDBFsX&Us z$iUD{*T6{E$T-B%z{<$j%D__Fz|hLTplQdmP81Ef`6-!cmAEy0ei~;A)L;m*p|~vF zDk-rzRkyS#lOZiLC)G+{U%w=`KtDGzJu^95*U;3`(j><@N7pYWG$gDbqH=P}*=C?- N22WQ%mvv4FO#mr}5K;gD From 586abc65085890aa510f746a4de9c2c645b8a39d Mon Sep 17 00:00:00 2001 From: f4exb Date: Tue, 23 Feb 2016 11:09:45 +0100 Subject: [PATCH 39/51] SDRdaemon plugin: added status bar in the UI --- .../samplesource/sdrdaemon/sdrdaemongui.ui | 151 ++++++++++++++++-- 1 file changed, 141 insertions(+), 10 deletions(-) diff --git a/plugins/samplesource/sdrdaemon/sdrdaemongui.ui b/plugins/samplesource/sdrdaemon/sdrdaemongui.ui index e15476be9..c432e8a4d 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemongui.ui +++ b/plugins/samplesource/sdrdaemon/sdrdaemongui.ui @@ -225,6 +225,147 @@
+ + + + + + false + + + Stream locked status i.e. synced with meta data + + + ... + + + + :/locked.png:/locked.png + + + + + + + + 50 + 0 + + + + Frame size in kB + + + 0000 + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Qt::Vertical + + + + + + + false + + + Stream is compressed with LZ4 + + + ... + + + + :/compressed.png:/compressed.png + + + + + + + + 40 + 0 + + + + Stream comopression ratio (compressed / original) + + + 0.00 + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 40 + 0 + + + + Data CRC OK (%) + + + 100 + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 40 + 0 + + + + LZ4 successful decodes (%) + + + 100 + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + Qt::Horizontal + + + @@ -361,16 +502,6 @@ - - - - Qt::Horizontal - - - - - - From 6b368f10b67fd8d30e95ea0de726d04bdc1317f2 Mon Sep 17 00:00:00 2001 From: f4exb Date: Tue, 23 Feb 2016 14:57:40 +0100 Subject: [PATCH 40/51] SDRdaemon plugin: report stream locked in UI --- plugins/samplesource/sdrdaemon/sdrdaemongui.cpp | 8 ++++++++ plugins/samplesource/sdrdaemon/sdrdaemongui.h | 3 +++ plugins/samplesource/sdrdaemon/sdrdaemoninput.h | 17 +++++++++++++---- .../sdrdaemon/sdrdaemonudphandler.cpp | 3 ++- 4 files changed, 26 insertions(+), 5 deletions(-) diff --git a/plugins/samplesource/sdrdaemon/sdrdaemongui.cpp b/plugins/samplesource/sdrdaemon/sdrdaemongui.cpp index 7514836aa..28ef410d4 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemongui.cpp +++ b/plugins/samplesource/sdrdaemon/sdrdaemongui.cpp @@ -39,6 +39,7 @@ SDRdaemonGui::SDRdaemonGui(PluginAPI* pluginAPI, QWidget* parent) : m_sampleRate(0), m_sampleRateStream(0), m_centerFrequency(0), + m_syncLocked(false), m_samplesCount(0), m_tickCount(0), m_address("127.0.0.1"), @@ -198,6 +199,7 @@ bool SDRdaemonGui::handleMessage(const Message& message) { m_startingTimeStamp.tv_sec = ((SDRdaemonInput::MsgReportSDRdaemonStreamTiming&)message).get_tv_sec(); m_startingTimeStamp.tv_usec = ((SDRdaemonInput::MsgReportSDRdaemonStreamTiming&)message).get_tv_usec(); + m_syncLocked = ((SDRdaemonInput::MsgReportSDRdaemonStreamTiming&)message).getSyncLock(); updateWithStreamTime(); return true; } @@ -300,6 +302,12 @@ void SDRdaemonGui::updateWithStreamTime() QDateTime dt = QDateTime::fromMSecsSinceEpoch(startingTimeStampMsec); QString s_date = dt.toString("yyyy-MM-dd hh:mm:ss.zzz"); ui->absTimeText->setText(s_date); + + if (m_syncLocked) { + ui->streamLocked->setStyleSheet("QToolButton { background-color : green; }"); + } else { + ui->streamLocked->setStyleSheet("QToolButton { background:rgb(79,79,79); }"); + } } void SDRdaemonGui::tick() diff --git a/plugins/samplesource/sdrdaemon/sdrdaemongui.h b/plugins/samplesource/sdrdaemon/sdrdaemongui.h index 346e134c2..2f307b38e 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemongui.h +++ b/plugins/samplesource/sdrdaemon/sdrdaemongui.h @@ -54,10 +54,13 @@ private: QTimer m_updateTimer; SampleSource* m_sampleSource; bool m_acquisition; + int m_sampleRate; int m_sampleRateStream; quint64 m_centerFrequency; struct timeval m_startingTimeStamp; + bool m_syncLocked; + int m_samplesCount; std::size_t m_tickCount; diff --git a/plugins/samplesource/sdrdaemon/sdrdaemoninput.h b/plugins/samplesource/sdrdaemon/sdrdaemoninput.h index 0bad392ec..7f4451df8 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemoninput.h +++ b/plugins/samplesource/sdrdaemon/sdrdaemoninput.h @@ -168,20 +168,29 @@ public: public: uint32_t get_tv_sec() const { return m_tv_sec; } uint32_t get_tv_usec() const { return m_tv_usec; } + bool getSyncLock() const { return m_syncLock; } - static MsgReportSDRdaemonStreamTiming* create(uint32_t tv_sec, uint32_t tv_usec) + static MsgReportSDRdaemonStreamTiming* create(uint32_t tv_sec, + uint32_t tv_usec, + bool syncLock) { - return new MsgReportSDRdaemonStreamTiming(tv_sec, tv_usec); + return new MsgReportSDRdaemonStreamTiming(tv_sec, + tv_usec, + syncLock); } protected: uint32_t m_tv_sec; uint32_t m_tv_usec; + bool m_syncLock; - MsgReportSDRdaemonStreamTiming(uint32_t tv_sec, uint32_t tv_usec) : + MsgReportSDRdaemonStreamTiming(uint32_t tv_sec, + uint32_t tv_usec, + bool syncLock) : Message(), m_tv_sec(tv_sec), - m_tv_usec(tv_usec) + m_tv_usec(tv_usec), + m_syncLock(syncLock) { } }; diff --git a/plugins/samplesource/sdrdaemon/sdrdaemonudphandler.cpp b/plugins/samplesource/sdrdaemon/sdrdaemonudphandler.cpp index 3342882d4..d5c907fb2 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemonudphandler.cpp +++ b/plugins/samplesource/sdrdaemon/sdrdaemonudphandler.cpp @@ -208,7 +208,8 @@ void SDRdaemonUDPHandler::tick() m_tickCount = 0; SDRdaemonInput::MsgReportSDRdaemonStreamTiming *report = SDRdaemonInput::MsgReportSDRdaemonStreamTiming::create( m_tv_sec, - m_tv_usec); + m_tv_usec, + m_sdrDaemonBuffer.isSyncLocked()); m_outputMessageQueueToGUI->push(report); } } From 16c3e3e72fc9eb80a8fa536972e3b72e42afedf6 Mon Sep 17 00:00:00 2001 From: f4exb Date: Tue, 23 Feb 2016 18:09:20 +0100 Subject: [PATCH 41/51] SDRdaemon plugin: report frame soze in UI. Reorganized UI --- .../samplesource/sdrdaemon/sdrdaemonbuffer.h | 1 + .../samplesource/sdrdaemon/sdrdaemongui.cpp | 4 + plugins/samplesource/sdrdaemon/sdrdaemongui.h | 1 + .../samplesource/sdrdaemon/sdrdaemongui.ui | 282 +++++++++--------- .../samplesource/sdrdaemon/sdrdaemoninput.h | 14 +- .../sdrdaemon/sdrdaemonudphandler.cpp | 3 +- 6 files changed, 167 insertions(+), 138 deletions(-) diff --git a/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h b/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h index cb1b5fcf8..2f35f48bf 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h +++ b/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h @@ -72,6 +72,7 @@ public: void updateBlockCounts(uint32_t nbBytesReceived); bool isSync() const { return m_sync; } bool isSyncLocked() const { return m_syncLock; } + uint32_t getFrameSize() const { return m_frameSize; } static const int m_udpPayloadSize; static const int m_sampleSize; diff --git a/plugins/samplesource/sdrdaemon/sdrdaemongui.cpp b/plugins/samplesource/sdrdaemon/sdrdaemongui.cpp index 28ef410d4..4d0317877 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemongui.cpp +++ b/plugins/samplesource/sdrdaemon/sdrdaemongui.cpp @@ -200,6 +200,7 @@ bool SDRdaemonGui::handleMessage(const Message& message) m_startingTimeStamp.tv_sec = ((SDRdaemonInput::MsgReportSDRdaemonStreamTiming&)message).get_tv_sec(); m_startingTimeStamp.tv_usec = ((SDRdaemonInput::MsgReportSDRdaemonStreamTiming&)message).get_tv_usec(); m_syncLocked = ((SDRdaemonInput::MsgReportSDRdaemonStreamTiming&)message).getSyncLock(); + m_frameSize = ((SDRdaemonInput::MsgReportSDRdaemonStreamTiming&)message).getFrameSize(); updateWithStreamTime(); return true; } @@ -308,6 +309,9 @@ void SDRdaemonGui::updateWithStreamTime() } else { ui->streamLocked->setStyleSheet("QToolButton { background:rgb(79,79,79); }"); } + + QString s = QString::number(m_frameSize / 1024.0, 'f', 0); + ui->frameSizeText->setText(tr("%1").arg(s)); } void SDRdaemonGui::tick() diff --git a/plugins/samplesource/sdrdaemon/sdrdaemongui.h b/plugins/samplesource/sdrdaemon/sdrdaemongui.h index 2f307b38e..2f024d39e 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemongui.h +++ b/plugins/samplesource/sdrdaemon/sdrdaemongui.h @@ -60,6 +60,7 @@ private: quint64 m_centerFrequency; struct timeval m_startingTimeStamp; bool m_syncLocked; + uint32_t m_frameSize; int m_samplesCount; std::size_t m_tickCount; diff --git a/plugins/samplesource/sdrdaemon/sdrdaemongui.ui b/plugins/samplesource/sdrdaemon/sdrdaemongui.ui index c432e8a4d..5d863e957 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemongui.ui +++ b/plugins/samplesource/sdrdaemon/sdrdaemongui.ui @@ -2,19 +2,11 @@ SDRdaemonGui - - - 0 - 0 - 375 - 207 - - - - - 0 - 0 - + + + 360 + 0 + @@ -104,87 +96,43 @@ - + Qt::Horizontal - + - - - - 50 - 0 - + + + Auto Corr + + + + - Nominal sample rate from stream data (kS/s) + DC Offset auto correction - 00000 - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + DC - - - Qt::Vertical - - - - - - - - 70 - 0 - - + - Actual sample rate (kS/s) + IQ Imbalance auto correction - 0000.000 - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + IQ - - - Qt::Vertical - - - - - - - - 40 - 0 - - - - Sample rate skew from stream nominal rate (%) - - - -00.00 - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - + Qt::Horizontal @@ -196,13 +144,6 @@ - - - - Qt::Vertical - - - @@ -219,14 +160,14 @@ - + Qt::Horizontal - + @@ -264,12 +205,114 @@ - + Qt::Vertical + + + + + 50 + 0 + + + + Nominal sample rate from stream data (kS/s) + + + 00000 + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Qt::Vertical + + + + + + + + 70 + 0 + + + + Actual sample rate (kS/s) + + + 0000.000 + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Qt::Vertical + + + + + + + + 50 + 0 + + + + Sample rate skew from stream nominal rate (%) + + + -00.00 + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Qt::Vertical + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + Qt::Horizontal + + + + + @@ -291,7 +334,7 @@ - 40 + 50 0 @@ -306,6 +349,13 @@ + + + + Qt::Vertical + + + @@ -325,6 +375,13 @@ + + + + Qt::Vertical + + + @@ -345,58 +402,14 @@ - + - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - Qt::Horizontal - - - - - - - - - Auto corr + Qt::Vertical - - - DC Offset auto correction - - - DC Offset - - - - - - - IQ Imbalance auto correction - - - IQ Imbalance - - - - - + Qt::Horizontal @@ -433,7 +446,7 @@ - 120 + 150 0 @@ -457,10 +470,10 @@ true - + 50 - 0 + 16777215 @@ -469,6 +482,9 @@ 9090 + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + diff --git a/plugins/samplesource/sdrdaemon/sdrdaemoninput.h b/plugins/samplesource/sdrdaemon/sdrdaemoninput.h index 7f4451df8..29a4f9d89 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemoninput.h +++ b/plugins/samplesource/sdrdaemon/sdrdaemoninput.h @@ -169,28 +169,34 @@ public: uint32_t get_tv_sec() const { return m_tv_sec; } uint32_t get_tv_usec() const { return m_tv_usec; } bool getSyncLock() const { return m_syncLock; } + uint32_t getFrameSize() const { return m_frameSize; } static MsgReportSDRdaemonStreamTiming* create(uint32_t tv_sec, uint32_t tv_usec, - bool syncLock) + bool syncLock, + uint32_t frameSize) { return new MsgReportSDRdaemonStreamTiming(tv_sec, tv_usec, - syncLock); + syncLock, + frameSize); } protected: uint32_t m_tv_sec; uint32_t m_tv_usec; bool m_syncLock; + uint32_t m_frameSize; MsgReportSDRdaemonStreamTiming(uint32_t tv_sec, uint32_t tv_usec, - bool syncLock) : + bool syncLock, + uint32_t frameSize) : Message(), m_tv_sec(tv_sec), m_tv_usec(tv_usec), - m_syncLock(syncLock) + m_syncLock(syncLock), + m_frameSize(frameSize) { } }; diff --git a/plugins/samplesource/sdrdaemon/sdrdaemonudphandler.cpp b/plugins/samplesource/sdrdaemon/sdrdaemonudphandler.cpp index d5c907fb2..26bb5ad07 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemonudphandler.cpp +++ b/plugins/samplesource/sdrdaemon/sdrdaemonudphandler.cpp @@ -209,7 +209,8 @@ void SDRdaemonUDPHandler::tick() SDRdaemonInput::MsgReportSDRdaemonStreamTiming *report = SDRdaemonInput::MsgReportSDRdaemonStreamTiming::create( m_tv_sec, m_tv_usec, - m_sdrDaemonBuffer.isSyncLocked()); + m_sdrDaemonBuffer.isSyncLocked(), + m_sdrDaemonBuffer.getFrameSize()); m_outputMessageQueueToGUI->push(report); } } From 23750b10f688da1a1f902c1172dadc59ad0c6ae7 Mon Sep 17 00:00:00 2001 From: f4exb Date: Tue, 23 Feb 2016 18:19:35 +0100 Subject: [PATCH 42/51] SDRdaemon plugin: report LZ4 compression status --- plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h | 1 + plugins/samplesource/sdrdaemon/sdrdaemongui.cpp | 7 +++++++ plugins/samplesource/sdrdaemon/sdrdaemongui.h | 1 + plugins/samplesource/sdrdaemon/sdrdaemongui.ui | 2 +- plugins/samplesource/sdrdaemon/sdrdaemoninput.h | 14 ++++++++++---- .../samplesource/sdrdaemon/sdrdaemonudphandler.cpp | 3 ++- 6 files changed, 22 insertions(+), 6 deletions(-) diff --git a/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h b/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h index 2f35f48bf..425ccef0e 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h +++ b/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h @@ -73,6 +73,7 @@ public: bool isSync() const { return m_sync; } bool isSyncLocked() const { return m_syncLock; } uint32_t getFrameSize() const { return m_frameSize; } + bool isLz4Compressed() const { return m_lz4; } static const int m_udpPayloadSize; static const int m_sampleSize; diff --git a/plugins/samplesource/sdrdaemon/sdrdaemongui.cpp b/plugins/samplesource/sdrdaemon/sdrdaemongui.cpp index 4d0317877..71dfb1ad9 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemongui.cpp +++ b/plugins/samplesource/sdrdaemon/sdrdaemongui.cpp @@ -201,6 +201,7 @@ bool SDRdaemonGui::handleMessage(const Message& message) m_startingTimeStamp.tv_usec = ((SDRdaemonInput::MsgReportSDRdaemonStreamTiming&)message).get_tv_usec(); m_syncLocked = ((SDRdaemonInput::MsgReportSDRdaemonStreamTiming&)message).getSyncLock(); m_frameSize = ((SDRdaemonInput::MsgReportSDRdaemonStreamTiming&)message).getFrameSize(); + m_lz4 = ((SDRdaemonInput::MsgReportSDRdaemonStreamTiming&)message).getLz4Compression(); updateWithStreamTime(); return true; } @@ -312,6 +313,12 @@ void SDRdaemonGui::updateWithStreamTime() QString s = QString::number(m_frameSize / 1024.0, 'f', 0); ui->frameSizeText->setText(tr("%1").arg(s)); + + if (m_lz4) { + ui->lz4Compressed->setStyleSheet("QToolButton { background-color : green; }"); + } else { + ui->lz4Compressed->setStyleSheet("QToolButton { background:rgb(79,79,79); }"); + } } void SDRdaemonGui::tick() diff --git a/plugins/samplesource/sdrdaemon/sdrdaemongui.h b/plugins/samplesource/sdrdaemon/sdrdaemongui.h index 2f024d39e..3674b861a 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemongui.h +++ b/plugins/samplesource/sdrdaemon/sdrdaemongui.h @@ -61,6 +61,7 @@ private: struct timeval m_startingTimeStamp; bool m_syncLocked; uint32_t m_frameSize; + bool m_lz4; int m_samplesCount; std::size_t m_tickCount; diff --git a/plugins/samplesource/sdrdaemon/sdrdaemongui.ui b/plugins/samplesource/sdrdaemon/sdrdaemongui.ui index 5d863e957..81e0be2ca 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemongui.ui +++ b/plugins/samplesource/sdrdaemon/sdrdaemongui.ui @@ -314,7 +314,7 @@ - + false diff --git a/plugins/samplesource/sdrdaemon/sdrdaemoninput.h b/plugins/samplesource/sdrdaemon/sdrdaemoninput.h index 29a4f9d89..28ad15337 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemoninput.h +++ b/plugins/samplesource/sdrdaemon/sdrdaemoninput.h @@ -170,16 +170,19 @@ public: uint32_t get_tv_usec() const { return m_tv_usec; } bool getSyncLock() const { return m_syncLock; } uint32_t getFrameSize() const { return m_frameSize; } + bool getLz4Compression() const { return m_lz4; } static MsgReportSDRdaemonStreamTiming* create(uint32_t tv_sec, uint32_t tv_usec, bool syncLock, - uint32_t frameSize) + uint32_t frameSize, + bool lz4) { return new MsgReportSDRdaemonStreamTiming(tv_sec, tv_usec, syncLock, - frameSize); + frameSize, + lz4); } protected: @@ -187,16 +190,19 @@ public: uint32_t m_tv_usec; bool m_syncLock; uint32_t m_frameSize; + bool m_lz4; MsgReportSDRdaemonStreamTiming(uint32_t tv_sec, uint32_t tv_usec, bool syncLock, - uint32_t frameSize) : + uint32_t frameSize, + bool lz4) : Message(), m_tv_sec(tv_sec), m_tv_usec(tv_usec), m_syncLock(syncLock), - m_frameSize(frameSize) + m_frameSize(frameSize), + m_lz4(lz4) { } }; diff --git a/plugins/samplesource/sdrdaemon/sdrdaemonudphandler.cpp b/plugins/samplesource/sdrdaemon/sdrdaemonudphandler.cpp index 26bb5ad07..d72380057 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemonudphandler.cpp +++ b/plugins/samplesource/sdrdaemon/sdrdaemonudphandler.cpp @@ -210,7 +210,8 @@ void SDRdaemonUDPHandler::tick() m_tv_sec, m_tv_usec, m_sdrDaemonBuffer.isSyncLocked(), - m_sdrDaemonBuffer.getFrameSize()); + m_sdrDaemonBuffer.getFrameSize(), + m_sdrDaemonBuffer.isLz4Compressed()); m_outputMessageQueueToGUI->push(report); } } From e5f2a49835961ec852b542eaa1bafbb5944dba30 Mon Sep 17 00:00:00 2001 From: f4exb Date: Tue, 23 Feb 2016 18:29:08 +0100 Subject: [PATCH 43/51] SDRdaemon plugin: report LZ4 compression ratio --- plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h | 1 + plugins/samplesource/sdrdaemon/sdrdaemongui.cpp | 4 ++++ plugins/samplesource/sdrdaemon/sdrdaemongui.h | 1 + plugins/samplesource/sdrdaemon/sdrdaemongui.ui | 4 ++-- plugins/samplesource/sdrdaemon/sdrdaemoninput.h | 13 +++++++++---- .../samplesource/sdrdaemon/sdrdaemonudphandler.cpp | 3 ++- 6 files changed, 19 insertions(+), 7 deletions(-) diff --git a/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h b/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h index 425ccef0e..b47c8553a 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h +++ b/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h @@ -74,6 +74,7 @@ public: bool isSyncLocked() const { return m_syncLock; } uint32_t getFrameSize() const { return m_frameSize; } bool isLz4Compressed() const { return m_lz4; } + float getCompressionRatio() const { return (m_frameSize ? (float) m_lz4InSize / (float) m_frameSize : 1.0); } static const int m_udpPayloadSize; static const int m_sampleSize; diff --git a/plugins/samplesource/sdrdaemon/sdrdaemongui.cpp b/plugins/samplesource/sdrdaemon/sdrdaemongui.cpp index 71dfb1ad9..08bd72604 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemongui.cpp +++ b/plugins/samplesource/sdrdaemon/sdrdaemongui.cpp @@ -202,6 +202,7 @@ bool SDRdaemonGui::handleMessage(const Message& message) m_syncLocked = ((SDRdaemonInput::MsgReportSDRdaemonStreamTiming&)message).getSyncLock(); m_frameSize = ((SDRdaemonInput::MsgReportSDRdaemonStreamTiming&)message).getFrameSize(); m_lz4 = ((SDRdaemonInput::MsgReportSDRdaemonStreamTiming&)message).getLz4Compression(); + m_compressionRatio = ((SDRdaemonInput::MsgReportSDRdaemonStreamTiming&)message).getLz4Compression(); updateWithStreamTime(); return true; } @@ -319,6 +320,9 @@ void SDRdaemonGui::updateWithStreamTime() } else { ui->lz4Compressed->setStyleSheet("QToolButton { background:rgb(79,79,79); }"); } + + s = QString::number(m_compressionRatio, 'f', 2); + ui->compressionRatioText->setText(tr("%1").arg(s)); } void SDRdaemonGui::tick() diff --git a/plugins/samplesource/sdrdaemon/sdrdaemongui.h b/plugins/samplesource/sdrdaemon/sdrdaemongui.h index 3674b861a..0035c8ff8 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemongui.h +++ b/plugins/samplesource/sdrdaemon/sdrdaemongui.h @@ -62,6 +62,7 @@ private: bool m_syncLocked; uint32_t m_frameSize; bool m_lz4; + float m_compressionRatio; int m_samplesCount; std::size_t m_tickCount; diff --git a/plugins/samplesource/sdrdaemon/sdrdaemongui.ui b/plugins/samplesource/sdrdaemon/sdrdaemongui.ui index 81e0be2ca..959be62cf 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemongui.ui +++ b/plugins/samplesource/sdrdaemon/sdrdaemongui.ui @@ -4,7 +4,7 @@ - 360 + 340 0 @@ -472,7 +472,7 @@ - 50 + 80 16777215 diff --git a/plugins/samplesource/sdrdaemon/sdrdaemoninput.h b/plugins/samplesource/sdrdaemon/sdrdaemoninput.h index 28ad15337..ff927ca26 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemoninput.h +++ b/plugins/samplesource/sdrdaemon/sdrdaemoninput.h @@ -176,13 +176,15 @@ public: uint32_t tv_usec, bool syncLock, uint32_t frameSize, - bool lz4) + bool lz4, + float compressionRatio) { return new MsgReportSDRdaemonStreamTiming(tv_sec, tv_usec, syncLock, frameSize, - lz4); + lz4, + compressionRatio); } protected: @@ -191,18 +193,21 @@ public: bool m_syncLock; uint32_t m_frameSize; bool m_lz4; + float m_compressionRatio; MsgReportSDRdaemonStreamTiming(uint32_t tv_sec, uint32_t tv_usec, bool syncLock, uint32_t frameSize, - bool lz4) : + bool lz4, + float compressionRatio) : Message(), m_tv_sec(tv_sec), m_tv_usec(tv_usec), m_syncLock(syncLock), m_frameSize(frameSize), - m_lz4(lz4) + m_lz4(lz4), + m_compressionRatio(compressionRatio) { } }; diff --git a/plugins/samplesource/sdrdaemon/sdrdaemonudphandler.cpp b/plugins/samplesource/sdrdaemon/sdrdaemonudphandler.cpp index d72380057..4e2b25e74 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemonudphandler.cpp +++ b/plugins/samplesource/sdrdaemon/sdrdaemonudphandler.cpp @@ -211,7 +211,8 @@ void SDRdaemonUDPHandler::tick() m_tv_usec, m_sdrDaemonBuffer.isSyncLocked(), m_sdrDaemonBuffer.getFrameSize(), - m_sdrDaemonBuffer.isLz4Compressed()); + m_sdrDaemonBuffer.isLz4Compressed(), + m_sdrDaemonBuffer.getCompressionRatio()); m_outputMessageQueueToGUI->push(report); } } From 153b1c017c29865d84b97e2f61d43920955e6729 Mon Sep 17 00:00:00 2001 From: f4exb Date: Tue, 23 Feb 2016 19:27:47 +0100 Subject: [PATCH 44/51] SDRdaemon plugin: report LZ4 statistics --- .../sdrdaemon/sdrdaemonbuffer.cpp | 4 ++++ .../samplesource/sdrdaemon/sdrdaemonbuffer.h | 6 ++++- .../samplesource/sdrdaemon/sdrdaemongui.cpp | 22 ++++++++++++++++++- plugins/samplesource/sdrdaemon/sdrdaemongui.h | 2 ++ .../samplesource/sdrdaemon/sdrdaemongui.ui | 4 ++-- .../samplesource/sdrdaemon/sdrdaemoninput.h | 21 ++++++++++++++---- .../sdrdaemon/sdrdaemonudphandler.cpp | 4 +++- 7 files changed, 54 insertions(+), 9 deletions(-) diff --git a/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.cpp b/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.cpp index 5d1f476ce..0126a1b2b 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.cpp +++ b/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.cpp @@ -38,6 +38,8 @@ SDRdaemonBuffer::SDRdaemonBuffer(uint32_t rateDivider) : m_nbLz4Decodes(0), m_nbLz4SuccessfulDecodes(0), m_nbLz4CRCOK(0), + m_nbLastLz4SuccessfulDecodes(0), + m_nbLastLz4CRCOK(0), m_dataCRC(0), m_sampleRateStream(0), m_sampleRate(0), @@ -199,6 +201,8 @@ void SDRdaemonBuffer::writeDataLZ4(const char *array, uint32_t length) << "/" << m_nbLz4Decodes << std::endl; + m_nbLastLz4SuccessfulDecodes = m_nbLz4SuccessfulDecodes; + m_nbLastLz4CRCOK = m_nbLz4CRCOK; m_nbLz4Decodes = 0; m_nbLz4SuccessfulDecodes = 0; m_nbLz4CRCOK = 0; diff --git a/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h b/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h index b47c8553a..d4e27cd17 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h +++ b/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h @@ -74,7 +74,9 @@ public: bool isSyncLocked() const { return m_syncLock; } uint32_t getFrameSize() const { return m_frameSize; } bool isLz4Compressed() const { return m_lz4; } - float getCompressionRatio() const { return (m_frameSize ? (float) m_lz4InSize / (float) m_frameSize : 1.0); } + float getCompressionRatio() const { return (m_frameSize > 0 ? (float) m_lz4InSize / (float) m_frameSize : 1.0); } + uint32_t getLz4DataCRCOK() const { return m_nbLastLz4CRCOK; } + uint32_t getLz4SuccessfulDecodes() const { return m_nbLastLz4SuccessfulDecodes; } static const int m_udpPayloadSize; static const int m_sampleSize; @@ -104,6 +106,8 @@ private: uint32_t m_nbLz4Decodes; uint32_t m_nbLz4SuccessfulDecodes; uint32_t m_nbLz4CRCOK; + uint32_t m_nbLastLz4SuccessfulDecodes; + uint32_t m_nbLastLz4CRCOK; uint64_t m_dataCRC; uint32_t m_sampleRateStream; //!< Current sample rate from the stream diff --git a/plugins/samplesource/sdrdaemon/sdrdaemongui.cpp b/plugins/samplesource/sdrdaemon/sdrdaemongui.cpp index 08bd72604..349b43417 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemongui.cpp +++ b/plugins/samplesource/sdrdaemon/sdrdaemongui.cpp @@ -40,6 +40,11 @@ SDRdaemonGui::SDRdaemonGui(PluginAPI* pluginAPI, QWidget* parent) : m_sampleRateStream(0), m_centerFrequency(0), m_syncLocked(false), + m_frameSize(0), + m_lz4(false), + m_compressionRatio(1.0), + m_nbLz4DataCRCOK(0), + m_nbLz4SuccessfulDecodes(0), m_samplesCount(0), m_tickCount(0), m_address("127.0.0.1"), @@ -202,7 +207,16 @@ bool SDRdaemonGui::handleMessage(const Message& message) m_syncLocked = ((SDRdaemonInput::MsgReportSDRdaemonStreamTiming&)message).getSyncLock(); m_frameSize = ((SDRdaemonInput::MsgReportSDRdaemonStreamTiming&)message).getFrameSize(); m_lz4 = ((SDRdaemonInput::MsgReportSDRdaemonStreamTiming&)message).getLz4Compression(); - m_compressionRatio = ((SDRdaemonInput::MsgReportSDRdaemonStreamTiming&)message).getLz4Compression(); + + if (m_lz4) { + m_compressionRatio = ((SDRdaemonInput::MsgReportSDRdaemonStreamTiming&)message).getLz4CompressionRatio(); + } else { + m_compressionRatio = 1.0; + } + + m_nbLz4DataCRCOK = ((SDRdaemonInput::MsgReportSDRdaemonStreamTiming&)message).getLz4DataCRCOK(); + m_nbLz4SuccessfulDecodes = ((SDRdaemonInput::MsgReportSDRdaemonStreamTiming&)message).getLz4SuccessfulDecodes(); + updateWithStreamTime(); return true; } @@ -323,6 +337,12 @@ void SDRdaemonGui::updateWithStreamTime() s = QString::number(m_compressionRatio, 'f', 2); ui->compressionRatioText->setText(tr("%1").arg(s)); + + s = QString::number(m_nbLz4DataCRCOK, 'f', 0); + ui->dataCRCOKText->setText(tr("%1").arg(s)); + + s = QString::number(m_nbLz4SuccessfulDecodes, 'f', 0); + ui->lz4DecodesOKText->setText(tr("%1").arg(s)); } void SDRdaemonGui::tick() diff --git a/plugins/samplesource/sdrdaemon/sdrdaemongui.h b/plugins/samplesource/sdrdaemon/sdrdaemongui.h index 0035c8ff8..baac02844 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemongui.h +++ b/plugins/samplesource/sdrdaemon/sdrdaemongui.h @@ -63,6 +63,8 @@ private: uint32_t m_frameSize; bool m_lz4; float m_compressionRatio; + uint32_t m_nbLz4DataCRCOK; + uint32_t m_nbLz4SuccessfulDecodes; int m_samplesCount; std::size_t m_tickCount; diff --git a/plugins/samplesource/sdrdaemon/sdrdaemongui.ui b/plugins/samplesource/sdrdaemon/sdrdaemongui.ui index 959be62cf..371187940 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemongui.ui +++ b/plugins/samplesource/sdrdaemon/sdrdaemongui.ui @@ -368,7 +368,7 @@ Data CRC OK (%) - 100 + 0 Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter @@ -394,7 +394,7 @@ LZ4 successful decodes (%) - 100 + 0 Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter diff --git a/plugins/samplesource/sdrdaemon/sdrdaemoninput.h b/plugins/samplesource/sdrdaemon/sdrdaemoninput.h index ff927ca26..6befbc5d4 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemoninput.h +++ b/plugins/samplesource/sdrdaemon/sdrdaemoninput.h @@ -171,20 +171,27 @@ public: bool getSyncLock() const { return m_syncLock; } uint32_t getFrameSize() const { return m_frameSize; } bool getLz4Compression() const { return m_lz4; } + float getLz4CompressionRatio() const { return m_compressionRatio; } + uint32_t getLz4DataCRCOK() const { return m_nbLz4CRCOK; } + uint32_t getLz4SuccessfulDecodes() const { return m_nbLz4SuccessfulDecodes; } static MsgReportSDRdaemonStreamTiming* create(uint32_t tv_sec, uint32_t tv_usec, bool syncLock, uint32_t frameSize, bool lz4, - float compressionRatio) + float compressionRatio, + uint32_t nbLz4CRCOK, + uint32_t nbLz4SuccessfulDecodes) { return new MsgReportSDRdaemonStreamTiming(tv_sec, tv_usec, syncLock, frameSize, lz4, - compressionRatio); + compressionRatio, + nbLz4CRCOK, + nbLz4SuccessfulDecodes); } protected: @@ -194,20 +201,26 @@ public: uint32_t m_frameSize; bool m_lz4; float m_compressionRatio; + uint32_t m_nbLz4CRCOK; + uint32_t m_nbLz4SuccessfulDecodes; MsgReportSDRdaemonStreamTiming(uint32_t tv_sec, uint32_t tv_usec, bool syncLock, uint32_t frameSize, bool lz4, - float compressionRatio) : + float compressionRatio, + uint32_t nbLz4CRCOK, + uint32_t nbLz4SuccessfulDecodes) : Message(), m_tv_sec(tv_sec), m_tv_usec(tv_usec), m_syncLock(syncLock), m_frameSize(frameSize), m_lz4(lz4), - m_compressionRatio(compressionRatio) + m_compressionRatio(compressionRatio), + m_nbLz4CRCOK(nbLz4CRCOK), + m_nbLz4SuccessfulDecodes(nbLz4SuccessfulDecodes) { } }; diff --git a/plugins/samplesource/sdrdaemon/sdrdaemonudphandler.cpp b/plugins/samplesource/sdrdaemon/sdrdaemonudphandler.cpp index 4e2b25e74..63d88bcb1 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemonudphandler.cpp +++ b/plugins/samplesource/sdrdaemon/sdrdaemonudphandler.cpp @@ -212,7 +212,9 @@ void SDRdaemonUDPHandler::tick() m_sdrDaemonBuffer.isSyncLocked(), m_sdrDaemonBuffer.getFrameSize(), m_sdrDaemonBuffer.isLz4Compressed(), - m_sdrDaemonBuffer.getCompressionRatio()); + m_sdrDaemonBuffer.getCompressionRatio(), + m_sdrDaemonBuffer.getLz4DataCRCOK(), + m_sdrDaemonBuffer.getLz4SuccessfulDecodes()); m_outputMessageQueueToGUI->push(report); } } From 591ffd2f0e30dd194e5b329860e9a27fbeabc56f Mon Sep 17 00:00:00 2001 From: f4exb Date: Tue, 23 Feb 2016 21:22:27 +0100 Subject: [PATCH 45/51] SDRdaemon plugin: display stream rate with two decimals in UI --- plugins/samplesource/sdrdaemon/sdrdaemongui.cpp | 2 +- plugins/samplesource/sdrdaemon/sdrdaemongui.ui | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/plugins/samplesource/sdrdaemon/sdrdaemongui.cpp b/plugins/samplesource/sdrdaemon/sdrdaemongui.cpp index 349b43417..7ac3164fe 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemongui.cpp +++ b/plugins/samplesource/sdrdaemon/sdrdaemongui.cpp @@ -303,7 +303,7 @@ void SDRdaemonGui::updateWithAcquisition() void SDRdaemonGui::updateWithStreamData() { ui->centerFrequency->setValue(m_centerFrequency / 1000); - QString s0 = QString::number(m_sampleRateStream/1000.0, 'f', 0); + QString s0 = QString::number(m_sampleRateStream/1000.0, 'f', 2); ui->sampleRateStreamText->setText(tr("%1").arg(s0)); QString s1 = QString::number(m_sampleRate/1000.0, 'f', 3); ui->sampleRateText->setText(tr("%1").arg(s1)); diff --git a/plugins/samplesource/sdrdaemon/sdrdaemongui.ui b/plugins/samplesource/sdrdaemon/sdrdaemongui.ui index 371187940..b0b368e61 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemongui.ui +++ b/plugins/samplesource/sdrdaemon/sdrdaemongui.ui @@ -215,7 +215,7 @@ - 50 + 70 0 @@ -223,7 +223,7 @@ Nominal sample rate from stream data (kS/s) - 00000 + 0000.00 Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter From 09e724bbdbb045853b79bb4155f16213e4ed20cd Mon Sep 17 00:00:00 2001 From: f4exb Date: Tue, 23 Feb 2016 22:24:25 +0100 Subject: [PATCH 46/51] SDRdaemon plugin: fixed start not actually starting --- plugins/samplesource/sdrdaemon/sdrdaemonudphandler.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/plugins/samplesource/sdrdaemon/sdrdaemonudphandler.cpp b/plugins/samplesource/sdrdaemon/sdrdaemonudphandler.cpp index 63d88bcb1..d0af8a0ae 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemonudphandler.cpp +++ b/plugins/samplesource/sdrdaemon/sdrdaemonudphandler.cpp @@ -76,6 +76,10 @@ void SDRdaemonUDPHandler::start() m_dataConnected = false; } } + + // Need to notify the DSP engine to actually start + DSPSignalNotification *notif = new DSPSignalNotification(m_samplerate, m_centerFrequency * 1000); // Frequency in Hz for the DSP engine + DSPEngine::instance()->getInputMessageQueue()->push(notif); } void SDRdaemonUDPHandler::stop() From 5ab1f76538ed46050ee8c74541aa5b7fe4fbda71 Mon Sep 17 00:00:00 2001 From: f4exb Date: Tue, 23 Feb 2016 23:16:05 +0100 Subject: [PATCH 47/51] SDRdaemon plugin: fixed UDP setting in UI --- Readme.md | 3 --- .../samplesource/sdrdaemon/sdrdaemongui.cpp | 27 ++++++++++--------- sdrbase/gui/aboutdialog.ui | 2 +- 3 files changed, 16 insertions(+), 16 deletions(-) diff --git a/Readme.md b/Readme.md index edb1d8ed9..55d8753f1 100644 --- a/Readme.md +++ b/Readme.md @@ -109,8 +109,6 @@ Note that this plugin does not require any of the hardware support libraries nor

SDRdaemon input

-Warning: this is experimental and not fully debugged yet. - This is the client side of the SDRdaemon server. See the [SDRdaemon](https://github.com/f4exb/sdrdaemon) project in this Github repository. You must specify the address and UDP port to which the server connects and samples will flow into the SDRangel application (default is `127.0.0.1`port `9090`). It uses the meta data to retrieve the sample flow characteristics such as sample rate and receiveng center frequency. There is an automated skew rate compensation in place. During rate readjustemnt streaming can be suspended or signal glitches can occur for about one second. @@ -211,7 +209,6 @@ See the v1.0.1 first official relase [release notes](https://github.com/f4exb/sd

To Do

- - UDP source plugin: add the possibility to launch an external command that will process the samples like a GNUradio headless flowgraph - Allow the handling of more than one device at the same time. For Rx/Tx devices like the BladeRF Rx and Tx appear as two logical devices with two plugin instances and a common handler for the physical device services both plugins. This effectively opens Tx support. - Tx channels - Possibility to connect channels for example Rx to Tx or single Rx channel to dual Rx channel supporting MI(MO) features like 360 degree polarization detection. diff --git a/plugins/samplesource/sdrdaemon/sdrdaemongui.cpp b/plugins/samplesource/sdrdaemon/sdrdaemongui.cpp index 7ac3164fe..f19e7dd52 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemongui.cpp +++ b/plugins/samplesource/sdrdaemon/sdrdaemongui.cpp @@ -251,6 +251,18 @@ void SDRdaemonGui::displaySettings() void SDRdaemonGui::on_applyButton_clicked(bool checked) { + bool ok; + QString udpAddress = ui->address->text(); + int udpPort = ui->port->text().toInt(&ok); + + if((!ok) || (udpPort < 1024) || (udpPort > 65535)) + { + udpPort = 9090; + } + + m_address = udpAddress; + m_port = udpPort; + configureUDPLink(); } @@ -274,19 +286,10 @@ void SDRdaemonGui::on_iqImbalance_toggled(bool checked) void SDRdaemonGui::configureUDPLink() { - bool ok; - QString udpAddress = ui->address->text(); - int udpPort = ui->port->text().toInt(&ok); + qDebug() << "SDRdaemonGui::configureUDPLink: " << m_address.toStdString().c_str() + << " : " << m_port; - if((!ok) || (udpPort < 1024) || (udpPort > 65535)) - { - udpPort = 9090; - } - - qDebug() << "SDRdaemonGui::configureUDPLink: " << udpAddress.toStdString().c_str() - << " : " << udpPort; - - SDRdaemonInput::MsgConfigureSDRdaemonUDPLink* message = SDRdaemonInput::MsgConfigureSDRdaemonUDPLink::create(udpAddress, udpPort); + SDRdaemonInput::MsgConfigureSDRdaemonUDPLink* message = SDRdaemonInput::MsgConfigureSDRdaemonUDPLink::create(m_address, m_port); m_sampleSource->getInputMessageQueue()->push(message); } diff --git a/sdrbase/gui/aboutdialog.ui b/sdrbase/gui/aboutdialog.ui index bc7a5a41b..0bca1892f 100644 --- a/sdrbase/gui/aboutdialog.ui +++ b/sdrbase/gui/aboutdialog.ui @@ -84,7 +84,7 @@ - <html><head/><body><p>Copyright (C) 2015 Edouard Griffiths, F4EXB. </p><p>Code at <a href="https://github.com/f4exb/sdrangel"><span style=" text-decoration: underline; color:#0000ff;">https://github.com/f4exb/sdrangel</span></a> This is a complete redesign from RTL-SDRangelove at <a href="https://github.com/hexameron/rtl-sdrangelove"><span style=" text-decoration: underline; color:#0000ff;">https://github.com/hexameron/rtl-sdrangelove</span></a></p><p>Many thanks to the original developers:</p><p>The osmocom developer team - especially horizon, Hoernchen &amp; tnt.</p><p>Christian Daniel from maintech GmbH.</p><p>John Greb (hexameron) for the contributions in RTL-SDRangelove</p><p>The following rules apply to the SDRangel main application and libsdrbase:<br/>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; either version 2 of the License, or (at your option) any later version. 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. You should have received a copy of the GNU General Public License along with this program. If not, see <a href="http://www.gnu.org/licenses/"><span style=" text-decoration: underline; color:#0000ff;">http://www.gnu.org/licenses/</span></a>.</p><p>For the license of installed plugins, look into the plugin list.</p></body></html> + <html><head/><body><p>Version 1.1 Copyright (C) 2015 Edouard Griffiths, F4EXB. </p><p>Code at <a href="https://github.com/f4exb/sdrangel"><span style=" text-decoration: underline; color:#0000ff;">https://github.com/f4exb/sdrangel</span></a> This is a complete redesign from RTL-SDRangelove at <a href="https://github.com/hexameron/rtl-sdrangelove"><span style=" text-decoration: underline; color:#0000ff;">https://github.com/hexameron/rtl-sdrangelove</span></a></p><p>Many thanks to the original developers:</p><p>The osmocom developer team - especially horizon, Hoernchen &amp; tnt.</p><p>Christian Daniel from maintech GmbH.</p><p>John Greb (hexameron) for the contributions in RTL-SDRangelove</p><p>The following rules apply to the SDRangel main application and libsdrbase:<br/>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; either version 2 of the License, or (at your option) any later version. 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. You should have received a copy of the GNU General Public License along with this program. If not, see <a href="http://www.gnu.org/licenses/"><span style=" text-decoration: underline; color:#0000ff;">http://www.gnu.org/licenses/</span></a>.</p><p>For the license of installed plugins, look into the plugin list.</p></body></html> true From 6fd9e4f5bcd1574b206cfe46e35ccc8e19707b33 Mon Sep 17 00:00:00 2001 From: f4exb Date: Wed, 24 Feb 2016 11:51:36 +0100 Subject: [PATCH 48/51] cmake: added install and uninstall targets --- CMakeLists.txt | 34 +++++++++++++++++++ cmake_uninstall.cmake.in | 21 ++++++++++++ fcdhid/CMakeLists.txt | 2 ++ fcdlib/CMakeLists.txt | 2 ++ plugins/channel/am/CMakeLists.txt | 4 ++- plugins/channel/bfm/CMakeLists.txt | 4 ++- plugins/channel/chanalyzer/CMakeLists.txt | 2 ++ plugins/channel/lora/CMakeLists.txt | 2 ++ plugins/channel/nfm/CMakeLists.txt | 4 ++- plugins/channel/ssb/CMakeLists.txt | 2 ++ plugins/channel/tcpsrc/CMakeLists.txt | 2 ++ plugins/channel/udpsrc/CMakeLists.txt | 2 ++ plugins/channel/wfm/CMakeLists.txt | 4 ++- plugins/samplesource/airspy/CMakeLists.txt | 2 ++ plugins/samplesource/bladerf/CMakeLists.txt | 2 ++ plugins/samplesource/fcdpro/CMakeLists.txt | 2 ++ .../samplesource/fcdproplus/CMakeLists.txt | 2 ++ .../samplesource/filesource/CMakeLists.txt | 2 ++ plugins/samplesource/hackrf/CMakeLists.txt | 2 ++ plugins/samplesource/rtlsdr/CMakeLists.txt | 2 ++ plugins/samplesource/sdrdaemon/CMakeLists.txt | 2 ++ sdrbase/plugin/pluginmanager.cpp | 10 ++++-- 22 files changed, 104 insertions(+), 7 deletions(-) create mode 100644 cmake_uninstall.cmake.in diff --git a/CMakeLists.txt b/CMakeLists.txt index 2f5d9b1b2..7e09d655f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,23 @@ cmake_minimum_required(VERSION 3.0.2) cmake_policy(SET CMP0043 OLD) +# use, i.e. don't skip the full RPATH for the build tree +set(CMAKE_SKIP_BUILD_RPATH FALSE) + +# when building, don't use the install RPATH already +# (but later on when installing) +set(CMAKE_BUILD_WITH_INSTALL_RPATH FALSE) + +# the RPATH to be used when installing, but only if it's not a system directory +list(FIND CMAKE_PLATFORM_IMPLICIT_LINK_DIRECTORIES "${CMAKE_INSTALL_PREFIX}/lib" isSystemDir) +if("${isSystemDir}" STREQUAL "-1") + set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib") +endif("${isSystemDir}" STREQUAL "-1") + +# add the automatically determined parts of the RPATH +# which point to directories outside the build tree to the install RPATH +set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) + option(V4L-RTL "Use Linux Kernel RTL-SDR Source." OFF) option(V4L-MSI "Use Linux Kernel MSI2500 Source." OFF) option(BUILD_TYPE "Build type (RELEASE, RELEASEWITHDBGINFO, DEBUG" RELEASE) @@ -357,3 +374,20 @@ if(LIBUSB_FOUND AND UNIX) add_subdirectory(fcdhid) add_subdirectory(fcdlib) endif(LIBUSB_FOUND AND UNIX) + +############################################################################## + +#install targets +install(TARGETS sdrangel DESTINATION bin) +install(TARGETS sdrbase DESTINATION lib) + +############################################################################## + +# uninstall target +configure_file( + "${CMAKE_CURRENT_SOURCE_DIR}/cmake_uninstall.cmake.in" + "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake" + IMMEDIATE @ONLY) + +add_custom_target(uninstall + COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake) diff --git a/cmake_uninstall.cmake.in b/cmake_uninstall.cmake.in new file mode 100644 index 000000000..2c34c8199 --- /dev/null +++ b/cmake_uninstall.cmake.in @@ -0,0 +1,21 @@ +if(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt") + message(FATAL_ERROR "Cannot find install manifest: @CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt") +endif(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt") + +file(READ "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt" files) +string(REGEX REPLACE "\n" ";" files "${files}") +foreach(file ${files}) + message(STATUS "Uninstalling $ENV{DESTDIR}${file}") + if(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}") + exec_program( + "@CMAKE_COMMAND@" ARGS "-E remove \"$ENV{DESTDIR}${file}\"" + OUTPUT_VARIABLE rm_out + RETURN_VALUE rm_retval + ) + if(NOT "${rm_retval}" STREQUAL 0) + message(FATAL_ERROR "Problem when removing $ENV{DESTDIR}${file}") + endif(NOT "${rm_retval}" STREQUAL 0) + else(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}") + message(STATUS "File $ENV{DESTDIR}${file} does not exist.") + endif(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}") +endforeach(file) \ No newline at end of file diff --git a/fcdhid/CMakeLists.txt b/fcdhid/CMakeLists.txt index 45fb37102..f1d820cde 100644 --- a/fcdhid/CMakeLists.txt +++ b/fcdhid/CMakeLists.txt @@ -28,3 +28,5 @@ add_library(fcdhid SHARED target_link_libraries(fcdhid ${LIBUSB_LIBRARIES} ) + +install(TARGETS fcdhid DESTINATION lib) \ No newline at end of file diff --git a/fcdlib/CMakeLists.txt b/fcdlib/CMakeLists.txt index 487afb96a..d313bf85c 100644 --- a/fcdlib/CMakeLists.txt +++ b/fcdlib/CMakeLists.txt @@ -27,3 +27,5 @@ add_library(fcdlib SHARED ) target_link_libraries(fcdlib) + +install(TARGETS fcdlib DESTINATION lib) \ No newline at end of file diff --git a/plugins/channel/am/CMakeLists.txt b/plugins/channel/am/CMakeLists.txt index 77bbbdfd5..983d5d215 100644 --- a/plugins/channel/am/CMakeLists.txt +++ b/plugins/channel/am/CMakeLists.txt @@ -44,4 +44,6 @@ target_link_libraries(demodam sdrbase ) -qt5_use_modules(demodam Core Widgets OpenGL Multimedia) \ No newline at end of file +qt5_use_modules(demodam Core Widgets OpenGL Multimedia) + +install(TARGETS demodam DESTINATION lib/plugins/channel) \ No newline at end of file diff --git a/plugins/channel/bfm/CMakeLists.txt b/plugins/channel/bfm/CMakeLists.txt index fd78a8cc7..cfd0e3f28 100644 --- a/plugins/channel/bfm/CMakeLists.txt +++ b/plugins/channel/bfm/CMakeLists.txt @@ -51,4 +51,6 @@ target_link_libraries(demodbfm sdrbase ) -qt5_use_modules(demodbfm Core Widgets OpenGL Multimedia) \ No newline at end of file +qt5_use_modules(demodbfm Core Widgets OpenGL Multimedia) + +install(TARGETS demodbfm DESTINATION lib/plugins/channel) \ No newline at end of file diff --git a/plugins/channel/chanalyzer/CMakeLists.txt b/plugins/channel/chanalyzer/CMakeLists.txt index b25d28121..743bb3fbd 100644 --- a/plugins/channel/chanalyzer/CMakeLists.txt +++ b/plugins/channel/chanalyzer/CMakeLists.txt @@ -45,3 +45,5 @@ target_link_libraries(chanalyzer ) qt5_use_modules(chanalyzer Core Widgets OpenGL Multimedia) + +install(TARGETS chanalyzer DESTINATION lib/plugins/channel) diff --git a/plugins/channel/lora/CMakeLists.txt b/plugins/channel/lora/CMakeLists.txt index 209874b0b..149652655 100644 --- a/plugins/channel/lora/CMakeLists.txt +++ b/plugins/channel/lora/CMakeLists.txt @@ -45,3 +45,5 @@ target_link_libraries(demodlora ) qt5_use_modules(demodlora Core Widgets OpenGL Multimedia) + +install(TARGETS demodlora DESTINATION lib/plugins/channel) diff --git a/plugins/channel/nfm/CMakeLists.txt b/plugins/channel/nfm/CMakeLists.txt index feeb89116..75cf0b338 100644 --- a/plugins/channel/nfm/CMakeLists.txt +++ b/plugins/channel/nfm/CMakeLists.txt @@ -44,4 +44,6 @@ target_link_libraries(demodnfm sdrbase ) -qt5_use_modules(demodnfm Core Widgets OpenGL Multimedia) \ No newline at end of file +qt5_use_modules(demodnfm Core Widgets OpenGL Multimedia) + +install(TARGETS demodnfm DESTINATION lib/plugins/channel) \ No newline at end of file diff --git a/plugins/channel/ssb/CMakeLists.txt b/plugins/channel/ssb/CMakeLists.txt index e50d4ae5a..8ff93d773 100644 --- a/plugins/channel/ssb/CMakeLists.txt +++ b/plugins/channel/ssb/CMakeLists.txt @@ -45,3 +45,5 @@ target_link_libraries(demodssb ) qt5_use_modules(demodssb Core Widgets OpenGL Multimedia) + +install(TARGETS demodssb DESTINATION lib/plugins/channel) diff --git a/plugins/channel/tcpsrc/CMakeLists.txt b/plugins/channel/tcpsrc/CMakeLists.txt index df7c4d4da..fcf8c1e79 100644 --- a/plugins/channel/tcpsrc/CMakeLists.txt +++ b/plugins/channel/tcpsrc/CMakeLists.txt @@ -45,3 +45,5 @@ target_link_libraries(demodtcpsrc ) qt5_use_modules(demodtcpsrc Core Widgets OpenGL Network) + +install(TARGETS demodtcpsrc DESTINATION lib/plugins/channel) diff --git a/plugins/channel/udpsrc/CMakeLists.txt b/plugins/channel/udpsrc/CMakeLists.txt index c5a79b75f..938a05671 100644 --- a/plugins/channel/udpsrc/CMakeLists.txt +++ b/plugins/channel/udpsrc/CMakeLists.txt @@ -45,3 +45,5 @@ target_link_libraries(demodudpsrc ) qt5_use_modules(demodudpsrc Core Widgets OpenGL Network) + +install(TARGETS demodudpsrc DESTINATION lib/plugins/channel) diff --git a/plugins/channel/wfm/CMakeLists.txt b/plugins/channel/wfm/CMakeLists.txt index 552a129c4..8e11cb338 100644 --- a/plugins/channel/wfm/CMakeLists.txt +++ b/plugins/channel/wfm/CMakeLists.txt @@ -44,4 +44,6 @@ target_link_libraries(demodwfm sdrbase ) -qt5_use_modules(demodwfm Core Widgets OpenGL Multimedia) \ No newline at end of file +qt5_use_modules(demodwfm Core Widgets OpenGL Multimedia) + +install(TARGETS demodwfm DESTINATION lib/plugins/channel) \ No newline at end of file diff --git a/plugins/samplesource/airspy/CMakeLists.txt b/plugins/samplesource/airspy/CMakeLists.txt index b734742df..d49c18f1a 100644 --- a/plugins/samplesource/airspy/CMakeLists.txt +++ b/plugins/samplesource/airspy/CMakeLists.txt @@ -51,3 +51,5 @@ target_link_libraries(inputairspy ) qt5_use_modules(inputairspy Core Widgets OpenGL Multimedia) + +install(TARGETS inputairspy DESTINATION lib/plugins/samplesource) diff --git a/plugins/samplesource/bladerf/CMakeLists.txt b/plugins/samplesource/bladerf/CMakeLists.txt index ce61f68fb..406a7f256 100644 --- a/plugins/samplesource/bladerf/CMakeLists.txt +++ b/plugins/samplesource/bladerf/CMakeLists.txt @@ -50,3 +50,5 @@ target_link_libraries(inputbladerf ) qt5_use_modules(inputbladerf Core Widgets OpenGL Multimedia) + +install(TARGETS inputbladerf DESTINATION lib/plugins/samplesource) diff --git a/plugins/samplesource/fcdpro/CMakeLists.txt b/plugins/samplesource/fcdpro/CMakeLists.txt index b29faaf00..4f70e502d 100644 --- a/plugins/samplesource/fcdpro/CMakeLists.txt +++ b/plugins/samplesource/fcdpro/CMakeLists.txt @@ -53,3 +53,5 @@ target_link_libraries(inputfcdpro ) qt5_use_modules(inputfcdpro Core Widgets OpenGL Multimedia) + +install(TARGETS inputfcdpro DESTINATION lib/plugins/samplesource) \ No newline at end of file diff --git a/plugins/samplesource/fcdproplus/CMakeLists.txt b/plugins/samplesource/fcdproplus/CMakeLists.txt index 85ff6cbaf..c23702ba1 100644 --- a/plugins/samplesource/fcdproplus/CMakeLists.txt +++ b/plugins/samplesource/fcdproplus/CMakeLists.txt @@ -53,3 +53,5 @@ target_link_libraries(inputfcdproplus ) qt5_use_modules(inputfcdproplus Core Widgets OpenGL Multimedia) + +install(TARGETS inputfcdproplus DESTINATION lib/plugins/samplesource) diff --git a/plugins/samplesource/filesource/CMakeLists.txt b/plugins/samplesource/filesource/CMakeLists.txt index c94ac1a0b..248dc0a7a 100644 --- a/plugins/samplesource/filesource/CMakeLists.txt +++ b/plugins/samplesource/filesource/CMakeLists.txt @@ -45,3 +45,5 @@ target_link_libraries(inputfilesource ) qt5_use_modules(inputfilesource Core Widgets OpenGL Multimedia) + +install(TARGETS inputfilesource DESTINATION lib/plugins/samplesource) diff --git a/plugins/samplesource/hackrf/CMakeLists.txt b/plugins/samplesource/hackrf/CMakeLists.txt index c366e6d68..116acceec 100644 --- a/plugins/samplesource/hackrf/CMakeLists.txt +++ b/plugins/samplesource/hackrf/CMakeLists.txt @@ -51,3 +51,5 @@ target_link_libraries(inputhackrf ) qt5_use_modules(inputhackrf Core Widgets OpenGL Multimedia) + +install(TARGETS inputhackrf DESTINATION lib/plugins/samplesource) diff --git a/plugins/samplesource/rtlsdr/CMakeLists.txt b/plugins/samplesource/rtlsdr/CMakeLists.txt index 58b2f910f..e28775ebc 100644 --- a/plugins/samplesource/rtlsdr/CMakeLists.txt +++ b/plugins/samplesource/rtlsdr/CMakeLists.txt @@ -50,3 +50,5 @@ target_link_libraries(inputrtlsdr ) qt5_use_modules(inputrtlsdr Core Widgets OpenGL Multimedia) + +install(TARGETS inputrtlsdr DESTINATION lib/plugins/samplesource) diff --git a/plugins/samplesource/sdrdaemon/CMakeLists.txt b/plugins/samplesource/sdrdaemon/CMakeLists.txt index a191fe0f7..f69e8bf90 100644 --- a/plugins/samplesource/sdrdaemon/CMakeLists.txt +++ b/plugins/samplesource/sdrdaemon/CMakeLists.txt @@ -54,3 +54,5 @@ target_link_libraries(inputsdrdaemon ) qt5_use_modules(inputsdrdaemon Core Widgets OpenGL Multimedia) + +install(TARGETS inputsdrdaemon DESTINATION lib/plugins/samplesource) diff --git a/sdrbase/plugin/pluginmanager.cpp b/sdrbase/plugin/pluginmanager.cpp index bd660f7f3..988afcc0d 100644 --- a/sdrbase/plugin/pluginmanager.cpp +++ b/sdrbase/plugin/pluginmanager.cpp @@ -30,11 +30,15 @@ PluginManager::~PluginManager() void PluginManager::loadPlugins() { - qDebug() << "PluginManager::loadPlugins: " << qPrintable(QApplication::instance()->applicationDirPath()); + QString applicationDirPath = QApplication::instance()->applicationDirPath(); + QString applicationLibPath = applicationDirPath + "/../lib"; + qDebug() << "PluginManager::loadPlugins: " << qPrintable(applicationDirPath) << ", " << qPrintable(applicationLibPath); - QDir pluginsDir = QDir(QApplication::instance()->applicationDirPath()); + QDir pluginsBinDir = QDir(applicationDirPath); + QDir pluginsLibDir = QDir(applicationLibPath); - loadPlugins(pluginsDir); + loadPlugins(pluginsBinDir); + loadPlugins(pluginsLibDir); qSort(m_plugins); From e7249eb72d95392dabfaeae2866523d075d3ed54 Mon Sep 17 00:00:00 2001 From: f4exb Date: Wed, 24 Feb 2016 12:14:23 +0100 Subject: [PATCH 49/51] Added not on software installation in the readme --- Readme.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Readme.md b/Readme.md index 55d8753f1..f82ab7be4 100644 --- a/Readme.md +++ b/Readme.md @@ -191,6 +191,12 @@ Then you should be all set to build the software with `cmake` and `make` as disc - Note1 for udev rules: the same as for openSUSE and Fedora applies. - Note2: A package has been created in the AUR (thanks Mikos!), see: [sdrangel-git](https://aur.archlinux.org/packages/sdrangel-git). It is based on the `205fee6` commit of 8th December 2015. +

Software installation

+ +Simply do `make install` or `sudo make install` depending on you user rights on the target installation directory. On most systems the default installation directory is `/usr/local` a custom installation directory can be specified with the `-DCMAKE_INSTALL_PREFIX` on the `cmake` command line as usual with cmake. + +You can uninstall the software with `make uninstall` or `sudo make uninstall` from the build directory (it needs the `install_manifest.txt` file in the same directory. It is automatically created by the `make install`command). Note that this will not remove the possible empty directories. +

Known Issues

- The message queuing model supports a n:1 connection to an object (on its input queue) and a 1:1 connection from an object (on its output queue). Assuming a different model can cause insidious disruptions. From ee4ea7aa89060e38230245390504a2226da77e8a Mon Sep 17 00:00:00 2001 From: f4exb Date: Wed, 24 Feb 2016 12:16:19 +0100 Subject: [PATCH 50/51] Software installation readme update --- Readme.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Readme.md b/Readme.md index f82ab7be4..abcbfdb40 100644 --- a/Readme.md +++ b/Readme.md @@ -193,9 +193,9 @@ Then you should be all set to build the software with `cmake` and `make` as disc

Software installation

-Simply do `make install` or `sudo make install` depending on you user rights on the target installation directory. On most systems the default installation directory is `/usr/local` a custom installation directory can be specified with the `-DCMAKE_INSTALL_PREFIX` on the `cmake` command line as usual with cmake. +Simply do `make install` or `sudo make install` depending on you user rights on the target installation directory. On most systems the default installation directory is `/usr/local` a custom installation directory can be specified with the `-DCMAKE_INSTALL_PREFIX=...` option on the `cmake` command line as usual with cmake. -You can uninstall the software with `make uninstall` or `sudo make uninstall` from the build directory (it needs the `install_manifest.txt` file in the same directory. It is automatically created by the `make install`command). Note that this will not remove the possible empty directories. +You can uninstall the software with `make uninstall` or `sudo make uninstall` from the build directory (it needs the `install_manifest.txt` file in the same directory and is automatically created by the `make install`command). Note that this will not remove the possible empty directories.

Known Issues

From aa15e95ef388d8c5e3f4cb4610946e67adffa7cb Mon Sep 17 00:00:00 2001 From: f4exb Date: Wed, 24 Feb 2016 15:27:05 +0100 Subject: [PATCH 51/51] cmake install: set rpath even for system installation directories --- CMakeLists.txt | 6 +----- Readme.md | 8 ++++---- 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7e09d655f..1a1502fd5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -8,11 +8,7 @@ set(CMAKE_SKIP_BUILD_RPATH FALSE) # (but later on when installing) set(CMAKE_BUILD_WITH_INSTALL_RPATH FALSE) -# the RPATH to be used when installing, but only if it's not a system directory -list(FIND CMAKE_PLATFORM_IMPLICIT_LINK_DIRECTORIES "${CMAKE_INSTALL_PREFIX}/lib" isSystemDir) -if("${isSystemDir}" STREQUAL "-1") - set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib") -endif("${isSystemDir}" STREQUAL "-1") +SET(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib") # add the automatically determined parts of the RPATH # which point to directories outside the build tree to the install RPATH diff --git a/Readme.md b/Readme.md index abcbfdb40..7f2b38318 100644 --- a/Readme.md +++ b/Readme.md @@ -134,7 +134,7 @@ Install cmake version 3:

With newer versions just do:

- - `sudo apt-get install cmake g++ pkg-config libfftw3-dev libqt5multimedia5-plugins qtmultimedia5-dev qttools5-dev qttools5-dev-tools libqt5opengl5-dev qtbase5-dev libusb-1.0 librtlsdr-dev libboost-all-dev libasound2-dev pulseaudio` + - `sudo apt-get install cmake g++ pkg-config libfftw3-dev libqt5multimedia5-plugins qtmultimedia5-dev qttools5-dev qttools5-dev-tools libqt5opengl5-dev qtbase5-dev libusb-1.0 librtlsdr-dev libboost-all-dev libasound2-dev pulseaudio liblz4-dev` - `mkdir build && cd build && cmake ../ && make` `librtlsdr-dev` is in the `universe` repo. (utopic 14.10 amd64.) @@ -161,7 +161,7 @@ For Debian Jessie or Stretch: This has been tested with the bleeding edge "Thumbleweed" distribution: -`sudo zypper install cmake fftw3-devel gcc-c++ libusb-1_0-devel libqt5-qtbase-devel libQt5OpenGL-devel libqt5-qtmultimedia-devel libqt5-qttools-devel libQt5Network-devel libQt5Widgets-devel boost-devel alsa-devel pulseaudio` +`sudo zypper install cmake fftw3-devel gcc-c++ libusb-1_0-devel libqt5-qtbase-devel libQt5OpenGL-devel libqt5-qtmultimedia-devel libqt5-qttools-devel libQt5Network-devel libQt5Widgets-devel boost-devel alsa-devel pulseaudio liblz4 liblz4-devel` Then you should be all set to build the software with `cmake` and `make` as discussed earlier. @@ -174,7 +174,7 @@ This has been tested with Fedora 23 and 22: - `sudo dnf groupinstall "C Development Tools and Libraries"` - `sudo dnf install mesa-libGL-devel` - - `sudo dnf install cmake gcc-c++ pkgconfig fftw-devel libusb-devel qt5-qtbase-devel qt5-qtmultimedia-devel qt5-qttools-devel boost-devel pulseaudio alsa-lib-devel` + - `sudo dnf install cmake gcc-c++ pkgconfig fftw-devel libusb-devel qt5-qtbase-devel qt5-qtmultimedia-devel qt5-qttools-devel boost-devel pulseaudio alsa-lib-devel liblz4 liblz4-devel` Then you should be all set to build the software with `cmake` and `make` as discussed earlier. @@ -184,7 +184,7 @@ Then you should be all set to build the software with `cmake` and `make` as disc Tested with the 15.09 version with LXDE desktop (community supported). The exact desktop environment should not matter anyway. Since Manjaro is Arch Linux based prerequisites should be similar for Arch and all derivatives. -`sudo pacman -S cmake pkg-config fftw qt5-multimedia qt5-tools qt5-base libusb boost boost-libs pulseaudio` +`sudo pacman -S cmake pkg-config fftw qt5-multimedia qt5-tools qt5-base libusb boost boost-libs pulseaudio lz4` Then you should be all set to build the software with `cmake` and `make` as discussed earlier.