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 032b0b2eb1..5e1ec48eb8 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 0000000000..f693b6adb7 --- /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 0000000000..b8dd917e3f --- /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 0000000000..b9216f9b0d --- /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 0000000000..9dcf1e942a --- /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 0000000000..896972e648 --- /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 0000000000..e0c180b202 --- /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 0000000000..5bdf647809 --- /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 0000000000..3dd77313f3 --- /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 0000000000..4a261a2f99 --- /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 0000000000..9d3ff1d3a2 --- /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 0000000000..51f1338400 --- /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 f693b6adb7..0ae1cb3b07 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 | 212 ++++++++++++---- .../samplesource/sdrdaemon/sdrdaemonthread.h | 4 + sdrbase/util/CRC64.cpp | 159 ++++++++++++ 8 files changed, 698 insertions(+), 47 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 c1d4e5687d..9ce27a3dbe 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 0000000000..bede1df55a --- /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 0ae1cb3b07..2fc7bb122c 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 0000000000..a468eaa1f0 --- /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 0000000000..4a8e0de6a7 --- /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 9dcf1e942a..228619b6ac 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 @@ -120,62 +111,79 @@ - + - + + + Addr: + + + + + - 24 - 24 + 120 + 0 - + + + + + + Port: + + + + + + - 24 - 24 + 50 + 0 - - Open file + + + + + + + 30 + 16777215 + - - - - - :/preset-load.png:/preset-load.png + OK - - - false - - - File currently opened - - - ... + + + Qt::Horizontal - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + 40 + 20 + - + - - - - Qt::Horizontal - - - + + + 50 + 0 + + 8 @@ -187,6 +195,9 @@ 0k + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + @@ -224,6 +235,115 @@ + + + + + + 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 + + + + + + + + + Qt::Horizontal + + + diff --git a/plugins/samplesource/sdrdaemon/sdrdaemonthread.h b/plugins/samplesource/sdrdaemon/sdrdaemonthread.h index 9d3ff1d3a2..3464a095ec 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 @@ class SDRdaemonThread : public QThread { 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 0000000000..e07cf0d14a --- /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 4a8e0de6a7..01757f8acd 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 @@ class SDRdaemonBuffer 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 a468eaa1f0..8017e630f5 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 01757f8acd..7f90e21685 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h +++ b/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h @@ -69,6 +69,7 @@ class SDRdaemonBuffer 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 @@ class SDRdaemonBuffer 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 8017e630f5..e81b4863eb 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 7f90e21685..38f53f9f19 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h +++ b/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h @@ -63,12 +63,14 @@ class SDRdaemonBuffer 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 4a261a2f99..91cc84ba65 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 3464a095ec..c1b1d1b30d 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 @@ class SDRdaemonThread : public QThread { 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 @@ class SDRdaemonThread : public QThread { 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 | 66 +++++++++++-------- .../samplesource/sdrdaemon/sdrdaemonbuffer.h | 7 +- 2 files changed, 42 insertions(+), 31 deletions(-) diff --git a/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.cpp b/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.cpp index e81b4863eb..6e4ee3e1e7 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; - - if (originalSize != m_lz4OutSize) - { - uint32_t masInputSize = LZ4_compressBound(originalSize); + uint32_t masInputSize = LZ4_compressBound(frameSize); - if (m_lz4InBuffer) { - delete[] m_lz4InBuffer; - } + 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[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_lz4OutBuffer) { + delete[] m_lz4OutBuffer; } - m_lz4InCount = 0; + 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 38f53f9f19..5aa80202ae 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h +++ b/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h @@ -69,9 +69,9 @@ class SDRdaemonBuffer 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 @@ class SDRdaemonBuffer 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 6e4ee3e1e7..7d1db9254b 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 5aa80202ae..b88dc0ace9 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h +++ b/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h @@ -71,6 +71,7 @@ class SDRdaemonBuffer 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 @@ class SDRdaemonBuffer 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 @@ class SDRdaemonBuffer 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 59c2d7d6ed..0000000000 --- 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 7d1db9254b..d7d9927dda 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 b88dc0ace9..2ce6d1daf7 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h +++ b/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h @@ -73,6 +73,7 @@ class SDRdaemonBuffer 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 @@ class SDRdaemonBuffer 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 13f90777ec..0000000000 --- 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 d7d9927dda..e850af4376 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 2ce6d1daf7..b1a613df7f 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h +++ b/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h @@ -61,19 +61,21 @@ class SDRdaemonBuffer }; #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 @@ class SDRdaemonBuffer 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 91cc84ba65..934b1c17b6 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 e850af4376..8aca1add36 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 b1a613df7f..37778fba88 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h +++ b/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h @@ -65,6 +65,7 @@ class SDRdaemonBuffer ~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 @@ class SDRdaemonBuffer 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 896972e648..55e3b998db 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 e0c180b202..01e004b6c0 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 @@ class SDRdaemonInput : public SampleSource { private: QMutex m_mutex; Settings m_settings; - std::ifstream m_ifstream; SDRdaemonThread* m_SDRdaemonThread; QString m_deviceDescription; QString m_fileName; @@ -207,7 +205,6 @@ class SDRdaemonInput : public SampleSource { 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 934b1c17b6..222e5ea5dc 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 c1b1d1b30d..373348598e 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 @@ public slots: 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 | 109 +++++---- 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, 133 insertions(+), 355 deletions(-) diff --git a/Readme.md b/Readme.md index f2e7e73666..a6ddeed908 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 8d873d2638..f7418ad2c1 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 b8dd917e3f..9c7205bc48 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,38 +77,63 @@ QString SDRdaemonGui::getName() const 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 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) { - if(m_settings.deserialize(data)) { - displaySettings(); - sendSettings(); + 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; +} + +void SDRdaemonGui::setCenterFrequency(qint64 centerFrequency) +{ + m_centerFrequency = centerFrequency; + displaySettings(); } 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)")); + configureUDPLink(); +} - if (fileName != "") +void SDRdaemonGui::configureUDPLink() +{ + bool ok; + QString udpAddress = ui->address->text(); + int udpPort = ui->port->text().toInt(&ok); + + if((!ok) || (udpPort < 1024) || (udpPort > 65535)) { - m_fileName = fileName; - ui->fileNameText->setText(m_fileName); - configureFileName(); + udpPort = 9090; } -} -void SDRdaemonGui::configureFileName() -{ - qDebug() << "SDRdaemonGui::configureFileName: " << m_fileName.toStdString().c_str(); - SDRdaemonInput::MsgConfigureSDRdaemonName* message = SDRdaemonInput::MsgConfigureSDRdaemonName::create(m_fileName); + 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 b9216f9b0d..d192453f7c 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemongui.h +++ b/plugins/samplesource/sdrdaemon/sdrdaemongui.h @@ -40,22 +40,19 @@ class SDRdaemonGui : public QWidget, public PluginGUI { 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 @@ class SDRdaemonGui : public QWidget, public PluginGUI { 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 228619b6ac..c6e778eeb4 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 55e3b998db..f5005be782 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 01e004b6c0..46d0fef0be 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 { - 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 { + class MsgConfigureSDRdaemonUDPLink : public Message { MESSAGE_CLASS_DECLARATION public: - const QString& getFileName() const { return m_fileName; } + const QString& getAddress() const { return m_address; } + quint16 getPort() const { return m_port; } - static MsgConfigureSDRdaemonName* create(const QString& fileName) + static MsgConfigureSDRdaemonUDPLink* create(const QString& address, quint16 port) { - return new MsgConfigureSDRdaemonName(fileName); + return new MsgConfigureSDRdaemonUDPLink(address, port); } private: - QString m_fileName; + QString m_address; + quint16 m_port; - MsgConfigureSDRdaemonName(const QString& fileName) : + MsgConfigureSDRdaemonUDPLink(const QString& address, quint16 port) : Message(), - m_fileName(fileName) + m_address(address), + m_port(port) { } }; @@ -195,16 +169,17 @@ class SDRdaemonInput : public SampleSource { 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 373348598e..046d108e75 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemonthread.h +++ b/plugins/samplesource/sdrdaemon/sdrdaemonthread.h @@ -43,6 +43,7 @@ class SDRdaemonThread : public QThread { 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 8aca1add36..bb66eb41a5 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 37778fba88..1c223b31e6 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h +++ b/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h @@ -76,7 +76,7 @@ class SDRdaemonBuffer 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 | 121 ++++++++++++------ .../samplesource/sdrdaemon/sdrdaemonthread.h | 4 +- 5 files changed, 123 insertions(+), 120 deletions(-) diff --git a/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.cpp b/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.cpp index bb66eb41a5..e0822da33d 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 f5005be782..3b172c93e9 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 46d0fef0be..5666ce8e93 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemoninput.h +++ b/plugins/samplesource/sdrdaemon/sdrdaemoninput.h @@ -179,7 +179,6 @@ class SDRdaemonInput : public SampleSource { 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 222e5ea5dc..a3c360cd7a 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(); - } + 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; + 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); - } + 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); - 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_samplerate = samplerate; + 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 046d108e75..35e9fb9cab 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemonthread.h +++ b/plugins/samplesource/sdrdaemon/sdrdaemonthread.h @@ -42,7 +42,6 @@ class SDRdaemonThread : public QThread { 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 @@ public slots: 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 @@ public slots: 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 d0e03b90cc..46d1788a28 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 9360351924..fe16d3576c 100644 --- a/plugins/samplesource/filesource/filesourceinput.h +++ b/plugins/samplesource/filesource/filesourceinput.h @@ -206,7 +206,6 @@ class FileSourceInput : public SampleSource { 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 1c223b31e6..95c5270300 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h +++ b/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h @@ -31,7 +31,7 @@ class SDRdaemonBuffer 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 9c7205bc48..3f5ebe5ea0 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 d192453f7c..8ed697b8d1 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 @@ class SDRdaemonGui : public QWidget, public PluginGUI { 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 @@ class SDRdaemonGui : public QWidget, public PluginGUI { 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 c6e778eeb4..77943b0a6a 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 3b172c93e9..5aab189cb5 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 5666ce8e93..461a0190fe 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 @@ class SDRdaemonInput : public SampleSource { 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 a3c360cd7a..f27da2ad36 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 35e9fb9cab..a3e0fa4c3b 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 @@ public slots: 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 2fc7bb122c..2258a55a19 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 3f5ebe5ea0..6cccf59ea7 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 5aab189cb5..e0693390b2 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 461a0190fe..e17c8676ce 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 @@ class SDRdaemonInput : public SampleSource { 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 @@ class SDRdaemonInput : public SampleSource { 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 0000000000..f1ce3082c2 --- /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 0000000000..8f033cf01d --- /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 e0822da33d..1c48565246 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 9ce27a3dbe..2f5d9b1b2d 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 23d26212e7..c94ac1a0bf 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 2258a55a19..082f1bd644 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 1c48565246..6584de7777 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 95c5270300..92a7c0d1a8 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h +++ b/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h @@ -61,7 +61,7 @@ class SDRdaemonBuffer }; #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 @@ class SDRdaemonBuffer 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 @@ class SDRdaemonBuffer 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 f1ce3082c2..769bd447b1 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 | 182 +++++++++++------- .../samplesource/sdrdaemon/sdrdaemoninput.cpp | 10 + .../samplesource/sdrdaemon/sdrdaemoninput.h | 22 +++ 6 files changed, 180 insertions(+), 91 deletions(-) diff --git a/plugins/samplesource/sdrdaemon/CMakeLists.txt b/plugins/samplesource/sdrdaemon/CMakeLists.txt index 082f1bd644..a191fe0f7c 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 6cccf59ea7..a9bebf7010 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 8ed697b8d1..baa6403741 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemongui.h +++ b/plugins/samplesource/sdrdaemon/sdrdaemongui.h @@ -60,6 +60,9 @@ class SDRdaemonGui : public QWidget, public PluginGUI { int m_samplesCount; std::size_t m_tickCount; + bool m_dcBlock; + bool m_iqCorrection; + void displaySettings(); void displayTime(); void configureUDPLink(); @@ -70,6 +73,8 @@ class SDRdaemonGui : public QWidget, public PluginGUI { 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 77943b0a6a..f19d280263 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemongui.ui +++ b/plugins/samplesource/sdrdaemon/sdrdaemongui.ui @@ -104,76 +104,12 @@ - + Qt::Horizontal - - - - - - Addr: - - - - - - - - 120 - 0 - - - - - - - - Port: - - - - - - - - 50 - 0 - - - - - - - - - 30 - 16777215 - - - - OK - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - @@ -243,7 +179,116 @@ - + + + Qt::Horizontal + + + + + + + + + Auto corr + + + + + + + DC Offset auto correction + + + DC Offset + + + + + + + IQ Imbalance auto correction + + + IQ Imbalance + + + + + + + + + Qt::Horizontal + + + + + + + + + Addr: + + + + + + + + 120 + 0 + + + + + + + + Port: + + + + + + + + 50 + 0 + + + + + + + + + 30 + 16777215 + + + + OK + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + 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 e0693390b2..4ce93a06f3 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 e17c8676ce..f89be1e810 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemoninput.h +++ b/plugins/samplesource/sdrdaemon/sdrdaemoninput.h @@ -51,6 +51,28 @@ class SDRdaemonInput : public SampleSource { { } }; + 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 f19d280263..3f35fd068a 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 769bd447b1..ff6c2f3f1a 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 a6ddeed908..b3d4376751 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 6584de7777..1e1198d613 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 a9bebf7010..93dbfbfc7a 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 baa6403741..3760f7c122 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemongui.h +++ b/plugins/samplesource/sdrdaemon/sdrdaemongui.h @@ -60,12 +60,15 @@ class SDRdaemonGui : public QWidget, public PluginGUI { 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 1e1198d613..7fa12bbf52 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 92a7c0d1a8..55c6f7ca10 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h +++ b/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h @@ -73,7 +73,6 @@ class SDRdaemonBuffer 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 @@ class SDRdaemonBuffer 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 ff6c2f3f1a..cf08f181ec 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 8f033cf01d..c056f4cfc1 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemonudphandler.h +++ b/plugins/samplesource/sdrdaemon/sdrdaemonudphandler.h @@ -41,13 +41,8 @@ class SDRdaemonUDPHandler : public QObject 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 @@ public slots: 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 b3d4376751..6bd609853b 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 7fa12bbf52..f8afe5e8d5 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 cf08f181ec..9a1c4618a2 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 c056f4cfc1..66becc1a5d 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemonudphandler.h +++ b/plugins/samplesource/sdrdaemon/sdrdaemonudphandler.h @@ -41,8 +41,13 @@ class SDRdaemonUDPHandler : public QObject 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 f8afe5e8d5..75630fcbe6 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) - { - uint32_t readCount = m_readCount; - m_readCount += length; - return &m_rawBuffer[readCount]; - } - //else if (m_readCount > 0) - else + // 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 (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 55c6f7ca10..f2abe33462 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h +++ b/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h @@ -61,24 +61,27 @@ class SDRdaemonBuffer }; #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 @@ class SDRdaemonBuffer 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 9a1c4618a2..e58d509b4b 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 66becc1a5d..f82b2ec627 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemonudphandler.h +++ b/plugins/samplesource/sdrdaemon/sdrdaemonudphandler.h @@ -55,8 +55,6 @@ public slots: 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 @@ public slots: 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 75630fcbe6..43410666a6 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 f27da2ad36..0000000000 --- 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 a3e0fa4c3b..0000000000 --- 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 e58d509b4b..4cbefe34d3 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 f82b2ec627..f7fe0adfca 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemonudphandler.h +++ b/plugins/samplesource/sdrdaemon/sdrdaemonudphandler.h @@ -41,13 +41,8 @@ class SDRdaemonUDPHandler : public QObject 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 6bd609853b..3ee82d9395 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 93dbfbfc7a..926fbadff4 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 4cbefe34d3..a1dc0690f9 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 43410666a6..12a0791cff 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 f2abe33462..89aa0660b9 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h +++ b/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h @@ -94,9 +94,9 @@ class SDRdaemonBuffer 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 3f35fd068a..4c87455413 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 4ce93a06f3..8e29a77ce6 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 a1dc0690f9..15f869591f 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 f7fe0adfca..50ed52f2c5 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 @@ public slots: 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 12a0791cff..3b2d807359 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 89aa0660b9..8e48aaf9d3 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h +++ b/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h @@ -69,6 +69,7 @@ class SDRdaemonBuffer 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 @@ class SDRdaemonBuffer 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 4c87455413..d4e5132d06 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 3b2d807359..504467dac3 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 8e48aaf9d3..e3c9a4bae2 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h +++ b/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h @@ -67,6 +67,7 @@ class SDRdaemonBuffer 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 @@ class SDRdaemonBuffer 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 @@ class SDRdaemonBuffer 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 15f869591f..231006c54f 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 504467dac3..e05811d579 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 | 76 ++++++++++++++++--- .../samplesource/sdrdaemon/sdrdaemoninput.h | 9 ++- .../sdrdaemon/sdrdaemonudphandler.cpp | 1 + 6 files changed, 86 insertions(+), 15 deletions(-) diff --git a/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h b/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h index e3c9a4bae2..31cf04494a 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h +++ b/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h @@ -67,6 +67,7 @@ class SDRdaemonBuffer 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 926fbadff4..7514836aa7 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 3760f7c122..346e134c24 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemongui.h +++ b/plugins/samplesource/sdrdaemon/sdrdaemongui.h @@ -55,6 +55,7 @@ class SDRdaemonGui : public QWidget, public PluginGUI { 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 d4e5132d06..c57d99dd56 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemongui.ui +++ b/plugins/samplesource/sdrdaemon/sdrdaemongui.ui @@ -113,9 +113,33 @@ - + + + + 50 + 0 + + + + + 8 + + + + Nominal sample rate from stream data (kS/s) + - Rate: + 00000 + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Qt::Vertical @@ -123,20 +147,41 @@ - 50 + 70 0 - - - 8 - + + Actual sample rate (kS/s) + + + 0000.000 + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Qt::Vertical + + + + + + + + 40 + 0 + - Record sample rate + Sample rate skew from stream nominal rate (%) - 0k + -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 f89be1e810..0bad392ec9 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemoninput.h +++ b/plugins/samplesource/sdrdaemon/sdrdaemoninput.h @@ -134,24 +134,27 @@ class SDRdaemonInput : public SampleSource { 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 231006c54f..3342882d43 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 3ee82d9395..0b5f2e4228 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 e05811d579..5804f806e5 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 5804f806e5..8e999f7d02 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 31cf04494a..cb1b5fcf8e 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h +++ b/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h @@ -80,7 +80,7 @@ class SDRdaemonBuffer 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 0b5f2e4228..edb1d8ed9b 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 8e999f7d02..a6dffb8e3e 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 c57d99dd56..e15476be91 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 8d605b41d5..85d65915bf 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 a6dffb8e3e..5d1f476ce1 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 5bdf647809..c016d13ce6 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 e15476be91..c432e8a4d8 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 7514836aa7..28ef410d4b 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 346e134c24..2f307b38ea 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemongui.h +++ b/plugins/samplesource/sdrdaemon/sdrdaemongui.h @@ -54,10 +54,13 @@ class SDRdaemonGui : public QWidget, public PluginGUI { 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 0bad392ec9..7f4451df8a 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemoninput.h +++ b/plugins/samplesource/sdrdaemon/sdrdaemoninput.h @@ -168,20 +168,29 @@ class SDRdaemonInput : public SampleSource { 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 3342882d43..d5c907fb2e 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 | 260 ++++++++++-------- .../samplesource/sdrdaemon/sdrdaemoninput.h | 14 +- .../sdrdaemon/sdrdaemonudphandler.cpp | 3 +- 6 files changed, 156 insertions(+), 127 deletions(-) diff --git a/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h b/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h index cb1b5fcf8e..2f35f48bff 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h +++ b/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h @@ -72,6 +72,7 @@ class SDRdaemonBuffer 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 28ef410d4b..4d03178776 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 2f307b38ea..2f024d39ea 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemongui.h +++ b/plugins/samplesource/sdrdaemon/sdrdaemongui.h @@ -60,6 +60,7 @@ class SDRdaemonGui : public QWidget, public PluginGUI { 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 c432e8a4d8..5d863e957f 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 - - - - Nominal sample rate from stream data (kS/s) - + - 00000 - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - Qt::Vertical + Auto Corr - - - - 70 - 0 - - + - Actual sample rate (kS/s) + DC Offset auto correction - 0000.000 - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + DC - - - Qt::Vertical - - - - - - - - 40 - 0 - - + - Sample rate skew from stream nominal rate (%) + IQ Imbalance auto correction - -00.00 - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + IQ - + Qt::Horizontal @@ -196,13 +144,6 @@ - - - - Qt::Vertical - - - @@ -219,14 +160,14 @@ - + Qt::Horizontal - + @@ -264,42 +205,25 @@ - + Qt::Vertical - - - false - - - Stream is compressed with LZ4 - - - ... - - - - :/compressed.png:/compressed.png - - - - - + - 40 + 50 0 - Stream comopression ratio (compressed / original) + Nominal sample rate from stream data (kS/s) - 0.00 + 00000 Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter @@ -307,18 +231,25 @@ - + + + Qt::Vertical + + + + + - 40 + 70 0 - Data CRC OK (%) + Actual sample rate (kS/s) - 100 + 0000.000 Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter @@ -326,18 +257,25 @@ - + + + Qt::Vertical + + + + + - 40 + 50 0 - LZ4 successful decodes (%) + Sample rate skew from stream nominal rate (%) - 100 + -00.00 Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter @@ -345,7 +283,14 @@ - + + + Qt::Vertical + + + + + Qt::Horizontal @@ -360,43 +305,111 @@ - + Qt::Horizontal - + - + + + false + + + Stream is compressed with LZ4 + - Auto corr + ... + + + + :/compressed.png:/compressed.png - + + + + 50 + 0 + + - DC Offset auto correction + Stream comopression ratio (compressed / original) - DC Offset + 0.00 + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - + + + Qt::Vertical + + + + + + + + 40 + 0 + + - IQ Imbalance auto correction + Data CRC OK (%) - IQ Imbalance + 100 + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - + + + Qt::Vertical + + + + + + + + 40 + 0 + + + + LZ4 successful decodes (%) + + + 100 + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Qt::Vertical + + + + + 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 7f4451df8a..29a4f9d899 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemoninput.h +++ b/plugins/samplesource/sdrdaemon/sdrdaemoninput.h @@ -169,28 +169,34 @@ class SDRdaemonInput : public SampleSource { 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 d5c907fb2e..26bb5ad07a 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 2f35f48bff..425ccef0ee 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h +++ b/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h @@ -73,6 +73,7 @@ class SDRdaemonBuffer 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 4d03178776..71dfb1ad96 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 2f024d39ea..3674b861aa 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemongui.h +++ b/plugins/samplesource/sdrdaemon/sdrdaemongui.h @@ -61,6 +61,7 @@ class SDRdaemonGui : public QWidget, public PluginGUI { 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 5d863e957f..81e0be2caf 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 29a4f9d899..28ad15337d 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemoninput.h +++ b/plugins/samplesource/sdrdaemon/sdrdaemoninput.h @@ -170,16 +170,19 @@ class SDRdaemonInput : public SampleSource { 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 @@ class SDRdaemonInput : public SampleSource { 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 26bb5ad07a..d723800572 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 425ccef0ee..b47c8553a8 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h +++ b/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h @@ -74,6 +74,7 @@ class SDRdaemonBuffer 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 71dfb1ad96..08bd72604d 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 3674b861aa..0035c8ff88 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemongui.h +++ b/plugins/samplesource/sdrdaemon/sdrdaemongui.h @@ -62,6 +62,7 @@ class SDRdaemonGui : public QWidget, public PluginGUI { 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 81e0be2caf..959be62cf7 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 28ad15337d..ff927ca269 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemoninput.h +++ b/plugins/samplesource/sdrdaemon/sdrdaemoninput.h @@ -176,13 +176,15 @@ class SDRdaemonInput : public SampleSource { 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 @@ class SDRdaemonInput : public SampleSource { 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 d723800572..4e2b25e741 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 5d1f476ce1..0126a1b2b2 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 b47c8553a8..d4e27cd177 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h +++ b/plugins/samplesource/sdrdaemon/sdrdaemonbuffer.h @@ -74,7 +74,9 @@ class SDRdaemonBuffer 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 @@ class SDRdaemonBuffer 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 08bd72604d..349b434179 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 0035c8ff88..baac028440 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemongui.h +++ b/plugins/samplesource/sdrdaemon/sdrdaemongui.h @@ -63,6 +63,8 @@ class SDRdaemonGui : public QWidget, public PluginGUI { 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 959be62cf7..371187940b 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 ff927ca269..6befbc5d4d 100644 --- a/plugins/samplesource/sdrdaemon/sdrdaemoninput.h +++ b/plugins/samplesource/sdrdaemon/sdrdaemoninput.h @@ -171,20 +171,27 @@ class SDRdaemonInput : public SampleSource { 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 @@ class SDRdaemonInput : public SampleSource { 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 4e2b25e741..63d88bcb10 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 349b434179..7ac3164fe3 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 371187940b..b0b368e619 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 63d88bcb10..d0af8a0aeb 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 edb1d8ed9b..55d8753f1a 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 7ac3164fe3..f19e7dd52f 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); - - if((!ok) || (udpPort < 1024) || (udpPort > 65535)) - { - udpPort = 9090; - } - - qDebug() << "SDRdaemonGui::configureUDPLink: " << udpAddress.toStdString().c_str() - << " : " << udpPort; + qDebug() << "SDRdaemonGui::configureUDPLink: " << m_address.toStdString().c_str() + << " : " << m_port; - 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 bc7a5a41b3..0bca1892f6 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 2f5d9b1b2d..7e09d655f0 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 0000000000..2c34c81994 --- /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 45fb37102c..f1d820cde0 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 487afb96a8..d313bf85cf 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 77bbbdfd51..983d5d215d 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 fd78a8cc78..cfd0e3f284 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 b25d281217..743bb3fbd4 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 209874b0b0..1496526550 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 feeb891166..75cf0b3382 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 e50d4ae5a5..8ff93d7732 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 df7c4d4da0..fcf8c1e79a 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 c5a79b75f8..938a056718 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 552a129c4e..8e11cb338b 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 b734742dfd..d49c18f1a0 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 ce61f68fb9..406a7f256c 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 b29faaf00e..4f70e502d0 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 85ff6cbafe..c23702ba17 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 c94ac1a0bf..248dc0a7a3 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 c366e6d68f..116acceecc 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 58b2f910f6..e28775ebcb 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 a191fe0f7c..f69e8bf900 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 bd660f7f3d..988afcc0d5 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 55d8753f1a..f82ab7be4f 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 f82ab7be4f..abcbfdb40f 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 7e09d655f0..1a1502fd57 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 abcbfdb40f..7f2b383187 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.