mirror of
https://github.com/f4exb/sdrangel.git
synced 2025-05-25 03:32:29 -04:00
Removal of ChannelAnalyzer and TCPSrc plugins
This commit is contained in:
parent
c961fa368d
commit
111b3da5ce
@ -5,10 +5,8 @@ add_subdirectory(demodam)
|
|||||||
add_subdirectory(demodbfm)
|
add_subdirectory(demodbfm)
|
||||||
add_subdirectory(demodnfm)
|
add_subdirectory(demodnfm)
|
||||||
add_subdirectory(demodssb)
|
add_subdirectory(demodssb)
|
||||||
add_subdirectory(tcpsrc)
|
|
||||||
add_subdirectory(udpsrc)
|
add_subdirectory(udpsrc)
|
||||||
add_subdirectory(demodwfm)
|
add_subdirectory(demodwfm)
|
||||||
add_subdirectory(chanalyzer)
|
|
||||||
add_subdirectory(chanalyzerng)
|
add_subdirectory(chanalyzerng)
|
||||||
add_subdirectory(demodatv)
|
add_subdirectory(demodatv)
|
||||||
|
|
||||||
|
@ -1,46 +0,0 @@
|
|||||||
project(chanalyzer)
|
|
||||||
|
|
||||||
set(chanalyzer_SOURCES
|
|
||||||
chanalyzer.cpp
|
|
||||||
chanalyzergui.cpp
|
|
||||||
chanalyzerplugin.cpp
|
|
||||||
)
|
|
||||||
|
|
||||||
set(chanalyzer_HEADERS
|
|
||||||
chanalyzer.h
|
|
||||||
chanalyzergui.h
|
|
||||||
chanalyzerplugin.h
|
|
||||||
)
|
|
||||||
|
|
||||||
set(chanalyzer_FORMS
|
|
||||||
chanalyzergui.ui
|
|
||||||
)
|
|
||||||
|
|
||||||
include_directories(
|
|
||||||
.
|
|
||||||
${CMAKE_CURRENT_BINARY_DIR}
|
|
||||||
)
|
|
||||||
|
|
||||||
#include(${QT_USE_FILE})
|
|
||||||
add_definitions(${QT_DEFINITIONS})
|
|
||||||
add_definitions(-DQT_PLUGIN)
|
|
||||||
add_definitions(-DQT_SHARED)
|
|
||||||
|
|
||||||
#qt5_wrap_cpp(chanalyzer_HEADERS_MOC ${chanalyzer_HEADERS})
|
|
||||||
qt5_wrap_ui(chanalyzer_FORMS_HEADERS ${chanalyzer_FORMS})
|
|
||||||
|
|
||||||
add_library(chanalyzer SHARED
|
|
||||||
${chanalyzer_SOURCES}
|
|
||||||
${chanalyzer_HEADERS_MOC}
|
|
||||||
${chanalyzer_FORMS_HEADERS}
|
|
||||||
)
|
|
||||||
|
|
||||||
target_link_libraries(chanalyzer
|
|
||||||
${QT_LIBRARIES}
|
|
||||||
sdrbase
|
|
||||||
sdrgui
|
|
||||||
)
|
|
||||||
|
|
||||||
qt5_use_modules(chanalyzer Core Widgets )
|
|
||||||
|
|
||||||
install(TARGETS chanalyzer DESTINATION lib/plugins/channelrx)
|
|
@ -1,242 +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 <http://www.gnu.org/licenses/>. //
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
#include "chanalyzer.h"
|
|
||||||
|
|
||||||
#include <QTime>
|
|
||||||
#include <QDebug>
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
#include <dsp/downchannelizer.h>
|
|
||||||
#include "dsp/threadedbasebandsamplesink.h"
|
|
||||||
#include "device/devicesourceapi.h"
|
|
||||||
#include "audio/audiooutput.h"
|
|
||||||
|
|
||||||
MESSAGE_CLASS_DEFINITION(ChannelAnalyzer::MsgConfigureChannelAnalyzer, Message)
|
|
||||||
MESSAGE_CLASS_DEFINITION(ChannelAnalyzer::MsgConfigureChannelizer, Message)
|
|
||||||
MESSAGE_CLASS_DEFINITION(ChannelAnalyzer::MsgReportChannelSampleRateChanged, Message)
|
|
||||||
|
|
||||||
const QString ChannelAnalyzer::m_channelIdURI = "org.f4exb.sdrangelove.channel.chanalyzer";
|
|
||||||
const QString ChannelAnalyzer::m_channelId = "ChannelAnalyzer";
|
|
||||||
|
|
||||||
ChannelAnalyzer::ChannelAnalyzer(DeviceSourceAPI *deviceAPI) :
|
|
||||||
ChannelSinkAPI(m_channelIdURI),
|
|
||||||
m_deviceAPI(deviceAPI),
|
|
||||||
m_sampleSink(0),
|
|
||||||
m_settingsMutex(QMutex::Recursive)
|
|
||||||
{
|
|
||||||
setObjectName(m_channelId);
|
|
||||||
|
|
||||||
m_Bandwidth = 5000;
|
|
||||||
m_LowCutoff = 300;
|
|
||||||
m_spanLog2 = 3;
|
|
||||||
m_sampleRate = 96000;
|
|
||||||
m_frequency = 0;
|
|
||||||
m_nco.setFreq(m_frequency, m_sampleRate);
|
|
||||||
m_undersampleCount = 0;
|
|
||||||
m_sum = 0;
|
|
||||||
m_usb = true;
|
|
||||||
m_ssb = true;
|
|
||||||
m_magsq = 0;
|
|
||||||
SSBFilter = new fftfilt(m_LowCutoff / m_sampleRate, m_Bandwidth / m_sampleRate, ssbFftLen);
|
|
||||||
DSBFilter = new fftfilt(m_Bandwidth / m_sampleRate, 2*ssbFftLen);
|
|
||||||
|
|
||||||
m_channelizer = new DownChannelizer(this);
|
|
||||||
m_threadedChannelizer = new ThreadedBasebandSampleSink(m_channelizer, this);
|
|
||||||
connect(m_channelizer, SIGNAL(inputSampleRateChanged()), this, SLOT(channelSampleRateChanged()));
|
|
||||||
m_deviceAPI->addThreadedSink(m_threadedChannelizer);
|
|
||||||
m_deviceAPI->addChannelAPI(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
ChannelAnalyzer::~ChannelAnalyzer()
|
|
||||||
{
|
|
||||||
m_deviceAPI->removeChannelAPI(this);
|
|
||||||
m_deviceAPI->removeThreadedSink(m_threadedChannelizer);
|
|
||||||
delete m_threadedChannelizer;
|
|
||||||
delete m_channelizer;
|
|
||||||
if (SSBFilter) delete SSBFilter;
|
|
||||||
if (DSBFilter) delete DSBFilter;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ChannelAnalyzer::configure(MessageQueue* messageQueue,
|
|
||||||
Real Bandwidth,
|
|
||||||
Real LowCutoff,
|
|
||||||
int spanLog2,
|
|
||||||
bool ssb)
|
|
||||||
{
|
|
||||||
Message* cmd = MsgConfigureChannelAnalyzer::create(Bandwidth, LowCutoff, spanLog2, ssb);
|
|
||||||
messageQueue->push(cmd);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ChannelAnalyzer::feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end, bool positiveOnly __attribute__((unused)))
|
|
||||||
{
|
|
||||||
fftfilt::cmplx *sideband;
|
|
||||||
int n_out;
|
|
||||||
int decim = 1<<m_spanLog2;
|
|
||||||
unsigned char decim_mask = decim - 1; // counter LSB bit mask for decimation by 2^(m_scaleLog2 - 1)
|
|
||||||
|
|
||||||
m_settingsMutex.lock();
|
|
||||||
|
|
||||||
for(SampleVector::const_iterator it = begin; it < end; ++it)
|
|
||||||
{
|
|
||||||
Complex c(it->real(), it->imag());
|
|
||||||
c *= m_nco.nextIQ();
|
|
||||||
|
|
||||||
if (m_ssb)
|
|
||||||
{
|
|
||||||
n_out = SSBFilter->runSSB(c, &sideband, m_usb);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
n_out = DSBFilter->runDSB(c, &sideband);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < n_out; i++)
|
|
||||||
{
|
|
||||||
// Downsample by 2^(m_scaleLog2 - 1) for SSB band spectrum display
|
|
||||||
// smart decimation with bit gain using float arithmetic (23 bits significand)
|
|
||||||
|
|
||||||
m_sum += sideband[i];
|
|
||||||
|
|
||||||
if (!(m_undersampleCount++ & decim_mask))
|
|
||||||
{
|
|
||||||
m_sum /= decim;
|
|
||||||
Real re = m_sum.real() / SDR_RX_SCALED;
|
|
||||||
Real im = m_sum.imag() / SDR_RX_SCALED;
|
|
||||||
m_magsq = re*re + im*im;
|
|
||||||
|
|
||||||
if (m_ssb & !m_usb)
|
|
||||||
{ // invert spectrum for LSB
|
|
||||||
m_sampleBuffer.push_back(Sample(m_sum.imag(), m_sum.real()));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
m_sampleBuffer.push_back(Sample(m_sum.real(), m_sum.imag()));
|
|
||||||
}
|
|
||||||
|
|
||||||
m_sum = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(m_sampleSink != NULL)
|
|
||||||
{
|
|
||||||
m_sampleSink->feed(m_sampleBuffer.begin(), m_sampleBuffer.end(), m_ssb); // m_ssb = positive only
|
|
||||||
}
|
|
||||||
|
|
||||||
m_sampleBuffer.clear();
|
|
||||||
|
|
||||||
m_settingsMutex.unlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
void ChannelAnalyzer::start()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void ChannelAnalyzer::stop()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void ChannelAnalyzer::channelSampleRateChanged()
|
|
||||||
{
|
|
||||||
MsgReportChannelSampleRateChanged *msg = MsgReportChannelSampleRateChanged::create();
|
|
||||||
getMessageQueueToGUI()->push(msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ChannelAnalyzer::handleMessage(const Message& cmd)
|
|
||||||
{
|
|
||||||
float band, lowCutoff;
|
|
||||||
|
|
||||||
qDebug() << "ChannelAnalyzer::handleMessage";
|
|
||||||
|
|
||||||
if (DownChannelizer::MsgChannelizerNotification::match(cmd))
|
|
||||||
{
|
|
||||||
DownChannelizer::MsgChannelizerNotification& notif = (DownChannelizer::MsgChannelizerNotification&) cmd;
|
|
||||||
|
|
||||||
m_sampleRate = notif.getSampleRate();
|
|
||||||
m_nco.setFreq(-notif.getFrequencyOffset(), m_sampleRate);
|
|
||||||
|
|
||||||
qDebug() << "ChannelAnalyzer::handleMessage: MsgChannelizerNotification: m_sampleRate: " << m_sampleRate
|
|
||||||
<< " frequencyOffset: " << notif.getFrequencyOffset();
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else if (MsgConfigureChannelizer::match(cmd))
|
|
||||||
{
|
|
||||||
MsgConfigureChannelizer& cfg = (MsgConfigureChannelizer&) cmd;
|
|
||||||
|
|
||||||
m_channelizer->configure(m_channelizer->getInputMessageQueue(),
|
|
||||||
m_channelizer->getInputSampleRate(),
|
|
||||||
cfg.getCenterFrequency());
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else if (MsgConfigureChannelAnalyzer::match(cmd))
|
|
||||||
{
|
|
||||||
MsgConfigureChannelAnalyzer& cfg = (MsgConfigureChannelAnalyzer&) cmd;
|
|
||||||
|
|
||||||
band = cfg.getBandwidth();
|
|
||||||
lowCutoff = cfg.getLoCutoff();
|
|
||||||
|
|
||||||
if (band < 0)
|
|
||||||
{
|
|
||||||
band = -band;
|
|
||||||
lowCutoff = -lowCutoff;
|
|
||||||
m_usb = false;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
m_usb = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (band < 100.0f)
|
|
||||||
{
|
|
||||||
band = 100.0f;
|
|
||||||
lowCutoff = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_settingsMutex.lock();
|
|
||||||
|
|
||||||
m_Bandwidth = band;
|
|
||||||
m_LowCutoff = lowCutoff;
|
|
||||||
|
|
||||||
SSBFilter->create_filter(m_LowCutoff / m_sampleRate, m_Bandwidth / m_sampleRate);
|
|
||||||
DSBFilter->create_dsb_filter(m_Bandwidth / m_sampleRate);
|
|
||||||
|
|
||||||
m_spanLog2 = cfg.getSpanLog2();
|
|
||||||
m_ssb = cfg.getSSB();
|
|
||||||
|
|
||||||
m_settingsMutex.unlock();
|
|
||||||
|
|
||||||
qDebug() << "ChannelAnalyzer::handleMessage: MsgConfigureChannelAnalyzer: m_Bandwidth: " << m_Bandwidth
|
|
||||||
<< " m_LowCutoff: " << m_LowCutoff
|
|
||||||
<< " m_spanLog2: " << m_spanLog2
|
|
||||||
<< " m_ssb: " << m_ssb;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (m_sampleSink != 0)
|
|
||||||
{
|
|
||||||
return m_sampleSink->handleMessage(cmd);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,167 +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 <http://www.gnu.org/licenses/>. //
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
#ifndef INCLUDE_CHANALYZER_H
|
|
||||||
#define INCLUDE_CHANALYZER_H
|
|
||||||
|
|
||||||
#include <QMutex>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
#include "dsp/basebandsamplesink.h"
|
|
||||||
#include "channel/channelsinkapi.h"
|
|
||||||
#include "dsp/ncof.h"
|
|
||||||
#include "dsp/fftfilt.h"
|
|
||||||
#include "audio/audiofifo.h"
|
|
||||||
#include "util/message.h"
|
|
||||||
|
|
||||||
#define ssbFftLen 1024
|
|
||||||
|
|
||||||
class DeviceSourceAPI;
|
|
||||||
class ThreadedBasebandSampleSink;
|
|
||||||
class DownChannelizer;
|
|
||||||
|
|
||||||
class ChannelAnalyzer : public BasebandSampleSink, public ChannelSinkAPI {
|
|
||||||
public:
|
|
||||||
class MsgConfigureChannelAnalyzer : public Message {
|
|
||||||
MESSAGE_CLASS_DECLARATION
|
|
||||||
|
|
||||||
public:
|
|
||||||
Real getBandwidth() const { return m_Bandwidth; }
|
|
||||||
Real getLoCutoff() const { return m_LowCutoff; }
|
|
||||||
int getSpanLog2() const { return m_spanLog2; }
|
|
||||||
bool getSSB() const { return m_ssb; }
|
|
||||||
|
|
||||||
static MsgConfigureChannelAnalyzer* create(Real Bandwidth,
|
|
||||||
Real LowCutoff,
|
|
||||||
int spanLog2,
|
|
||||||
bool ssb)
|
|
||||||
{
|
|
||||||
return new MsgConfigureChannelAnalyzer(Bandwidth, LowCutoff, spanLog2, ssb);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
Real m_Bandwidth;
|
|
||||||
Real m_LowCutoff;
|
|
||||||
int m_spanLog2;
|
|
||||||
bool m_ssb;
|
|
||||||
|
|
||||||
MsgConfigureChannelAnalyzer(Real Bandwidth,
|
|
||||||
Real LowCutoff,
|
|
||||||
int spanLog2,
|
|
||||||
bool ssb) :
|
|
||||||
Message(),
|
|
||||||
m_Bandwidth(Bandwidth),
|
|
||||||
m_LowCutoff(LowCutoff),
|
|
||||||
m_spanLog2(spanLog2),
|
|
||||||
m_ssb(ssb)
|
|
||||||
{ }
|
|
||||||
};
|
|
||||||
|
|
||||||
class MsgConfigureChannelizer : public Message {
|
|
||||||
MESSAGE_CLASS_DECLARATION
|
|
||||||
|
|
||||||
public:
|
|
||||||
int getCenterFrequency() const { return m_centerFrequency; }
|
|
||||||
|
|
||||||
static MsgConfigureChannelizer* create(int centerFrequency)
|
|
||||||
{
|
|
||||||
return new MsgConfigureChannelizer(centerFrequency);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
int m_centerFrequency;
|
|
||||||
|
|
||||||
MsgConfigureChannelizer(int centerFrequency) :
|
|
||||||
Message(),
|
|
||||||
m_centerFrequency(centerFrequency)
|
|
||||||
{ }
|
|
||||||
};
|
|
||||||
|
|
||||||
class MsgReportChannelSampleRateChanged : public Message {
|
|
||||||
MESSAGE_CLASS_DECLARATION
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
static MsgReportChannelSampleRateChanged* create()
|
|
||||||
{
|
|
||||||
return new MsgReportChannelSampleRateChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
MsgReportChannelSampleRateChanged() :
|
|
||||||
Message()
|
|
||||||
{ }
|
|
||||||
};
|
|
||||||
|
|
||||||
ChannelAnalyzer(DeviceSourceAPI *deviceAPI);
|
|
||||||
virtual ~ChannelAnalyzer();
|
|
||||||
virtual void destroy() { delete this; }
|
|
||||||
void setSampleSink(BasebandSampleSink* sampleSink) { m_sampleSink = sampleSink; }
|
|
||||||
|
|
||||||
void configure(MessageQueue* messageQueue,
|
|
||||||
Real Bandwidth,
|
|
||||||
Real LowCutoff,
|
|
||||||
int spanLog2,
|
|
||||||
bool ssb);
|
|
||||||
|
|
||||||
int getSampleRate() const { return m_sampleRate; }
|
|
||||||
Real getMagSq() const { return m_magsq; }
|
|
||||||
|
|
||||||
virtual void feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end, bool positiveOnly);
|
|
||||||
virtual void start();
|
|
||||||
virtual void stop();
|
|
||||||
virtual bool handleMessage(const Message& cmd);
|
|
||||||
|
|
||||||
virtual void getIdentifier(QString& id) { id = objectName(); }
|
|
||||||
virtual void getTitle(QString& title) { title = objectName(); }
|
|
||||||
virtual qint64 getCenterFrequency() const { return m_frequency; }
|
|
||||||
|
|
||||||
virtual QByteArray serialize() const { return QByteArray(); }
|
|
||||||
virtual bool deserialize(const QByteArray& data __attribute__((unused))) { return false; }
|
|
||||||
|
|
||||||
static const QString m_channelIdURI;
|
|
||||||
static const QString m_channelId;
|
|
||||||
|
|
||||||
private slots:
|
|
||||||
void channelSampleRateChanged();
|
|
||||||
|
|
||||||
private:
|
|
||||||
DeviceSourceAPI *m_deviceAPI;
|
|
||||||
ThreadedBasebandSampleSink* m_threadedChannelizer;
|
|
||||||
DownChannelizer* m_channelizer;
|
|
||||||
|
|
||||||
Real m_Bandwidth;
|
|
||||||
Real m_LowCutoff;
|
|
||||||
int m_spanLog2;
|
|
||||||
int m_undersampleCount;
|
|
||||||
fftfilt::cmplx m_sum;
|
|
||||||
int m_sampleRate;
|
|
||||||
int m_frequency;
|
|
||||||
bool m_usb;
|
|
||||||
bool m_ssb;
|
|
||||||
Real m_magsq;
|
|
||||||
|
|
||||||
NCOF m_nco;
|
|
||||||
fftfilt* SSBFilter;
|
|
||||||
fftfilt* DSBFilter;
|
|
||||||
|
|
||||||
BasebandSampleSink* m_sampleSink;
|
|
||||||
SampleVector m_sampleBuffer;
|
|
||||||
QMutex m_settingsMutex;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // INCLUDE_CHANALYZER_H
|
|
@ -1,46 +0,0 @@
|
|||||||
#--------------------------------------------------------
|
|
||||||
#
|
|
||||||
# Pro file for Android and Windows builds with Qt Creator
|
|
||||||
#
|
|
||||||
#--------------------------------------------------------
|
|
||||||
|
|
||||||
TEMPLATE = lib
|
|
||||||
CONFIG += plugin
|
|
||||||
|
|
||||||
QT += core gui widgets multimedia opengl
|
|
||||||
|
|
||||||
TARGET = chanalyzer
|
|
||||||
|
|
||||||
DEFINES += USE_SSE2=1
|
|
||||||
QMAKE_CXXFLAGS += -msse2
|
|
||||||
DEFINES += USE_SSE4_1=1
|
|
||||||
QMAKE_CXXFLAGS += -msse4.1
|
|
||||||
QMAKE_CXXFLAGS += -std=c++11
|
|
||||||
|
|
||||||
INCLUDEPATH += $$PWD
|
|
||||||
INCLUDEPATH += ../../../exports
|
|
||||||
INCLUDEPATH += ../../../sdrbase
|
|
||||||
INCLUDEPATH += ../../../sdrgui
|
|
||||||
|
|
||||||
CONFIG(ANDROID):INCLUDEPATH += /opt/softs/boost_1_60_0
|
|
||||||
CONFIG(MINGW32):INCLUDEPATH += "D:\boost_1_58_0"
|
|
||||||
CONFIG(MINGW64):INCLUDEPATH += "D:\boost_1_58_0"
|
|
||||||
CONFIG(macx):INCLUDEPATH += "../../../../../boost_1_64_0"
|
|
||||||
|
|
||||||
CONFIG(Release):build_subdir = release
|
|
||||||
CONFIG(Debug):build_subdir = debug
|
|
||||||
|
|
||||||
SOURCES += chanalyzer.cpp\
|
|
||||||
chanalyzergui.cpp\
|
|
||||||
chanalyzerplugin.cpp
|
|
||||||
|
|
||||||
HEADERS += chanalyzer.h\
|
|
||||||
chanalyzergui.h\
|
|
||||||
chanalyzerplugin.h
|
|
||||||
|
|
||||||
FORMS += chanalyzergui.ui
|
|
||||||
|
|
||||||
LIBS += -L../../../sdrbase/$${build_subdir} -lsdrbase
|
|
||||||
LIBS += -L../../../sdrgui/$${build_subdir} -lsdrgui
|
|
||||||
|
|
||||||
RESOURCES = ../../../sdrgui/resources/res.qrc
|
|
@ -1,487 +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 <http://www.gnu.org/licenses/>. //
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
#include "chanalyzergui.h"
|
|
||||||
|
|
||||||
#include <device/devicesourceapi.h>
|
|
||||||
#include "device/deviceuiset.h"
|
|
||||||
#include <dsp/downchannelizer.h>
|
|
||||||
#include <QDockWidget>
|
|
||||||
#include <QMainWindow>
|
|
||||||
|
|
||||||
#include "dsp/threadedbasebandsamplesink.h"
|
|
||||||
#include "ui_chanalyzergui.h"
|
|
||||||
#include "dsp/spectrumscopecombovis.h"
|
|
||||||
#include "dsp/spectrumvis.h"
|
|
||||||
#include "dsp/scopevis.h"
|
|
||||||
#include "gui/glspectrum.h"
|
|
||||||
#include "gui/glscope.h"
|
|
||||||
#include "plugin/pluginapi.h"
|
|
||||||
#include "util/simpleserializer.h"
|
|
||||||
#include "util/db.h"
|
|
||||||
#include "dsp/dspengine.h"
|
|
||||||
#include "mainwindow.h"
|
|
||||||
|
|
||||||
#include "chanalyzer.h"
|
|
||||||
|
|
||||||
ChannelAnalyzerGUI* ChannelAnalyzerGUI::create(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, BasebandSampleSink *rxChannel)
|
|
||||||
{
|
|
||||||
ChannelAnalyzerGUI* gui = new ChannelAnalyzerGUI(pluginAPI, deviceUISet, rxChannel);
|
|
||||||
return gui;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ChannelAnalyzerGUI::destroy()
|
|
||||||
{
|
|
||||||
delete this;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ChannelAnalyzerGUI::setName(const QString& name)
|
|
||||||
{
|
|
||||||
setObjectName(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
QString ChannelAnalyzerGUI::getName() const
|
|
||||||
{
|
|
||||||
return objectName();
|
|
||||||
}
|
|
||||||
|
|
||||||
qint64 ChannelAnalyzerGUI::getCenterFrequency() const
|
|
||||||
{
|
|
||||||
return m_channelMarker.getCenterFrequency();
|
|
||||||
}
|
|
||||||
|
|
||||||
void ChannelAnalyzerGUI::setCenterFrequency(qint64 centerFrequency)
|
|
||||||
{
|
|
||||||
m_channelMarker.setCenterFrequency(centerFrequency);
|
|
||||||
applySettings();
|
|
||||||
}
|
|
||||||
|
|
||||||
void ChannelAnalyzerGUI::resetToDefaults()
|
|
||||||
{
|
|
||||||
blockApplySettings(true);
|
|
||||||
|
|
||||||
ui->BW->setValue(30);
|
|
||||||
ui->deltaFrequency->setValue(0);
|
|
||||||
ui->spanLog2->setValue(3);
|
|
||||||
|
|
||||||
blockApplySettings(false);
|
|
||||||
applySettings();
|
|
||||||
}
|
|
||||||
|
|
||||||
QByteArray ChannelAnalyzerGUI::serialize() const
|
|
||||||
{
|
|
||||||
SimpleSerializer s(1);
|
|
||||||
s.writeS32(1, m_channelMarker.getCenterFrequency());
|
|
||||||
s.writeS32(2, ui->BW->value());
|
|
||||||
s.writeBlob(3, ui->spectrumGUI->serialize());
|
|
||||||
s.writeU32(4, m_channelMarker.getColor().rgb());
|
|
||||||
s.writeS32(5, ui->lowCut->value());
|
|
||||||
s.writeS32(6, ui->spanLog2->value());
|
|
||||||
s.writeBool(7, ui->ssb->isChecked());
|
|
||||||
s.writeBlob(8, ui->scopeGUI->serialize());
|
|
||||||
|
|
||||||
return s.final();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ChannelAnalyzerGUI::deserialize(const QByteArray& data)
|
|
||||||
{
|
|
||||||
SimpleDeserializer d(data);
|
|
||||||
|
|
||||||
if(!d.isValid())
|
|
||||||
{
|
|
||||||
resetToDefaults();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(d.getVersion() == 1)
|
|
||||||
{
|
|
||||||
QByteArray bytetmp;
|
|
||||||
quint32 u32tmp;
|
|
||||||
qint32 tmp, bw, lowCut;
|
|
||||||
bool tmpBool;
|
|
||||||
|
|
||||||
blockApplySettings(true);
|
|
||||||
m_channelMarker.blockSignals(true);
|
|
||||||
|
|
||||||
d.readS32(1, &tmp, 0);
|
|
||||||
m_channelMarker.setCenterFrequency(tmp);
|
|
||||||
d.readS32(2, &bw, 30);
|
|
||||||
ui->BW->setValue(bw);
|
|
||||||
d.readBlob(3, &bytetmp);
|
|
||||||
ui->spectrumGUI->deserialize(bytetmp);
|
|
||||||
|
|
||||||
if(d.readU32(4, &u32tmp))
|
|
||||||
{
|
|
||||||
m_channelMarker.setColor(u32tmp);
|
|
||||||
}
|
|
||||||
|
|
||||||
d.readS32(5, &lowCut, 3);
|
|
||||||
ui->lowCut->setValue(lowCut);
|
|
||||||
d.readS32(6, &tmp, 20);
|
|
||||||
ui->spanLog2->setValue(tmp);
|
|
||||||
setNewRate(tmp);
|
|
||||||
d.readBool(7, &tmpBool, false);
|
|
||||||
ui->ssb->setChecked(tmpBool);
|
|
||||||
d.readBlob(8, &bytetmp);
|
|
||||||
ui->scopeGUI->deserialize(bytetmp);
|
|
||||||
|
|
||||||
blockApplySettings(false);
|
|
||||||
m_channelMarker.blockSignals(false);
|
|
||||||
m_channelMarker.emitChangedByAPI();
|
|
||||||
|
|
||||||
ui->BW->setValue(bw);
|
|
||||||
ui->lowCut->setValue(lowCut); // does applySettings();
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
resetToDefaults();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ChannelAnalyzerGUI::handleMessage(const Message& message)
|
|
||||||
{
|
|
||||||
if (ChannelAnalyzer::MsgReportChannelSampleRateChanged::match(message))
|
|
||||||
{
|
|
||||||
setNewRate(m_spanLog2);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ChannelAnalyzerGUI::handleInputMessages()
|
|
||||||
{
|
|
||||||
Message* message;
|
|
||||||
|
|
||||||
while ((message = getInputMessageQueue()->pop()) != 0)
|
|
||||||
{
|
|
||||||
qDebug("ChannelAnalyzerGUI::handleInputMessages: message: %s", message->getIdentifier());
|
|
||||||
|
|
||||||
if (handleMessage(*message))
|
|
||||||
{
|
|
||||||
delete message;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ChannelAnalyzerGUI::channelMarkerChangedByCursor()
|
|
||||||
{
|
|
||||||
ui->deltaFrequency->setValue(abs(m_channelMarker.getCenterFrequency()));
|
|
||||||
ui->deltaMinus->setChecked(m_channelMarker.getCenterFrequency() < 0);
|
|
||||||
|
|
||||||
applySettings();
|
|
||||||
}
|
|
||||||
|
|
||||||
void ChannelAnalyzerGUI::channelMarkerHighlightedByCursor()
|
|
||||||
{
|
|
||||||
setHighlighted(m_channelMarker.getHighlighted());
|
|
||||||
}
|
|
||||||
|
|
||||||
void ChannelAnalyzerGUI::tick()
|
|
||||||
{
|
|
||||||
Real powDb = CalcDb::dbPower(m_channelAnalyzer->getMagSq());
|
|
||||||
m_channelPowerDbAvg(powDb);
|
|
||||||
ui->channelPower->setText(QString::number((Real) m_channelPowerDbAvg, 'f', 1));
|
|
||||||
}
|
|
||||||
|
|
||||||
void ChannelAnalyzerGUI::on_deltaMinus_toggled(bool minus)
|
|
||||||
{
|
|
||||||
int deltaFrequency = m_channelMarker.getCenterFrequency();
|
|
||||||
bool minusDelta = (deltaFrequency < 0);
|
|
||||||
|
|
||||||
if (minus ^ minusDelta) // sign change
|
|
||||||
{
|
|
||||||
m_channelMarker.setCenterFrequency(-deltaFrequency);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ChannelAnalyzerGUI::on_deltaFrequency_changed(quint64 value)
|
|
||||||
{
|
|
||||||
if (ui->deltaMinus->isChecked()) {
|
|
||||||
m_channelMarker.setCenterFrequency(-value);
|
|
||||||
} else {
|
|
||||||
m_channelMarker.setCenterFrequency(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
applySettings();
|
|
||||||
}
|
|
||||||
|
|
||||||
void ChannelAnalyzerGUI::on_BW_valueChanged(int value)
|
|
||||||
{
|
|
||||||
QString s = QString::number(value/10.0, 'f', 1);
|
|
||||||
ui->BWText->setText(tr("%1k").arg(s));
|
|
||||||
m_channelMarker.setBandwidth(value * 100 * 2);
|
|
||||||
|
|
||||||
if (ui->ssb->isChecked())
|
|
||||||
{
|
|
||||||
if (value < 0) {
|
|
||||||
m_channelMarker.setSidebands(ChannelMarker::lsb);
|
|
||||||
} else {
|
|
||||||
m_channelMarker.setSidebands(ChannelMarker::usb);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
m_channelMarker.setSidebands(ChannelMarker::dsb);
|
|
||||||
}
|
|
||||||
|
|
||||||
on_lowCut_valueChanged(m_channelMarker.getLowCutoff()/100);
|
|
||||||
}
|
|
||||||
|
|
||||||
int ChannelAnalyzerGUI::getEffectiveLowCutoff(int lowCutoff)
|
|
||||||
{
|
|
||||||
int ssbBW = m_channelMarker.getBandwidth() / 2;
|
|
||||||
int effectiveLowCutoff = lowCutoff;
|
|
||||||
const int guard = 100;
|
|
||||||
|
|
||||||
if (ssbBW < 0) {
|
|
||||||
if (effectiveLowCutoff < ssbBW + guard) {
|
|
||||||
effectiveLowCutoff = ssbBW + guard;
|
|
||||||
}
|
|
||||||
if (effectiveLowCutoff > 0) {
|
|
||||||
effectiveLowCutoff = 0;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (effectiveLowCutoff > ssbBW - guard) {
|
|
||||||
effectiveLowCutoff = ssbBW - guard;
|
|
||||||
}
|
|
||||||
if (effectiveLowCutoff < 0) {
|
|
||||||
effectiveLowCutoff = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return effectiveLowCutoff;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ChannelAnalyzerGUI::on_lowCut_valueChanged(int value)
|
|
||||||
{
|
|
||||||
int lowCutoff = getEffectiveLowCutoff(value * 100);
|
|
||||||
m_channelMarker.setLowCutoff(lowCutoff);
|
|
||||||
QString s = QString::number(lowCutoff/1000.0, 'f', 1);
|
|
||||||
ui->lowCutText->setText(tr("%1k").arg(s));
|
|
||||||
ui->lowCut->setValue(lowCutoff/100);
|
|
||||||
applySettings();
|
|
||||||
}
|
|
||||||
|
|
||||||
void ChannelAnalyzerGUI::on_spanLog2_valueChanged(int value)
|
|
||||||
{
|
|
||||||
if (setNewRate(value)) {
|
|
||||||
applySettings();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void ChannelAnalyzerGUI::on_ssb_toggled(bool checked)
|
|
||||||
{
|
|
||||||
if (checked)
|
|
||||||
{
|
|
||||||
if (ui->BW->value() < 0) {
|
|
||||||
m_channelMarker.setSidebands(ChannelMarker::lsb);
|
|
||||||
} else {
|
|
||||||
m_channelMarker.setSidebands(ChannelMarker::usb);
|
|
||||||
}
|
|
||||||
|
|
||||||
ui->glSpectrum->setCenterFrequency(m_rate/4);
|
|
||||||
ui->glSpectrum->setSampleRate(m_rate/2);
|
|
||||||
ui->glSpectrum->setSsbSpectrum(true);
|
|
||||||
|
|
||||||
on_lowCut_valueChanged(m_channelMarker.getLowCutoff()/100);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
m_channelMarker.setSidebands(ChannelMarker::dsb);
|
|
||||||
|
|
||||||
ui->glSpectrum->setCenterFrequency(0);
|
|
||||||
ui->glSpectrum->setSampleRate(m_rate);
|
|
||||||
ui->glSpectrum->setSsbSpectrum(false);
|
|
||||||
|
|
||||||
applySettings();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ChannelAnalyzerGUI::onWidgetRolled(QWidget* widget __attribute__((unused)), bool rollDown __attribute__((unused)))
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
if((widget == ui->spectrumContainer) && (m_ssbDemod != NULL))
|
|
||||||
m_ssbDemod->setSpectrum(m_threadedSampleSink->getMessageQueue(), rollDown);
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
|
|
||||||
ChannelAnalyzerGUI::ChannelAnalyzerGUI(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, BasebandSampleSink *rxChannel, QWidget* parent) :
|
|
||||||
RollupWidget(parent),
|
|
||||||
ui(new Ui::ChannelAnalyzerGUI),
|
|
||||||
m_pluginAPI(pluginAPI),
|
|
||||||
m_deviceUISet(deviceUISet),
|
|
||||||
m_channelMarker(this),
|
|
||||||
m_doApplySettings(true),
|
|
||||||
m_rate(6000),
|
|
||||||
m_spanLog2(3)
|
|
||||||
{
|
|
||||||
ui->setupUi(this);
|
|
||||||
setAttribute(Qt::WA_DeleteOnClose, true);
|
|
||||||
connect(this, SIGNAL(widgetRolled(QWidget*,bool)), this, SLOT(onWidgetRolled(QWidget*,bool)));
|
|
||||||
|
|
||||||
m_spectrumVis = new SpectrumVis(SDR_RX_SCALEF, ui->glSpectrum);
|
|
||||||
m_scopeVis = new ScopeVis(SDR_RX_SCALEF, ui->glScope);
|
|
||||||
m_spectrumScopeComboVis = new SpectrumScopeComboVis(m_spectrumVis, m_scopeVis);
|
|
||||||
m_channelAnalyzer = (ChannelAnalyzer*) rxChannel; //new ChannelAnalyzer(m_deviceUISet->m_deviceSourceAPI);
|
|
||||||
m_channelAnalyzer->setSampleSink(m_spectrumScopeComboVis);
|
|
||||||
m_channelAnalyzer->setMessageQueueToGUI(getInputMessageQueue());
|
|
||||||
|
|
||||||
ui->deltaFrequency->setColorMapper(ColorMapper(ColorMapper::ReverseGold));
|
|
||||||
ui->deltaFrequency->setValueRange(7, 0U, 9999999U);
|
|
||||||
|
|
||||||
ui->glSpectrum->setCenterFrequency(m_rate/2);
|
|
||||||
ui->glSpectrum->setSampleRate(m_rate);
|
|
||||||
ui->glSpectrum->setDisplayWaterfall(true);
|
|
||||||
ui->glSpectrum->setDisplayMaxHold(true);
|
|
||||||
ui->glSpectrum->setSsbSpectrum(true);
|
|
||||||
|
|
||||||
ui->glSpectrum->connectTimer(MainWindow::getInstance()->getMasterTimer());
|
|
||||||
ui->glScope->connectTimer(MainWindow::getInstance()->getMasterTimer());
|
|
||||||
connect(&MainWindow::getInstance()->getMasterTimer(), SIGNAL(timeout()), this, SLOT(tick()));
|
|
||||||
|
|
||||||
m_channelMarker.blockSignals(true);
|
|
||||||
m_channelMarker.setColor(Qt::gray);
|
|
||||||
m_channelMarker.setBandwidth(m_rate);
|
|
||||||
m_channelMarker.setSidebands(ChannelMarker::usb);
|
|
||||||
m_channelMarker.setCenterFrequency(0);
|
|
||||||
m_channelMarker.blockSignals(false);
|
|
||||||
m_channelMarker.setVisible(true); // activate signal on the last setting only
|
|
||||||
setTitleColor(m_channelMarker.getColor());
|
|
||||||
|
|
||||||
m_deviceUISet->registerRxChannelInstance(ChannelAnalyzer::m_channelIdURI, this);
|
|
||||||
m_deviceUISet->addChannelMarker(&m_channelMarker);
|
|
||||||
m_deviceUISet->addRollupWidget(this);
|
|
||||||
|
|
||||||
ui->spectrumGUI->setBuddies(m_spectrumVis->getInputMessageQueue(), m_spectrumVis, ui->glSpectrum);
|
|
||||||
ui->scopeGUI->setBuddies(m_scopeVis->getInputMessageQueue(), m_scopeVis, ui->glScope);
|
|
||||||
|
|
||||||
connect(&m_channelMarker, SIGNAL(changedByCursor()), this, SLOT(channelMarkerChangedByCursor()));
|
|
||||||
connect(&m_channelMarker, SIGNAL(highlightedByCursor()), this, SLOT(channelMarkerHighlightedByCursor()));
|
|
||||||
connect(getInputMessageQueue(), SIGNAL(messageEnqueued()), this, SLOT(handleInputMessages()));
|
|
||||||
|
|
||||||
applySettings();
|
|
||||||
setNewRate(m_spanLog2);
|
|
||||||
}
|
|
||||||
|
|
||||||
ChannelAnalyzerGUI::~ChannelAnalyzerGUI()
|
|
||||||
{
|
|
||||||
m_deviceUISet->removeRxChannelInstance(this);
|
|
||||||
delete m_channelAnalyzer; // TODO: check this: when the GUI closes it has to delete the demodulator
|
|
||||||
delete m_spectrumVis;
|
|
||||||
delete m_scopeVis;
|
|
||||||
delete m_spectrumScopeComboVis;
|
|
||||||
delete ui;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ChannelAnalyzerGUI::setNewRate(int spanLog2)
|
|
||||||
{
|
|
||||||
qDebug("ChannelAnalyzerGUI::setNewRate");
|
|
||||||
|
|
||||||
if ((spanLog2 < 0) || (spanLog2 > 6)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_spanLog2 = spanLog2;
|
|
||||||
m_rate = m_channelAnalyzer->getSampleRate() / (1<<spanLog2);
|
|
||||||
|
|
||||||
if (ui->BW->value() < -m_rate/200) {
|
|
||||||
ui->BW->setValue(-m_rate/200);
|
|
||||||
m_channelMarker.setBandwidth(-m_rate*2);
|
|
||||||
} else if (ui->BW->value() > m_rate/200) {
|
|
||||||
ui->BW->setValue(m_rate/200);
|
|
||||||
m_channelMarker.setBandwidth(m_rate*2);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ui->lowCut->value() < -m_rate/200) {
|
|
||||||
ui->lowCut->setValue(-m_rate/200);
|
|
||||||
m_channelMarker.setLowCutoff(-m_rate);
|
|
||||||
} else if (ui->lowCut->value() > m_rate/200) {
|
|
||||||
ui->lowCut->setValue(m_rate/200);
|
|
||||||
m_channelMarker.setLowCutoff(m_rate);
|
|
||||||
}
|
|
||||||
|
|
||||||
ui->BW->setMinimum(-m_rate/200);
|
|
||||||
ui->lowCut->setMinimum(-m_rate/200);
|
|
||||||
ui->BW->setMaximum(m_rate/200);
|
|
||||||
ui->lowCut->setMaximum(m_rate/200);
|
|
||||||
|
|
||||||
QString s = QString::number(m_rate/1000.0, 'f', 1);
|
|
||||||
ui->spanText->setText(tr("%1k").arg(s));
|
|
||||||
|
|
||||||
if (ui->ssb->isChecked())
|
|
||||||
{
|
|
||||||
if (ui->BW->value() < 0) {
|
|
||||||
m_channelMarker.setSidebands(ChannelMarker::lsb);
|
|
||||||
} else {
|
|
||||||
m_channelMarker.setSidebands(ChannelMarker::usb);
|
|
||||||
}
|
|
||||||
|
|
||||||
ui->glSpectrum->setCenterFrequency(m_rate/4);
|
|
||||||
ui->glSpectrum->setSampleRate(m_rate/2);
|
|
||||||
ui->glSpectrum->setSsbSpectrum(true);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
m_channelMarker.setSidebands(ChannelMarker::dsb);
|
|
||||||
|
|
||||||
ui->glSpectrum->setCenterFrequency(0);
|
|
||||||
ui->glSpectrum->setSampleRate(m_rate);
|
|
||||||
ui->glSpectrum->setSsbSpectrum(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
ui->glScope->setSampleRate(m_rate);
|
|
||||||
m_scopeVis->setSampleRate(m_rate);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ChannelAnalyzerGUI::blockApplySettings(bool block)
|
|
||||||
{
|
|
||||||
ui->glScope->blockSignals(block);
|
|
||||||
ui->glSpectrum->blockSignals(block);
|
|
||||||
m_doApplySettings = !block;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ChannelAnalyzerGUI::applySettings()
|
|
||||||
{
|
|
||||||
if (m_doApplySettings)
|
|
||||||
{
|
|
||||||
ChannelAnalyzer::MsgConfigureChannelizer *msg = ChannelAnalyzer::MsgConfigureChannelizer::create(m_channelMarker.getCenterFrequency());
|
|
||||||
m_channelAnalyzer->getInputMessageQueue()->push(msg);
|
|
||||||
|
|
||||||
m_channelAnalyzer->configure(m_channelAnalyzer->getInputMessageQueue(),
|
|
||||||
ui->BW->value() * 100.0,
|
|
||||||
ui->lowCut->value() * 100.0,
|
|
||||||
m_spanLog2,
|
|
||||||
ui->ssb->isChecked());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ChannelAnalyzerGUI::leaveEvent(QEvent*)
|
|
||||||
{
|
|
||||||
m_channelMarker.setHighlighted(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ChannelAnalyzerGUI::enterEvent(QEvent*)
|
|
||||||
{
|
|
||||||
m_channelMarker.setHighlighted(true);
|
|
||||||
}
|
|
||||||
|
|
@ -1,101 +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 <http://www.gnu.org/licenses/>. //
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
#ifndef INCLUDE_CHANNELANALYZERGUI_H
|
|
||||||
#define INCLUDE_CHANNELANALYZERGUI_H
|
|
||||||
|
|
||||||
#include <plugin/plugininstancegui.h>
|
|
||||||
#include "gui/rollupwidget.h"
|
|
||||||
#include "dsp/channelmarker.h"
|
|
||||||
#include "dsp/dsptypes.h"
|
|
||||||
#include "util/movingaverage.h"
|
|
||||||
#include "util/messagequeue.h"
|
|
||||||
|
|
||||||
class PluginAPI;
|
|
||||||
class DeviceUISet;
|
|
||||||
class BasebandSampleSink;
|
|
||||||
class ChannelAnalyzer;
|
|
||||||
class SpectrumScopeComboVis;
|
|
||||||
class SpectrumVis;
|
|
||||||
class ScopeVis;
|
|
||||||
|
|
||||||
namespace Ui {
|
|
||||||
class ChannelAnalyzerGUI;
|
|
||||||
}
|
|
||||||
|
|
||||||
class ChannelAnalyzerGUI : public RollupWidget, public PluginInstanceGUI {
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
static ChannelAnalyzerGUI* create(PluginAPI* pluginAPI, DeviceUISet *deviceUIset, BasebandSampleSink *rxChannel);
|
|
||||||
virtual void destroy();
|
|
||||||
|
|
||||||
void setName(const QString& name);
|
|
||||||
QString getName() const;
|
|
||||||
virtual qint64 getCenterFrequency() const;
|
|
||||||
virtual void setCenterFrequency(qint64 centerFrequency);
|
|
||||||
|
|
||||||
void resetToDefaults();
|
|
||||||
QByteArray serialize() const;
|
|
||||||
bool deserialize(const QByteArray& data);
|
|
||||||
virtual MessageQueue *getInputMessageQueue() { return &m_inputMessageQueue; }
|
|
||||||
virtual bool handleMessage(const Message& message);
|
|
||||||
|
|
||||||
public slots:
|
|
||||||
void channelMarkerChangedByCursor();
|
|
||||||
void channelMarkerHighlightedByCursor();
|
|
||||||
|
|
||||||
private:
|
|
||||||
Ui::ChannelAnalyzerGUI* ui;
|
|
||||||
PluginAPI* m_pluginAPI;
|
|
||||||
DeviceUISet* m_deviceUISet;
|
|
||||||
ChannelMarker m_channelMarker;
|
|
||||||
bool m_doApplySettings;
|
|
||||||
int m_rate;
|
|
||||||
int m_spanLog2;
|
|
||||||
MovingAverageUtil<Real, double, 40> m_channelPowerDbAvg;
|
|
||||||
|
|
||||||
ChannelAnalyzer* m_channelAnalyzer;
|
|
||||||
SpectrumScopeComboVis* m_spectrumScopeComboVis;
|
|
||||||
SpectrumVis* m_spectrumVis;
|
|
||||||
ScopeVis* m_scopeVis;
|
|
||||||
MessageQueue m_inputMessageQueue;
|
|
||||||
|
|
||||||
explicit ChannelAnalyzerGUI(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, BasebandSampleSink *rxChannel, QWidget* parent = 0);
|
|
||||||
virtual ~ChannelAnalyzerGUI();
|
|
||||||
|
|
||||||
int getEffectiveLowCutoff(int lowCutoff);
|
|
||||||
bool setNewRate(int spanLog2);
|
|
||||||
|
|
||||||
void blockApplySettings(bool block);
|
|
||||||
void applySettings();
|
|
||||||
|
|
||||||
void leaveEvent(QEvent*);
|
|
||||||
void enterEvent(QEvent*);
|
|
||||||
|
|
||||||
private slots:
|
|
||||||
void on_deltaFrequency_changed(quint64 value);
|
|
||||||
void on_deltaMinus_toggled(bool minus);
|
|
||||||
void on_BW_valueChanged(int value);
|
|
||||||
void on_lowCut_valueChanged(int value);
|
|
||||||
void on_spanLog2_valueChanged(int value);
|
|
||||||
void on_ssb_toggled(bool checked);
|
|
||||||
void onWidgetRolled(QWidget* widget, bool rollDown);
|
|
||||||
void handleInputMessages();
|
|
||||||
void tick();
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // INCLUDE_CHANNELANALYZERGUI_H
|
|
@ -1,540 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<ui version="4.0">
|
|
||||||
<class>ChannelAnalyzerGUI</class>
|
|
||||||
<widget class="RollupWidget" name="ChannelAnalyzerGUI">
|
|
||||||
<property name="geometry">
|
|
||||||
<rect>
|
|
||||||
<x>0</x>
|
|
||||||
<y>0</y>
|
|
||||||
<width>640</width>
|
|
||||||
<height>814</height>
|
|
||||||
</rect>
|
|
||||||
</property>
|
|
||||||
<property name="minimumSize">
|
|
||||||
<size>
|
|
||||||
<width>640</width>
|
|
||||||
<height>0</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="font">
|
|
||||||
<font>
|
|
||||||
<family>Liberation Sans</family>
|
|
||||||
<pointsize>9</pointsize>
|
|
||||||
</font>
|
|
||||||
</property>
|
|
||||||
<property name="windowTitle">
|
|
||||||
<string>Channel Analyzer</string>
|
|
||||||
</property>
|
|
||||||
<widget class="QWidget" name="settingsContainer" native="true">
|
|
||||||
<property name="geometry">
|
|
||||||
<rect>
|
|
||||||
<x>0</x>
|
|
||||||
<y>10</y>
|
|
||||||
<width>301</width>
|
|
||||||
<height>131</height>
|
|
||||||
</rect>
|
|
||||||
</property>
|
|
||||||
<property name="windowTitle">
|
|
||||||
<string>Settings</string>
|
|
||||||
</property>
|
|
||||||
<layout class="QVBoxLayout" name="verticalLayout">
|
|
||||||
<property name="spacing">
|
|
||||||
<number>3</number>
|
|
||||||
</property>
|
|
||||||
<property name="leftMargin">
|
|
||||||
<number>2</number>
|
|
||||||
</property>
|
|
||||||
<property name="topMargin">
|
|
||||||
<number>2</number>
|
|
||||||
</property>
|
|
||||||
<property name="rightMargin">
|
|
||||||
<number>2</number>
|
|
||||||
</property>
|
|
||||||
<property name="bottomMargin">
|
|
||||||
<number>2</number>
|
|
||||||
</property>
|
|
||||||
<item>
|
|
||||||
<layout class="QHBoxLayout" name="DeltaFreqPowLayout">
|
|
||||||
<item>
|
|
||||||
<layout class="QHBoxLayout" name="DeltaFrequencyLayout">
|
|
||||||
<item>
|
|
||||||
<widget class="QToolButton" name="deltaMinus">
|
|
||||||
<property name="toolTip">
|
|
||||||
<string>Frequency shift direction</string>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>...</string>
|
|
||||||
</property>
|
|
||||||
<property name="icon">
|
|
||||||
<iconset>
|
|
||||||
<selectedoff>:/plus.png</selectedoff>
|
|
||||||
<selectedon>:/minus.png</selectedon>
|
|
||||||
</iconset>
|
|
||||||
</property>
|
|
||||||
<property name="checkable">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
<property name="checked">
|
|
||||||
<bool>false</bool>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="ValueDial" name="deltaFrequency" native="true">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Maximum" vsizetype="Maximum">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="minimumSize">
|
|
||||||
<size>
|
|
||||||
<width>32</width>
|
|
||||||
<height>16</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="font">
|
|
||||||
<font>
|
|
||||||
<family>Monospace</family>
|
|
||||||
<pointsize>12</pointsize>
|
|
||||||
</font>
|
|
||||||
</property>
|
|
||||||
<property name="cursor">
|
|
||||||
<cursorShape>SizeVerCursor</cursorShape>
|
|
||||||
</property>
|
|
||||||
<property name="focusPolicy">
|
|
||||||
<enum>Qt::StrongFocus</enum>
|
|
||||||
</property>
|
|
||||||
<property name="toolTip">
|
|
||||||
<string>Demod shift frequency from center in Hz</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QLabel" name="deltaUnits">
|
|
||||||
<property name="palette">
|
|
||||||
<palette>
|
|
||||||
<active>
|
|
||||||
<colorrole role="Text">
|
|
||||||
<brush brushstyle="SolidPattern">
|
|
||||||
<color alpha="255">
|
|
||||||
<red>26</red>
|
|
||||||
<green>26</green>
|
|
||||||
<blue>26</blue>
|
|
||||||
</color>
|
|
||||||
</brush>
|
|
||||||
</colorrole>
|
|
||||||
<colorrole role="BrightText">
|
|
||||||
<brush brushstyle="SolidPattern">
|
|
||||||
<color alpha="255">
|
|
||||||
<red>255</red>
|
|
||||||
<green>255</green>
|
|
||||||
<blue>255</blue>
|
|
||||||
</color>
|
|
||||||
</brush>
|
|
||||||
</colorrole>
|
|
||||||
</active>
|
|
||||||
<inactive>
|
|
||||||
<colorrole role="Text">
|
|
||||||
<brush brushstyle="SolidPattern">
|
|
||||||
<color alpha="255">
|
|
||||||
<red>26</red>
|
|
||||||
<green>26</green>
|
|
||||||
<blue>26</blue>
|
|
||||||
</color>
|
|
||||||
</brush>
|
|
||||||
</colorrole>
|
|
||||||
<colorrole role="BrightText">
|
|
||||||
<brush brushstyle="SolidPattern">
|
|
||||||
<color alpha="255">
|
|
||||||
<red>255</red>
|
|
||||||
<green>255</green>
|
|
||||||
<blue>255</blue>
|
|
||||||
</color>
|
|
||||||
</brush>
|
|
||||||
</colorrole>
|
|
||||||
</inactive>
|
|
||||||
<disabled>
|
|
||||||
<colorrole role="Text">
|
|
||||||
<brush brushstyle="SolidPattern">
|
|
||||||
<color alpha="255">
|
|
||||||
<red>118</red>
|
|
||||||
<green>118</green>
|
|
||||||
<blue>117</blue>
|
|
||||||
</color>
|
|
||||||
</brush>
|
|
||||||
</colorrole>
|
|
||||||
<colorrole role="BrightText">
|
|
||||||
<brush brushstyle="SolidPattern">
|
|
||||||
<color alpha="255">
|
|
||||||
<red>255</red>
|
|
||||||
<green>255</green>
|
|
||||||
<blue>255</blue>
|
|
||||||
</color>
|
|
||||||
</brush>
|
|
||||||
</colorrole>
|
|
||||||
</disabled>
|
|
||||||
</palette>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string> Hz</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<spacer name="horizontalSpacer">
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Horizontal</enum>
|
|
||||||
</property>
|
|
||||||
<property name="sizeHint" stdset="0">
|
|
||||||
<size>
|
|
||||||
<width>40</width>
|
|
||||||
<height>20</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
</spacer>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<layout class="QHBoxLayout" name="ChannelPowerLayout">
|
|
||||||
<item>
|
|
||||||
<widget class="QLabel" name="channelPower">
|
|
||||||
<property name="toolTip">
|
|
||||||
<string>Channel power</string>
|
|
||||||
</property>
|
|
||||||
<property name="layoutDirection">
|
|
||||||
<enum>Qt::LeftToRight</enum>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>0.0</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QLabel" name="channelPowerUnits">
|
|
||||||
<property name="text">
|
|
||||||
<string> dB</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<layout class="QHBoxLayout" name="SpanLayout">
|
|
||||||
<item>
|
|
||||||
<widget class="QLabel" name="spanLabel">
|
|
||||||
<property name="text">
|
|
||||||
<string>Rate</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QSlider" name="spanLog2">
|
|
||||||
<property name="toolTip">
|
|
||||||
<string>Channel sample rate</string>
|
|
||||||
</property>
|
|
||||||
<property name="minimum">
|
|
||||||
<number>0</number>
|
|
||||||
</property>
|
|
||||||
<property name="maximum">
|
|
||||||
<number>6</number>
|
|
||||||
</property>
|
|
||||||
<property name="pageStep">
|
|
||||||
<number>1</number>
|
|
||||||
</property>
|
|
||||||
<property name="value">
|
|
||||||
<number>3</number>
|
|
||||||
</property>
|
|
||||||
<property name="sliderPosition">
|
|
||||||
<number>3</number>
|
|
||||||
</property>
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Horizontal</enum>
|
|
||||||
</property>
|
|
||||||
<property name="invertedAppearance">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
<property name="invertedControls">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QLabel" name="spanText">
|
|
||||||
<property name="text">
|
|
||||||
<string>6.0k</string>
|
|
||||||
</property>
|
|
||||||
<property name="alignment">
|
|
||||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QCheckBox" name="ssb">
|
|
||||||
<property name="toolTip">
|
|
||||||
<string>SSB/DSB toggle</string>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>SSB</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<layout class="QHBoxLayout" name="BWLayout">
|
|
||||||
<item>
|
|
||||||
<widget class="QLabel" name="BWLabel">
|
|
||||||
<property name="text">
|
|
||||||
<string>BW</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QSlider" name="BW">
|
|
||||||
<property name="toolTip">
|
|
||||||
<string>Lowpass filter cutoff frequency</string>
|
|
||||||
</property>
|
|
||||||
<property name="minimum">
|
|
||||||
<number>-60</number>
|
|
||||||
</property>
|
|
||||||
<property name="maximum">
|
|
||||||
<number>60</number>
|
|
||||||
</property>
|
|
||||||
<property name="pageStep">
|
|
||||||
<number>1</number>
|
|
||||||
</property>
|
|
||||||
<property name="value">
|
|
||||||
<number>30</number>
|
|
||||||
</property>
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Horizontal</enum>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QLabel" name="BWText">
|
|
||||||
<property name="minimumSize">
|
|
||||||
<size>
|
|
||||||
<width>50</width>
|
|
||||||
<height>0</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>3.0k</string>
|
|
||||||
</property>
|
|
||||||
<property name="alignment">
|
|
||||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<layout class="QHBoxLayout" name="LowCutLayout">
|
|
||||||
<item>
|
|
||||||
<widget class="QLabel" name="lowCutLabel">
|
|
||||||
<property name="text">
|
|
||||||
<string>Low cut.</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QSlider" name="lowCut">
|
|
||||||
<property name="toolTip">
|
|
||||||
<string>Highpass filter cutoff frequency (SSB)</string>
|
|
||||||
</property>
|
|
||||||
<property name="minimum">
|
|
||||||
<number>-60</number>
|
|
||||||
</property>
|
|
||||||
<property name="maximum">
|
|
||||||
<number>60</number>
|
|
||||||
</property>
|
|
||||||
<property name="pageStep">
|
|
||||||
<number>1</number>
|
|
||||||
</property>
|
|
||||||
<property name="value">
|
|
||||||
<number>3</number>
|
|
||||||
</property>
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Horizontal</enum>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QLabel" name="lowCutText">
|
|
||||||
<property name="minimumSize">
|
|
||||||
<size>
|
|
||||||
<width>50</width>
|
|
||||||
<height>0</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>0.3k</string>
|
|
||||||
</property>
|
|
||||||
<property name="alignment">
|
|
||||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
<widget class="QWidget" name="spectrumContainer" native="true">
|
|
||||||
<property name="geometry">
|
|
||||||
<rect>
|
|
||||||
<x>10</x>
|
|
||||||
<y>180</y>
|
|
||||||
<width>636</width>
|
|
||||||
<height>284</height>
|
|
||||||
</rect>
|
|
||||||
</property>
|
|
||||||
<property name="minimumSize">
|
|
||||||
<size>
|
|
||||||
<width>636</width>
|
|
||||||
<height>0</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="windowTitle">
|
|
||||||
<string>Channel Spectrum</string>
|
|
||||||
</property>
|
|
||||||
<layout class="QVBoxLayout" name="verticalLayoutSpectrum">
|
|
||||||
<property name="spacing">
|
|
||||||
<number>2</number>
|
|
||||||
</property>
|
|
||||||
<property name="leftMargin">
|
|
||||||
<number>2</number>
|
|
||||||
</property>
|
|
||||||
<property name="topMargin">
|
|
||||||
<number>2</number>
|
|
||||||
</property>
|
|
||||||
<property name="rightMargin">
|
|
||||||
<number>2</number>
|
|
||||||
</property>
|
|
||||||
<property name="bottomMargin">
|
|
||||||
<number>2</number>
|
|
||||||
</property>
|
|
||||||
<item>
|
|
||||||
<widget class="GLSpectrum" name="glSpectrum" native="true">
|
|
||||||
<property name="minimumSize">
|
|
||||||
<size>
|
|
||||||
<width>200</width>
|
|
||||||
<height>250</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="font">
|
|
||||||
<font>
|
|
||||||
<family>Monospace</family>
|
|
||||||
<pointsize>8</pointsize>
|
|
||||||
</font>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="GLSpectrumGUI" name="spectrumGUI" native="true"/>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
<widget class="QWidget" name="scopeContainer" native="true">
|
|
||||||
<property name="geometry">
|
|
||||||
<rect>
|
|
||||||
<x>0</x>
|
|
||||||
<y>470</y>
|
|
||||||
<width>636</width>
|
|
||||||
<height>284</height>
|
|
||||||
</rect>
|
|
||||||
</property>
|
|
||||||
<property name="minimumSize">
|
|
||||||
<size>
|
|
||||||
<width>636</width>
|
|
||||||
<height>0</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="windowTitle">
|
|
||||||
<string>Channel Scope</string>
|
|
||||||
</property>
|
|
||||||
<layout class="QVBoxLayout" name="verticalLayoutScope">
|
|
||||||
<property name="spacing">
|
|
||||||
<number>2</number>
|
|
||||||
</property>
|
|
||||||
<property name="leftMargin">
|
|
||||||
<number>3</number>
|
|
||||||
</property>
|
|
||||||
<property name="topMargin">
|
|
||||||
<number>3</number>
|
|
||||||
</property>
|
|
||||||
<property name="rightMargin">
|
|
||||||
<number>3</number>
|
|
||||||
</property>
|
|
||||||
<property name="bottomMargin">
|
|
||||||
<number>3</number>
|
|
||||||
</property>
|
|
||||||
<item>
|
|
||||||
<widget class="GLScope" name="glScope" native="true">
|
|
||||||
<property name="minimumSize">
|
|
||||||
<size>
|
|
||||||
<width>200</width>
|
|
||||||
<height>250</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="font">
|
|
||||||
<font>
|
|
||||||
<family>Monospace</family>
|
|
||||||
<pointsize>8</pointsize>
|
|
||||||
</font>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="GLScopeGUI" name="scopeGUI" native="true"/>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
</widget>
|
|
||||||
<customwidgets>
|
|
||||||
<customwidget>
|
|
||||||
<class>RollupWidget</class>
|
|
||||||
<extends>QWidget</extends>
|
|
||||||
<header>gui/rollupwidget.h</header>
|
|
||||||
<container>1</container>
|
|
||||||
</customwidget>
|
|
||||||
<customwidget>
|
|
||||||
<class>ValueDial</class>
|
|
||||||
<extends>QWidget</extends>
|
|
||||||
<header>gui/valuedial.h</header>
|
|
||||||
<container>1</container>
|
|
||||||
</customwidget>
|
|
||||||
<customwidget>
|
|
||||||
<class>GLSpectrum</class>
|
|
||||||
<extends>QWidget</extends>
|
|
||||||
<header>gui/glspectrum.h</header>
|
|
||||||
<container>1</container>
|
|
||||||
</customwidget>
|
|
||||||
<customwidget>
|
|
||||||
<class>GLSpectrumGUI</class>
|
|
||||||
<extends>QWidget</extends>
|
|
||||||
<header>gui/glspectrumgui.h</header>
|
|
||||||
<container>1</container>
|
|
||||||
</customwidget>
|
|
||||||
<customwidget>
|
|
||||||
<class>GLScope</class>
|
|
||||||
<extends>QWidget</extends>
|
|
||||||
<header>gui/glscope.h</header>
|
|
||||||
<container>1</container>
|
|
||||||
</customwidget>
|
|
||||||
<customwidget>
|
|
||||||
<class>GLScopeGUI</class>
|
|
||||||
<extends>QWidget</extends>
|
|
||||||
<header>gui/glscopegui.h</header>
|
|
||||||
<container>1</container>
|
|
||||||
</customwidget>
|
|
||||||
</customwidgets>
|
|
||||||
<resources>
|
|
||||||
<include location="../../../sdrgui/resources/res.qrc"/>
|
|
||||||
</resources>
|
|
||||||
<connections/>
|
|
||||||
</ui>
|
|
@ -1,50 +0,0 @@
|
|||||||
#include "chanalyzerplugin.h"
|
|
||||||
|
|
||||||
#include <QtPlugin>
|
|
||||||
#include "plugin/pluginapi.h"
|
|
||||||
|
|
||||||
#include "chanalyzergui.h"
|
|
||||||
#include "chanalyzer.h"
|
|
||||||
|
|
||||||
const PluginDescriptor ChannelAnalyzerPlugin::m_pluginDescriptor = {
|
|
||||||
QString("Channel Analyzer"),
|
|
||||||
QString("3.14.5"),
|
|
||||||
QString("(c) Edouard Griffiths, F4EXB"),
|
|
||||||
QString("https://github.com/f4exb/sdrangel"),
|
|
||||||
true,
|
|
||||||
QString("https://github.com/f4exb/sdrangel")
|
|
||||||
};
|
|
||||||
|
|
||||||
ChannelAnalyzerPlugin::ChannelAnalyzerPlugin(QObject* parent) :
|
|
||||||
QObject(parent),
|
|
||||||
m_pluginAPI(0)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
const PluginDescriptor& ChannelAnalyzerPlugin::getPluginDescriptor() const
|
|
||||||
{
|
|
||||||
return m_pluginDescriptor;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ChannelAnalyzerPlugin::initPlugin(PluginAPI* pluginAPI)
|
|
||||||
{
|
|
||||||
m_pluginAPI = pluginAPI;
|
|
||||||
|
|
||||||
// register demodulator
|
|
||||||
m_pluginAPI->registerRxChannel(ChannelAnalyzer::m_channelIdURI, ChannelAnalyzer::m_channelId, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
PluginInstanceGUI* ChannelAnalyzerPlugin::createRxChannelGUI(DeviceUISet *deviceUISet, BasebandSampleSink *rxChannel)
|
|
||||||
{
|
|
||||||
return ChannelAnalyzerGUI::create(m_pluginAPI, deviceUISet, rxChannel);
|
|
||||||
}
|
|
||||||
|
|
||||||
BasebandSampleSink* ChannelAnalyzerPlugin::createRxChannelBS(DeviceSourceAPI *deviceAPI)
|
|
||||||
{
|
|
||||||
return new ChannelAnalyzer(deviceAPI);
|
|
||||||
}
|
|
||||||
|
|
||||||
ChannelSinkAPI* ChannelAnalyzerPlugin::createRxChannelCS(DeviceSourceAPI *deviceAPI)
|
|
||||||
{
|
|
||||||
return new ChannelAnalyzer(deviceAPI);
|
|
||||||
}
|
|
@ -1,32 +0,0 @@
|
|||||||
#ifndef INCLUDE_CHANALYZERPLUGIN_H
|
|
||||||
#define INCLUDE_CHANALYZERPLUGIN_H
|
|
||||||
|
|
||||||
#include <QObject>
|
|
||||||
#include "plugin/plugininterface.h"
|
|
||||||
|
|
||||||
class DeviceUISet;
|
|
||||||
class BasebandSampleSink;
|
|
||||||
class ChannelSinkAPI;
|
|
||||||
|
|
||||||
class ChannelAnalyzerPlugin : public QObject, PluginInterface {
|
|
||||||
Q_OBJECT
|
|
||||||
Q_INTERFACES(PluginInterface)
|
|
||||||
Q_PLUGIN_METADATA(IID "org.f4exb.sdrangelove.channel.chanalyzer")
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit ChannelAnalyzerPlugin(QObject* parent = NULL);
|
|
||||||
|
|
||||||
const PluginDescriptor& getPluginDescriptor() const;
|
|
||||||
void initPlugin(PluginAPI* pluginAPI);
|
|
||||||
|
|
||||||
virtual PluginInstanceGUI* createRxChannelGUI(DeviceUISet *deviceUISet, BasebandSampleSink *rxChannel);
|
|
||||||
virtual BasebandSampleSink* createRxChannelBS(DeviceSourceAPI *deviceAPI);
|
|
||||||
virtual ChannelSinkAPI* createRxChannelCS(DeviceSourceAPI *deviceAPI);
|
|
||||||
|
|
||||||
private:
|
|
||||||
static const PluginDescriptor m_pluginDescriptor;
|
|
||||||
|
|
||||||
PluginAPI* m_pluginAPI;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // INCLUDE_CHANALYZERPLUGIN_H
|
|
@ -1,48 +0,0 @@
|
|||||||
project(tcpsrc)
|
|
||||||
|
|
||||||
set(tcpsrc_SOURCES
|
|
||||||
tcpsrc.cpp
|
|
||||||
tcpsrcgui.cpp
|
|
||||||
tcpsrcplugin.cpp
|
|
||||||
tcpsrcsettings.cpp
|
|
||||||
)
|
|
||||||
|
|
||||||
set(tcpsrc_HEADERS
|
|
||||||
tcpsrc.h
|
|
||||||
tcpsrcgui.h
|
|
||||||
tcpsrcplugin.h
|
|
||||||
tcpsrcsettings.h
|
|
||||||
)
|
|
||||||
|
|
||||||
set(tcpsrc_FORMS
|
|
||||||
tcpsrcgui.ui
|
|
||||||
)
|
|
||||||
|
|
||||||
include_directories(
|
|
||||||
.
|
|
||||||
${CMAKE_CURRENT_BINARY_DIR}
|
|
||||||
)
|
|
||||||
|
|
||||||
#include(${QT_USE_FILE})
|
|
||||||
add_definitions(${QT_DEFINITIONS})
|
|
||||||
add_definitions(-DQT_PLUGIN)
|
|
||||||
add_definitions(-DQT_SHARED)
|
|
||||||
|
|
||||||
#qt5_wrap_cpp(tcpsrc_HEADERS_MOC ${tcpsrc_HEADERS})
|
|
||||||
qt5_wrap_ui(tcpsrc_FORMS_HEADERS ${tcpsrc_FORMS})
|
|
||||||
|
|
||||||
add_library(demodtcpsrc SHARED
|
|
||||||
${tcpsrc_SOURCES}
|
|
||||||
${tcpsrc_HEADERS_MOC}
|
|
||||||
${tcpsrc_FORMS_HEADERS}
|
|
||||||
)
|
|
||||||
|
|
||||||
target_link_libraries(demodtcpsrc
|
|
||||||
${QT_LIBRARIES}
|
|
||||||
sdrbase
|
|
||||||
sdrgui
|
|
||||||
)
|
|
||||||
|
|
||||||
qt5_use_modules(demodtcpsrc Core Widgets Network)
|
|
||||||
|
|
||||||
install(TARGETS demodtcpsrc DESTINATION lib/plugins/channelrx)
|
|
@ -1,487 +0,0 @@
|
|||||||
// Copyright (C) 2012 maintech GmbH, Otto-Hahn-Str. 15, 97204 Hoechberg, Germany //
|
|
||||||
// (C) 2015 John Greb //
|
|
||||||
// //
|
|
||||||
// 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 <http://www.gnu.org/licenses/>. //
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
#include "tcpsrc.h"
|
|
||||||
|
|
||||||
#include <QTcpServer>
|
|
||||||
#include <QTcpSocket>
|
|
||||||
|
|
||||||
#include "dsp/downchannelizer.h"
|
|
||||||
#include "dsp/threadedbasebandsamplesink.h"
|
|
||||||
#include "dsp/dspcommands.h"
|
|
||||||
#include "device/devicesourceapi.h"
|
|
||||||
|
|
||||||
#include "tcpsrcgui.h"
|
|
||||||
|
|
||||||
MESSAGE_CLASS_DEFINITION(TCPSrc::MsgConfigureTCPSrc, Message)
|
|
||||||
MESSAGE_CLASS_DEFINITION(TCPSrc::MsgConfigureChannelizer, Message)
|
|
||||||
MESSAGE_CLASS_DEFINITION(TCPSrc::MsgTCPSrcConnection, Message)
|
|
||||||
MESSAGE_CLASS_DEFINITION(TCPSrc::MsgTCPSrcSpectrum, Message)
|
|
||||||
|
|
||||||
const QString TCPSrc::m_channelIdURI = "sdrangel.channel.tcpsrc";
|
|
||||||
const QString TCPSrc::m_channelId = "TCPSrc";
|
|
||||||
|
|
||||||
TCPSrc::TCPSrc(DeviceSourceAPI* deviceAPI) :
|
|
||||||
ChannelSinkAPI(m_channelIdURI),
|
|
||||||
m_deviceAPI(deviceAPI),
|
|
||||||
m_absoluteFrequencyOffset(0),
|
|
||||||
m_settingsMutex(QMutex::Recursive)
|
|
||||||
{
|
|
||||||
setObjectName(m_channelId);
|
|
||||||
|
|
||||||
m_inputSampleRate = 96000;
|
|
||||||
m_sampleFormat = TCPSrcSettings::FormatSSB;
|
|
||||||
m_outputSampleRate = 48000;
|
|
||||||
m_rfBandwidth = 32000;
|
|
||||||
m_tcpServer = 0;
|
|
||||||
m_tcpPort = 9999;
|
|
||||||
m_nco.setFreq(0, m_inputSampleRate);
|
|
||||||
m_interpolator.create(16, m_inputSampleRate, m_rfBandwidth / 2.0);
|
|
||||||
m_sampleDistanceRemain = m_inputSampleRate / m_outputSampleRate;
|
|
||||||
m_spectrum = 0;
|
|
||||||
m_spectrumEnabled = false;
|
|
||||||
m_nextSSBId = 0;
|
|
||||||
m_nextS16leId = 0;
|
|
||||||
|
|
||||||
m_last = 0;
|
|
||||||
m_this = 0;
|
|
||||||
m_scale = 0;
|
|
||||||
m_volume = 0;
|
|
||||||
m_magsq = 0;
|
|
||||||
|
|
||||||
m_sampleBufferSSB.resize(tcpFftLen);
|
|
||||||
TCPFilter = new fftfilt(0.3 / 48.0, 16.0 / 48.0, tcpFftLen);
|
|
||||||
|
|
||||||
m_channelizer = new DownChannelizer(this);
|
|
||||||
m_threadedChannelizer = new ThreadedBasebandSampleSink(m_channelizer, this);
|
|
||||||
m_deviceAPI->addThreadedSink(m_threadedChannelizer);
|
|
||||||
m_deviceAPI->addChannelAPI(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
TCPSrc::~TCPSrc()
|
|
||||||
{
|
|
||||||
m_deviceAPI->removeChannelAPI(this);
|
|
||||||
m_deviceAPI->removeThreadedSink(m_threadedChannelizer);
|
|
||||||
delete m_threadedChannelizer;
|
|
||||||
delete m_channelizer;
|
|
||||||
delete TCPFilter;
|
|
||||||
}
|
|
||||||
|
|
||||||
void TCPSrc::setSpectrum(MessageQueue* messageQueue, bool enabled)
|
|
||||||
{
|
|
||||||
Message* cmd = MsgTCPSrcSpectrum::create(enabled);
|
|
||||||
messageQueue->push(cmd);
|
|
||||||
}
|
|
||||||
|
|
||||||
void TCPSrc::feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end, bool positiveOnly)
|
|
||||||
{
|
|
||||||
Complex ci;
|
|
||||||
fftfilt::cmplx* sideband;
|
|
||||||
Real l, r;
|
|
||||||
|
|
||||||
m_sampleBuffer.clear();
|
|
||||||
|
|
||||||
m_settingsMutex.lock();
|
|
||||||
|
|
||||||
// Rtl-Sdr uses full 16-bit scale; FCDPP does not
|
|
||||||
int rescale = (1 << m_volume);
|
|
||||||
|
|
||||||
for(SampleVector::const_iterator it = begin; it < end; ++it) {
|
|
||||||
Complex c(it->real(), it->imag());
|
|
||||||
c *= m_nco.nextIQ();
|
|
||||||
|
|
||||||
if(m_interpolator.decimate(&m_sampleDistanceRemain, c, &ci))
|
|
||||||
{
|
|
||||||
m_magsq = ((ci.real()*ci.real() + ci.imag()*ci.imag())*rescale*rescale) / (SDR_RX_SCALED*SDR_RX_SCALED);
|
|
||||||
m_sampleBuffer.push_back(Sample(ci.real() * rescale, ci.imag() * rescale));
|
|
||||||
m_sampleDistanceRemain += m_inputSampleRate / m_outputSampleRate;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if((m_spectrum != 0) && (m_spectrumEnabled))
|
|
||||||
{
|
|
||||||
m_spectrum->feed(m_sampleBuffer.begin(), m_sampleBuffer.end(), positiveOnly);
|
|
||||||
}
|
|
||||||
|
|
||||||
for(int i = 0; i < m_s16leSockets.count(); i++)
|
|
||||||
{
|
|
||||||
m_s16leSockets[i].socket->write((const char*)&m_sampleBuffer[0], m_sampleBuffer.size() * 4);
|
|
||||||
}
|
|
||||||
|
|
||||||
if((m_sampleFormat == TCPSrcSettings::FormatSSB) && (m_ssbSockets.count() > 0)) {
|
|
||||||
for(SampleVector::const_iterator it = m_sampleBuffer.begin(); it != m_sampleBuffer.end(); ++it) {
|
|
||||||
//Complex cj(it->real() / 30000.0, it->imag() / 30000.0);
|
|
||||||
Complex cj(it->real(), it->imag());
|
|
||||||
int n_out = TCPFilter->runSSB(cj, &sideband, true);
|
|
||||||
if (n_out) {
|
|
||||||
for (int i = 0; i < n_out; i+=2) {
|
|
||||||
//l = (sideband[i].real() + sideband[i].imag()) * 0.7 * 32000.0;
|
|
||||||
//r = (sideband[i+1].real() + sideband[i+1].imag()) * 0.7 * 32000.0;
|
|
||||||
l = (sideband[i].real() + sideband[i].imag()) * 0.7;
|
|
||||||
r = (sideband[i+1].real() + sideband[i+1].imag()) * 0.7;
|
|
||||||
m_sampleBufferSSB.push_back(Sample(l, r));
|
|
||||||
}
|
|
||||||
for(int i = 0; i < m_ssbSockets.count(); i++)
|
|
||||||
m_ssbSockets[i].socket->write((const char*)&m_sampleBufferSSB[0], n_out * 2);
|
|
||||||
m_sampleBufferSSB.clear();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if((m_sampleFormat == TCPSrcSettings::FormatNFM) && (m_ssbSockets.count() > 0)) {
|
|
||||||
for(SampleVector::const_iterator it = m_sampleBuffer.begin(); it != m_sampleBuffer.end(); ++it) {
|
|
||||||
Complex cj(it->real() / SDR_RX_SCALEF, it->imag() / SDR_RX_SCALEF);
|
|
||||||
// An FFT filter here is overkill, but was already set up for SSB
|
|
||||||
int n_out = TCPFilter->runFilt(cj, &sideband);
|
|
||||||
if (n_out) {
|
|
||||||
Real sum = 1.0;
|
|
||||||
for (int i = 0; i < n_out; i+=2) {
|
|
||||||
l = m_this.real() * (m_last.imag() - sideband[i].imag())
|
|
||||||
- m_this.imag() * (m_last.real() - sideband[i].real());
|
|
||||||
m_last = sideband[i];
|
|
||||||
r = m_last.real() * (m_this.imag() - sideband[i+1].imag())
|
|
||||||
- m_last.imag() * (m_this.real() - sideband[i+1].real());
|
|
||||||
m_this = sideband[i+1];
|
|
||||||
m_sampleBufferSSB.push_back(Sample(l * m_scale, r * m_scale));
|
|
||||||
sum += m_this.real() * m_this.real() + m_this.imag() * m_this.imag();
|
|
||||||
}
|
|
||||||
// TODO: correct levels
|
|
||||||
m_scale = 24000 * tcpFftLen / sum;
|
|
||||||
for(int i = 0; i < m_ssbSockets.count(); i++)
|
|
||||||
m_ssbSockets[i].socket->write((const char*)&m_sampleBufferSSB[0], n_out * 2);
|
|
||||||
m_sampleBufferSSB.clear();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
m_settingsMutex.unlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
void TCPSrc::start()
|
|
||||||
{
|
|
||||||
m_tcpServer = new QTcpServer();
|
|
||||||
connect(m_tcpServer, SIGNAL(newConnection()), this, SLOT(onNewConnection()));
|
|
||||||
connect(m_tcpServer, SIGNAL(acceptError(QAbstractSocket::SocketError)), this, SLOT(onTcpServerError(QAbstractSocket::SocketError)));
|
|
||||||
m_tcpServer->listen(QHostAddress::Any, m_tcpPort);
|
|
||||||
}
|
|
||||||
|
|
||||||
void TCPSrc::stop()
|
|
||||||
{
|
|
||||||
closeAllSockets(&m_ssbSockets);
|
|
||||||
closeAllSockets(&m_s16leSockets);
|
|
||||||
|
|
||||||
if(m_tcpServer->isListening())
|
|
||||||
m_tcpServer->close();
|
|
||||||
delete m_tcpServer;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool TCPSrc::handleMessage(const Message& cmd)
|
|
||||||
{
|
|
||||||
if (DownChannelizer::MsgChannelizerNotification::match(cmd))
|
|
||||||
{
|
|
||||||
DownChannelizer::MsgChannelizerNotification& notif = (DownChannelizer::MsgChannelizerNotification&) cmd;
|
|
||||||
|
|
||||||
m_settingsMutex.lock();
|
|
||||||
|
|
||||||
m_inputSampleRate = notif.getSampleRate();
|
|
||||||
m_nco.setFreq(-notif.getFrequencyOffset(), m_inputSampleRate);
|
|
||||||
m_interpolator.create(16, m_inputSampleRate, m_rfBandwidth / 2.0);
|
|
||||||
m_sampleDistanceRemain = m_inputSampleRate / m_outputSampleRate;
|
|
||||||
|
|
||||||
m_settingsMutex.unlock();
|
|
||||||
|
|
||||||
qDebug() << "TCPSrc::handleMessage: MsgChannelizerNotification: m_inputSampleRate: " << m_inputSampleRate
|
|
||||||
<< " frequencyOffset: " << notif.getFrequencyOffset();
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else if (MsgConfigureChannelizer::match(cmd))
|
|
||||||
{
|
|
||||||
MsgConfigureChannelizer& cfg = (MsgConfigureChannelizer&) cmd;
|
|
||||||
|
|
||||||
m_channelizer->configure(m_channelizer->getInputMessageQueue(),
|
|
||||||
cfg.getSampleRate(),
|
|
||||||
cfg.getCenterFrequency());
|
|
||||||
|
|
||||||
qDebug() << "TCPSrc::handleMessage: MsgConfigureChannelizer:"
|
|
||||||
<< " sampleRate: " << cfg.getSampleRate()
|
|
||||||
<< " centerFrequency: " << cfg.getCenterFrequency();
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else if (MsgConfigureTCPSrc::match(cmd))
|
|
||||||
{
|
|
||||||
MsgConfigureTCPSrc& cfg = (MsgConfigureTCPSrc&) cmd;
|
|
||||||
|
|
||||||
TCPSrcSettings settings = cfg.getSettings();
|
|
||||||
|
|
||||||
// These settings are set with DownChannelizer::MsgChannelizerNotification
|
|
||||||
m_absoluteFrequencyOffset = settings.m_inputFrequencyOffset;
|
|
||||||
settings.m_inputSampleRate = m_settings.m_inputSampleRate;
|
|
||||||
settings.m_inputFrequencyOffset = m_settings.m_inputFrequencyOffset;
|
|
||||||
|
|
||||||
m_settingsMutex.lock();
|
|
||||||
|
|
||||||
m_sampleFormat = settings.m_sampleFormat;
|
|
||||||
m_outputSampleRate = settings.m_outputSampleRate;
|
|
||||||
m_rfBandwidth = settings.m_rfBandwidth;
|
|
||||||
|
|
||||||
if (settings.m_tcpPort != m_tcpPort)
|
|
||||||
{
|
|
||||||
m_tcpPort = settings.m_tcpPort;
|
|
||||||
|
|
||||||
if(m_tcpServer->isListening())
|
|
||||||
{
|
|
||||||
m_tcpServer->close();
|
|
||||||
}
|
|
||||||
|
|
||||||
m_tcpServer->listen(QHostAddress::Any, m_tcpPort);
|
|
||||||
}
|
|
||||||
|
|
||||||
m_volume = settings.m_volume;
|
|
||||||
m_interpolator.create(16, m_inputSampleRate, m_rfBandwidth / 2.0);
|
|
||||||
m_sampleDistanceRemain = m_inputSampleRate / m_outputSampleRate;
|
|
||||||
|
|
||||||
if (m_sampleFormat == TCPSrcSettings::FormatSSB)
|
|
||||||
{
|
|
||||||
TCPFilter->create_filter(0.3 / 48.0, m_rfBandwidth / 2.0 / m_outputSampleRate);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
TCPFilter->create_filter(0.0, m_rfBandwidth / 2.0 / m_outputSampleRate);
|
|
||||||
}
|
|
||||||
|
|
||||||
m_settingsMutex.unlock();
|
|
||||||
|
|
||||||
qDebug() << "TCPSrc::handleMessage: MsgConfigureTCPSrc:"
|
|
||||||
<< " m_sampleFormat: " << m_sampleFormat
|
|
||||||
<< " m_outputSampleRate: " << m_outputSampleRate
|
|
||||||
<< " m_rfBandwidth: " << m_rfBandwidth
|
|
||||||
<< " m_volume: " << m_volume;
|
|
||||||
|
|
||||||
m_settings = settings;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else if (MsgTCPSrcSpectrum::match(cmd))
|
|
||||||
{
|
|
||||||
MsgTCPSrcSpectrum& spc = (MsgTCPSrcSpectrum&) cmd;
|
|
||||||
|
|
||||||
m_spectrumEnabled = spc.getEnabled();
|
|
||||||
|
|
||||||
qDebug() << "TCPSrc::handleMessage: MsgTCPSrcSpectrum: m_spectrumEnabled: " << m_spectrumEnabled;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else if (MsgTCPSrcConnection::match(cmd))
|
|
||||||
{
|
|
||||||
MsgTCPSrcConnection& con = (MsgTCPSrcConnection&) cmd;
|
|
||||||
|
|
||||||
qDebug() << "TCPSrc::handleMessage: MsgTCPSrcConnection"
|
|
||||||
<< " connect: " << con.getConnect()
|
|
||||||
<< " id: " << con.getID()
|
|
||||||
<< " peer address: " << con.getPeerAddress()
|
|
||||||
<< " peer port: " << con.getPeerPort();
|
|
||||||
|
|
||||||
if (con.getConnect())
|
|
||||||
{
|
|
||||||
processNewConnection();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
processDeconnection();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (DSPSignalNotification::match(cmd))
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if(m_spectrum != 0)
|
|
||||||
{
|
|
||||||
return m_spectrum->handleMessage(cmd);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void TCPSrc::closeAllSockets(Sockets* sockets)
|
|
||||||
{
|
|
||||||
for(int i = 0; i < sockets->count(); ++i)
|
|
||||||
{
|
|
||||||
MsgTCPSrcConnection* msg = MsgTCPSrcConnection::create(false, sockets->at(i).id, QHostAddress(), 0);
|
|
||||||
getInputMessageQueue()->push(msg);
|
|
||||||
|
|
||||||
if (getMessageQueueToGUI()) { // Propagate to GUI
|
|
||||||
getMessageQueueToGUI()->push(msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
sockets->at(i).socket->close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void TCPSrc::onNewConnection()
|
|
||||||
{
|
|
||||||
qDebug("TCPSrc::onNewConnection");
|
|
||||||
processNewConnection();
|
|
||||||
}
|
|
||||||
|
|
||||||
void TCPSrc::processNewConnection()
|
|
||||||
{
|
|
||||||
qDebug("TCPSrc::processNewConnection");
|
|
||||||
|
|
||||||
while(m_tcpServer->hasPendingConnections())
|
|
||||||
{
|
|
||||||
qDebug("TCPSrc::processNewConnection: has a pending connection");
|
|
||||||
QTcpSocket* connection = m_tcpServer->nextPendingConnection();
|
|
||||||
connection->setSocketOption(QAbstractSocket:: KeepAliveOption, 1);
|
|
||||||
connect(connection, SIGNAL(disconnected()), this, SLOT(onDisconnected()));
|
|
||||||
|
|
||||||
switch(m_sampleFormat) {
|
|
||||||
|
|
||||||
case TCPSrcSettings::FormatNFM:
|
|
||||||
case TCPSrcSettings::FormatSSB:
|
|
||||||
{
|
|
||||||
quint32 id = (TCPSrcSettings::FormatSSB << 24) | m_nextSSBId;
|
|
||||||
m_nextSSBId = (m_nextSSBId + 1) & 0xffffff;
|
|
||||||
m_ssbSockets.push_back(Socket(id, connection));
|
|
||||||
|
|
||||||
if (getMessageQueueToGUI()) // Notify GUI of peer details
|
|
||||||
{
|
|
||||||
MsgTCPSrcConnection* msg = MsgTCPSrcConnection::create(true, id, connection->peerAddress(), connection->peerPort());
|
|
||||||
getMessageQueueToGUI()->push(msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case TCPSrcSettings::FormatS16LE:
|
|
||||||
{
|
|
||||||
qDebug("TCPSrc::processNewConnection: establish new S16LE connection");
|
|
||||||
quint32 id = (TCPSrcSettings::FormatS16LE << 24) | m_nextS16leId;
|
|
||||||
m_nextS16leId = (m_nextS16leId + 1) & 0xffffff;
|
|
||||||
m_s16leSockets.push_back(Socket(id, connection));
|
|
||||||
|
|
||||||
if (getMessageQueueToGUI()) // Notify GUI of peer details
|
|
||||||
{
|
|
||||||
MsgTCPSrcConnection* msg = MsgTCPSrcConnection::create(true, id, connection->peerAddress(), connection->peerPort());
|
|
||||||
getMessageQueueToGUI()->push(msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
|
||||||
delete connection;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void TCPSrc::onDisconnected()
|
|
||||||
{
|
|
||||||
qDebug("TCPSrc::onDisconnected");
|
|
||||||
MsgTCPSrcConnection *cmd = MsgTCPSrcConnection::create(false, 0, QHostAddress::Any, 0);
|
|
||||||
getInputMessageQueue()->push(cmd);
|
|
||||||
|
|
||||||
if (getMessageQueueToGUI()) { // Propagate to GUI
|
|
||||||
getMessageQueueToGUI()->push(cmd);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void TCPSrc::processDeconnection()
|
|
||||||
{
|
|
||||||
quint32 id;
|
|
||||||
QTcpSocket* socket = 0;
|
|
||||||
|
|
||||||
qDebug("TCPSrc::processDeconnection");
|
|
||||||
|
|
||||||
for(int i = 0; i < m_ssbSockets.count(); i++)
|
|
||||||
{
|
|
||||||
if(m_ssbSockets[i].socket == sender())
|
|
||||||
{
|
|
||||||
id = m_ssbSockets[i].id;
|
|
||||||
socket = m_ssbSockets[i].socket;
|
|
||||||
socket->close();
|
|
||||||
m_ssbSockets.removeAt(i);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(socket == 0)
|
|
||||||
{
|
|
||||||
for(int i = 0; i < m_s16leSockets.count(); i++)
|
|
||||||
{
|
|
||||||
if(m_s16leSockets[i].socket == sender())
|
|
||||||
{
|
|
||||||
qDebug("TCPSrc::processDeconnection: remove S16LE socket #%d", i);
|
|
||||||
|
|
||||||
id = m_s16leSockets[i].id;
|
|
||||||
socket = m_s16leSockets[i].socket;
|
|
||||||
socket->close();
|
|
||||||
m_s16leSockets.removeAt(i);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(socket != 0)
|
|
||||||
{
|
|
||||||
MsgTCPSrcConnection* msg = MsgTCPSrcConnection::create(false, id, QHostAddress(), 0);
|
|
||||||
getInputMessageQueue()->push(msg);
|
|
||||||
|
|
||||||
if (getMessageQueueToGUI()) { // Propagate to GUI
|
|
||||||
getMessageQueueToGUI()->push(msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
socket->deleteLater();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void TCPSrc::onTcpServerError(QAbstractSocket::SocketError socketError __attribute__((unused)))
|
|
||||||
{
|
|
||||||
qDebug("TCPSrc::onTcpServerError: %s", qPrintable(m_tcpServer->errorString()));
|
|
||||||
}
|
|
||||||
|
|
||||||
QByteArray TCPSrc::serialize() const
|
|
||||||
{
|
|
||||||
return m_settings.serialize();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool TCPSrc::deserialize(const QByteArray& data)
|
|
||||||
{
|
|
||||||
if (m_settings.deserialize(data))
|
|
||||||
{
|
|
||||||
MsgConfigureTCPSrc *msg = MsgConfigureTCPSrc::create(m_settings, true);
|
|
||||||
m_inputMessageQueue.push(msg);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
m_settings.resetToDefaults();
|
|
||||||
MsgConfigureTCPSrc *msg = MsgConfigureTCPSrc::create(m_settings, true);
|
|
||||||
m_inputMessageQueue.push(msg);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,224 +0,0 @@
|
|||||||
#ifndef INCLUDE_TCPSRC_H
|
|
||||||
#define INCLUDE_TCPSRC_H
|
|
||||||
|
|
||||||
#include <QMutex>
|
|
||||||
#include <QHostAddress>
|
|
||||||
|
|
||||||
#include "dsp/basebandsamplesink.h"
|
|
||||||
#include "channel/channelsinkapi.h"
|
|
||||||
#include "dsp/nco.h"
|
|
||||||
#include "dsp/fftfilt.h"
|
|
||||||
#include "dsp/interpolator.h"
|
|
||||||
#include "util/message.h"
|
|
||||||
|
|
||||||
#include "tcpsrcsettings.h"
|
|
||||||
|
|
||||||
#define tcpFftLen 2048
|
|
||||||
|
|
||||||
class QTcpServer;
|
|
||||||
class QTcpSocket;
|
|
||||||
class TCPSrcGUI;
|
|
||||||
class DeviceSourceAPI;
|
|
||||||
class ThreadedBasebandSampleSink;
|
|
||||||
class DownChannelizer;
|
|
||||||
|
|
||||||
class TCPSrc : public BasebandSampleSink, public ChannelSinkAPI {
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
class MsgConfigureTCPSrc : public Message {
|
|
||||||
MESSAGE_CLASS_DECLARATION
|
|
||||||
|
|
||||||
public:
|
|
||||||
const TCPSrcSettings& getSettings() const { return m_settings; }
|
|
||||||
bool getForce() const { return m_force; }
|
|
||||||
|
|
||||||
static MsgConfigureTCPSrc* create(const TCPSrcSettings& settings, bool force)
|
|
||||||
{
|
|
||||||
return new MsgConfigureTCPSrc(settings, force);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
TCPSrcSettings m_settings;
|
|
||||||
bool m_force;
|
|
||||||
|
|
||||||
MsgConfigureTCPSrc(const TCPSrcSettings& settings, bool force) :
|
|
||||||
Message(),
|
|
||||||
m_settings(settings),
|
|
||||||
m_force(force)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class MsgConfigureChannelizer : public Message {
|
|
||||||
MESSAGE_CLASS_DECLARATION
|
|
||||||
|
|
||||||
public:
|
|
||||||
int getSampleRate() const { return m_sampleRate; }
|
|
||||||
int getCenterFrequency() const { return m_centerFrequency; }
|
|
||||||
|
|
||||||
static MsgConfigureChannelizer* create(int sampleRate, int centerFrequency)
|
|
||||||
{
|
|
||||||
return new MsgConfigureChannelizer(sampleRate, centerFrequency);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
int m_sampleRate;
|
|
||||||
int m_centerFrequency;
|
|
||||||
|
|
||||||
MsgConfigureChannelizer(int sampleRate, int centerFrequency) :
|
|
||||||
Message(),
|
|
||||||
m_sampleRate(sampleRate),
|
|
||||||
m_centerFrequency(centerFrequency)
|
|
||||||
{ }
|
|
||||||
};
|
|
||||||
|
|
||||||
class MsgTCPSrcConnection : public Message {
|
|
||||||
MESSAGE_CLASS_DECLARATION
|
|
||||||
|
|
||||||
public:
|
|
||||||
bool getConnect() const { return m_connect; }
|
|
||||||
quint32 getID() const { return m_id; }
|
|
||||||
const QHostAddress& getPeerAddress() const { return m_peerAddress; }
|
|
||||||
int getPeerPort() const { return m_peerPort; }
|
|
||||||
|
|
||||||
static MsgTCPSrcConnection* create(bool connect, quint32 id, const QHostAddress& peerAddress, int peerPort)
|
|
||||||
{
|
|
||||||
return new MsgTCPSrcConnection(connect, id, peerAddress, peerPort);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
bool m_connect;
|
|
||||||
quint32 m_id;
|
|
||||||
QHostAddress m_peerAddress;
|
|
||||||
int m_peerPort;
|
|
||||||
|
|
||||||
MsgTCPSrcConnection(bool connect, quint32 id, const QHostAddress& peerAddress, int peerPort) :
|
|
||||||
Message(),
|
|
||||||
m_connect(connect),
|
|
||||||
m_id(id),
|
|
||||||
m_peerAddress(peerAddress),
|
|
||||||
m_peerPort(peerPort)
|
|
||||||
{ }
|
|
||||||
};
|
|
||||||
|
|
||||||
TCPSrc(DeviceSourceAPI* m_deviceAPI);
|
|
||||||
virtual ~TCPSrc();
|
|
||||||
virtual void destroy() { delete this; }
|
|
||||||
void setSpectrum(BasebandSampleSink* spectrum) { m_spectrum = spectrum; }
|
|
||||||
|
|
||||||
void setSpectrum(MessageQueue* messageQueue, bool enabled);
|
|
||||||
double getMagSq() const { return m_magsq; }
|
|
||||||
|
|
||||||
virtual void feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end, bool positiveOnly);
|
|
||||||
virtual void start();
|
|
||||||
virtual void stop();
|
|
||||||
virtual bool handleMessage(const Message& cmd);
|
|
||||||
|
|
||||||
virtual void getIdentifier(QString& id) { id = objectName(); }
|
|
||||||
virtual void getTitle(QString& title) { title = m_settings.m_title; }
|
|
||||||
virtual qint64 getCenterFrequency() const { return m_settings.m_inputFrequencyOffset; }
|
|
||||||
|
|
||||||
virtual QByteArray serialize() const;
|
|
||||||
virtual bool deserialize(const QByteArray& data);
|
|
||||||
|
|
||||||
static const QString m_channelIdURI;
|
|
||||||
static const QString m_channelId;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
class MsgTCPSrcSpectrum : public Message {
|
|
||||||
MESSAGE_CLASS_DECLARATION
|
|
||||||
|
|
||||||
public:
|
|
||||||
bool getEnabled() const { return m_enabled; }
|
|
||||||
|
|
||||||
static MsgTCPSrcSpectrum* create(bool enabled)
|
|
||||||
{
|
|
||||||
return new MsgTCPSrcSpectrum(enabled);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
bool m_enabled;
|
|
||||||
|
|
||||||
MsgTCPSrcSpectrum(bool enabled) :
|
|
||||||
Message(),
|
|
||||||
m_enabled(enabled)
|
|
||||||
{ }
|
|
||||||
};
|
|
||||||
class MsgTCPConnection : public Message {
|
|
||||||
MESSAGE_CLASS_DECLARATION
|
|
||||||
|
|
||||||
public:
|
|
||||||
bool getConnect() const { return m_connect; }
|
|
||||||
|
|
||||||
static MsgTCPConnection* create(bool connect)
|
|
||||||
{
|
|
||||||
return new MsgTCPConnection(connect);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
bool m_connect;
|
|
||||||
|
|
||||||
MsgTCPConnection(bool connect) :
|
|
||||||
Message(),
|
|
||||||
m_connect(connect)
|
|
||||||
{ }
|
|
||||||
};
|
|
||||||
|
|
||||||
DeviceSourceAPI* m_deviceAPI;
|
|
||||||
ThreadedBasebandSampleSink* m_threadedChannelizer;
|
|
||||||
DownChannelizer* m_channelizer;
|
|
||||||
|
|
||||||
TCPSrcSettings m_settings;
|
|
||||||
int m_absoluteFrequencyOffset;
|
|
||||||
|
|
||||||
int m_inputSampleRate;
|
|
||||||
|
|
||||||
int m_sampleFormat;
|
|
||||||
Real m_outputSampleRate;
|
|
||||||
Real m_rfBandwidth;
|
|
||||||
int m_tcpPort;
|
|
||||||
int m_volume;
|
|
||||||
double m_magsq;
|
|
||||||
|
|
||||||
Real m_scale;
|
|
||||||
Complex m_last, m_this;
|
|
||||||
|
|
||||||
NCO m_nco;
|
|
||||||
Interpolator m_interpolator;
|
|
||||||
Real m_sampleDistanceRemain;
|
|
||||||
fftfilt* TCPFilter;
|
|
||||||
|
|
||||||
SampleVector m_sampleBuffer;
|
|
||||||
SampleVector m_sampleBufferSSB;
|
|
||||||
BasebandSampleSink* m_spectrum;
|
|
||||||
bool m_spectrumEnabled;
|
|
||||||
|
|
||||||
QTcpServer* m_tcpServer;
|
|
||||||
struct Socket {
|
|
||||||
quint32 id;
|
|
||||||
QTcpSocket* socket;
|
|
||||||
Socket(quint32 _id, QTcpSocket* _socket) :
|
|
||||||
id(_id),
|
|
||||||
socket(_socket)
|
|
||||||
{ }
|
|
||||||
};
|
|
||||||
typedef QList<Socket> Sockets;
|
|
||||||
Sockets m_ssbSockets;
|
|
||||||
Sockets m_s16leSockets;
|
|
||||||
quint32 m_nextSSBId;
|
|
||||||
quint32 m_nextS16leId;
|
|
||||||
|
|
||||||
QMutex m_settingsMutex;
|
|
||||||
|
|
||||||
void closeAllSockets(Sockets* sockets);
|
|
||||||
void processNewConnection();
|
|
||||||
void processDeconnection();
|
|
||||||
|
|
||||||
protected slots:
|
|
||||||
void onNewConnection();
|
|
||||||
void onDisconnected();
|
|
||||||
void onTcpServerError(QAbstractSocket::SocketError socketError);
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // INCLUDE_TCPSRC_H
|
|
@ -1,43 +0,0 @@
|
|||||||
#--------------------------------------------------------
|
|
||||||
#
|
|
||||||
# Pro file for Android and Windows builds with Qt Creator
|
|
||||||
#
|
|
||||||
#--------------------------------------------------------
|
|
||||||
|
|
||||||
TEMPLATE = lib
|
|
||||||
CONFIG += plugin
|
|
||||||
|
|
||||||
QT += core gui widgets multimedia network opengl
|
|
||||||
|
|
||||||
TARGET = tcpsrc
|
|
||||||
|
|
||||||
DEFINES += USE_SSE2=1
|
|
||||||
QMAKE_CXXFLAGS += -msse2
|
|
||||||
DEFINES += USE_SSE4_1=1
|
|
||||||
QMAKE_CXXFLAGS += -msse4.1
|
|
||||||
QMAKE_CXXFLAGS += -std=c++11
|
|
||||||
|
|
||||||
INCLUDEPATH += $$PWD
|
|
||||||
INCLUDEPATH += ../../../exports
|
|
||||||
INCLUDEPATH += ../../../sdrbase
|
|
||||||
INCLUDEPATH += ../../../sdrgui
|
|
||||||
|
|
||||||
CONFIG(Release):build_subdir = release
|
|
||||||
CONFIG(Debug):build_subdir = debug
|
|
||||||
|
|
||||||
SOURCES += tcpsrc.cpp\
|
|
||||||
tcpsrcgui.cpp\
|
|
||||||
tcpsrcplugin.cpp\
|
|
||||||
tcpsrcsettings.cpp
|
|
||||||
|
|
||||||
HEADERS += tcpsrc.h\
|
|
||||||
tcpsrcgui.h\
|
|
||||||
tcpsrcplugin.h\
|
|
||||||
tcpsrcsettings.h
|
|
||||||
|
|
||||||
FORMS += tcpsrcgui.ui
|
|
||||||
|
|
||||||
LIBS += -L../../../sdrbase/$${build_subdir} -lsdrbase
|
|
||||||
LIBS += -L../../../sdrgui/$${build_subdir} -lsdrgui
|
|
||||||
|
|
||||||
RESOURCES = ../../../sdrgui/resources/res.qrc
|
|
@ -1,397 +0,0 @@
|
|||||||
#include "tcpsrcgui.h"
|
|
||||||
|
|
||||||
#include <device/devicesourceapi.h>
|
|
||||||
#include "device/deviceuiset.h"
|
|
||||||
#include "plugin/pluginapi.h"
|
|
||||||
#include "dsp/spectrumvis.h"
|
|
||||||
#include "dsp/dspengine.h"
|
|
||||||
#include "util/simpleserializer.h"
|
|
||||||
#include "util/db.h"
|
|
||||||
#include "ui_tcpsrcgui.h"
|
|
||||||
#include "mainwindow.h"
|
|
||||||
#include "tcpsrc.h"
|
|
||||||
|
|
||||||
TCPSrcGUI* TCPSrcGUI::create(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, BasebandSampleSink *rxChannel)
|
|
||||||
{
|
|
||||||
TCPSrcGUI* gui = new TCPSrcGUI(pluginAPI, deviceUISet, rxChannel);
|
|
||||||
return gui;
|
|
||||||
}
|
|
||||||
|
|
||||||
void TCPSrcGUI::destroy()
|
|
||||||
{
|
|
||||||
delete this;
|
|
||||||
}
|
|
||||||
|
|
||||||
void TCPSrcGUI::setName(const QString& name)
|
|
||||||
{
|
|
||||||
setObjectName(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
qint64 TCPSrcGUI::getCenterFrequency() const
|
|
||||||
{
|
|
||||||
return m_channelMarker.getCenterFrequency();
|
|
||||||
}
|
|
||||||
|
|
||||||
void TCPSrcGUI::setCenterFrequency(qint64 centerFrequency)
|
|
||||||
{
|
|
||||||
m_channelMarker.setCenterFrequency(centerFrequency);
|
|
||||||
applySettings();
|
|
||||||
}
|
|
||||||
|
|
||||||
QString TCPSrcGUI::getName() const
|
|
||||||
{
|
|
||||||
return objectName();
|
|
||||||
}
|
|
||||||
|
|
||||||
void TCPSrcGUI::resetToDefaults()
|
|
||||||
{
|
|
||||||
m_settings.resetToDefaults();
|
|
||||||
displaySettings();
|
|
||||||
applySettings();
|
|
||||||
}
|
|
||||||
|
|
||||||
QByteArray TCPSrcGUI::serialize() const
|
|
||||||
{
|
|
||||||
return m_settings.serialize();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool TCPSrcGUI::deserialize(const QByteArray& data)
|
|
||||||
{
|
|
||||||
if(m_settings.deserialize(data))
|
|
||||||
{
|
|
||||||
qDebug("TCPSrcGUI::deserialize: m_squelchGate: %d", m_settings.m_squelchGate);
|
|
||||||
displaySettings();
|
|
||||||
applySettings();
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
resetToDefaults();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool TCPSrcGUI::handleMessage(const Message& message)
|
|
||||||
{
|
|
||||||
if (TCPSrc::MsgTCPSrcConnection::match(message))
|
|
||||||
{
|
|
||||||
TCPSrc::MsgTCPSrcConnection& con = (TCPSrc::MsgTCPSrcConnection&) message;
|
|
||||||
|
|
||||||
if(con.getConnect())
|
|
||||||
{
|
|
||||||
addConnection(con.getID(), con.getPeerAddress(), con.getPeerPort());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
delConnection(con.getID());
|
|
||||||
}
|
|
||||||
|
|
||||||
qDebug() << "TCPSrcGUI::handleMessage: TCPSrc::MsgTCPSrcConnection: " << con.getConnect()
|
|
||||||
<< " ID: " << con.getID()
|
|
||||||
<< " peerAddress: " << con.getPeerAddress()
|
|
||||||
<< " peerPort: " << con.getPeerPort();
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void TCPSrcGUI::channelMarkerChangedByCursor()
|
|
||||||
{
|
|
||||||
ui->deltaFrequency->setValue(m_channelMarker.getCenterFrequency());
|
|
||||||
m_settings.m_inputFrequencyOffset = m_channelMarker.getCenterFrequency();
|
|
||||||
applySettings();
|
|
||||||
}
|
|
||||||
|
|
||||||
void TCPSrcGUI::channelMarkerHighlightedByCursor()
|
|
||||||
{
|
|
||||||
setHighlighted(m_channelMarker.getHighlighted());
|
|
||||||
}
|
|
||||||
|
|
||||||
void TCPSrcGUI::tick()
|
|
||||||
{
|
|
||||||
double powDb = CalcDb::dbPower(m_tcpSrc->getMagSq());
|
|
||||||
m_channelPowerDbAvg(powDb);
|
|
||||||
ui->channelPower->setText(QString::number(m_channelPowerDbAvg.asDouble(), 'f', 1));
|
|
||||||
}
|
|
||||||
|
|
||||||
TCPSrcGUI::TCPSrcGUI(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, BasebandSampleSink *rxChannel, QWidget* parent) :
|
|
||||||
RollupWidget(parent),
|
|
||||||
ui(new Ui::TCPSrcGUI),
|
|
||||||
m_pluginAPI(pluginAPI),
|
|
||||||
m_deviceUISet(deviceUISet),
|
|
||||||
m_tcpSrc(0),
|
|
||||||
m_channelMarker(this),
|
|
||||||
m_rfBandwidthChanged(false),
|
|
||||||
m_doApplySettings(true)
|
|
||||||
{
|
|
||||||
ui->setupUi(this);
|
|
||||||
ui->connectedClientsBox->hide();
|
|
||||||
connect(this, SIGNAL(widgetRolled(QWidget*,bool)), this, SLOT(onWidgetRolled(QWidget*,bool)));
|
|
||||||
setAttribute(Qt::WA_DeleteOnClose, true);
|
|
||||||
|
|
||||||
m_spectrumVis = new SpectrumVis(SDR_RX_SCALEF, ui->glSpectrum);
|
|
||||||
m_tcpSrc = (TCPSrc*) rxChannel; //new TCPSrc(m_deviceUISet->m_deviceSourceAPI);
|
|
||||||
m_tcpSrc->setSpectrum(m_spectrumVis);
|
|
||||||
|
|
||||||
ui->deltaFrequencyLabel->setText(QString("%1f").arg(QChar(0x94, 0x03)));
|
|
||||||
ui->deltaFrequency->setColorMapper(ColorMapper(ColorMapper::GrayGold));
|
|
||||||
ui->deltaFrequency->setValueRange(false, 7, -9999999, 9999999);
|
|
||||||
|
|
||||||
ui->glSpectrum->setCenterFrequency(0);
|
|
||||||
ui->glSpectrum->setSampleRate(ui->sampleRate->text().toInt());
|
|
||||||
ui->glSpectrum->setDisplayWaterfall(true);
|
|
||||||
ui->glSpectrum->setDisplayMaxHold(true);
|
|
||||||
m_spectrumVis->configure(m_spectrumVis->getInputMessageQueue(), 64, 10, FFTWindow::BlackmanHarris);
|
|
||||||
|
|
||||||
ui->glSpectrum->connectTimer(MainWindow::getInstance()->getMasterTimer());
|
|
||||||
connect(&MainWindow::getInstance()->getMasterTimer(), SIGNAL(timeout()), this, SLOT(tick()));
|
|
||||||
|
|
||||||
m_channelMarker.blockSignals(true);
|
|
||||||
m_channelMarker.setBandwidth(16000);
|
|
||||||
m_channelMarker.setCenterFrequency(0);
|
|
||||||
m_channelMarker.setColor(m_settings.m_rgbColor);
|
|
||||||
m_channelMarker.blockSignals(false);
|
|
||||||
m_channelMarker.setVisible(true); // activate signal on the last setting only
|
|
||||||
|
|
||||||
setTitleColor(m_channelMarker.getColor());
|
|
||||||
|
|
||||||
m_deviceUISet->registerRxChannelInstance(TCPSrc::m_channelIdURI, this);
|
|
||||||
m_deviceUISet->addChannelMarker(&m_channelMarker);
|
|
||||||
m_deviceUISet->addRollupWidget(this);
|
|
||||||
|
|
||||||
connect(&m_channelMarker, SIGNAL(changedByCursor()), this, SLOT(channelMarkerChangedByCursor()));
|
|
||||||
connect(&m_channelMarker, SIGNAL(highlightedByCursor()), this, SLOT(channelMarkerHighlightedByCursor()));
|
|
||||||
|
|
||||||
ui->spectrumGUI->setBuddies(m_spectrumVis->getInputMessageQueue(), m_spectrumVis, ui->glSpectrum);
|
|
||||||
|
|
||||||
m_settings.setSpectrumGUI(ui->spectrumGUI);
|
|
||||||
m_settings.setChannelMarker(&m_channelMarker);
|
|
||||||
|
|
||||||
displaySettings();
|
|
||||||
applySettings();
|
|
||||||
}
|
|
||||||
|
|
||||||
TCPSrcGUI::~TCPSrcGUI()
|
|
||||||
{
|
|
||||||
m_deviceUISet->removeRxChannelInstance(this);
|
|
||||||
delete m_tcpSrc; // TODO: check this: when the GUI closes it has to delete the demodulator
|
|
||||||
delete m_spectrumVis;
|
|
||||||
delete ui;
|
|
||||||
}
|
|
||||||
|
|
||||||
void TCPSrcGUI::blockApplySettings(bool block)
|
|
||||||
{
|
|
||||||
m_doApplySettings = !block;
|
|
||||||
}
|
|
||||||
|
|
||||||
void TCPSrcGUI::applySettings()
|
|
||||||
{
|
|
||||||
if (m_doApplySettings)
|
|
||||||
{
|
|
||||||
ui->glSpectrum->setSampleRate(m_settings.m_outputSampleRate);
|
|
||||||
|
|
||||||
TCPSrc::MsgConfigureChannelizer* channelConfigMsg = TCPSrc::MsgConfigureChannelizer::create(
|
|
||||||
m_settings.m_outputSampleRate, m_channelMarker.getCenterFrequency());
|
|
||||||
m_tcpSrc->getInputMessageQueue()->push(channelConfigMsg);
|
|
||||||
|
|
||||||
TCPSrc::MsgConfigureTCPSrc* message = TCPSrc::MsgConfigureTCPSrc::create( m_settings, false);
|
|
||||||
m_tcpSrc->getInputMessageQueue()->push(message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void TCPSrcGUI::on_deltaFrequency_changed(qint64 value)
|
|
||||||
{
|
|
||||||
m_channelMarker.setCenterFrequency(value);
|
|
||||||
m_settings.m_inputFrequencyOffset = m_channelMarker.getCenterFrequency();
|
|
||||||
applySettings();
|
|
||||||
}
|
|
||||||
|
|
||||||
void TCPSrcGUI::on_sampleFormat_currentIndexChanged(int index)
|
|
||||||
{
|
|
||||||
setSampleFormat(index);
|
|
||||||
|
|
||||||
ui->applyBtn->setEnabled(true);
|
|
||||||
ui->applyBtn->setStyleSheet("QPushButton { background-color : green; }");
|
|
||||||
}
|
|
||||||
|
|
||||||
void TCPSrcGUI::on_sampleRate_textEdited(const QString& arg1 __attribute__((unused)))
|
|
||||||
{
|
|
||||||
bool ok;
|
|
||||||
Real outputSampleRate = ui->sampleRate->text().toDouble(&ok);
|
|
||||||
|
|
||||||
if((!ok) || (outputSampleRate < 1000))
|
|
||||||
{
|
|
||||||
m_settings.m_outputSampleRate = 48000;
|
|
||||||
ui->sampleRate->setText(QString("%1").arg(outputSampleRate, 0));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
m_settings.m_outputSampleRate = outputSampleRate;
|
|
||||||
}
|
|
||||||
|
|
||||||
ui->applyBtn->setEnabled(true);
|
|
||||||
ui->applyBtn->setStyleSheet("QPushButton { background-color : green; }");
|
|
||||||
}
|
|
||||||
|
|
||||||
void TCPSrcGUI::on_rfBandwidth_textEdited(const QString& arg1 __attribute__((unused)))
|
|
||||||
{
|
|
||||||
bool ok;
|
|
||||||
Real rfBandwidth = ui->rfBandwidth->text().toDouble(&ok);
|
|
||||||
|
|
||||||
if((!ok) || (rfBandwidth > m_settings.m_outputSampleRate))
|
|
||||||
{
|
|
||||||
m_settings.m_rfBandwidth = m_settings.m_outputSampleRate;
|
|
||||||
ui->rfBandwidth->setText(QString("%1").arg(m_settings.m_rfBandwidth, 0));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
m_settings.m_rfBandwidth = rfBandwidth;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_rfBandwidthChanged = true;
|
|
||||||
|
|
||||||
ui->applyBtn->setEnabled(true);
|
|
||||||
ui->applyBtn->setStyleSheet("QPushButton { background-color : green; }");
|
|
||||||
}
|
|
||||||
|
|
||||||
void TCPSrcGUI::on_tcpPort_textEdited(const QString& arg1 __attribute__((unused)))
|
|
||||||
{
|
|
||||||
bool ok;
|
|
||||||
int tcpPort = ui->tcpPort->text().toInt(&ok);
|
|
||||||
|
|
||||||
if((!ok) || (tcpPort < 1) || (tcpPort > 65535))
|
|
||||||
{
|
|
||||||
m_settings.m_tcpPort = 9999;
|
|
||||||
ui->tcpPort->setText(QString("%1").arg(m_settings.m_tcpPort, 0));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
m_settings.m_tcpPort = tcpPort;
|
|
||||||
}
|
|
||||||
|
|
||||||
ui->applyBtn->setEnabled(true);
|
|
||||||
ui->applyBtn->setStyleSheet("QPushButton { background-color : green; }");
|
|
||||||
}
|
|
||||||
|
|
||||||
void TCPSrcGUI::on_applyBtn_clicked()
|
|
||||||
{
|
|
||||||
if (m_rfBandwidthChanged)
|
|
||||||
{
|
|
||||||
blockApplySettings(true);
|
|
||||||
m_channelMarker.setBandwidth((int) m_settings.m_rfBandwidth);
|
|
||||||
m_rfBandwidthChanged = false;
|
|
||||||
blockApplySettings(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
ui->glSpectrum->setSampleRate(m_settings.m_outputSampleRate);
|
|
||||||
|
|
||||||
ui->applyBtn->setEnabled(false);
|
|
||||||
ui->applyBtn->setStyleSheet("QPushButton { background:rgb(79,79,79); }");
|
|
||||||
|
|
||||||
applySettings();
|
|
||||||
}
|
|
||||||
|
|
||||||
void TCPSrcGUI::displaySettings()
|
|
||||||
{
|
|
||||||
m_channelMarker.blockSignals(true);
|
|
||||||
m_channelMarker.setCenterFrequency(m_settings.m_inputFrequencyOffset);
|
|
||||||
m_channelMarker.setBandwidth(m_settings.m_rfBandwidth);
|
|
||||||
m_channelMarker.setTitle(m_settings.m_title);
|
|
||||||
m_channelMarker.blockSignals(false);
|
|
||||||
m_channelMarker.setColor(m_settings.m_rgbColor); // activate signal on the last setting only
|
|
||||||
|
|
||||||
setTitleColor(m_settings.m_rgbColor);
|
|
||||||
setWindowTitle(m_channelMarker.getTitle());
|
|
||||||
|
|
||||||
blockApplySettings(true);
|
|
||||||
|
|
||||||
ui->deltaFrequency->setValue(m_channelMarker.getCenterFrequency());
|
|
||||||
|
|
||||||
ui->sampleRate->setText(QString("%1").arg(m_settings.m_outputSampleRate, 0));
|
|
||||||
setSampleFormatIndex(m_settings.m_sampleFormat);
|
|
||||||
|
|
||||||
ui->rfBandwidth->setText(QString("%1").arg(m_settings.m_rfBandwidth, 0));
|
|
||||||
|
|
||||||
ui->volume->setValue(m_settings.m_volume);
|
|
||||||
ui->volumeText->setText(QString("%1").arg(ui->volume->value()));
|
|
||||||
|
|
||||||
ui->glSpectrum->setSampleRate(m_settings.m_outputSampleRate);
|
|
||||||
|
|
||||||
blockApplySettings(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
void TCPSrcGUI::setSampleFormatIndex(const TCPSrcSettings::SampleFormat& sampleFormat)
|
|
||||||
{
|
|
||||||
switch(sampleFormat)
|
|
||||||
{
|
|
||||||
case TCPSrcSettings::FormatS16LE:
|
|
||||||
ui->sampleFormat->setCurrentIndex(0);
|
|
||||||
break;
|
|
||||||
case TCPSrcSettings::FormatNFM:
|
|
||||||
ui->sampleFormat->setCurrentIndex(1);
|
|
||||||
break;
|
|
||||||
case TCPSrcSettings::FormatSSB:
|
|
||||||
ui->sampleFormat->setCurrentIndex(2);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
ui->sampleFormat->setCurrentIndex(0);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void TCPSrcGUI::setSampleFormat(int index)
|
|
||||||
{
|
|
||||||
switch(index)
|
|
||||||
{
|
|
||||||
case 0:
|
|
||||||
m_settings.m_sampleFormat = TCPSrcSettings::FormatS16LE;
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
m_settings.m_sampleFormat = TCPSrcSettings::FormatNFM;
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
m_settings.m_sampleFormat = TCPSrcSettings::FormatSSB;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
m_settings.m_sampleFormat = TCPSrcSettings::FormatS16LE;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void TCPSrcGUI::on_volume_valueChanged(int value)
|
|
||||||
{
|
|
||||||
ui->volume->setValue(value);
|
|
||||||
ui->volumeText->setText(QString("%1").arg(value));
|
|
||||||
ui->applyBtn->setEnabled(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
void TCPSrcGUI::onWidgetRolled(QWidget* widget, bool rollDown)
|
|
||||||
{
|
|
||||||
if ((widget == ui->spectrumBox) && (m_tcpSrc != 0))
|
|
||||||
{
|
|
||||||
m_tcpSrc->setSpectrum(m_tcpSrc->getInputMessageQueue(), rollDown);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void TCPSrcGUI::addConnection(quint32 id, const QHostAddress& peerAddress, int peerPort)
|
|
||||||
{
|
|
||||||
QStringList l;
|
|
||||||
l.append(QString("%1:%2").arg(peerAddress.toString()).arg(peerPort));
|
|
||||||
new QTreeWidgetItem(ui->connections, l, id);
|
|
||||||
ui->connectedClientsBox->setWindowTitle(tr("Connected Clients (%1)").arg(ui->connections->topLevelItemCount()));
|
|
||||||
}
|
|
||||||
|
|
||||||
void TCPSrcGUI::delConnection(quint32 id)
|
|
||||||
{
|
|
||||||
for(int i = 0; i < ui->connections->topLevelItemCount(); i++)
|
|
||||||
{
|
|
||||||
if(ui->connections->topLevelItem(i)->type() == (int)id)
|
|
||||||
{
|
|
||||||
delete ui->connections->topLevelItem(i);
|
|
||||||
ui->connectedClientsBox->setWindowTitle(tr("Connected Clients (%1)").arg(ui->connections->topLevelItemCount()));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,92 +0,0 @@
|
|||||||
#ifndef INCLUDE_TCPSRCGUI_H
|
|
||||||
#define INCLUDE_TCPSRCGUI_H
|
|
||||||
|
|
||||||
#include <plugin/plugininstancegui.h>
|
|
||||||
#include <QHostAddress>
|
|
||||||
|
|
||||||
#include "gui/rollupwidget.h"
|
|
||||||
#include "dsp/channelmarker.h"
|
|
||||||
#include "util/movingaverage.h"
|
|
||||||
#include "util/messagequeue.h"
|
|
||||||
|
|
||||||
#include "tcpsrc.h"
|
|
||||||
#include "tcpsrcsettings.h"
|
|
||||||
|
|
||||||
class PluginAPI;
|
|
||||||
class DeviceUISet;
|
|
||||||
class TCPSrc;
|
|
||||||
class SpectrumVis;
|
|
||||||
|
|
||||||
namespace Ui {
|
|
||||||
class TCPSrcGUI;
|
|
||||||
}
|
|
||||||
|
|
||||||
class TCPSrcGUI : public RollupWidget, public PluginInstanceGUI {
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
static TCPSrcGUI* create(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, BasebandSampleSink *rxChannel);
|
|
||||||
virtual void destroy();
|
|
||||||
|
|
||||||
void setName(const QString& name);
|
|
||||||
QString getName() const;
|
|
||||||
virtual qint64 getCenterFrequency() const;
|
|
||||||
virtual void setCenterFrequency(qint64 centerFrequency);
|
|
||||||
|
|
||||||
void resetToDefaults();
|
|
||||||
QByteArray serialize() const;
|
|
||||||
bool deserialize(const QByteArray& data);
|
|
||||||
virtual MessageQueue *getInputMessageQueue() { return &m_inputMessageQueue; }
|
|
||||||
virtual bool handleMessage(const Message& message);
|
|
||||||
|
|
||||||
public slots:
|
|
||||||
void channelMarkerChangedByCursor();
|
|
||||||
void channelMarkerHighlightedByCursor();
|
|
||||||
|
|
||||||
private:
|
|
||||||
Ui::TCPSrcGUI* ui;
|
|
||||||
PluginAPI* m_pluginAPI;
|
|
||||||
DeviceUISet* m_deviceUISet;
|
|
||||||
TCPSrc* m_tcpSrc;
|
|
||||||
ChannelMarker m_channelMarker;
|
|
||||||
MovingAverageUtil<Real, double, 40> m_channelPowerDbAvg;
|
|
||||||
|
|
||||||
// settings
|
|
||||||
TCPSrcSettings m_settings;
|
|
||||||
TCPSrcSettings::SampleFormat m_sampleFormat;
|
|
||||||
Real m_outputSampleRate;
|
|
||||||
Real m_rfBandwidth;
|
|
||||||
int m_boost;
|
|
||||||
int m_tcpPort;
|
|
||||||
bool m_rfBandwidthChanged;
|
|
||||||
bool m_doApplySettings;
|
|
||||||
|
|
||||||
// RF path
|
|
||||||
SpectrumVis* m_spectrumVis;
|
|
||||||
MessageQueue m_inputMessageQueue;
|
|
||||||
|
|
||||||
explicit TCPSrcGUI(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, BasebandSampleSink *rxChannel, QWidget* parent = 0);
|
|
||||||
virtual ~TCPSrcGUI();
|
|
||||||
|
|
||||||
void blockApplySettings(bool block);
|
|
||||||
void applySettings();
|
|
||||||
void displaySettings();
|
|
||||||
void setSampleFormat(int index);
|
|
||||||
void setSampleFormatIndex(const TCPSrcSettings::SampleFormat& sampleFormat);
|
|
||||||
|
|
||||||
void addConnection(quint32 id, const QHostAddress& peerAddress, int peerPort);
|
|
||||||
void delConnection(quint32 id);
|
|
||||||
|
|
||||||
private slots:
|
|
||||||
void on_deltaFrequency_changed(qint64 value);
|
|
||||||
void on_sampleFormat_currentIndexChanged(int index);
|
|
||||||
void on_sampleRate_textEdited(const QString& arg1);
|
|
||||||
void on_rfBandwidth_textEdited(const QString& arg1);
|
|
||||||
void on_tcpPort_textEdited(const QString& arg1);
|
|
||||||
void on_applyBtn_clicked();
|
|
||||||
void onWidgetRolled(QWidget* widget, bool rollDown);
|
|
||||||
void on_volume_valueChanged(int value);
|
|
||||||
void tick();
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // INCLUDE_TCPSRCGUI_H
|
|
@ -1,480 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<ui version="4.0">
|
|
||||||
<class>TCPSrcGUI</class>
|
|
||||||
<widget class="RollupWidget" name="TCPSrcGUI">
|
|
||||||
<property name="geometry">
|
|
||||||
<rect>
|
|
||||||
<x>0</x>
|
|
||||||
<y>0</y>
|
|
||||||
<width>400</width>
|
|
||||||
<height>443</height>
|
|
||||||
</rect>
|
|
||||||
</property>
|
|
||||||
<property name="font">
|
|
||||||
<font>
|
|
||||||
<family>Liberation Sans</family>
|
|
||||||
<pointsize>9</pointsize>
|
|
||||||
</font>
|
|
||||||
</property>
|
|
||||||
<property name="windowTitle">
|
|
||||||
<string>TCP Sample Source</string>
|
|
||||||
</property>
|
|
||||||
<widget class="QWidget" name="widget" native="true">
|
|
||||||
<property name="geometry">
|
|
||||||
<rect>
|
|
||||||
<x>10</x>
|
|
||||||
<y>5</y>
|
|
||||||
<width>201</width>
|
|
||||||
<height>142</height>
|
|
||||||
</rect>
|
|
||||||
</property>
|
|
||||||
<property name="windowTitle">
|
|
||||||
<string>Settings</string>
|
|
||||||
</property>
|
|
||||||
<layout class="QGridLayout" name="gridLayout">
|
|
||||||
<property name="leftMargin">
|
|
||||||
<number>2</number>
|
|
||||||
</property>
|
|
||||||
<property name="topMargin">
|
|
||||||
<number>2</number>
|
|
||||||
</property>
|
|
||||||
<property name="rightMargin">
|
|
||||||
<number>2</number>
|
|
||||||
</property>
|
|
||||||
<property name="bottomMargin">
|
|
||||||
<number>2</number>
|
|
||||||
</property>
|
|
||||||
<property name="spacing">
|
|
||||||
<number>3</number>
|
|
||||||
</property>
|
|
||||||
<item row="1" column="0">
|
|
||||||
<widget class="QLabel" name="label">
|
|
||||||
<property name="text">
|
|
||||||
<string>Sample Format</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="2" column="0">
|
|
||||||
<widget class="QComboBox" name="sampleFormat">
|
|
||||||
<property name="toolTip">
|
|
||||||
<string>Sample format</string>
|
|
||||||
</property>
|
|
||||||
<property name="currentIndex">
|
|
||||||
<number>0</number>
|
|
||||||
</property>
|
|
||||||
<item>
|
|
||||||
<property name="text">
|
|
||||||
<string>S16LE I/Q</string>
|
|
||||||
</property>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<property name="text">
|
|
||||||
<string>S16LE NFM</string>
|
|
||||||
</property>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<property name="text">
|
|
||||||
<string>S16LE SSB</string>
|
|
||||||
</property>
|
|
||||||
</item>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="4" column="1">
|
|
||||||
<widget class="QLineEdit" name="rfBandwidth">
|
|
||||||
<property name="toolTip">
|
|
||||||
<string>Channel bandwidth</string>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>32000</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="3" column="1">
|
|
||||||
<widget class="QLabel" name="label_3">
|
|
||||||
<property name="text">
|
|
||||||
<string>RF Bandwidth (Hz)</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="1">
|
|
||||||
<widget class="QLabel" name="label_2">
|
|
||||||
<property name="text">
|
|
||||||
<string>Samplerate (Hz)</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="3" column="0">
|
|
||||||
<widget class="QLabel" name="label_4">
|
|
||||||
<property name="text">
|
|
||||||
<string>TCP Port</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="2" column="1">
|
|
||||||
<widget class="QLineEdit" name="sampleRate">
|
|
||||||
<property name="toolTip">
|
|
||||||
<string>Data stream sample rate</string>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>48000</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="4" column="0">
|
|
||||||
<widget class="QLineEdit" name="tcpPort">
|
|
||||||
<property name="toolTip">
|
|
||||||
<string>TCP port number</string>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>9999</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="5" column="0">
|
|
||||||
<widget class="QPushButton" name="applyBtn">
|
|
||||||
<property name="enabled">
|
|
||||||
<bool>false</bool>
|
|
||||||
</property>
|
|
||||||
<property name="toolTip">
|
|
||||||
<string>Apply changes</string>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>Apply</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="0" column="0">
|
|
||||||
<layout class="QHBoxLayout" name="DeltaFrequencyLayout">
|
|
||||||
<property name="topMargin">
|
|
||||||
<number>2</number>
|
|
||||||
</property>
|
|
||||||
<item>
|
|
||||||
<widget class="QLabel" name="deltaFrequencyLabel">
|
|
||||||
<property name="maximumSize">
|
|
||||||
<size>
|
|
||||||
<width>16</width>
|
|
||||||
<height>16777215</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>Df</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="ValueDialZ" name="deltaFrequency" native="true">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Maximum" vsizetype="Maximum">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="minimumSize">
|
|
||||||
<size>
|
|
||||||
<width>32</width>
|
|
||||||
<height>16</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="font">
|
|
||||||
<font>
|
|
||||||
<family>Liberation Mono</family>
|
|
||||||
<pointsize>12</pointsize>
|
|
||||||
</font>
|
|
||||||
</property>
|
|
||||||
<property name="cursor">
|
|
||||||
<cursorShape>PointingHandCursor</cursorShape>
|
|
||||||
</property>
|
|
||||||
<property name="focusPolicy">
|
|
||||||
<enum>Qt::StrongFocus</enum>
|
|
||||||
</property>
|
|
||||||
<property name="toolTip">
|
|
||||||
<string>Demod shift frequency from center in Hz</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QLabel" name="deltaUnits">
|
|
||||||
<property name="palette">
|
|
||||||
<palette>
|
|
||||||
<active>
|
|
||||||
<colorrole role="Text">
|
|
||||||
<brush brushstyle="SolidPattern">
|
|
||||||
<color alpha="255">
|
|
||||||
<red>26</red>
|
|
||||||
<green>26</green>
|
|
||||||
<blue>26</blue>
|
|
||||||
</color>
|
|
||||||
</brush>
|
|
||||||
</colorrole>
|
|
||||||
<colorrole role="BrightText">
|
|
||||||
<brush brushstyle="SolidPattern">
|
|
||||||
<color alpha="255">
|
|
||||||
<red>255</red>
|
|
||||||
<green>255</green>
|
|
||||||
<blue>255</blue>
|
|
||||||
</color>
|
|
||||||
</brush>
|
|
||||||
</colorrole>
|
|
||||||
</active>
|
|
||||||
<inactive>
|
|
||||||
<colorrole role="Text">
|
|
||||||
<brush brushstyle="SolidPattern">
|
|
||||||
<color alpha="255">
|
|
||||||
<red>26</red>
|
|
||||||
<green>26</green>
|
|
||||||
<blue>26</blue>
|
|
||||||
</color>
|
|
||||||
</brush>
|
|
||||||
</colorrole>
|
|
||||||
<colorrole role="BrightText">
|
|
||||||
<brush brushstyle="SolidPattern">
|
|
||||||
<color alpha="255">
|
|
||||||
<red>255</red>
|
|
||||||
<green>255</green>
|
|
||||||
<blue>255</blue>
|
|
||||||
</color>
|
|
||||||
</brush>
|
|
||||||
</colorrole>
|
|
||||||
</inactive>
|
|
||||||
<disabled>
|
|
||||||
<colorrole role="Text">
|
|
||||||
<brush brushstyle="SolidPattern">
|
|
||||||
<color alpha="255">
|
|
||||||
<red>118</red>
|
|
||||||
<green>118</green>
|
|
||||||
<blue>117</blue>
|
|
||||||
</color>
|
|
||||||
</brush>
|
|
||||||
</colorrole>
|
|
||||||
<colorrole role="BrightText">
|
|
||||||
<brush brushstyle="SolidPattern">
|
|
||||||
<color alpha="255">
|
|
||||||
<red>255</red>
|
|
||||||
<green>255</green>
|
|
||||||
<blue>255</blue>
|
|
||||||
</color>
|
|
||||||
</brush>
|
|
||||||
</colorrole>
|
|
||||||
</disabled>
|
|
||||||
</palette>
|
|
||||||
</property>
|
|
||||||
<property name="font">
|
|
||||||
<font>
|
|
||||||
<pointsize>8</pointsize>
|
|
||||||
</font>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string> Hz</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</item>
|
|
||||||
<item row="0" column="1">
|
|
||||||
<layout class="QHBoxLayout" name="ChannelPowerLayout">
|
|
||||||
<item>
|
|
||||||
<spacer name="horizontalSpacer">
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Horizontal</enum>
|
|
||||||
</property>
|
|
||||||
<property name="sizeHint" stdset="0">
|
|
||||||
<size>
|
|
||||||
<width>40</width>
|
|
||||||
<height>20</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
</spacer>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QLabel" name="channelPower">
|
|
||||||
<property name="toolTip">
|
|
||||||
<string>Channel power</string>
|
|
||||||
</property>
|
|
||||||
<property name="layoutDirection">
|
|
||||||
<enum>Qt::LeftToRight</enum>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>0.0</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QLabel" name="channelPowerUnits">
|
|
||||||
<property name="text">
|
|
||||||
<string> dB</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</item>
|
|
||||||
<item row="5" column="1">
|
|
||||||
<layout class="QHBoxLayout" name="BoostLayout">
|
|
||||||
<item>
|
|
||||||
<widget class="QLabel" name="volumeLabel">
|
|
||||||
<property name="text">
|
|
||||||
<string>Vol</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QSlider" name="volume">
|
|
||||||
<property name="toolTip">
|
|
||||||
<string>Amplitude boost</string>
|
|
||||||
</property>
|
|
||||||
<property name="maximum">
|
|
||||||
<number>3</number>
|
|
||||||
</property>
|
|
||||||
<property name="pageStep">
|
|
||||||
<number>1</number>
|
|
||||||
</property>
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Horizontal</enum>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QLabel" name="volumeText">
|
|
||||||
<property name="text">
|
|
||||||
<string>0</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
<widget class="QWidget" name="spectrumBox" native="true">
|
|
||||||
<property name="geometry">
|
|
||||||
<rect>
|
|
||||||
<x>15</x>
|
|
||||||
<y>160</y>
|
|
||||||
<width>231</width>
|
|
||||||
<height>156</height>
|
|
||||||
</rect>
|
|
||||||
</property>
|
|
||||||
<property name="windowTitle">
|
|
||||||
<string>Channel Spectrum</string>
|
|
||||||
</property>
|
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
|
||||||
<property name="spacing">
|
|
||||||
<number>3</number>
|
|
||||||
</property>
|
|
||||||
<property name="leftMargin">
|
|
||||||
<number>2</number>
|
|
||||||
</property>
|
|
||||||
<property name="topMargin">
|
|
||||||
<number>2</number>
|
|
||||||
</property>
|
|
||||||
<property name="rightMargin">
|
|
||||||
<number>2</number>
|
|
||||||
</property>
|
|
||||||
<property name="bottomMargin">
|
|
||||||
<number>2</number>
|
|
||||||
</property>
|
|
||||||
<item>
|
|
||||||
<widget class="GLSpectrum" name="glSpectrum" native="true">
|
|
||||||
<property name="font">
|
|
||||||
<font>
|
|
||||||
<family>Liberation Mono</family>
|
|
||||||
<pointsize>9</pointsize>
|
|
||||||
</font>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="GLSpectrumGUI" name="spectrumGUI" native="true"/>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
<widget class="QWidget" name="connectedClientsBox" native="true">
|
|
||||||
<property name="geometry">
|
|
||||||
<rect>
|
|
||||||
<x>15</x>
|
|
||||||
<y>330</y>
|
|
||||||
<width>274</width>
|
|
||||||
<height>101</height>
|
|
||||||
</rect>
|
|
||||||
</property>
|
|
||||||
<property name="windowTitle">
|
|
||||||
<string>Connected Clients (0)</string>
|
|
||||||
</property>
|
|
||||||
<layout class="QVBoxLayout" name="verticalLayout">
|
|
||||||
<property name="spacing">
|
|
||||||
<number>3</number>
|
|
||||||
</property>
|
|
||||||
<property name="leftMargin">
|
|
||||||
<number>2</number>
|
|
||||||
</property>
|
|
||||||
<property name="topMargin">
|
|
||||||
<number>2</number>
|
|
||||||
</property>
|
|
||||||
<property name="rightMargin">
|
|
||||||
<number>2</number>
|
|
||||||
</property>
|
|
||||||
<property name="bottomMargin">
|
|
||||||
<number>2</number>
|
|
||||||
</property>
|
|
||||||
<item>
|
|
||||||
<widget class="QTreeWidget" name="connections">
|
|
||||||
<property name="maximumSize">
|
|
||||||
<size>
|
|
||||||
<width>400</width>
|
|
||||||
<height>100</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="rootIsDecorated">
|
|
||||||
<bool>false</bool>
|
|
||||||
</property>
|
|
||||||
<property name="itemsExpandable">
|
|
||||||
<bool>false</bool>
|
|
||||||
</property>
|
|
||||||
<attribute name="headerVisible">
|
|
||||||
<bool>false</bool>
|
|
||||||
</attribute>
|
|
||||||
<column>
|
|
||||||
<property name="text">
|
|
||||||
<string>IP:Port</string>
|
|
||||||
</property>
|
|
||||||
</column>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
</widget>
|
|
||||||
<customwidgets>
|
|
||||||
<customwidget>
|
|
||||||
<class>RollupWidget</class>
|
|
||||||
<extends>QWidget</extends>
|
|
||||||
<header>gui/rollupwidget.h</header>
|
|
||||||
<container>1</container>
|
|
||||||
</customwidget>
|
|
||||||
<customwidget>
|
|
||||||
<class>GLSpectrum</class>
|
|
||||||
<extends>QWidget</extends>
|
|
||||||
<header>gui/glspectrum.h</header>
|
|
||||||
<container>1</container>
|
|
||||||
</customwidget>
|
|
||||||
<customwidget>
|
|
||||||
<class>GLSpectrumGUI</class>
|
|
||||||
<extends>QWidget</extends>
|
|
||||||
<header>gui/glspectrumgui.h</header>
|
|
||||||
<container>1</container>
|
|
||||||
</customwidget>
|
|
||||||
<customwidget>
|
|
||||||
<class>ValueDialZ</class>
|
|
||||||
<extends>QWidget</extends>
|
|
||||||
<header>gui/valuedialz.h</header>
|
|
||||||
<container>1</container>
|
|
||||||
</customwidget>
|
|
||||||
</customwidgets>
|
|
||||||
<tabstops>
|
|
||||||
<tabstop>sampleFormat</tabstop>
|
|
||||||
<tabstop>tcpPort</tabstop>
|
|
||||||
<tabstop>sampleRate</tabstop>
|
|
||||||
<tabstop>rfBandwidth</tabstop>
|
|
||||||
<tabstop>applyBtn</tabstop>
|
|
||||||
<tabstop>connections</tabstop>
|
|
||||||
</tabstops>
|
|
||||||
<resources/>
|
|
||||||
<connections/>
|
|
||||||
</ui>
|
|
@ -1,51 +0,0 @@
|
|||||||
#include "tcpsrcplugin.h"
|
|
||||||
|
|
||||||
#include <QtPlugin>
|
|
||||||
#include "plugin/pluginapi.h"
|
|
||||||
|
|
||||||
#include "tcpsrcgui.h"
|
|
||||||
#include "tcpsrc.h"
|
|
||||||
|
|
||||||
const PluginDescriptor TCPSrcPlugin::m_pluginDescriptor = {
|
|
||||||
QString("TCP Channel Source"),
|
|
||||||
QString("3.14.5"),
|
|
||||||
QString("(c) Edouard Griffiths, F4EXB"),
|
|
||||||
QString("https://github.com/f4exb/sdrangel"),
|
|
||||||
true,
|
|
||||||
QString("https://github.com/f4exb/sdrangel")
|
|
||||||
};
|
|
||||||
|
|
||||||
TCPSrcPlugin::TCPSrcPlugin(QObject* parent) :
|
|
||||||
QObject(parent),
|
|
||||||
m_pluginAPI(0)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
const PluginDescriptor& TCPSrcPlugin::getPluginDescriptor() const
|
|
||||||
{
|
|
||||||
return m_pluginDescriptor;
|
|
||||||
}
|
|
||||||
|
|
||||||
void TCPSrcPlugin::initPlugin(PluginAPI* pluginAPI)
|
|
||||||
{
|
|
||||||
m_pluginAPI = pluginAPI;
|
|
||||||
|
|
||||||
// register TCP Channel Source
|
|
||||||
m_pluginAPI->registerRxChannel(TCPSrc::m_channelIdURI, TCPSrc::m_channelId, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
PluginInstanceGUI* TCPSrcPlugin::createRxChannelGUI(DeviceUISet *deviceUISet, BasebandSampleSink *rxChannel)
|
|
||||||
{
|
|
||||||
return TCPSrcGUI::create(m_pluginAPI, deviceUISet, rxChannel);
|
|
||||||
}
|
|
||||||
|
|
||||||
BasebandSampleSink* TCPSrcPlugin::createRxChannelBS(DeviceSourceAPI *deviceAPI)
|
|
||||||
{
|
|
||||||
return new TCPSrc(deviceAPI);
|
|
||||||
}
|
|
||||||
|
|
||||||
ChannelSinkAPI* TCPSrcPlugin::createRxChannelCS(DeviceSourceAPI *deviceAPI)
|
|
||||||
{
|
|
||||||
return new TCPSrc(deviceAPI);
|
|
||||||
}
|
|
||||||
|
|
@ -1,31 +0,0 @@
|
|||||||
#ifndef INCLUDE_TCPSRCPLUGIN_H
|
|
||||||
#define INCLUDE_TCPSRCPLUGIN_H
|
|
||||||
|
|
||||||
#include <QObject>
|
|
||||||
#include "plugin/plugininterface.h"
|
|
||||||
|
|
||||||
class DeviceUISet;
|
|
||||||
class BasebandSampleSink;
|
|
||||||
|
|
||||||
class TCPSrcPlugin : public QObject, PluginInterface {
|
|
||||||
Q_OBJECT
|
|
||||||
Q_INTERFACES(PluginInterface)
|
|
||||||
Q_PLUGIN_METADATA(IID "sdrangel.demod.tcpsrc")
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit TCPSrcPlugin(QObject* parent = NULL);
|
|
||||||
|
|
||||||
const PluginDescriptor& getPluginDescriptor() const;
|
|
||||||
void initPlugin(PluginAPI* pluginAPI);
|
|
||||||
|
|
||||||
virtual PluginInstanceGUI* createRxChannelGUI(DeviceUISet *deviceUISet, BasebandSampleSink *rxChannel);
|
|
||||||
virtual BasebandSampleSink* createRxChannelBS(DeviceSourceAPI *deviceAPI);
|
|
||||||
virtual ChannelSinkAPI* createRxChannelCS(DeviceSourceAPI *deviceAPI);
|
|
||||||
|
|
||||||
private:
|
|
||||||
static const PluginDescriptor m_pluginDescriptor;
|
|
||||||
|
|
||||||
PluginAPI* m_pluginAPI;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // INCLUDE_TCPSRCPLUGIN_H
|
|
@ -1,150 +0,0 @@
|
|||||||
///////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Copyright (C) 2017 Edouard Griffiths, F4EXB //
|
|
||||||
// //
|
|
||||||
// This program is free software; you can redistribute it and/or modify //
|
|
||||||
// it under the terms of the GNU General Public License as published by //
|
|
||||||
// the Free Software Foundation as version 3 of the License, or //
|
|
||||||
// //
|
|
||||||
// This program is distributed in the hope that it will be useful, //
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
|
|
||||||
// GNU General Public License V3 for more details. //
|
|
||||||
// //
|
|
||||||
// You should have received a copy of the GNU General Public License //
|
|
||||||
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
#include <QColor>
|
|
||||||
|
|
||||||
#include "dsp/dspengine.h"
|
|
||||||
#include "util/simpleserializer.h"
|
|
||||||
#include "settings/serializable.h"
|
|
||||||
#include "tcpsrcsettings.h"
|
|
||||||
|
|
||||||
TCPSrcSettings::TCPSrcSettings() :
|
|
||||||
m_channelMarker(0),
|
|
||||||
m_spectrumGUI(0)
|
|
||||||
{
|
|
||||||
resetToDefaults();
|
|
||||||
}
|
|
||||||
|
|
||||||
void TCPSrcSettings::resetToDefaults()
|
|
||||||
{
|
|
||||||
m_outputSampleRate = 48000;
|
|
||||||
m_sampleFormat = FormatS16LE;
|
|
||||||
m_inputSampleRate = 48000;
|
|
||||||
m_inputFrequencyOffset = 0;
|
|
||||||
m_rfBandwidth = 12500;
|
|
||||||
m_tcpPort = 9999;
|
|
||||||
m_fmDeviation = 2500;
|
|
||||||
m_channelMute = false;
|
|
||||||
m_gain = 1.0;
|
|
||||||
m_squelchdB = -60;
|
|
||||||
m_squelchGate = 0.0;
|
|
||||||
m_squelchEnabled = true;
|
|
||||||
m_agc = false;
|
|
||||||
m_audioActive = false;
|
|
||||||
m_audioStereo = false;
|
|
||||||
m_volume = 20;
|
|
||||||
m_udpAddress = "127.0.0.1";
|
|
||||||
m_udpPort = 9999;
|
|
||||||
m_audioPort = 9998;
|
|
||||||
m_rgbColor = QColor(225, 25, 99).rgb();
|
|
||||||
m_title = "TCP Source";
|
|
||||||
}
|
|
||||||
|
|
||||||
QByteArray TCPSrcSettings::serialize() const
|
|
||||||
{
|
|
||||||
SimpleSerializer s(1);
|
|
||||||
s.writeS32(2, m_inputFrequencyOffset);
|
|
||||||
s.writeS32(3, (int) m_sampleFormat);
|
|
||||||
s.writeReal(4, m_outputSampleRate);
|
|
||||||
s.writeReal(5, m_rfBandwidth);
|
|
||||||
s.writeS32(6, m_tcpPort);
|
|
||||||
|
|
||||||
if (m_channelMarker) {
|
|
||||||
s.writeBlob(10, m_channelMarker->serialize());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_spectrumGUI) {
|
|
||||||
s.writeBlob(7, m_spectrumGUI->serialize());
|
|
||||||
}
|
|
||||||
|
|
||||||
s.writeS32(8, m_gain*10.0);
|
|
||||||
s.writeU32(9, m_rgbColor);
|
|
||||||
s.writeBool(11, m_audioActive);
|
|
||||||
s.writeS32(12, m_volume);
|
|
||||||
s.writeBool(14, m_audioStereo);
|
|
||||||
s.writeS32(15, m_fmDeviation);
|
|
||||||
s.writeS32(16, m_squelchdB);
|
|
||||||
s.writeS32(17, m_squelchGate);
|
|
||||||
s.writeBool(18, m_agc);
|
|
||||||
s.writeString(19, m_title);
|
|
||||||
|
|
||||||
return s.final();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
bool TCPSrcSettings::deserialize(const QByteArray& data)
|
|
||||||
{
|
|
||||||
SimpleDeserializer d(data);
|
|
||||||
|
|
||||||
if (!d.isValid())
|
|
||||||
{
|
|
||||||
resetToDefaults();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (d.getVersion() == 1)
|
|
||||||
{
|
|
||||||
QByteArray bytetmp;
|
|
||||||
QString strtmp;
|
|
||||||
int32_t s32tmp;
|
|
||||||
|
|
||||||
if (m_channelMarker) {
|
|
||||||
d.readBlob(10, &bytetmp);
|
|
||||||
m_channelMarker->deserialize(bytetmp);
|
|
||||||
}
|
|
||||||
|
|
||||||
d.readS32(2, &s32tmp, 0);
|
|
||||||
m_inputFrequencyOffset = s32tmp;
|
|
||||||
|
|
||||||
d.readS32(3, &s32tmp, FormatS16LE);
|
|
||||||
|
|
||||||
if ((s32tmp >= 0) && (s32tmp < (int) FormatNone)) {
|
|
||||||
m_sampleFormat = (SampleFormat) s32tmp;
|
|
||||||
} else {
|
|
||||||
m_sampleFormat = FormatS16LE;
|
|
||||||
}
|
|
||||||
|
|
||||||
d.readReal(4, &m_outputSampleRate, 48000.0);
|
|
||||||
d.readReal(5, &m_rfBandwidth, 32000.0);
|
|
||||||
d.readS32(6, &s32tmp, 10);
|
|
||||||
m_tcpPort = s32tmp < 1024 ? 9999 : s32tmp % (1<<16);
|
|
||||||
|
|
||||||
if (m_spectrumGUI) {
|
|
||||||
d.readBlob(7, &bytetmp);
|
|
||||||
m_spectrumGUI->deserialize(bytetmp);
|
|
||||||
}
|
|
||||||
|
|
||||||
d.readS32(8, &s32tmp, 10);
|
|
||||||
m_gain = s32tmp / 10.0;
|
|
||||||
d.readU32(9, &m_rgbColor);
|
|
||||||
d.readBool(11, &m_audioActive, false);
|
|
||||||
d.readS32(12, &m_volume, 0);
|
|
||||||
d.readBool(14, &m_audioStereo, false);
|
|
||||||
d.readS32(15, &m_fmDeviation, 2500);
|
|
||||||
d.readS32(16, &m_squelchdB, -60);
|
|
||||||
d.readS32(17, &m_squelchGate, 5);
|
|
||||||
d.readBool(18, &m_agc, false);
|
|
||||||
d.readString(19, &m_title, "TCP Source");
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
resetToDefaults();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,72 +0,0 @@
|
|||||||
///////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Copyright (C) 2017 Edouard Griffiths, F4EXB //
|
|
||||||
// //
|
|
||||||
// This program is free software; you can redistribute it and/or modify //
|
|
||||||
// it under the terms of the GNU General Public License as published by //
|
|
||||||
// the Free Software Foundation as version 3 of the License, or //
|
|
||||||
// //
|
|
||||||
// This program is distributed in the hope that it will be useful, //
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
|
|
||||||
// GNU General Public License V3 for more details. //
|
|
||||||
// //
|
|
||||||
// You should have received a copy of the GNU General Public License //
|
|
||||||
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
#ifndef PLUGINS_CHANNELRX_TCPSRC_TCPSRCSETTINGS_H_
|
|
||||||
#define PLUGINS_CHANNELRX_TCPSRC_TCPSRCSETTINGS_H_
|
|
||||||
|
|
||||||
#include <QByteArray>
|
|
||||||
#include <QString>
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
class Serializable;
|
|
||||||
|
|
||||||
struct TCPSrcSettings
|
|
||||||
{
|
|
||||||
enum SampleFormat {
|
|
||||||
FormatS16LE,
|
|
||||||
FormatNFM,
|
|
||||||
FormatSSB,
|
|
||||||
FormatNone
|
|
||||||
};
|
|
||||||
|
|
||||||
float m_outputSampleRate;
|
|
||||||
SampleFormat m_sampleFormat;
|
|
||||||
float m_inputSampleRate;
|
|
||||||
int64_t m_inputFrequencyOffset;
|
|
||||||
float m_rfBandwidth;
|
|
||||||
uint16_t m_tcpPort;
|
|
||||||
int m_fmDeviation;
|
|
||||||
bool m_channelMute;
|
|
||||||
float m_gain;
|
|
||||||
int m_squelchdB; //!< power dB
|
|
||||||
int m_squelchGate; //!< 100ths seconds
|
|
||||||
bool m_squelchEnabled;
|
|
||||||
bool m_agc;
|
|
||||||
bool m_audioActive;
|
|
||||||
bool m_audioStereo;
|
|
||||||
int m_volume;
|
|
||||||
quint32 m_rgbColor;
|
|
||||||
|
|
||||||
QString m_udpAddress;
|
|
||||||
uint16_t m_udpPort;
|
|
||||||
uint16_t m_audioPort;
|
|
||||||
|
|
||||||
QString m_title;
|
|
||||||
|
|
||||||
Serializable *m_channelMarker;
|
|
||||||
Serializable *m_spectrumGUI;
|
|
||||||
|
|
||||||
TCPSrcSettings();
|
|
||||||
void resetToDefaults();
|
|
||||||
void setChannelMarker(Serializable *channelMarker) { m_channelMarker = channelMarker; }
|
|
||||||
void setSpectrumGUI(Serializable *spectrumGUI) { m_spectrumGUI = spectrumGUI; }
|
|
||||||
QByteArray serialize() const;
|
|
||||||
bool deserialize(const QByteArray& data);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* PLUGINS_CHANNELRX_TCPSRC_TCPSRCSETTINGS_H_ */
|
|
Loading…
x
Reference in New Issue
Block a user