merge with dev
@ -264,6 +264,8 @@ set(sdrbase_SOURCES
|
||||
sdrbase/gui/samplingdevicecontrol.cpp
|
||||
sdrbase/gui/scale.cpp
|
||||
sdrbase/gui/scaleengine.cpp
|
||||
sdrbase/gui/transverterbutton.cpp
|
||||
sdrbase/gui/transverterdialog.cpp
|
||||
sdrbase/gui/valuedial.cpp
|
||||
sdrbase/gui/valuedialz.cpp
|
||||
|
||||
@ -386,6 +388,8 @@ set(sdrbase_HEADERS
|
||||
sdrbase/gui/samplingdevicecontrol.h
|
||||
sdrbase/gui/scale.h
|
||||
sdrbase/gui/scaleengine.h
|
||||
sdrbase/gui/transverterbutton.h
|
||||
sdrbase/gui/transverterdialog.h
|
||||
sdrbase/gui/valuedial.h
|
||||
sdrbase/gui/valuedialz.h
|
||||
|
||||
@ -393,7 +397,7 @@ set(sdrbase_HEADERS
|
||||
sdrbase/dsp/devicesamplesink.h
|
||||
|
||||
sdrbase/plugin/pluginapi.h
|
||||
sdrbase/plugin/plugininstanceui.h
|
||||
sdrbase/plugin/plugininstancegui.h
|
||||
sdrbase/plugin/plugininterface.h
|
||||
sdrbase/plugin/pluginmanager.h
|
||||
|
||||
@ -439,6 +443,7 @@ set(sdrbase_FORMS
|
||||
sdrbase/gui/audiodialog.ui
|
||||
sdrbase/gui/samplingdevicecontrol.ui
|
||||
sdrbase/gui/myposdialog.ui
|
||||
sdrbase/gui/transverterdialog.ui
|
||||
)
|
||||
|
||||
set(sdrbase_RESOURCES
|
||||
|
@ -6,6 +6,7 @@
|
||||
|
||||
QT += core gui multimedia opengl
|
||||
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
|
||||
QMAKE_CXXFLAGS += -std=c++11
|
||||
|
||||
TEMPLATE = app
|
||||
TARGET = sdrangel
|
||||
|
8
debian/changelog
vendored
@ -1,3 +1,11 @@
|
||||
sdrangel (3.7.3-1) unstable; urgency=medium
|
||||
|
||||
* For Airspy, Funcube Pro and Pro+, PlutoSDR Rx and Tx, RTLSDR:
|
||||
* Button and dialog to set frequency translation for transverter operation
|
||||
* GUI and demod separation step 1 partial
|
||||
|
||||
-- Edouard Griffiths, F4EXB <f4exb06@gmail.com> Wed, 04 Oct 2017 23:14:18 +0200
|
||||
|
||||
sdrangel (3.7.2-1) unstable; urgency=medium
|
||||
|
||||
* PlutoSDR: Remove from device enumeration if device is not accessible
|
||||
|
2
debian/control
vendored
@ -10,7 +10,7 @@ Homepage: https://github.com/f4exb/sdrangel
|
||||
|
||||
Package: sdrangel
|
||||
Architecture: any
|
||||
Depends: libc6, libasound2, libfftw3-single3, libgcc1, libgl1-mesa-glx, libnanomsg0, libqt5core5a, libqt5gui5, libqt5multimedia5, libqt5network5, libqt5opengl5, libqt5widgets5, libqt5multimedia5-plugins, libstdc++6, libusb-1.0-0, libopencv-dev, libsqlite3-dev, pulseaudio, libxml2, ${shlibs:Depends}, ${misc:Depends}
|
||||
Depends: libc6, libasound2, libfftw3-single3, libgcc1, libgl1-mesa-glx, libnanomsg0|libnanomsg4, libqt5core5a, libqt5gui5, libqt5multimedia5, libqt5network5, libqt5opengl5, libqt5widgets5, libqt5multimedia5-plugins, libstdc++6, libusb-1.0-0, libopencv-dev, libsqlite3-dev, pulseaudio, libxml2, ${shlibs:Depends}, ${misc:Depends}
|
||||
Description: SDR/Analyzer/Generator front-end for various hardware
|
||||
SDR/Analyzer/Generator front-end for Airspy, BladeRF, HackRF, RTL-SDR, FunCube, LimeSDR, PlutoSDR.
|
||||
Also File source and sink for I/Q samples, network I/Q sources with SDRDaemon.
|
||||
|
@ -56,20 +56,41 @@ bool DeviceLimeSDR::setNCOFrequency(lms_device_t *device, bool dir_tx, std::size
|
||||
return false;
|
||||
}
|
||||
|
||||
if (dir_tx)
|
||||
{
|
||||
if (LMS_WriteParam(device,LMS7param(CMIX_BYP_TXTSP),0) < 0) {
|
||||
fprintf(stderr, "DeviceLimeSDR::setNCOFrequency: cannot enable Tx NCO\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (LMS_WriteParam(device,LMS7param(CMIX_BYP_RXTSP),0) < 0) {
|
||||
fprintf(stderr, "DeviceLimeSDR::setNCOFrequency: cannot enable Rx NCO\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (LMS_SetNCOIndex(device, dir_tx, chan, LMS_NCO_VAL_COUNT, true) < 0)
|
||||
if (dir_tx)
|
||||
{
|
||||
fprintf(stderr, "DeviceLimeSDR::setNCOFrequency: cannot disable NCO\n");
|
||||
return false;
|
||||
if (LMS_WriteParam(device,LMS7param(CMIX_BYP_TXTSP),1) < 0) {
|
||||
fprintf(stderr, "DeviceLimeSDR::setNCOFrequency: cannot disable Tx NCO\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "DeviceLimeSDR::setNCOFrequency: NCO disabled\n");
|
||||
return true;
|
||||
if (LMS_WriteParam(device,LMS7param(CMIX_BYP_RXTSP),1) < 0) {
|
||||
fprintf(stderr, "DeviceLimeSDR::setNCOFrequency: cannot disable Rx NCO\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
Before Width: | Height: | Size: 31 KiB After Width: | Height: | Size: 32 KiB |
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 27 KiB |
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 25 KiB |
BIN
doc/img/RTLSDR_plugin_xvrt.png
Normal file
After Width: | Height: | Size: 10 KiB |
@ -1,5 +1,6 @@
|
||||
# Udev rules for the Funcube Dongle Pro+ (0xfb31)
|
||||
|
||||
# HIDAPI/libusb:
|
||||
SUBSYSTEMS=="usb", ATTRS{idVendor}=="04d8", ATTRS{idProduct}=="fb31", GROUP:="audio", MODE:="0666"
|
||||
SUBSYSTEMS=="usb", ATTRS{idVendor}=="04d8", ATTRS{idProduct}=="fb56", MODE:="0666"
|
||||
SUBSYSTEMS=="usb", ATTRS{idVendor}=="04d8", ATTRS{idProduct}=="fb31", MODE:="0666"
|
||||
|
@ -22,5 +22,11 @@ const char *fcd_traits<ProPlus>::displayedName = "FunCube Dongle Pro+";
|
||||
const char *fcd_traits<Pro>::pluginDisplayedName = "FunCube Pro Input";
|
||||
const char *fcd_traits<ProPlus>::pluginDisplayedName = "FunCube Pro+ Input";
|
||||
|
||||
const char *fcd_traits<Pro>::pluginVersion = "3.5.0";
|
||||
const char *fcd_traits<ProPlus>::pluginVersion = "3.5.0";
|
||||
const char *fcd_traits<Pro>::pluginVersion = "3.7.3";
|
||||
const char *fcd_traits<ProPlus>::pluginVersion = "3.7.3";
|
||||
|
||||
const int64_t fcd_traits<Pro>::loLowLimitFreq = 64000000L;
|
||||
const int64_t fcd_traits<ProPlus>::loLowLimitFreq = 150000L;
|
||||
|
||||
const int64_t fcd_traits<Pro>::loHighLimitFreq = 1700000000L;
|
||||
const int64_t fcd_traits<ProPlus>::loHighLimitFreq = 2000000000L;
|
||||
|
@ -30,6 +30,8 @@ struct fcd_traits
|
||||
static const char *displayedName;
|
||||
static const char *pluginDisplayedName;
|
||||
static const char *pluginVersion;
|
||||
static const int64_t loLowLimitFreq;
|
||||
static const int64_t loHighLimitFreq;
|
||||
};
|
||||
|
||||
template<>
|
||||
@ -46,6 +48,8 @@ struct fcd_traits<Pro>
|
||||
static const char *displayedName;
|
||||
static const char *pluginDisplayedName;
|
||||
static const char *pluginVersion;
|
||||
static const int64_t loLowLimitFreq;
|
||||
static const int64_t loHighLimitFreq;
|
||||
};
|
||||
|
||||
template<>
|
||||
@ -62,6 +66,8 @@ struct fcd_traits<ProPlus>
|
||||
static const char *displayedName;
|
||||
static const char *pluginDisplayedName;
|
||||
static const char *pluginVersion;
|
||||
static const int64_t loLowLimitFreq;
|
||||
static const int64_t loHighLimitFreq;
|
||||
};
|
||||
|
||||
template <fcd_type FCDType> const char *fcd_traits<FCDType>::alsaDeviceName = "";
|
||||
|
@ -14,19 +14,25 @@
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "../../channelrx/chanalyzer/chanalyzer.h"
|
||||
#include "chanalyzer.h"
|
||||
|
||||
#include <dsp/downchannelizer.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)
|
||||
|
||||
ChannelAnalyzer::ChannelAnalyzer(BasebandSampleSink* sampleSink) :
|
||||
m_sampleSink(sampleSink),
|
||||
ChannelAnalyzer::ChannelAnalyzer(DeviceSourceAPI *deviceAPI) :
|
||||
m_deviceAPI(deviceAPI),
|
||||
m_sampleSink(0),
|
||||
m_settingsMutex(QMutex::Recursive)
|
||||
{
|
||||
m_Bandwidth = 5000;
|
||||
@ -42,12 +48,20 @@ ChannelAnalyzer::ChannelAnalyzer(BasebandSampleSink* sampleSink) :
|
||||
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);
|
||||
}
|
||||
|
||||
ChannelAnalyzer::~ChannelAnalyzer()
|
||||
{
|
||||
if (SSBFilter) delete SSBFilter;
|
||||
if (DSBFilter) delete DSBFilter;
|
||||
m_deviceAPI->removeThreadedSink(m_threadedChannelizer);
|
||||
delete m_threadedChannelizer;
|
||||
delete m_channelizer;
|
||||
}
|
||||
|
||||
void ChannelAnalyzer::configure(MessageQueue* messageQueue,
|
||||
@ -130,6 +144,12 @@ void ChannelAnalyzer::stop()
|
||||
{
|
||||
}
|
||||
|
||||
void ChannelAnalyzer::channelSampleRateChanged()
|
||||
{
|
||||
MsgReportChannelSampleRateChanged *msg = MsgReportChannelSampleRateChanged::create();
|
||||
getMessageQueueToGUI()->push(msg);
|
||||
}
|
||||
|
||||
bool ChannelAnalyzer::handleMessage(const Message& cmd)
|
||||
{
|
||||
float band, lowCutoff;
|
||||
@ -148,6 +168,16 @@ bool ChannelAnalyzer::handleMessage(const Message& cmd)
|
||||
|
||||
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;
|
||||
|
@ -27,10 +27,87 @@
|
||||
|
||||
#define ssbFftLen 1024
|
||||
|
||||
class DeviceSourceAPI;
|
||||
class ThreadedBasebandSampleSink;
|
||||
class DownChannelizer;
|
||||
|
||||
class ChannelAnalyzer : public BasebandSampleSink {
|
||||
public:
|
||||
ChannelAnalyzer(BasebandSampleSink* m_sampleSink);
|
||||
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();
|
||||
void setSampleSink(BasebandSampleSink* sampleSink) { m_sampleSink = sampleSink; }
|
||||
|
||||
void configure(MessageQueue* messageQueue,
|
||||
Real Bandwidth,
|
||||
@ -46,41 +123,13 @@ public:
|
||||
virtual void stop();
|
||||
virtual bool handleMessage(const Message& cmd);
|
||||
|
||||
private slots:
|
||||
void channelSampleRateChanged();
|
||||
|
||||
private:
|
||||
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)
|
||||
{ }
|
||||
};
|
||||
DeviceSourceAPI *m_deviceAPI;
|
||||
ThreadedBasebandSampleSink* m_threadedChannelizer;
|
||||
DownChannelizer* m_channelizer;
|
||||
|
||||
Real m_Bandwidth;
|
||||
Real m_LowCutoff;
|
||||
|
@ -154,11 +154,32 @@ bool ChannelAnalyzerGUI::deserialize(const QByteArray& data)
|
||||
}
|
||||
}
|
||||
|
||||
bool ChannelAnalyzerGUI::handleMessage(const Message& message __attribute__((unused)))
|
||||
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::viewChanged()
|
||||
{
|
||||
applySettings();
|
||||
@ -171,11 +192,6 @@ void ChannelAnalyzerGUI::tick()
|
||||
ui->channelPower->setText(QString::number(m_channelPowerDbAvg.average(), 'f', 1));
|
||||
}
|
||||
|
||||
void ChannelAnalyzerGUI::channelSampleRateChanged()
|
||||
{
|
||||
setNewRate(m_spanLog2);
|
||||
}
|
||||
|
||||
void ChannelAnalyzerGUI::on_deltaMinus_toggled(bool minus)
|
||||
{
|
||||
int deltaFrequency = m_channelMarker.getCenterFrequency();
|
||||
@ -326,11 +342,9 @@ ChannelAnalyzerGUI::ChannelAnalyzerGUI(PluginAPI* pluginAPI, DeviceSourceAPI *de
|
||||
m_spectrumVis = new SpectrumVis(ui->glSpectrum);
|
||||
m_scopeVis = new ScopeVis(ui->glScope);
|
||||
m_spectrumScopeComboVis = new SpectrumScopeComboVis(m_spectrumVis, m_scopeVis);
|
||||
m_channelAnalyzer = new ChannelAnalyzer(m_spectrumScopeComboVis);
|
||||
m_channelizer = new DownChannelizer(m_channelAnalyzer);
|
||||
m_threadedChannelizer = new ThreadedBasebandSampleSink(m_channelizer, this);
|
||||
connect(m_channelizer, SIGNAL(inputSampleRateChanged()), this, SLOT(channelSampleRateChanged()));
|
||||
m_deviceAPI->addThreadedSink(m_threadedChannelizer);
|
||||
m_channelAnalyzer = new ChannelAnalyzer(m_deviceAPI);
|
||||
m_channelAnalyzer->setSampleSink(m_spectrumScopeComboVis);
|
||||
m_channelAnalyzer->setMessageQueueToGUI(getInputMessageQueue());
|
||||
|
||||
ui->deltaFrequency->setColorMapper(ColorMapper(ColorMapper::ReverseGold));
|
||||
ui->deltaFrequency->setValueRange(7, 0U, 9999999U);
|
||||
@ -361,6 +375,8 @@ ChannelAnalyzerGUI::ChannelAnalyzerGUI(PluginAPI* pluginAPI, DeviceSourceAPI *de
|
||||
ui->spectrumGUI->setBuddies(m_spectrumVis->getInputMessageQueue(), m_spectrumVis, ui->glSpectrum);
|
||||
ui->scopeGUI->setBuddies(m_scopeVis->getInputMessageQueue(), m_scopeVis, ui->glScope);
|
||||
|
||||
connect(getInputMessageQueue(), SIGNAL(messageEnqueued()), this, SLOT(handleInputMessages()));
|
||||
|
||||
applySettings();
|
||||
setNewRate(m_spanLog2);
|
||||
}
|
||||
@ -368,9 +384,6 @@ ChannelAnalyzerGUI::ChannelAnalyzerGUI(PluginAPI* pluginAPI, DeviceSourceAPI *de
|
||||
ChannelAnalyzerGUI::~ChannelAnalyzerGUI()
|
||||
{
|
||||
m_deviceAPI->removeChannelInstance(this);
|
||||
m_deviceAPI->removeThreadedSink(m_threadedChannelizer);
|
||||
delete m_threadedChannelizer;
|
||||
delete m_channelizer;
|
||||
delete m_channelAnalyzer;
|
||||
delete m_spectrumVis;
|
||||
delete m_scopeVis;
|
||||
@ -457,9 +470,8 @@ void ChannelAnalyzerGUI::applySettings()
|
||||
ui->deltaFrequency->setValue(abs(m_channelMarker.getCenterFrequency()));
|
||||
ui->deltaMinus->setChecked(m_channelMarker.getCenterFrequency() < 0);
|
||||
|
||||
m_channelizer->configure(m_channelizer->getInputMessageQueue(),
|
||||
m_channelizer->getInputSampleRate(),
|
||||
m_channelMarker.getCenterFrequency());
|
||||
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,
|
||||
|
@ -17,10 +17,10 @@
|
||||
#ifndef INCLUDE_CHANNELANALYZERGUI_H
|
||||
#define INCLUDE_CHANNELANALYZERGUI_H
|
||||
|
||||
#include <plugin/plugininstancegui.h>
|
||||
#include "gui/rollupwidget.h"
|
||||
#include "dsp/channelmarker.h"
|
||||
#include "dsp/movingaverage.h"
|
||||
#include "plugin/plugininstanceui.h"
|
||||
#include "util/messagequeue.h"
|
||||
|
||||
class PluginAPI;
|
||||
@ -37,7 +37,7 @@ namespace Ui {
|
||||
class ChannelAnalyzerGUI;
|
||||
}
|
||||
|
||||
class ChannelAnalyzerGUI : public RollupWidget, public PluginInstanceUI {
|
||||
class ChannelAnalyzerGUI : public RollupWidget, public PluginInstanceGUI {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
@ -59,7 +59,6 @@ public:
|
||||
|
||||
private slots:
|
||||
void viewChanged();
|
||||
void channelSampleRateChanged();
|
||||
void on_deltaFrequency_changed(quint64 value);
|
||||
void on_deltaMinus_toggled(bool minus);
|
||||
void on_BW_valueChanged(int value);
|
||||
@ -68,6 +67,7 @@ private slots:
|
||||
void on_ssb_toggled(bool checked);
|
||||
void onWidgetRolled(QWidget* widget, bool rollDown);
|
||||
void onMenuDoubleClicked();
|
||||
void handleInputMessages();
|
||||
void tick();
|
||||
|
||||
private:
|
||||
@ -81,8 +81,8 @@ private:
|
||||
int m_spanLog2;
|
||||
MovingAverage<Real> m_channelPowerDbAvg;
|
||||
|
||||
ThreadedBasebandSampleSink* m_threadedChannelizer;
|
||||
DownChannelizer* m_channelizer;
|
||||
// ThreadedBasebandSampleSink* m_threadedChannelizer;
|
||||
// DownChannelizer* m_channelizer;
|
||||
ChannelAnalyzer* m_channelAnalyzer;
|
||||
SpectrumScopeComboVis* m_spectrumScopeComboVis;
|
||||
SpectrumVis* m_spectrumVis;
|
||||
|
@ -33,7 +33,7 @@ void ChannelAnalyzerPlugin::initPlugin(PluginAPI* pluginAPI)
|
||||
m_pluginAPI->registerRxChannel(ChannelAnalyzerGUI::m_channelID, this);
|
||||
}
|
||||
|
||||
PluginInstanceUI* ChannelAnalyzerPlugin::createRxChannel(const QString& channelName, DeviceSourceAPI *deviceAPI)
|
||||
PluginInstanceGUI* ChannelAnalyzerPlugin::createRxChannel(const QString& channelName, DeviceSourceAPI *deviceAPI)
|
||||
{
|
||||
if(channelName == ChannelAnalyzerGUI::m_channelID)
|
||||
{
|
||||
|
@ -17,7 +17,7 @@ public:
|
||||
const PluginDescriptor& getPluginDescriptor() const;
|
||||
void initPlugin(PluginAPI* pluginAPI);
|
||||
|
||||
PluginInstanceUI* createRxChannel(const QString& channelName, DeviceSourceAPI *deviceAPI);
|
||||
PluginInstanceGUI* createRxChannel(const QString& channelName, DeviceSourceAPI *deviceAPI);
|
||||
|
||||
private:
|
||||
static const PluginDescriptor m_pluginDescriptor;
|
||||
|
@ -16,17 +16,23 @@
|
||||
|
||||
#include "chanalyzerng.h"
|
||||
|
||||
#include <dsp/downchannelizer.h>
|
||||
#include <QTime>
|
||||
#include <QDebug>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "device/devicesourceapi.h"
|
||||
#include "audio/audiooutput.h"
|
||||
#include "dsp/threadedbasebandsamplesink.h"
|
||||
#include "dsp/downchannelizer.h"
|
||||
|
||||
|
||||
MESSAGE_CLASS_DEFINITION(ChannelAnalyzerNG::MsgConfigureChannelAnalyzer, Message)
|
||||
MESSAGE_CLASS_DEFINITION(ChannelAnalyzerNG::MsgConfigureChannelizer, Message)
|
||||
MESSAGE_CLASS_DEFINITION(ChannelAnalyzerNG::MsgReportChannelSampleRateChanged, Message)
|
||||
|
||||
ChannelAnalyzerNG::ChannelAnalyzerNG(BasebandSampleSink* sampleSink) :
|
||||
m_sampleSink(sampleSink),
|
||||
ChannelAnalyzerNG::ChannelAnalyzerNG(DeviceSourceAPI *deviceAPI) :
|
||||
m_deviceAPI(deviceAPI),
|
||||
m_sampleSink(0),
|
||||
m_settingsMutex(QMutex::Recursive)
|
||||
{
|
||||
m_undersampleCount = 0;
|
||||
@ -38,6 +44,12 @@ ChannelAnalyzerNG::ChannelAnalyzerNG(BasebandSampleSink* sampleSink) :
|
||||
m_interpolatorDistanceRemain = 0.0f;
|
||||
SSBFilter = new fftfilt(m_config.m_LowCutoff / m_config.m_inputSampleRate, m_config.m_Bandwidth / m_config.m_inputSampleRate, ssbFftLen);
|
||||
DSBFilter = new fftfilt(m_config.m_Bandwidth / m_config.m_inputSampleRate, 2*ssbFftLen);
|
||||
|
||||
m_channelizer = new DownChannelizer(this);
|
||||
m_threadedChannelizer = new ThreadedBasebandSampleSink(m_channelizer, this);
|
||||
connect(m_channelizer, SIGNAL(inputSampleRateChanged()), this, SLOT(channelizerInputSampleRateChanged()));
|
||||
m_deviceAPI->addThreadedSink(m_threadedChannelizer);
|
||||
|
||||
apply(true);
|
||||
}
|
||||
|
||||
@ -45,6 +57,9 @@ ChannelAnalyzerNG::~ChannelAnalyzerNG()
|
||||
{
|
||||
if (SSBFilter) delete SSBFilter;
|
||||
if (DSBFilter) delete DSBFilter;
|
||||
m_deviceAPI->removeThreadedSink(m_threadedChannelizer);
|
||||
delete m_threadedChannelizer;
|
||||
delete m_channelizer;
|
||||
}
|
||||
|
||||
void ChannelAnalyzerNG::configure(MessageQueue* messageQueue,
|
||||
@ -54,7 +69,7 @@ void ChannelAnalyzerNG::configure(MessageQueue* messageQueue,
|
||||
int spanLog2,
|
||||
bool ssb)
|
||||
{
|
||||
Message* cmd = MsgConfigureChannelAnalyzer::create(channelSampleRate, Bandwidth, LowCutoff, spanLog2, ssb);
|
||||
Message* cmd = MsgConfigureChannelAnalyzer::create(channelSampleRate, Bandwidth, LowCutoff, spanLog2, ssb);
|
||||
messageQueue->push(cmd);
|
||||
}
|
||||
|
||||
@ -102,6 +117,12 @@ void ChannelAnalyzerNG::stop()
|
||||
{
|
||||
}
|
||||
|
||||
void ChannelAnalyzerNG::channelizerInputSampleRateChanged()
|
||||
{
|
||||
MsgReportChannelSampleRateChanged *msg = MsgReportChannelSampleRateChanged::create();
|
||||
getMessageQueueToGUI()->push(msg);
|
||||
}
|
||||
|
||||
bool ChannelAnalyzerNG::handleMessage(const Message& cmd)
|
||||
{
|
||||
qDebug() << "ChannelAnalyzerNG::handleMessage: " << cmd.getIdentifier();
|
||||
@ -120,11 +141,19 @@ bool ChannelAnalyzerNG::handleMessage(const Message& cmd)
|
||||
apply();
|
||||
return true;
|
||||
}
|
||||
else if (MsgConfigureChannelizer::match(cmd))
|
||||
{
|
||||
MsgConfigureChannelizer& cfg = (MsgConfigureChannelizer&) cmd;
|
||||
m_channelizer->configure(m_channelizer->getInputMessageQueue(),
|
||||
cfg.getSampleRate(),
|
||||
cfg.getCenterFrequency());
|
||||
return true;
|
||||
}
|
||||
else if (MsgConfigureChannelAnalyzer::match(cmd))
|
||||
{
|
||||
MsgConfigureChannelAnalyzer& cfg = (MsgConfigureChannelAnalyzer&) cmd;
|
||||
|
||||
m_config.m_channelSampleRate = cfg.getChannelSampleRate();
|
||||
m_config.m_channelSampleRate = cfg.getChannelSampleRate();
|
||||
m_config.m_Bandwidth = cfg.getBandwidth();
|
||||
m_config.m_LowCutoff = cfg.getLoCutoff();
|
||||
m_config.m_spanLog2 = cfg.getSpanLog2();
|
||||
@ -153,6 +182,8 @@ bool ChannelAnalyzerNG::handleMessage(const Message& cmd)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void ChannelAnalyzerNG::apply(bool force)
|
||||
{
|
||||
if ((m_running.m_frequency != m_config.m_frequency) ||
|
||||
|
@ -29,10 +29,102 @@
|
||||
|
||||
#define ssbFftLen 1024
|
||||
|
||||
class DeviceSourceAPI;
|
||||
class ThreadedBasebandSampleSink;
|
||||
class DownChannelizer;
|
||||
|
||||
class ChannelAnalyzerNG : public BasebandSampleSink {
|
||||
public:
|
||||
ChannelAnalyzerNG(BasebandSampleSink* m_sampleSink);
|
||||
class MsgConfigureChannelAnalyzer : public Message {
|
||||
MESSAGE_CLASS_DECLARATION
|
||||
|
||||
public:
|
||||
int getChannelSampleRate() const { return m_channelSampleRate; }
|
||||
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(
|
||||
int channelSampleRate,
|
||||
Real Bandwidth,
|
||||
Real LowCutoff,
|
||||
int spanLog2,
|
||||
bool ssb)
|
||||
{
|
||||
return new MsgConfigureChannelAnalyzer(
|
||||
channelSampleRate,
|
||||
Bandwidth,
|
||||
LowCutoff,
|
||||
spanLog2,
|
||||
ssb);
|
||||
}
|
||||
|
||||
private:
|
||||
int m_channelSampleRate;
|
||||
Real m_Bandwidth;
|
||||
Real m_LowCutoff;
|
||||
int m_spanLog2;
|
||||
bool m_ssb;
|
||||
|
||||
MsgConfigureChannelAnalyzer(
|
||||
int channelSampleRate,
|
||||
Real Bandwidth,
|
||||
Real LowCutoff,
|
||||
int spanLog2,
|
||||
bool ssb) :
|
||||
Message(),
|
||||
m_channelSampleRate(channelSampleRate),
|
||||
m_Bandwidth(Bandwidth),
|
||||
m_LowCutoff(LowCutoff),
|
||||
m_spanLog2(spanLog2),
|
||||
m_ssb(ssb)
|
||||
{ }
|
||||
};
|
||||
|
||||
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 MsgReportChannelSampleRateChanged : public Message {
|
||||
MESSAGE_CLASS_DECLARATION
|
||||
|
||||
public:
|
||||
|
||||
static MsgReportChannelSampleRateChanged* create()
|
||||
{
|
||||
return new MsgReportChannelSampleRateChanged();
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
MsgReportChannelSampleRateChanged() :
|
||||
Message()
|
||||
{ }
|
||||
};
|
||||
|
||||
ChannelAnalyzerNG(DeviceSourceAPI *deviceAPI);
|
||||
virtual ~ChannelAnalyzerNG();
|
||||
void setSampleSink(BasebandSampleSink* sampleSink) { m_sampleSink = sampleSink; }
|
||||
|
||||
void configure(MessageQueue* messageQueue,
|
||||
int channelSampleRate,
|
||||
@ -41,6 +133,7 @@ public:
|
||||
int spanLog2,
|
||||
bool ssb);
|
||||
|
||||
DownChannelizer *getChannelizer() { return m_channelizer; }
|
||||
int getInputSampleRate() const { return m_running.m_inputSampleRate; }
|
||||
int getChannelSampleRate() const { return m_running.m_channelSampleRate; }
|
||||
double getMagSq() const { return m_magsq; }
|
||||
@ -50,48 +143,10 @@ public:
|
||||
virtual void stop();
|
||||
virtual bool handleMessage(const Message& cmd);
|
||||
|
||||
private slots:
|
||||
void channelizerInputSampleRateChanged();
|
||||
|
||||
private:
|
||||
class MsgConfigureChannelAnalyzer : public Message {
|
||||
MESSAGE_CLASS_DECLARATION
|
||||
|
||||
public:
|
||||
int getChannelSampleRate() const { return m_channelSampleRate; }
|
||||
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(
|
||||
int channelSampleRate,
|
||||
Real Bandwidth,
|
||||
Real LowCutoff,
|
||||
int spanLog2,
|
||||
bool ssb)
|
||||
{
|
||||
return new MsgConfigureChannelAnalyzer(channelSampleRate, Bandwidth, LowCutoff, spanLog2, ssb);
|
||||
}
|
||||
|
||||
private:
|
||||
int m_channelSampleRate;
|
||||
Real m_Bandwidth;
|
||||
Real m_LowCutoff;
|
||||
int m_spanLog2;
|
||||
bool m_ssb;
|
||||
|
||||
MsgConfigureChannelAnalyzer(
|
||||
int channelSampleRate,
|
||||
Real Bandwidth,
|
||||
Real LowCutoff,
|
||||
int spanLog2,
|
||||
bool ssb) :
|
||||
Message(),
|
||||
m_channelSampleRate(channelSampleRate),
|
||||
m_Bandwidth(Bandwidth),
|
||||
m_LowCutoff(LowCutoff),
|
||||
m_spanLog2(spanLog2),
|
||||
m_ssb(ssb)
|
||||
{ }
|
||||
};
|
||||
|
||||
struct Config
|
||||
{
|
||||
@ -117,6 +172,10 @@ private:
|
||||
Config m_config;
|
||||
Config m_running;
|
||||
|
||||
DeviceSourceAPI *m_deviceAPI;
|
||||
ThreadedBasebandSampleSink* m_threadedChannelizer;
|
||||
DownChannelizer* m_channelizer;
|
||||
|
||||
int m_undersampleCount;
|
||||
fftfilt::cmplx m_sum;
|
||||
bool m_usb;
|
||||
|
@ -159,7 +159,29 @@ bool ChannelAnalyzerNGGUI::deserialize(const QByteArray& data)
|
||||
|
||||
bool ChannelAnalyzerNGGUI::handleMessage(const Message& message __attribute__((unused)))
|
||||
{
|
||||
return false;
|
||||
if (ChannelAnalyzerNG::MsgReportChannelSampleRateChanged::match(message))
|
||||
{
|
||||
setNewFinalRate(m_spanLog2);
|
||||
applySettings();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void ChannelAnalyzerNGGUI::handleInputMessages()
|
||||
{
|
||||
Message* message;
|
||||
|
||||
while ((message = getInputMessageQueue()->pop()) != 0)
|
||||
{
|
||||
qDebug("ChannelAnalyzerGUI::handleInputMessages: message: %s", message->getIdentifier());
|
||||
|
||||
if (handleMessage(*message))
|
||||
{
|
||||
delete message;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ChannelAnalyzerNGGUI::viewChanged()
|
||||
@ -174,12 +196,12 @@ void ChannelAnalyzerNGGUI::tick()
|
||||
ui->channelPower->setText(tr("%1 dB").arg(m_channelPowerDbAvg.average(), 0, 'f', 1));
|
||||
}
|
||||
|
||||
void ChannelAnalyzerNGGUI::channelizerInputSampleRateChanged()
|
||||
{
|
||||
//ui->channelSampleRate->setValueRange(7, 2000U, m_channelAnalyzer->getInputSampleRate());
|
||||
setNewFinalRate(m_spanLog2);
|
||||
applySettings();
|
||||
}
|
||||
//void ChannelAnalyzerNGGUI::channelizerInputSampleRateChanged()
|
||||
//{
|
||||
// //ui->channelSampleRate->setValueRange(7, 2000U, m_channelAnalyzer->getInputSampleRate());
|
||||
// setNewFinalRate(m_spanLog2);
|
||||
// applySettings();
|
||||
//}
|
||||
|
||||
void ChannelAnalyzerNGGUI::on_channelSampleRate_changed(quint64 value)
|
||||
{
|
||||
@ -204,7 +226,7 @@ int ChannelAnalyzerNGGUI::getRequestedChannelSampleRate()
|
||||
if (ui->useRationalDownsampler->isChecked()) {
|
||||
return ui->channelSampleRate->getValueNew();
|
||||
} else {
|
||||
return m_channelizer->getInputSampleRate();
|
||||
return m_channelAnalyzer->getChannelizer()->getInputSampleRate();
|
||||
}
|
||||
}
|
||||
|
||||
@ -348,11 +370,13 @@ ChannelAnalyzerNGGUI::ChannelAnalyzerNGGUI(PluginAPI* pluginAPI, DeviceSourceAPI
|
||||
m_spectrumVis = new SpectrumVis(ui->glSpectrum);
|
||||
m_scopeVis = new ScopeVisNG(ui->glScope);
|
||||
m_spectrumScopeComboVis = new SpectrumScopeNGComboVis(m_spectrumVis, m_scopeVis);
|
||||
m_channelAnalyzer = new ChannelAnalyzerNG(m_spectrumScopeComboVis);
|
||||
m_channelizer = new DownChannelizer(m_channelAnalyzer);
|
||||
m_threadedChannelizer = new ThreadedBasebandSampleSink(m_channelizer, this);
|
||||
connect(m_channelizer, SIGNAL(inputSampleRateChanged()), this, SLOT(channelizerInputSampleRateChanged()));
|
||||
m_deviceAPI->addThreadedSink(m_threadedChannelizer);
|
||||
m_channelAnalyzer = new ChannelAnalyzerNG(m_deviceAPI);
|
||||
m_channelAnalyzer->setSampleSink(m_spectrumScopeComboVis);
|
||||
m_channelAnalyzer->setMessageQueueToGUI(getInputMessageQueue());
|
||||
// m_channelizer = new DownChannelizer(m_channelAnalyzer);
|
||||
// m_threadedChannelizer = new ThreadedBasebandSampleSink(m_channelizer, this);
|
||||
// connect(m_channelizer, SIGNAL(inputSampleRateChanged()), this, SLOT(channelizerInputSampleRateChanged()));
|
||||
// m_deviceAPI->addThreadedSink(m_threadedChannelizer);
|
||||
|
||||
ui->deltaFrequencyLabel->setText(QString("%1f").arg(QChar(0x94, 0x03)));
|
||||
ui->deltaFrequency->setColorMapper(ColorMapper(ColorMapper::GrayGold));
|
||||
@ -389,6 +413,8 @@ ChannelAnalyzerNGGUI::ChannelAnalyzerNGGUI(PluginAPI* pluginAPI, DeviceSourceAPI
|
||||
ui->spectrumGUI->setBuddies(m_spectrumVis->getInputMessageQueue(), m_spectrumVis, ui->glSpectrum);
|
||||
ui->scopeGUI->setBuddies(m_scopeVis->getInputMessageQueue(), m_scopeVis, ui->glScope);
|
||||
|
||||
connect(getInputMessageQueue(), SIGNAL(messageEnqueued()), this, SLOT(handleInputMessages()));
|
||||
|
||||
applySettings();
|
||||
setNewFinalRate(m_spanLog2);
|
||||
}
|
||||
@ -396,9 +422,9 @@ ChannelAnalyzerNGGUI::ChannelAnalyzerNGGUI(PluginAPI* pluginAPI, DeviceSourceAPI
|
||||
ChannelAnalyzerNGGUI::~ChannelAnalyzerNGGUI()
|
||||
{
|
||||
m_deviceAPI->removeChannelInstance(this);
|
||||
m_deviceAPI->removeThreadedSink(m_threadedChannelizer);
|
||||
delete m_threadedChannelizer;
|
||||
delete m_channelizer;
|
||||
// m_deviceAPI->removeThreadedSink(m_threadedChannelizer);
|
||||
// delete m_threadedChannelizer;
|
||||
// delete m_channelizer;
|
||||
delete m_channelAnalyzer;
|
||||
delete m_spectrumVis;
|
||||
delete m_scopeVis;
|
||||
@ -514,14 +540,25 @@ void ChannelAnalyzerNGGUI::applySettings()
|
||||
setTitleColor(m_channelMarker.getColor());
|
||||
ui->deltaFrequency->setValue(m_channelMarker.getCenterFrequency());
|
||||
|
||||
m_channelizer->configure(m_channelizer->getInputMessageQueue(),
|
||||
//m_channelizer->getInputSampleRate(),
|
||||
getRequestedChannelSampleRate(),
|
||||
m_channelMarker.getCenterFrequency());
|
||||
int sampleRate = getRequestedChannelSampleRate();
|
||||
|
||||
ChannelAnalyzerNG::MsgConfigureChannelizer *msgChannelizer = ChannelAnalyzerNG::MsgConfigureChannelizer::create(sampleRate, m_channelMarker.getCenterFrequency());
|
||||
m_channelAnalyzer->getInputMessageQueue()->push(msgChannelizer);
|
||||
|
||||
ChannelAnalyzerNG::MsgConfigureChannelizer *msg =
|
||||
ChannelAnalyzerNG::MsgConfigureChannelizer::create(
|
||||
sampleRate,
|
||||
m_channelMarker.getCenterFrequency());
|
||||
m_channelAnalyzer->getInputMessageQueue()->push(msg);
|
||||
|
||||
// m_channelizer->configure(m_channelizer->getInputMessageQueue(),
|
||||
// //m_channelizer->getInputSampleRate(),
|
||||
// getRequestedChannelSampleRate(),
|
||||
// m_channelMarker.getCenterFrequency());
|
||||
|
||||
m_channelAnalyzer->configure(m_channelAnalyzer->getInputMessageQueue(),
|
||||
//m_channelizer->getInputSampleRate(), // TODO: specify required channel sample rate
|
||||
getRequestedChannelSampleRate(), // TODO: specify required channel sample rate
|
||||
sampleRate, // TODO: specify required channel sample rate
|
||||
ui->BW->value() * 100.0,
|
||||
ui->lowCut->value() * 100.0,
|
||||
m_spanLog2,
|
||||
|
@ -17,10 +17,10 @@
|
||||
#ifndef INCLUDE_CHANNELANALYZERNGGUI_H
|
||||
#define INCLUDE_CHANNELANALYZERNGGUI_H
|
||||
|
||||
#include <plugin/plugininstancegui.h>
|
||||
#include "gui/rollupwidget.h"
|
||||
#include "dsp/channelmarker.h"
|
||||
#include "dsp/movingaverage.h"
|
||||
#include "plugin/plugininstanceui.h"
|
||||
#include "util/messagequeue.h"
|
||||
|
||||
class PluginAPI;
|
||||
@ -37,7 +37,7 @@ namespace Ui {
|
||||
class ChannelAnalyzerNGGUI;
|
||||
}
|
||||
|
||||
class ChannelAnalyzerNGGUI : public RollupWidget, public PluginInstanceUI {
|
||||
class ChannelAnalyzerNGGUI : public RollupWidget, public PluginInstanceGUI {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
@ -59,7 +59,7 @@ public:
|
||||
|
||||
private slots:
|
||||
void viewChanged();
|
||||
void channelizerInputSampleRateChanged();
|
||||
// void channelizerInputSampleRateChanged();
|
||||
void on_deltaFrequency_changed(qint64 value);
|
||||
void on_channelSampleRate_changed(quint64 value);
|
||||
void on_useRationalDownsampler_toggled(bool checked);
|
||||
@ -69,6 +69,7 @@ private slots:
|
||||
void on_ssb_toggled(bool checked);
|
||||
void onWidgetRolled(QWidget* widget, bool rollDown);
|
||||
void onMenuDoubleClicked();
|
||||
void handleInputMessages();
|
||||
void tick();
|
||||
|
||||
private:
|
||||
@ -82,8 +83,8 @@ private:
|
||||
int m_spanLog2;
|
||||
MovingAverage<double> m_channelPowerDbAvg;
|
||||
|
||||
ThreadedBasebandSampleSink* m_threadedChannelizer;
|
||||
DownChannelizer* m_channelizer;
|
||||
// ThreadedBasebandSampleSink* m_threadedChannelizer;
|
||||
// DownChannelizer* m_channelizer;
|
||||
ChannelAnalyzerNG* m_channelAnalyzer;
|
||||
SpectrumScopeNGComboVis* m_spectrumScopeComboVis;
|
||||
SpectrumVis* m_spectrumVis;
|
||||
|
@ -48,7 +48,7 @@ void ChannelAnalyzerNGPlugin::initPlugin(PluginAPI* pluginAPI)
|
||||
m_pluginAPI->registerRxChannel(ChannelAnalyzerNGGUI::m_channelID, this);
|
||||
}
|
||||
|
||||
PluginInstanceUI* ChannelAnalyzerNGPlugin::createRxChannel(const QString& channelName, DeviceSourceAPI *deviceAPI)
|
||||
PluginInstanceGUI* ChannelAnalyzerNGPlugin::createRxChannel(const QString& channelName, DeviceSourceAPI *deviceAPI)
|
||||
{
|
||||
if(channelName == ChannelAnalyzerNGGUI::m_channelID)
|
||||
{
|
||||
|
@ -34,7 +34,7 @@ public:
|
||||
const PluginDescriptor& getPluginDescriptor() const;
|
||||
void initPlugin(PluginAPI* pluginAPI);
|
||||
|
||||
PluginInstanceUI* createRxChannel(const QString& channelName, DeviceSourceAPI *deviceAPI);
|
||||
PluginInstanceGUI* createRxChannel(const QString& channelName, DeviceSourceAPI *deviceAPI);
|
||||
|
||||
private:
|
||||
static const PluginDescriptor m_pluginDescriptor;
|
||||
|
@ -3,12 +3,14 @@ project(am)
|
||||
set(am_SOURCES
|
||||
amdemod.cpp
|
||||
amdemodgui.cpp
|
||||
amdemodsettings.cpp
|
||||
amdemodplugin.cpp
|
||||
)
|
||||
|
||||
set(am_HEADERS
|
||||
amdemod.h
|
||||
amdemodgui.h
|
||||
amdemodsettings.h
|
||||
amdemodplugin.h
|
||||
)
|
||||
|
||||
|
@ -26,12 +26,16 @@
|
||||
#include "audio/audiooutput.h"
|
||||
#include "dsp/dspengine.h"
|
||||
#include "dsp/pidcontroller.h"
|
||||
#include "dsp/threadedbasebandsamplesink.h"
|
||||
#include "device/devicesourceapi.h"
|
||||
|
||||
MESSAGE_CLASS_DEFINITION(AMDemod::MsgConfigureAMDemod, Message)
|
||||
MESSAGE_CLASS_DEFINITION(AMDemod::MsgConfigureChannelizer, Message)
|
||||
|
||||
const int AMDemod::m_udpBlockSize = 512;
|
||||
|
||||
AMDemod::AMDemod() :
|
||||
AMDemod::AMDemod(DeviceSourceAPI *deviceAPI) :
|
||||
m_deviceAPI(deviceAPI),
|
||||
m_squelchOpen(false),
|
||||
m_magsqSum(0.0f),
|
||||
m_magsqPeak(0.0f),
|
||||
@ -43,14 +47,9 @@ AMDemod::AMDemod() :
|
||||
{
|
||||
setObjectName("AMDemod");
|
||||
|
||||
m_config.m_inputSampleRate = 96000;
|
||||
m_config.m_inputFrequencyOffset = 0;
|
||||
m_config.m_rfBandwidth = 5000;
|
||||
m_config.m_squelch = -40.0;
|
||||
m_config.m_volume = 2.0;
|
||||
m_config.m_audioSampleRate = DSPEngine::instance()->getAudioSampleRate();
|
||||
|
||||
apply();
|
||||
m_channelizer = new DownChannelizer(this);
|
||||
m_threadedChannelizer = new ThreadedBasebandSampleSink(m_channelizer, this);
|
||||
m_deviceAPI->addThreadedSink(m_threadedChannelizer);
|
||||
|
||||
m_audioBuffer.resize(1<<14);
|
||||
m_audioBufferFill = 0;
|
||||
@ -60,7 +59,9 @@ AMDemod::AMDemod() :
|
||||
m_magsq = 0.0;
|
||||
|
||||
DSPEngine::instance()->addAudioSink(&m_audioFifo);
|
||||
m_udpBufferAudio = new UDPSink<qint16>(this, m_udpBlockSize, m_config.m_udpPort);
|
||||
m_udpBufferAudio = new UDPSink<qint16>(this, m_udpBlockSize, m_settings.m_udpPort);
|
||||
|
||||
applySettings(m_settings, true);
|
||||
}
|
||||
|
||||
AMDemod::~AMDemod()
|
||||
@ -69,29 +70,6 @@ AMDemod::~AMDemod()
|
||||
delete m_udpBufferAudio;
|
||||
}
|
||||
|
||||
void AMDemod::configure(MessageQueue* messageQueue,
|
||||
Real rfBandwidth,
|
||||
Real volume,
|
||||
Real squelch,
|
||||
bool audioMute,
|
||||
bool bandpassEnable,
|
||||
bool copyAudioToUDP,
|
||||
const QString& udpAddress,
|
||||
quint16 udpPort,
|
||||
bool force)
|
||||
{
|
||||
Message* cmd = MsgConfigureAMDemod::create(rfBandwidth,
|
||||
volume,
|
||||
squelch,
|
||||
audioMute,
|
||||
bandpassEnable,
|
||||
copyAudioToUDP,
|
||||
udpAddress,
|
||||
udpPort,
|
||||
force);
|
||||
messageQueue->push(cmd);
|
||||
}
|
||||
|
||||
void AMDemod::feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end, bool firstOfBurst __attribute__((unused)))
|
||||
{
|
||||
Complex ci;
|
||||
@ -142,8 +120,8 @@ void AMDemod::feed(const SampleVector::const_iterator& begin, const SampleVector
|
||||
|
||||
void AMDemod::start()
|
||||
{
|
||||
qDebug() << "AMDemod::start: m_inputSampleRate: " << m_config.m_inputSampleRate
|
||||
<< " m_inputFrequencyOffset: " << m_config.m_inputFrequencyOffset;
|
||||
qDebug() << "AMDemod::start: m_inputSampleRate: " << m_settings.m_inputSampleRate
|
||||
<< " m_inputFrequencyOffset: " << m_settings.m_inputFrequencyOffset;
|
||||
|
||||
m_squelchCount = 0;
|
||||
m_audioFifo.clear();
|
||||
@ -161,41 +139,51 @@ bool AMDemod::handleMessage(const Message& cmd)
|
||||
{
|
||||
DownChannelizer::MsgChannelizerNotification& notif = (DownChannelizer::MsgChannelizerNotification&) cmd;
|
||||
|
||||
m_config.m_inputSampleRate = notif.getSampleRate();
|
||||
m_config.m_inputFrequencyOffset = notif.getFrequencyOffset();
|
||||
AMDemodSettings settings = m_settings;
|
||||
|
||||
apply();
|
||||
settings.m_inputSampleRate = notif.getSampleRate();
|
||||
settings.m_inputFrequencyOffset = notif.getFrequencyOffset();
|
||||
|
||||
qDebug() << "AMDemod::handleMessage: MsgChannelizerNotification:"
|
||||
<< " m_inputSampleRate: " << m_config.m_inputSampleRate
|
||||
<< " m_inputFrequencyOffset: " << m_config.m_inputFrequencyOffset;
|
||||
applySettings(settings);
|
||||
|
||||
qDebug() << "AMDemod::handleMessage: MsgChannelizerNotification:"
|
||||
<< " m_inputSampleRate: " << settings.m_inputSampleRate
|
||||
<< " m_inputFrequencyOffset: " << settings.m_inputFrequencyOffset;
|
||||
|
||||
return true;
|
||||
}
|
||||
else if (MsgConfigureChannelizer::match(cmd))
|
||||
{
|
||||
MsgConfigureChannelizer& cfg = (MsgConfigureChannelizer&) cmd;
|
||||
|
||||
m_channelizer->configure(m_channelizer->getInputMessageQueue(),
|
||||
cfg.getSampleRate(),
|
||||
cfg.getCenterFrequency());
|
||||
|
||||
return true;
|
||||
}
|
||||
else if (MsgConfigureAMDemod::match(cmd))
|
||||
{
|
||||
MsgConfigureAMDemod& cfg = (MsgConfigureAMDemod&) cmd;
|
||||
MsgConfigureAMDemod& cfg = (MsgConfigureAMDemod&) cmd;
|
||||
|
||||
m_config.m_rfBandwidth = cfg.getRFBandwidth();
|
||||
m_config.m_volume = cfg.getVolume();
|
||||
m_config.m_squelch = cfg.getSquelch();
|
||||
m_config.m_audioMute = cfg.getAudioMute();
|
||||
m_config.m_bandpassEnable = cfg.getBandpassEnable();
|
||||
m_config.m_copyAudioToUDP = cfg.getCopyAudioToUDP();
|
||||
m_config.m_udpAddress = cfg.getUDPAddress();
|
||||
m_config.m_udpPort = cfg.getUDPPort();
|
||||
AMDemodSettings settings = cfg.getSettings();
|
||||
|
||||
apply(cfg.getForce());
|
||||
// These settings are set with DownChannelizer::MsgChannelizerNotification
|
||||
settings.m_inputSampleRate = m_settings.m_inputSampleRate;
|
||||
settings.m_inputFrequencyOffset = m_settings.m_inputFrequencyOffset;
|
||||
|
||||
qDebug() << "AMDemod::handleMessage: MsgConfigureAMDemod:"
|
||||
<< " m_rfBandwidth: " << m_config.m_rfBandwidth
|
||||
<< " m_volume: " << m_config.m_volume
|
||||
<< " m_squelch: " << m_config.m_squelch
|
||||
<< " m_audioMute: " << m_config.m_audioMute
|
||||
<< " m_bandpassEnable: " << m_config.m_bandpassEnable
|
||||
<< " m_copyAudioToUDP: " << m_config.m_copyAudioToUDP
|
||||
<< " m_udpAddress: " << m_config.m_udpAddress
|
||||
<< " m_udpPort: " << m_config.m_udpPort;
|
||||
applySettings(settings, cfg.getForce());
|
||||
|
||||
qDebug() << "AMDemod::handleMessage: MsgConfigureAMDemod:"
|
||||
<< " m_rfBandwidth: " << settings.m_rfBandwidth
|
||||
<< " m_volume: " << settings.m_volume
|
||||
<< " m_squelch: " << settings.m_squelch
|
||||
<< " m_audioMute: " << settings.m_audioMute
|
||||
<< " m_bandpassEnable: " << settings.m_bandpassEnable
|
||||
<< " m_copyAudioToUDP: " << settings.m_copyAudioToUDP
|
||||
<< " m_udpAddress: " << settings.m_udpAddress
|
||||
<< " m_udpPort: " << settings.m_udpPort
|
||||
<< " force: " << cfg.getForce();
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -205,40 +193,38 @@ bool AMDemod::handleMessage(const Message& cmd)
|
||||
}
|
||||
}
|
||||
|
||||
void AMDemod::apply(bool force)
|
||||
void AMDemod::applySettings(const AMDemodSettings& settings, bool force)
|
||||
{
|
||||
|
||||
if ((m_config.m_inputFrequencyOffset != m_running.m_inputFrequencyOffset) ||
|
||||
(m_config.m_inputSampleRate != m_running.m_inputSampleRate) || force)
|
||||
{
|
||||
m_nco.setFreq(-m_config.m_inputFrequencyOffset, m_config.m_inputSampleRate);
|
||||
}
|
||||
|
||||
if((m_config.m_inputSampleRate != m_running.m_inputSampleRate) ||
|
||||
(m_config.m_rfBandwidth != m_running.m_rfBandwidth) ||
|
||||
(m_config.m_audioSampleRate != m_running.m_audioSampleRate) ||
|
||||
(m_config.m_bandpassEnable != m_running.m_bandpassEnable) || force)
|
||||
{
|
||||
m_settingsMutex.lock();
|
||||
m_interpolator.create(16, m_config.m_inputSampleRate, m_config.m_rfBandwidth / 2.2f);
|
||||
m_interpolatorDistanceRemain = 0;
|
||||
m_interpolatorDistance = (Real) m_config.m_inputSampleRate / (Real) m_config.m_audioSampleRate;
|
||||
m_bandpass.create(301, m_config.m_audioSampleRate, 300.0, m_config.m_rfBandwidth / 2.0f);
|
||||
m_settingsMutex.unlock();
|
||||
}
|
||||
|
||||
if ((m_config.m_squelch != m_running.m_squelch) || force)
|
||||
{
|
||||
m_squelchLevel = pow(10.0, m_config.m_squelch / 20.0);
|
||||
m_squelchLevel *= m_squelchLevel;
|
||||
}
|
||||
|
||||
if ((m_config.m_udpAddress != m_running.m_udpAddress)
|
||||
|| (m_config.m_udpPort != m_running.m_udpPort) || force)
|
||||
if ((m_settings.m_inputFrequencyOffset != settings.m_inputFrequencyOffset) ||
|
||||
(m_settings.m_inputSampleRate != settings.m_inputSampleRate) || force)
|
||||
{
|
||||
m_udpBufferAudio->setAddress(m_config.m_udpAddress);
|
||||
m_udpBufferAudio->setPort(m_config.m_udpPort);
|
||||
m_nco.setFreq(-settings.m_inputFrequencyOffset, settings.m_inputSampleRate);
|
||||
}
|
||||
|
||||
m_running = m_config;
|
||||
if((m_settings.m_inputSampleRate != settings.m_inputSampleRate) ||
|
||||
(m_settings.m_rfBandwidth != settings.m_rfBandwidth) ||
|
||||
(m_settings.m_audioSampleRate != settings.m_audioSampleRate) ||
|
||||
(m_settings.m_bandpassEnable != settings.m_bandpassEnable) || force)
|
||||
{
|
||||
m_settingsMutex.lock();
|
||||
m_interpolator.create(16, settings.m_inputSampleRate, settings.m_rfBandwidth / 2.2f);
|
||||
m_interpolatorDistanceRemain = 0;
|
||||
m_interpolatorDistance = (Real) settings.m_inputSampleRate / (Real) settings.m_audioSampleRate;
|
||||
m_bandpass.create(301, settings.m_audioSampleRate, 300.0, settings.m_rfBandwidth / 2.0f);
|
||||
m_settingsMutex.unlock();
|
||||
}
|
||||
|
||||
if ((m_settings.m_squelch != settings.m_squelch) || force)
|
||||
{
|
||||
m_squelchLevel = pow(10.0, settings.m_squelch / 10.0);
|
||||
}
|
||||
|
||||
if ((m_settings.m_udpAddress != settings.m_udpAddress)
|
||||
|| (m_settings.m_udpPort != settings.m_udpPort) || force)
|
||||
{
|
||||
m_udpBufferAudio->setAddress(const_cast<QString&>(settings.m_udpAddress));
|
||||
m_udpBufferAudio->setPort(settings.m_udpPort);
|
||||
}
|
||||
|
||||
m_settings = settings;
|
||||
}
|
||||
|
@ -27,23 +27,63 @@
|
||||
#include "dsp/bandpass.h"
|
||||
#include "audio/audiofifo.h"
|
||||
#include "util/message.h"
|
||||
#include "amdemodsettings.h"
|
||||
|
||||
class DeviceSourceAPI;
|
||||
class DownChannelizer;
|
||||
class ThreadedBasebandSampleSink;
|
||||
|
||||
class AMDemod : public BasebandSampleSink {
|
||||
Q_OBJECT
|
||||
public:
|
||||
AMDemod();
|
||||
~AMDemod();
|
||||
class MsgConfigureAMDemod : public Message {
|
||||
MESSAGE_CLASS_DECLARATION
|
||||
|
||||
void configure(MessageQueue* messageQueue,
|
||||
Real rfBandwidth,
|
||||
Real volume,
|
||||
Real squelch,
|
||||
bool audioMute,
|
||||
bool bandpassEnable,
|
||||
bool copyAudioToUDP,
|
||||
const QString& udpAddress,
|
||||
quint16 udpPort,
|
||||
bool force);
|
||||
public:
|
||||
const AMDemodSettings& getSettings() const { return m_settings; }
|
||||
bool getForce() const { return m_force; }
|
||||
|
||||
static MsgConfigureAMDemod* create(const AMDemodSettings& settings, bool force)
|
||||
{
|
||||
return new MsgConfigureAMDemod(settings, force);
|
||||
}
|
||||
|
||||
private:
|
||||
AMDemodSettings m_settings;
|
||||
bool m_force;
|
||||
|
||||
MsgConfigureAMDemod(const AMDemodSettings& 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)
|
||||
{ }
|
||||
};
|
||||
|
||||
AMDemod(DeviceSourceAPI *deviceAPI);
|
||||
~AMDemod();
|
||||
|
||||
virtual void feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end, bool po);
|
||||
virtual void start();
|
||||
@ -64,109 +104,16 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
class MsgConfigureAMDemod : public Message {
|
||||
MESSAGE_CLASS_DECLARATION
|
||||
|
||||
public:
|
||||
Real getRFBandwidth() const { return m_rfBandwidth; }
|
||||
Real getVolume() const { return m_volume; }
|
||||
Real getSquelch() const { return m_squelch; }
|
||||
bool getAudioMute() const { return m_audioMute; }
|
||||
bool getBandpassEnable() const { return m_bandpassEnable; }
|
||||
bool getCopyAudioToUDP() const { return m_copyAudioToUDP; }
|
||||
const QString& getUDPAddress() const { return m_udpAddress; }
|
||||
quint16 getUDPPort() const { return m_udpPort; }
|
||||
bool getForce() const { return m_force; }
|
||||
|
||||
static MsgConfigureAMDemod* create(Real rfBandwidth,
|
||||
Real volume,
|
||||
Real squelch,
|
||||
bool audioMute,
|
||||
bool bandpassEnable,
|
||||
bool copyAudioToUDP,
|
||||
const QString& udpAddress,
|
||||
quint16 udpPort,
|
||||
bool force)
|
||||
{
|
||||
return new MsgConfigureAMDemod(rfBandwidth,
|
||||
volume,
|
||||
squelch,
|
||||
audioMute,
|
||||
bandpassEnable,
|
||||
copyAudioToUDP,
|
||||
udpAddress,
|
||||
udpPort,
|
||||
force);
|
||||
}
|
||||
|
||||
private:
|
||||
Real m_rfBandwidth;
|
||||
Real m_volume;
|
||||
Real m_squelch;
|
||||
bool m_audioMute;
|
||||
bool m_bandpassEnable;
|
||||
bool m_copyAudioToUDP;
|
||||
QString m_udpAddress;
|
||||
quint16 m_udpPort;
|
||||
bool m_force;
|
||||
|
||||
MsgConfigureAMDemod(Real rfBandwidth,
|
||||
Real volume,
|
||||
Real squelch,
|
||||
bool audioMute,
|
||||
bool bandpassEnable,
|
||||
bool copyAudioToUDP,
|
||||
const QString& udpAddress,
|
||||
quint16 udpPort,
|
||||
bool force) :
|
||||
Message(),
|
||||
m_rfBandwidth(rfBandwidth),
|
||||
m_volume(volume),
|
||||
m_squelch(squelch),
|
||||
m_audioMute(audioMute),
|
||||
m_bandpassEnable(bandpassEnable),
|
||||
m_copyAudioToUDP(copyAudioToUDP),
|
||||
m_udpAddress(udpAddress),
|
||||
m_udpPort(udpPort),
|
||||
m_force(force)
|
||||
{ }
|
||||
};
|
||||
|
||||
enum RateState {
|
||||
RSInitialFill,
|
||||
RSRunning
|
||||
};
|
||||
|
||||
struct Config {
|
||||
int m_inputSampleRate;
|
||||
qint64 m_inputFrequencyOffset;
|
||||
Real m_rfBandwidth;
|
||||
Real m_squelch;
|
||||
Real m_volume;
|
||||
quint32 m_audioSampleRate;
|
||||
bool m_audioMute;
|
||||
bool m_bandpassEnable;
|
||||
bool m_copyAudioToUDP;
|
||||
QString m_udpAddress;
|
||||
quint16 m_udpPort;
|
||||
DeviceSourceAPI *m_deviceAPI;
|
||||
ThreadedBasebandSampleSink* m_threadedChannelizer;
|
||||
DownChannelizer* m_channelizer;
|
||||
|
||||
Config() :
|
||||
m_inputSampleRate(-1),
|
||||
m_inputFrequencyOffset(0),
|
||||
m_rfBandwidth(-1),
|
||||
m_squelch(0),
|
||||
m_volume(0),
|
||||
m_audioSampleRate(0),
|
||||
m_audioMute(false),
|
||||
m_bandpassEnable(false),
|
||||
m_copyAudioToUDP(false),
|
||||
m_udpAddress("127.0.0.1"),
|
||||
m_udpPort(9999)
|
||||
{ }
|
||||
};
|
||||
|
||||
Config m_config;
|
||||
Config m_running;
|
||||
AMDemodSettings m_settings;
|
||||
|
||||
NCO m_nco;
|
||||
Interpolator m_interpolator;
|
||||
@ -194,7 +141,8 @@ private:
|
||||
|
||||
QMutex m_settingsMutex;
|
||||
|
||||
void apply(bool force = false);
|
||||
// void apply(bool force = false);
|
||||
void applySettings(const AMDemodSettings& settings, bool force = false);
|
||||
|
||||
void processOneSample(Complex &ci)
|
||||
{
|
||||
@ -213,9 +161,9 @@ private:
|
||||
|
||||
if (m_magsq >= m_squelchLevel)
|
||||
{
|
||||
if (m_squelchCount <= m_running.m_audioSampleRate / 10)
|
||||
if (m_squelchCount <= m_settings.m_audioSampleRate / 10)
|
||||
{
|
||||
if (m_squelchCount == m_running.m_audioSampleRate / 20) {
|
||||
if (m_squelchCount == m_settings.m_audioSampleRate / 20) {
|
||||
m_volumeAGC.fill(1.0);
|
||||
}
|
||||
|
||||
@ -232,28 +180,28 @@ private:
|
||||
|
||||
qint16 sample;
|
||||
|
||||
if ((m_squelchCount >= m_running.m_audioSampleRate / 20) && !m_running.m_audioMute)
|
||||
if ((m_squelchCount >= m_settings.m_audioSampleRate / 20) && !m_settings.m_audioMute)
|
||||
{
|
||||
Real demod = sqrt(magsq);
|
||||
m_volumeAGC.feed(demod);
|
||||
demod = (demod - m_volumeAGC.getValue()) / m_volumeAGC.getValue();
|
||||
|
||||
if (m_running.m_bandpassEnable)
|
||||
if (m_settings.m_bandpassEnable)
|
||||
{
|
||||
demod = m_bandpass.filter(demod);
|
||||
demod /= 301.0f;
|
||||
}
|
||||
|
||||
Real attack = (m_squelchCount - 0.05f * m_running.m_audioSampleRate) / (0.05f * m_running.m_audioSampleRate);
|
||||
sample = demod * attack * 2048 * m_running.m_volume;
|
||||
if (m_running.m_copyAudioToUDP) m_udpBufferAudio->write(demod * attack * 32768);
|
||||
Real attack = (m_squelchCount - 0.05f * m_settings.m_audioSampleRate) / (0.05f * m_settings.m_audioSampleRate);
|
||||
sample = demod * attack * 2048 * m_settings.m_volume;
|
||||
if (m_settings.m_copyAudioToUDP) m_udpBufferAudio->write(demod * attack * 32768);
|
||||
|
||||
m_squelchOpen = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
sample = 0;
|
||||
if (m_running.m_copyAudioToUDP) m_udpBufferAudio->write(0);
|
||||
if (m_settings.m_copyAudioToUDP) m_udpBufferAudio->write(0);
|
||||
m_squelchOpen = false;
|
||||
}
|
||||
|
||||
@ -273,6 +221,7 @@ private:
|
||||
m_audioBufferFill = 0;
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#endif // INCLUDE_AMDEMOD_H
|
||||
|
@ -68,83 +68,27 @@ void AMDemodGUI::setCenterFrequency(qint64 centerFrequency)
|
||||
|
||||
void AMDemodGUI::resetToDefaults()
|
||||
{
|
||||
blockApplySettings(true);
|
||||
|
||||
ui->rfBW->setValue(50);
|
||||
ui->volume->setValue(20);
|
||||
ui->squelch->setValue(-40);
|
||||
ui->deltaFrequency->setValue(0);
|
||||
|
||||
blockApplySettings(false);
|
||||
applySettings();
|
||||
m_settings.resetToDefaults();
|
||||
displaySettings();
|
||||
applySettings(true);
|
||||
}
|
||||
|
||||
QByteArray AMDemodGUI::serialize() const
|
||||
{
|
||||
SimpleSerializer s(1);
|
||||
s.writeS32(1, m_channelMarker.getCenterFrequency());
|
||||
s.writeS32(2, ui->rfBW->value());
|
||||
s.writeS32(4, ui->volume->value());
|
||||
s.writeS32(5, ui->squelch->value());
|
||||
s.writeBlob(6, m_channelMarker.serialize());
|
||||
s.writeU32(7, m_channelMarker.getColor().rgb());
|
||||
s.writeBool(8, ui->bandpassEnable->isChecked());
|
||||
return s.final();
|
||||
return m_settings.serialize();
|
||||
}
|
||||
|
||||
bool AMDemodGUI::deserialize(const QByteArray& data)
|
||||
{
|
||||
SimpleDeserializer d(data);
|
||||
|
||||
if(!d.isValid())
|
||||
{
|
||||
resetToDefaults();
|
||||
return false;
|
||||
}
|
||||
|
||||
if(d.getVersion() == 1)
|
||||
{
|
||||
QByteArray bytetmp;
|
||||
quint32 u32tmp;
|
||||
qint32 tmp;
|
||||
bool boolTmp;
|
||||
QString strtmp;
|
||||
|
||||
blockApplySettings(true);
|
||||
m_channelMarker.blockSignals(true);
|
||||
|
||||
d.readBlob(6, &bytetmp);
|
||||
m_channelMarker.deserialize(bytetmp);
|
||||
d.readS32(1, &tmp, 0);
|
||||
m_channelMarker.setCenterFrequency(tmp);
|
||||
d.readS32(2, &tmp, 4);
|
||||
ui->rfBW->setValue(tmp);
|
||||
d.readS32(3, &tmp, 3);
|
||||
//ui->afBW->setValue(tmp);
|
||||
d.readS32(4, &tmp, 20);
|
||||
ui->volume->setValue(tmp);
|
||||
d.readS32(5, &tmp, -40);
|
||||
ui->squelch->setValue(tmp);
|
||||
if(d.readU32(7, &u32tmp)) {
|
||||
m_channelMarker.setColor(u32tmp);
|
||||
}
|
||||
d.readBool(8, &boolTmp, false);
|
||||
ui->bandpassEnable->setChecked(boolTmp);
|
||||
|
||||
this->setWindowTitle(m_channelMarker.getTitle());
|
||||
displayUDPAddress();
|
||||
|
||||
blockApplySettings(false);
|
||||
m_channelMarker.blockSignals(false);
|
||||
|
||||
applySettings(true);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
resetToDefaults();
|
||||
return false;
|
||||
}
|
||||
if(m_settings.deserialize(data)) {
|
||||
updateChannelMarker();
|
||||
displaySettings();
|
||||
applySettings(true);
|
||||
return true;
|
||||
} else {
|
||||
resetToDefaults();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool AMDemodGUI::handleMessage(const Message& message __attribute__((unused)))
|
||||
@ -155,17 +99,25 @@ bool AMDemodGUI::handleMessage(const Message& message __attribute__((unused)))
|
||||
void AMDemodGUI::channelMarkerChanged()
|
||||
{
|
||||
this->setWindowTitle(m_channelMarker.getTitle());
|
||||
m_settings.m_inputFrequencyOffset = m_channelMarker.getCenterFrequency();
|
||||
m_settings.m_udpAddress = m_channelMarker.getUDPAddress(),
|
||||
m_settings.m_udpPort = m_channelMarker.getUDPSendPort(),
|
||||
m_settings.m_rgbColor = m_channelMarker.getColor().rgb();
|
||||
displayUDPAddress();
|
||||
//m_settings.m_channelMarkerBytes = m_channelMarker.serialize();
|
||||
applySettings();
|
||||
}
|
||||
|
||||
void AMDemodGUI::on_deltaFrequency_changed(qint64 value)
|
||||
{
|
||||
m_channelMarker.setCenterFrequency(value);
|
||||
m_settings.m_inputFrequencyOffset = m_channelMarker.getCenterFrequency();
|
||||
applySettings();
|
||||
}
|
||||
|
||||
void AMDemodGUI::on_bandpassEnable_toggled(bool checked __attribute__((unused)))
|
||||
void AMDemodGUI::on_bandpassEnable_toggled(bool checked)
|
||||
{
|
||||
m_settings.m_bandpassEnable = checked;
|
||||
applySettings();
|
||||
}
|
||||
|
||||
@ -173,28 +125,33 @@ void AMDemodGUI::on_rfBW_valueChanged(int value)
|
||||
{
|
||||
ui->rfBWText->setText(QString("%1 kHz").arg(value / 10.0, 0, 'f', 1));
|
||||
m_channelMarker.setBandwidth(value * 100);
|
||||
m_settings.m_rfBandwidth = value * 100;
|
||||
applySettings();
|
||||
}
|
||||
|
||||
void AMDemodGUI::on_volume_valueChanged(int value)
|
||||
{
|
||||
ui->volumeText->setText(QString("%1").arg(value / 10.0, 0, 'f', 1));
|
||||
m_settings.m_volume = value / 10.0;
|
||||
applySettings();
|
||||
}
|
||||
|
||||
void AMDemodGUI::on_squelch_valueChanged(int value)
|
||||
{
|
||||
ui->squelchText->setText(QString("%1 dB").arg(value));
|
||||
m_settings.m_squelch = value;
|
||||
applySettings();
|
||||
}
|
||||
|
||||
void AMDemodGUI::on_audioMute_toggled(bool checked __attribute__((unused)))
|
||||
void AMDemodGUI::on_audioMute_toggled(bool checked)
|
||||
{
|
||||
m_settings.m_audioMute = checked;
|
||||
applySettings();
|
||||
}
|
||||
|
||||
void AMDemodGUI::on_copyAudioToUDP_toggled(bool checked __attribute__((unused)))
|
||||
void AMDemodGUI::on_copyAudioToUDP_toggled(bool checked)
|
||||
{
|
||||
m_settings.m_copyAudioToUDP = checked;
|
||||
applySettings();
|
||||
}
|
||||
|
||||
@ -228,11 +185,7 @@ AMDemodGUI::AMDemodGUI(PluginAPI* pluginAPI, DeviceSourceAPI *deviceAPI, QWidget
|
||||
connect(this, SIGNAL(widgetRolled(QWidget*,bool)), this, SLOT(onWidgetRolled(QWidget*,bool)));
|
||||
connect(this, SIGNAL(customContextMenuRequested(const QPoint &)), this, SLOT(onMenuDialogCalled(const QPoint &)));
|
||||
|
||||
m_amDemod = new AMDemod();
|
||||
m_channelizer = new DownChannelizer(m_amDemod);
|
||||
m_threadedChannelizer = new ThreadedBasebandSampleSink(m_channelizer, this);
|
||||
//m_pluginAPI->addThreadedSink(m_threadedChannelizer);
|
||||
m_deviceAPI->addThreadedSink(m_threadedChannelizer);
|
||||
m_amDemod = new AMDemod(m_deviceAPI);
|
||||
|
||||
connect(&m_pluginAPI->getMainWindow()->getMasterTimer(), SIGNAL(timeout()), this, SLOT(tick())); // 50 ms
|
||||
|
||||
@ -241,7 +194,6 @@ AMDemodGUI::AMDemodGUI(PluginAPI* pluginAPI, DeviceSourceAPI *deviceAPI, QWidget
|
||||
ui->deltaFrequency->setValueRange(false, 7, -9999999, 9999999);
|
||||
ui->channelPowerMeter->setColorTheme(LevelMeterSignalDB::ColorGreenAndBlue);
|
||||
|
||||
//m_channelMarker = new ChannelMarker(this);
|
||||
m_channelMarker.setColor(Qt::yellow);
|
||||
m_channelMarker.setBandwidth(5000);
|
||||
m_channelMarker.setCenterFrequency(0);
|
||||
@ -250,6 +202,7 @@ AMDemodGUI::AMDemodGUI(PluginAPI* pluginAPI, DeviceSourceAPI *deviceAPI, QWidget
|
||||
m_channelMarker.setUDPSendPort(9999);
|
||||
m_channelMarker.setVisible(true);
|
||||
setTitleColor(m_channelMarker.getColor());
|
||||
m_settings.setChannelMarker(&m_channelMarker);
|
||||
|
||||
connect(&m_channelMarker, SIGNAL(changed()), this, SLOT(channelMarkerChanged()));
|
||||
|
||||
@ -257,17 +210,14 @@ AMDemodGUI::AMDemodGUI(PluginAPI* pluginAPI, DeviceSourceAPI *deviceAPI, QWidget
|
||||
m_deviceAPI->addChannelMarker(&m_channelMarker);
|
||||
m_deviceAPI->addRollupWidget(this);
|
||||
|
||||
displaySettings();
|
||||
applySettings(true);
|
||||
}
|
||||
|
||||
AMDemodGUI::~AMDemodGUI()
|
||||
{
|
||||
m_deviceAPI->removeChannelInstance(this);
|
||||
m_deviceAPI->removeThreadedSink(m_threadedChannelizer);
|
||||
delete m_threadedChannelizer;
|
||||
delete m_channelizer;
|
||||
delete m_amDemod;
|
||||
//delete m_channelMarker;
|
||||
delete ui;
|
||||
}
|
||||
|
||||
@ -282,30 +232,62 @@ void AMDemodGUI::applySettings(bool force)
|
||||
{
|
||||
setTitleColor(m_channelMarker.getColor());
|
||||
|
||||
m_channelizer->configure(m_channelizer->getInputMessageQueue(),
|
||||
48000,
|
||||
m_channelMarker.getCenterFrequency());
|
||||
AMDemod::MsgConfigureChannelizer* channelConfigMsg = AMDemod::MsgConfigureChannelizer::create(
|
||||
48000, m_channelMarker.getCenterFrequency());
|
||||
m_amDemod->getInputMessageQueue()->push(channelConfigMsg);
|
||||
|
||||
ui->deltaFrequency->setValue(m_channelMarker.getCenterFrequency());
|
||||
|
||||
m_amDemod->configure(m_amDemod->getInputMessageQueue(),
|
||||
ui->rfBW->value() * 100.0,
|
||||
ui->volume->value() / 10.0,
|
||||
ui->squelch->value(),
|
||||
ui->audioMute->isChecked(),
|
||||
ui->bandpassEnable->isChecked(),
|
||||
ui->copyAudioToUDP->isChecked(),
|
||||
m_channelMarker.getUDPAddress(),
|
||||
m_channelMarker.getUDPSendPort(),
|
||||
force);
|
||||
AMDemod::MsgConfigureAMDemod* message = AMDemod::MsgConfigureAMDemod::create( m_settings, force);
|
||||
m_amDemod->getInputMessageQueue()->push(message);
|
||||
}
|
||||
}
|
||||
|
||||
void AMDemodGUI::displaySettings()
|
||||
{
|
||||
blockApplySettings(true);
|
||||
|
||||
int displayValue = m_settings.m_rfBandwidth/100.0;
|
||||
ui->rfBW->setValue(displayValue);
|
||||
ui->rfBWText->setText(QString("%1 kHz").arg(displayValue / 10.0, 0, 'f', 1));
|
||||
m_channelMarker.setBandwidth(m_settings.m_rfBandwidth);
|
||||
|
||||
ui->volume->setValue(m_settings.m_volume * 10.0);
|
||||
ui->volumeText->setText(QString("%1").arg(m_settings.m_volume, 0, 'f', 1));
|
||||
|
||||
ui->squelch->setValue(m_settings.m_squelch);
|
||||
ui->squelchText->setText(QString("%1 dB").arg(m_settings.m_squelch));
|
||||
|
||||
ui->audioMute->setChecked(m_settings.m_audioMute);
|
||||
ui->bandpassEnable->setChecked(m_settings.m_bandpassEnable);
|
||||
ui->copyAudioToUDP->setChecked(m_settings.m_copyAudioToUDP);
|
||||
|
||||
m_channelMarker.blockSignals(true);
|
||||
m_channelMarker.setCenterFrequency(m_settings.m_inputFrequencyOffset);
|
||||
m_channelMarker.setUDPAddress(m_settings.m_udpAddress);
|
||||
m_channelMarker.setUDPSendPort(m_settings.m_udpPort);
|
||||
m_channelMarker.setColor(m_settings.m_rgbColor);
|
||||
setTitleColor(m_settings.m_rgbColor);
|
||||
m_channelMarker.blockSignals(false);
|
||||
|
||||
blockApplySettings(false);
|
||||
}
|
||||
|
||||
void AMDemodGUI::displayUDPAddress()
|
||||
{
|
||||
ui->copyAudioToUDP->setToolTip(QString("Copy audio output to UDP %1:%2").arg(m_channelMarker.getUDPAddress()).arg(m_channelMarker.getUDPSendPort()));
|
||||
}
|
||||
|
||||
void AMDemodGUI::updateChannelMarker()
|
||||
{
|
||||
m_channelMarker.blockSignals(true);
|
||||
|
||||
//m_channelMarker.deserialize(m_settings.m_channelMarkerBytes);
|
||||
this->setWindowTitle(m_channelMarker.getTitle());
|
||||
|
||||
m_channelMarker.blockSignals(false);
|
||||
}
|
||||
|
||||
void AMDemodGUI::leaveEvent(QEvent*)
|
||||
{
|
||||
blockApplySettings(true);
|
||||
|
@ -1,11 +1,12 @@
|
||||
#ifndef INCLUDE_AMDEMODGUI_H
|
||||
#define INCLUDE_AMDEMODGUI_H
|
||||
|
||||
#include <plugin/plugininstancegui.h>
|
||||
#include "gui/rollupwidget.h"
|
||||
#include "dsp/channelmarker.h"
|
||||
#include "dsp/movingaverage.h"
|
||||
#include "plugin/plugininstanceui.h"
|
||||
#include "util/messagequeue.h"
|
||||
#include "amdemodsettings.h"
|
||||
|
||||
class PluginAPI;
|
||||
class DeviceSourceAPI;
|
||||
@ -18,7 +19,7 @@ namespace Ui {
|
||||
class AMDemodGUI;
|
||||
}
|
||||
|
||||
class AMDemodGUI : public RollupWidget, public PluginInstanceUI {
|
||||
class AMDemodGUI : public RollupWidget, public PluginInstanceGUI {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
@ -56,10 +57,11 @@ private:
|
||||
PluginAPI* m_pluginAPI;
|
||||
DeviceSourceAPI* m_deviceAPI;
|
||||
ChannelMarker m_channelMarker;
|
||||
AMDemodSettings m_settings;
|
||||
bool m_doApplySettings;
|
||||
|
||||
ThreadedBasebandSampleSink* m_threadedChannelizer;
|
||||
DownChannelizer* m_channelizer;
|
||||
// ThreadedBasebandSampleSink* m_threadedChannelizer;
|
||||
// DownChannelizer* m_channelizer;
|
||||
AMDemod* m_amDemod;
|
||||
bool m_squelchOpen;
|
||||
uint32_t m_tickCount;
|
||||
@ -70,7 +72,9 @@ private:
|
||||
|
||||
void blockApplySettings(bool block);
|
||||
void applySettings(bool force = false);
|
||||
void displaySettings();
|
||||
void displayUDPAddress();
|
||||
void updateChannelMarker();
|
||||
|
||||
void leaveEvent(QEvent*);
|
||||
void enterEvent(QEvent*);
|
||||
|
@ -7,7 +7,7 @@
|
||||
|
||||
const PluginDescriptor AMDemodPlugin::m_pluginDescriptor = {
|
||||
QString("AM Demodulator"),
|
||||
QString("3.6.1"),
|
||||
QString("3.7.3"),
|
||||
QString("(c) Edouard Griffiths, F4EXB"),
|
||||
QString("https://github.com/f4exb/sdrangel"),
|
||||
true,
|
||||
@ -33,7 +33,7 @@ void AMDemodPlugin::initPlugin(PluginAPI* pluginAPI)
|
||||
m_pluginAPI->registerRxChannel(AMDemodGUI::m_channelID, this);
|
||||
}
|
||||
|
||||
PluginInstanceUI* AMDemodPlugin::createRxChannel(const QString& channelName, DeviceSourceAPI *deviceAPI)
|
||||
PluginInstanceGUI* AMDemodPlugin::createRxChannel(const QString& channelName, DeviceSourceAPI *deviceAPI)
|
||||
{
|
||||
if(channelName == AMDemodGUI::m_channelID)
|
||||
{
|
||||
|
@ -33,7 +33,7 @@ public:
|
||||
const PluginDescriptor& getPluginDescriptor() const;
|
||||
void initPlugin(PluginAPI* pluginAPI);
|
||||
|
||||
PluginInstanceUI* createRxChannel(const QString& channelName, DeviceSourceAPI *deviceAPI);
|
||||
PluginInstanceGUI* createRxChannel(const QString& channelName, DeviceSourceAPI *deviceAPI);
|
||||
|
||||
private:
|
||||
static const PluginDescriptor m_pluginDescriptor;
|
||||
|
100
plugins/channelrx/demodam/amdemodsettings.cpp
Normal file
@ -0,0 +1,100 @@
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// 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 "dsp/dspengine.h"
|
||||
#include "util/simpleserializer.h"
|
||||
#include "settings/serializable.h"
|
||||
#include "amdemodsettings.h"
|
||||
|
||||
AMDemodSettings::AMDemodSettings() :
|
||||
m_channelMarker(0)
|
||||
{
|
||||
resetToDefaults();
|
||||
}
|
||||
|
||||
void AMDemodSettings::resetToDefaults()
|
||||
{
|
||||
m_inputSampleRate = 96000;
|
||||
m_inputFrequencyOffset = 0;
|
||||
m_rfBandwidth = 5000;
|
||||
m_squelch = -40.0;
|
||||
m_volume = 2.0;
|
||||
m_audioSampleRate = DSPEngine::instance()->getAudioSampleRate();
|
||||
m_audioMute = false;
|
||||
m_bandpassEnable = false;
|
||||
m_copyAudioToUDP = false;
|
||||
m_udpAddress = "127.0.0.1";
|
||||
m_udpPort = 9999;
|
||||
}
|
||||
|
||||
QByteArray AMDemodSettings::serialize() const
|
||||
{
|
||||
SimpleSerializer s(1);
|
||||
s.writeS32(1, m_inputFrequencyOffset);
|
||||
s.writeS32(2, m_rfBandwidth/100);
|
||||
s.writeS32(4, m_volume*10);
|
||||
s.writeS32(5, m_squelch);
|
||||
|
||||
if (m_channelMarker) {
|
||||
s.writeBlob(6, m_channelMarker->serialize());
|
||||
}
|
||||
|
||||
s.writeU32(7, m_rgbColor);
|
||||
s.writeBool(8, m_bandpassEnable);
|
||||
return s.final();
|
||||
}
|
||||
|
||||
bool AMDemodSettings::deserialize(const QByteArray& data)
|
||||
{
|
||||
SimpleDeserializer d(data);
|
||||
|
||||
if(!d.isValid())
|
||||
{
|
||||
resetToDefaults();
|
||||
return false;
|
||||
}
|
||||
|
||||
if(d.getVersion() == 1)
|
||||
{
|
||||
QByteArray bytetmp;
|
||||
qint32 tmp;
|
||||
QString strtmp;
|
||||
|
||||
d.readS32(1, &m_inputFrequencyOffset, 0);
|
||||
d.readS32(2, &tmp, 4);
|
||||
m_rfBandwidth = 100 * tmp;
|
||||
d.readS32(4, &tmp, 20);
|
||||
m_volume = tmp * 0.1;
|
||||
d.readS32(5, &tmp, -40);
|
||||
m_squelch = tmp;
|
||||
d.readBlob(6, &bytetmp);
|
||||
|
||||
if (m_channelMarker) {
|
||||
m_channelMarker->deserialize(bytetmp);
|
||||
}
|
||||
|
||||
d.readU32(7, &m_rgbColor);
|
||||
d.readBool(8, &m_bandpassEnable, false);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
resetToDefaults();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
49
plugins/channelrx/demodam/amdemodsettings.h
Normal file
@ -0,0 +1,49 @@
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// 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_DEMODAM_AMDEMODSETTINGS_H_
|
||||
#define PLUGINS_CHANNELRX_DEMODAM_AMDEMODSETTINGS_H_
|
||||
|
||||
#include <QByteArray>
|
||||
|
||||
class Serializable;
|
||||
|
||||
struct AMDemodSettings
|
||||
{
|
||||
int m_inputSampleRate;
|
||||
qint32 m_inputFrequencyOffset;
|
||||
Real m_rfBandwidth;
|
||||
Real m_squelch;
|
||||
Real m_volume;
|
||||
quint32 m_audioSampleRate;
|
||||
bool m_audioMute;
|
||||
bool m_bandpassEnable;
|
||||
bool m_copyAudioToUDP;
|
||||
QString m_udpAddress;
|
||||
quint16 m_udpPort;
|
||||
quint32 m_rgbColor;
|
||||
Serializable *m_channelMarker;
|
||||
|
||||
AMDemodSettings();
|
||||
void resetToDefaults();
|
||||
void setChannelMarker(Serializable *channelMarker) { m_channelMarker = channelMarker; }
|
||||
QByteArray serialize() const;
|
||||
bool deserialize(const QByteArray& data);
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif /* PLUGINS_CHANNELRX_DEMODAM_AMDEMODSETTINGS_H_ */
|
@ -25,11 +25,13 @@ CONFIG(Debug):build_subdir = debug
|
||||
|
||||
SOURCES += amdemod.cpp\
|
||||
amdemodgui.cpp\
|
||||
amdemodplugin.cpp
|
||||
amdemodplugin.cpp\
|
||||
amdemodsettings.cpp
|
||||
|
||||
HEADERS += amdemod.h\
|
||||
amdemodgui.h\
|
||||
amdemodplugin.h
|
||||
amdemodplugin.h\
|
||||
amdemodsettings.h
|
||||
|
||||
FORMS += amdemodgui.ui
|
||||
|
||||
|
@ -31,9 +31,9 @@ MESSAGE_CLASS_DEFINITION(ATVDemod::MsgReportEffectiveSampleRate, Message)
|
||||
|
||||
const int ATVDemod::m_ssbFftLen = 1024;
|
||||
|
||||
ATVDemod::ATVDemod(BasebandSampleSink* objScopeSink) :
|
||||
m_objScopeSink(objScopeSink),
|
||||
m_objRegisteredATVScreen(NULL),
|
||||
ATVDemod::ATVDemod(DeviceSourceAPI *deviceAPI) :
|
||||
m_deviceAPI(deviceAPI),
|
||||
m_registeredATVScreen(NULL),
|
||||
m_intNumberSamplePerTop(0),
|
||||
m_intImageIndex(0),
|
||||
m_intSynchroPoints(0),
|
||||
@ -70,7 +70,7 @@ ATVDemod::ATVDemod(BasebandSampleSink* objScopeSink) :
|
||||
|
||||
m_objMagSqAverage.resize(32, 1.0);
|
||||
|
||||
m_DSBFilter = new fftfilt((2.0f * m_objRFConfig.m_fltRFBandwidth) / 1000000, 2 * m_ssbFftLen); // arbitrary 1 MS/s sample rate
|
||||
m_DSBFilter = new fftfilt((2.0f * m_rfConfig.m_fltRFBandwidth) / 1000000, 2 * m_ssbFftLen); // arbitrary 1 MS/s sample rate
|
||||
m_DSBFilterBuffer = new Complex[m_ssbFftLen];
|
||||
memset(m_DSBFilterBuffer, 0, sizeof(Complex)*(m_ssbFftLen));
|
||||
|
||||
@ -88,7 +88,7 @@ ATVDemod::~ATVDemod()
|
||||
|
||||
void ATVDemod::setATVScreen(ATVScreen *objScreen)
|
||||
{
|
||||
m_objRegisteredATVScreen = objScreen;
|
||||
m_registeredATVScreen = objScreen;
|
||||
}
|
||||
|
||||
void ATVDemod::configure(
|
||||
@ -188,12 +188,12 @@ void ATVDemod::feed(const SampleVector::const_iterator& begin, const SampleVecto
|
||||
#endif
|
||||
Complex c(fltI, fltQ);
|
||||
|
||||
if (m_objRFRunning.m_intFrequencyOffset != 0)
|
||||
if (m_rfRunning.m_intFrequencyOffset != 0)
|
||||
{
|
||||
c *= m_nco.nextIQ();
|
||||
}
|
||||
|
||||
if (m_objRFRunning.m_blndecimatorEnable)
|
||||
if (m_rfRunning.m_blndecimatorEnable)
|
||||
{
|
||||
if (m_interpolator.decimate(&m_interpolatorDistanceRemain, c, &ci))
|
||||
{
|
||||
@ -207,10 +207,10 @@ void ATVDemod::feed(const SampleVector::const_iterator& begin, const SampleVecto
|
||||
}
|
||||
}
|
||||
|
||||
if ((m_objRunning.m_intVideoTabIndex == 1) && (m_objScopeSink != 0)) // do only if scope tab is selected and scope is available
|
||||
if ((m_running.m_intVideoTabIndex == 1) && (m_scopeSink != 0)) // do only if scope tab is selected and scope is available
|
||||
{
|
||||
m_objScopeSink->feed(m_objScopeSampleBuffer.begin(), m_objScopeSampleBuffer.end(), false); // m_ssb = positive only
|
||||
m_objScopeSampleBuffer.clear();
|
||||
m_scopeSink->feed(m_scopeSampleBuffer.begin(), m_scopeSampleBuffer.end(), false); // m_ssb = positive only
|
||||
m_scopeSampleBuffer.clear();
|
||||
}
|
||||
|
||||
if (ptrBufferToRelease != 0)
|
||||
@ -223,7 +223,7 @@ void ATVDemod::feed(const SampleVector::const_iterator& begin, const SampleVecto
|
||||
|
||||
void ATVDemod::demod(Complex& c)
|
||||
{
|
||||
float fltDivSynchroBlack = 1.0f - m_objRunning.m_fltVoltLevelSynchroBlack;
|
||||
float fltDivSynchroBlack = 1.0f - m_running.m_fltVoltLevelSynchroBlack;
|
||||
float fltNormI;
|
||||
float fltNormQ;
|
||||
float fltNorm;
|
||||
@ -232,12 +232,12 @@ void ATVDemod::demod(Complex& c)
|
||||
|
||||
//********** FFT filtering **********
|
||||
|
||||
if (m_objRFRunning.m_blnFFTFiltering)
|
||||
if (m_rfRunning.m_blnFFTFiltering)
|
||||
{
|
||||
int n_out;
|
||||
fftfilt::cmplx *filtered;
|
||||
|
||||
n_out = m_DSBFilter->runAsym(c, &filtered, m_objRFRunning.m_enmModulation != ATV_LSB); // all usb except explicitely lsb
|
||||
n_out = m_DSBFilter->runAsym(c, &filtered, m_rfRunning.m_enmModulation != ATV_LSB); // all usb except explicitely lsb
|
||||
|
||||
if (n_out > 0)
|
||||
{
|
||||
@ -250,11 +250,11 @@ void ATVDemod::demod(Complex& c)
|
||||
|
||||
//********** demodulation **********
|
||||
|
||||
const float& fltI = m_objRFRunning.m_blnFFTFiltering ? m_DSBFilterBuffer[m_DSBFilterBufferIndex-1].real() : c.real();
|
||||
const float& fltQ = m_objRFRunning.m_blnFFTFiltering ? m_DSBFilterBuffer[m_DSBFilterBufferIndex-1].imag() : c.imag();
|
||||
const float& fltI = m_rfRunning.m_blnFFTFiltering ? m_DSBFilterBuffer[m_DSBFilterBufferIndex-1].real() : c.real();
|
||||
const float& fltQ = m_rfRunning.m_blnFFTFiltering ? m_DSBFilterBuffer[m_DSBFilterBufferIndex-1].imag() : c.imag();
|
||||
double magSq;
|
||||
|
||||
if ((m_objRFRunning.m_enmModulation == ATV_FM1) || (m_objRFRunning.m_enmModulation == ATV_FM2))
|
||||
if ((m_rfRunning.m_enmModulation == ATV_FM1) || (m_rfRunning.m_enmModulation == ATV_FM2))
|
||||
{
|
||||
//Amplitude FM
|
||||
magSq = fltI*fltI + fltQ*fltQ;
|
||||
@ -266,7 +266,7 @@ void ATVDemod::demod(Complex& c)
|
||||
//-2 > 2 : 0 -> 1 volt
|
||||
//0->0.3 synchro 0.3->1 image
|
||||
|
||||
if (m_objRFRunning.m_enmModulation == ATV_FM1)
|
||||
if (m_rfRunning.m_enmModulation == ATV_FM1)
|
||||
{
|
||||
//YDiff Cd
|
||||
fltVal = m_fltBufferI[0]*(fltNormQ - m_fltBufferQ[1]);
|
||||
@ -304,12 +304,12 @@ void ATVDemod::demod(Complex& c)
|
||||
m_fltBufferI[0]=fltNormI;
|
||||
m_fltBufferQ[0]=fltNormQ;
|
||||
|
||||
if (m_objRFRunning.m_fmDeviation != 1.0f)
|
||||
if (m_rfRunning.m_fmDeviation != 1.0f)
|
||||
{
|
||||
fltVal = ((fltVal - 0.5f) / m_objRFRunning.m_fmDeviation) + 0.5f;
|
||||
fltVal = ((fltVal - 0.5f) / m_rfRunning.m_fmDeviation) + 0.5f;
|
||||
}
|
||||
}
|
||||
else if (m_objRFRunning.m_enmModulation == ATV_AM)
|
||||
else if (m_rfRunning.m_enmModulation == ATV_AM)
|
||||
{
|
||||
//Amplitude AM
|
||||
magSq = fltI*fltI + fltQ*fltQ;
|
||||
@ -334,7 +334,7 @@ void ATVDemod::demod(Complex& c)
|
||||
fltVal -= m_fltAmpMin;
|
||||
fltVal /=m_fltAmpDelta;
|
||||
}
|
||||
else if ((m_objRFRunning.m_enmModulation == ATV_USB) || (m_objRFRunning.m_enmModulation == ATV_LSB))
|
||||
else if ((m_rfRunning.m_enmModulation == ATV_USB) || (m_rfRunning.m_enmModulation == ATV_LSB))
|
||||
{
|
||||
magSq = fltI*fltI + fltQ*fltQ;
|
||||
m_objMagSqAverage.feed(magSq);
|
||||
@ -349,7 +349,7 @@ void ATVDemod::demod(Complex& c)
|
||||
float mixI = fltI * bfoValues[0] - fltQ * bfoValues[1];
|
||||
float mixQ = fltI * bfoValues[1] + fltQ * bfoValues[0];
|
||||
|
||||
if (m_objRFRunning.m_enmModulation == ATV_USB) {
|
||||
if (m_rfRunning.m_enmModulation == ATV_USB) {
|
||||
fltVal = (mixI + mixQ);
|
||||
} else {
|
||||
fltVal = (mixI - mixQ);
|
||||
@ -371,7 +371,7 @@ void ATVDemod::demod(Complex& c)
|
||||
fltVal -= m_fltAmpMin;
|
||||
fltVal /=m_fltAmpDelta;
|
||||
}
|
||||
else if (m_objRFRunning.m_enmModulation == ATV_FM3)
|
||||
else if (m_rfRunning.m_enmModulation == ATV_FM3)
|
||||
{
|
||||
float rawDeviation;
|
||||
fltVal = m_objPhaseDiscri.phaseDiscriminatorDelta(c, magSq, rawDeviation) + 0.5f;
|
||||
@ -387,18 +387,18 @@ void ATVDemod::demod(Complex& c)
|
||||
fltVal = 0.0f;
|
||||
}
|
||||
|
||||
fltVal = m_objRunning.m_blnInvertVideo ? 1.0f - fltVal : fltVal;
|
||||
fltVal = m_running.m_blnInvertVideo ? 1.0f - fltVal : fltVal;
|
||||
fltVal = (fltVal < -1.0f) ? -1.0f : (fltVal > 1.0f) ? 1.0f : fltVal;
|
||||
|
||||
if ((m_objRunning.m_intVideoTabIndex == 1) && (m_objScopeSink != 0)) { // feed scope buffer only if scope is present and visible
|
||||
m_objScopeSampleBuffer.push_back(Sample(fltVal*32767.0f, 0.0f));
|
||||
if ((m_running.m_intVideoTabIndex == 1) && (m_scopeSink != 0)) { // feed scope buffer only if scope is present and visible
|
||||
m_scopeSampleBuffer.push_back(Sample(fltVal*32767.0f, 0.0f));
|
||||
}
|
||||
|
||||
m_fltAmpLineAverage += fltVal;
|
||||
|
||||
//********** gray level **********
|
||||
//-0.3 -> 0.7
|
||||
intVal = (int) 255.0*(fltVal - m_objRunning.m_fltVoltLevelSynchroBlack) / fltDivSynchroBlack;
|
||||
intVal = (int) 255.0*(fltVal - m_running.m_fltVoltLevelSynchroBlack) / fltDivSynchroBlack;
|
||||
|
||||
//0 -> 255
|
||||
if(intVal<0)
|
||||
@ -412,7 +412,7 @@ void ATVDemod::demod(Complex& c)
|
||||
|
||||
//********** process video sample **********
|
||||
|
||||
if (m_objRunning.m_enmATVStandard == ATVStdHSkip)
|
||||
if (m_running.m_enmATVStandard == ATVStdHSkip)
|
||||
{
|
||||
processHSkip(fltVal, intVal);
|
||||
}
|
||||
@ -438,12 +438,12 @@ bool ATVDemod::handleMessage(const Message& cmd)
|
||||
if (DownChannelizer::MsgChannelizerNotification::match(cmd))
|
||||
{
|
||||
DownChannelizer::MsgChannelizerNotification& objNotif = (DownChannelizer::MsgChannelizerNotification&) cmd;
|
||||
m_objConfig.m_intSampleRate = objNotif.getSampleRate();
|
||||
m_objRFConfig.m_intFrequencyOffset = objNotif.getFrequencyOffset();
|
||||
m_config.m_intSampleRate = objNotif.getSampleRate();
|
||||
m_rfConfig.m_intFrequencyOffset = objNotif.getFrequencyOffset();
|
||||
|
||||
qDebug() << "ATVDemod::handleMessage: MsgChannelizerNotification:"
|
||||
<< " m_intSampleRate: " << m_objConfig.m_intSampleRate
|
||||
<< " m_intFrequencyOffset: " << m_objRFConfig.m_intFrequencyOffset;
|
||||
<< " m_intSampleRate: " << m_config.m_intSampleRate
|
||||
<< " m_intFrequencyOffset: " << m_rfConfig.m_intFrequencyOffset;
|
||||
|
||||
applySettings();
|
||||
|
||||
@ -453,17 +453,17 @@ bool ATVDemod::handleMessage(const Message& cmd)
|
||||
{
|
||||
MsgConfigureATVDemod& objCfg = (MsgConfigureATVDemod&) cmd;
|
||||
|
||||
m_objConfig = objCfg.m_objMsgConfig;
|
||||
m_config = objCfg.m_objMsgConfig;
|
||||
|
||||
qDebug() << "ATVDemod::handleMessage: MsgConfigureATVDemod:"
|
||||
<< " m_fltVoltLevelSynchroBlack:" << m_objConfig.m_fltVoltLevelSynchroBlack
|
||||
<< " m_fltVoltLevelSynchroTop:" << m_objConfig.m_fltVoltLevelSynchroTop
|
||||
<< " m_fltFramePerS:" << m_objConfig.m_fltFramePerS
|
||||
<< " m_fltLineDurationUs:" << m_objConfig.m_fltLineDuration
|
||||
<< " m_fltRatioOfRowsToDisplay:" << m_objConfig.m_fltRatioOfRowsToDisplay
|
||||
<< " m_fltTopDurationUs:" << m_objConfig.m_fltTopDuration
|
||||
<< " m_blnHSync:" << m_objConfig.m_blnHSync
|
||||
<< " m_blnVSync:" << m_objConfig.m_blnVSync;
|
||||
<< " m_fltVoltLevelSynchroBlack:" << m_config.m_fltVoltLevelSynchroBlack
|
||||
<< " m_fltVoltLevelSynchroTop:" << m_config.m_fltVoltLevelSynchroTop
|
||||
<< " m_fltFramePerS:" << m_config.m_fltFramePerS
|
||||
<< " m_fltLineDurationUs:" << m_config.m_fltLineDuration
|
||||
<< " m_fltRatioOfRowsToDisplay:" << m_config.m_fltRatioOfRowsToDisplay
|
||||
<< " m_fltTopDurationUs:" << m_config.m_fltTopDuration
|
||||
<< " m_blnHSync:" << m_config.m_blnHSync
|
||||
<< " m_blnVSync:" << m_config.m_blnVSync;
|
||||
|
||||
applySettings();
|
||||
|
||||
@ -473,16 +473,16 @@ bool ATVDemod::handleMessage(const Message& cmd)
|
||||
{
|
||||
MsgConfigureRFATVDemod& objCfg = (MsgConfigureRFATVDemod&) cmd;
|
||||
|
||||
m_objRFConfig = objCfg.m_objMsgConfig;
|
||||
m_rfConfig = objCfg.m_objMsgConfig;
|
||||
|
||||
qDebug() << "ATVDemod::handleMessage: MsgConfigureRFATVDemod:"
|
||||
<< " m_enmModulation:" << m_objRFConfig.m_enmModulation
|
||||
<< " m_fltRFBandwidth:" << m_objRFConfig.m_fltRFBandwidth
|
||||
<< " m_fltRFOppBandwidth:" << m_objRFConfig.m_fltRFOppBandwidth
|
||||
<< " m_blnFFTFiltering:" << m_objRFConfig.m_blnFFTFiltering
|
||||
<< " m_blnDecimatorEnable:" << m_objRFConfig.m_blndecimatorEnable
|
||||
<< " m_fltBFOFrequency:" << m_objRFConfig.m_fltBFOFrequency
|
||||
<< " m_fmDeviation:" << m_objRFConfig.m_fmDeviation;
|
||||
<< " m_enmModulation:" << m_rfConfig.m_enmModulation
|
||||
<< " m_fltRFBandwidth:" << m_rfConfig.m_fltRFBandwidth
|
||||
<< " m_fltRFOppBandwidth:" << m_rfConfig.m_fltRFOppBandwidth
|
||||
<< " m_blnFFTFiltering:" << m_rfConfig.m_blnFFTFiltering
|
||||
<< " m_blnDecimatorEnable:" << m_rfConfig.m_blndecimatorEnable
|
||||
<< " m_fltBFOFrequency:" << m_rfConfig.m_fltBFOFrequency
|
||||
<< " m_fmDeviation:" << m_rfConfig.m_fmDeviation;
|
||||
|
||||
applySettings();
|
||||
|
||||
@ -490,9 +490,9 @@ bool ATVDemod::handleMessage(const Message& cmd)
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_objScopeSink != 0)
|
||||
if (m_scopeSink != 0)
|
||||
{
|
||||
return m_objScopeSink->handleMessage(cmd);
|
||||
return m_scopeSink->handleMessage(cmd);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -504,30 +504,30 @@ bool ATVDemod::handleMessage(const Message& cmd)
|
||||
void ATVDemod::applySettings()
|
||||
{
|
||||
|
||||
if (m_objConfig.m_intSampleRate == 0)
|
||||
if (m_config.m_intSampleRate == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
bool forwardSampleRateChange = false;
|
||||
|
||||
if((m_objRFConfig.m_intFrequencyOffset != m_objRFRunning.m_intFrequencyOffset)
|
||||
|| (m_objRFConfig.m_enmModulation != m_objRFRunning.m_enmModulation)
|
||||
|| (m_objConfig.m_intSampleRate != m_objRunning.m_intSampleRate))
|
||||
if((m_rfConfig.m_intFrequencyOffset != m_rfRunning.m_intFrequencyOffset)
|
||||
|| (m_rfConfig.m_enmModulation != m_rfRunning.m_enmModulation)
|
||||
|| (m_config.m_intSampleRate != m_running.m_intSampleRate))
|
||||
{
|
||||
m_nco.setFreq(-m_objRFConfig.m_intFrequencyOffset, m_objConfig.m_intSampleRate);
|
||||
m_nco.setFreq(-m_rfConfig.m_intFrequencyOffset, m_config.m_intSampleRate);
|
||||
}
|
||||
|
||||
if ((m_objConfig.m_intSampleRate != m_objRunning.m_intSampleRate)
|
||||
|| (m_objRFConfig.m_fltRFBandwidth != m_objRFRunning.m_fltRFBandwidth)
|
||||
|| (m_objConfig.m_fltFramePerS != m_objRunning.m_fltFramePerS)
|
||||
|| (m_objConfig.m_intNumberOfLines != m_objRunning.m_intNumberOfLines))
|
||||
if ((m_config.m_intSampleRate != m_running.m_intSampleRate)
|
||||
|| (m_rfConfig.m_fltRFBandwidth != m_rfRunning.m_fltRFBandwidth)
|
||||
|| (m_config.m_fltFramePerS != m_running.m_fltFramePerS)
|
||||
|| (m_config.m_intNumberOfLines != m_running.m_intNumberOfLines))
|
||||
{
|
||||
m_objSettingsMutex.lock();
|
||||
|
||||
int linesPerSecond = m_objConfig.m_intNumberOfLines * m_objConfig.m_fltFramePerS;
|
||||
int linesPerSecond = m_config.m_intNumberOfLines * m_config.m_fltFramePerS;
|
||||
|
||||
int maxPoints = m_objConfig.m_intSampleRate / linesPerSecond;
|
||||
int maxPoints = m_config.m_intSampleRate / linesPerSecond;
|
||||
int i = maxPoints;
|
||||
|
||||
for (; i > 0; i--)
|
||||
@ -537,53 +537,53 @@ void ATVDemod::applySettings()
|
||||
}
|
||||
|
||||
int nbPointsPerRateUnit = i == 0 ? maxPoints : i;
|
||||
m_objConfigPrivate.m_intTVSampleRate = nbPointsPerRateUnit * linesPerSecond;
|
||||
m_configPrivate.m_intTVSampleRate = nbPointsPerRateUnit * linesPerSecond;
|
||||
|
||||
if (m_objConfigPrivate.m_intTVSampleRate > 0)
|
||||
if (m_configPrivate.m_intTVSampleRate > 0)
|
||||
{
|
||||
m_interpolatorDistance = (Real) m_objConfigPrivate.m_intTVSampleRate / (Real) m_objConfig.m_intSampleRate;
|
||||
m_interpolatorDistance = (Real) m_configPrivate.m_intTVSampleRate / (Real) m_config.m_intSampleRate;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_objConfigPrivate.m_intTVSampleRate = m_objConfig.m_intSampleRate;
|
||||
m_configPrivate.m_intTVSampleRate = m_config.m_intSampleRate;
|
||||
m_interpolatorDistance = 1.0f;
|
||||
}
|
||||
|
||||
m_interpolatorDistanceRemain = 0;
|
||||
m_interpolator.create(24,
|
||||
m_objConfigPrivate.m_intTVSampleRate,
|
||||
m_objRFConfig.m_fltRFBandwidth / getRFBandwidthDivisor(m_objRFConfig.m_enmModulation),
|
||||
m_configPrivate.m_intTVSampleRate,
|
||||
m_rfConfig.m_fltRFBandwidth / getRFBandwidthDivisor(m_rfConfig.m_enmModulation),
|
||||
3.0);
|
||||
m_objSettingsMutex.unlock();
|
||||
}
|
||||
|
||||
if((m_objConfig.m_fltFramePerS != m_objRunning.m_fltFramePerS)
|
||||
|| (m_objConfig.m_fltLineDuration != m_objRunning.m_fltLineDuration)
|
||||
|| (m_objConfig.m_intSampleRate != m_objRunning.m_intSampleRate)
|
||||
|| (m_objConfig.m_fltTopDuration != m_objRunning.m_fltTopDuration)
|
||||
|| (m_objConfig.m_fltRatioOfRowsToDisplay != m_objRunning.m_fltRatioOfRowsToDisplay)
|
||||
|| (m_objConfig.m_enmATVStandard != m_objRunning.m_enmATVStandard)
|
||||
|| (m_objConfig.m_intNumberOfLines != m_objRunning.m_intNumberOfLines))
|
||||
if((m_config.m_fltFramePerS != m_running.m_fltFramePerS)
|
||||
|| (m_config.m_fltLineDuration != m_running.m_fltLineDuration)
|
||||
|| (m_config.m_intSampleRate != m_running.m_intSampleRate)
|
||||
|| (m_config.m_fltTopDuration != m_running.m_fltTopDuration)
|
||||
|| (m_config.m_fltRatioOfRowsToDisplay != m_running.m_fltRatioOfRowsToDisplay)
|
||||
|| (m_config.m_enmATVStandard != m_running.m_enmATVStandard)
|
||||
|| (m_config.m_intNumberOfLines != m_running.m_intNumberOfLines))
|
||||
{
|
||||
m_objSettingsMutex.lock();
|
||||
|
||||
m_intNumberOfLines = m_objConfig.m_intNumberOfLines;
|
||||
m_intNumberOfLines = m_config.m_intNumberOfLines;
|
||||
|
||||
applyStandard();
|
||||
|
||||
m_objConfigPrivate.m_intNumberSamplePerLine = (int) (m_objConfig.m_fltLineDuration * m_objConfig.m_intSampleRate);
|
||||
m_intNumberSamplePerTop = (int) (m_objConfig.m_fltTopDuration * m_objConfig.m_intSampleRate);
|
||||
m_configPrivate.m_intNumberSamplePerLine = (int) (m_config.m_fltLineDuration * m_config.m_intSampleRate);
|
||||
m_intNumberSamplePerTop = (int) (m_config.m_fltTopDuration * m_config.m_intSampleRate);
|
||||
|
||||
m_objRegisteredATVScreen->setRenderImmediate(!(m_objConfig.m_fltFramePerS > 25.0f));
|
||||
m_objRegisteredATVScreen->resizeATVScreen(
|
||||
m_objConfigPrivate.m_intNumberSamplePerLine - m_intNumberSamplePerLineSignals,
|
||||
m_registeredATVScreen->setRenderImmediate(!(m_config.m_fltFramePerS > 25.0f));
|
||||
m_registeredATVScreen->resizeATVScreen(
|
||||
m_configPrivate.m_intNumberSamplePerLine - m_intNumberSamplePerLineSignals,
|
||||
m_intNumberOfLines - m_intNumberOfBlackLines);
|
||||
|
||||
qDebug() << "ATVDemod::applySettings:"
|
||||
<< " m_fltLineDuration: " << m_objConfig.m_fltLineDuration
|
||||
<< " m_fltFramePerS: " << m_objConfig.m_fltFramePerS
|
||||
<< " m_fltLineDuration: " << m_config.m_fltLineDuration
|
||||
<< " m_fltFramePerS: " << m_config.m_fltFramePerS
|
||||
<< " m_intNumberOfLines: " << m_intNumberOfLines
|
||||
<< " m_intNumberSamplePerLine: " << m_objConfigPrivate.m_intNumberSamplePerLine
|
||||
<< " m_intNumberSamplePerLine: " << m_configPrivate.m_intNumberSamplePerLine
|
||||
<< " m_intNumberOfBlackLines: " << m_intNumberOfBlackLines;
|
||||
|
||||
m_intImageIndex = 0;
|
||||
@ -593,56 +593,56 @@ void ATVDemod::applySettings()
|
||||
m_objSettingsMutex.unlock();
|
||||
}
|
||||
|
||||
if ((m_objConfigPrivate.m_intTVSampleRate != m_objRunningPrivate.m_intTVSampleRate)
|
||||
|| (m_objConfigPrivate.m_intNumberSamplePerLine != m_objRunningPrivate.m_intNumberSamplePerLine)
|
||||
|| (m_objConfig.m_intSampleRate != m_objRunning.m_intSampleRate)
|
||||
|| (m_objRFConfig.m_blndecimatorEnable != m_objRFRunning.m_blndecimatorEnable))
|
||||
if ((m_configPrivate.m_intTVSampleRate != m_runningPrivate.m_intTVSampleRate)
|
||||
|| (m_configPrivate.m_intNumberSamplePerLine != m_runningPrivate.m_intNumberSamplePerLine)
|
||||
|| (m_config.m_intSampleRate != m_running.m_intSampleRate)
|
||||
|| (m_rfConfig.m_blndecimatorEnable != m_rfRunning.m_blndecimatorEnable))
|
||||
{
|
||||
forwardSampleRateChange = true;
|
||||
}
|
||||
|
||||
if ((m_objConfigPrivate.m_intTVSampleRate != m_objRunningPrivate.m_intTVSampleRate)
|
||||
|| (m_objRFConfig.m_fltRFBandwidth != m_objRFRunning.m_fltRFBandwidth)
|
||||
|| (m_objRFConfig.m_fltRFOppBandwidth != m_objRFRunning.m_fltRFOppBandwidth))
|
||||
if ((m_configPrivate.m_intTVSampleRate != m_runningPrivate.m_intTVSampleRate)
|
||||
|| (m_rfConfig.m_fltRFBandwidth != m_rfRunning.m_fltRFBandwidth)
|
||||
|| (m_rfConfig.m_fltRFOppBandwidth != m_rfRunning.m_fltRFOppBandwidth))
|
||||
{
|
||||
m_objSettingsMutex.lock();
|
||||
m_DSBFilter->create_asym_filter(m_objRFConfig.m_fltRFOppBandwidth / m_objConfigPrivate.m_intTVSampleRate,
|
||||
m_objRFConfig.m_fltRFBandwidth / m_objConfigPrivate.m_intTVSampleRate);
|
||||
m_DSBFilter->create_asym_filter(m_rfConfig.m_fltRFOppBandwidth / m_configPrivate.m_intTVSampleRate,
|
||||
m_rfConfig.m_fltRFBandwidth / m_configPrivate.m_intTVSampleRate);
|
||||
memset(m_DSBFilterBuffer, 0, sizeof(Complex)*(m_ssbFftLen));
|
||||
m_DSBFilterBufferIndex = 0;
|
||||
m_objSettingsMutex.unlock();
|
||||
}
|
||||
|
||||
if ((m_objConfigPrivate.m_intTVSampleRate != m_objRunningPrivate.m_intTVSampleRate)
|
||||
|| (m_objRFConfig.m_fltBFOFrequency != m_objRFRunning.m_fltBFOFrequency))
|
||||
if ((m_configPrivate.m_intTVSampleRate != m_runningPrivate.m_intTVSampleRate)
|
||||
|| (m_rfConfig.m_fltBFOFrequency != m_rfRunning.m_fltBFOFrequency))
|
||||
{
|
||||
m_bfoPLL.configure(m_objRFConfig.m_fltBFOFrequency / m_objConfigPrivate.m_intTVSampleRate,
|
||||
100.0 / m_objConfigPrivate.m_intTVSampleRate,
|
||||
m_bfoPLL.configure(m_rfConfig.m_fltBFOFrequency / m_configPrivate.m_intTVSampleRate,
|
||||
100.0 / m_configPrivate.m_intTVSampleRate,
|
||||
0.01);
|
||||
m_bfoFilter.setFrequencies(m_objRFConfig.m_fltBFOFrequency, m_objConfigPrivate.m_intTVSampleRate);
|
||||
m_bfoFilter.setFrequencies(m_rfConfig.m_fltBFOFrequency, m_configPrivate.m_intTVSampleRate);
|
||||
}
|
||||
|
||||
if (m_objRFConfig.m_fmDeviation != m_objRFRunning.m_fmDeviation)
|
||||
if (m_rfConfig.m_fmDeviation != m_rfRunning.m_fmDeviation)
|
||||
{
|
||||
m_objPhaseDiscri.setFMScaling(1.0f / m_objRFConfig.m_fmDeviation);
|
||||
m_objPhaseDiscri.setFMScaling(1.0f / m_rfConfig.m_fmDeviation);
|
||||
}
|
||||
|
||||
m_objRunning = m_objConfig;
|
||||
m_objRFRunning = m_objRFConfig;
|
||||
m_objRunningPrivate = m_objConfigPrivate;
|
||||
m_running = m_config;
|
||||
m_rfRunning = m_rfConfig;
|
||||
m_runningPrivate = m_configPrivate;
|
||||
|
||||
if (forwardSampleRateChange)
|
||||
{
|
||||
int sampleRate = m_objRFRunning.m_blndecimatorEnable ? m_objRunningPrivate.m_intTVSampleRate : m_objRunning.m_intSampleRate;
|
||||
int sampleRate = m_rfRunning.m_blndecimatorEnable ? m_runningPrivate.m_intTVSampleRate : m_running.m_intSampleRate;
|
||||
MsgReportEffectiveSampleRate *report;
|
||||
report = MsgReportEffectiveSampleRate::create(sampleRate, m_objRunningPrivate.m_intNumberSamplePerLine);
|
||||
getOutputMessageQueue()->push(report);
|
||||
report = MsgReportEffectiveSampleRate::create(sampleRate, m_runningPrivate.m_intNumberSamplePerLine);
|
||||
getMessageQueueToGUI()->push(report);
|
||||
}
|
||||
}
|
||||
|
||||
void ATVDemod::applyStandard()
|
||||
{
|
||||
switch(m_objConfig.m_enmATVStandard)
|
||||
switch(m_config.m_enmATVStandard)
|
||||
{
|
||||
case ATVStdHSkip:
|
||||
// what is left in a line for the image
|
||||
@ -689,23 +689,23 @@ void ATVDemod::applyStandard()
|
||||
}
|
||||
|
||||
// for now all standards apply this
|
||||
m_intNumberSamplePerLineSignals = (int) ((12.0f/64.0f)*m_objConfig.m_fltLineDuration * m_objConfig.m_intSampleRate); // 12.0 = 7.3 + 4.7
|
||||
m_intNumberSaplesPerHSync = (int) ((9.6f/64.0f)*m_objConfig.m_fltLineDuration * m_objConfig.m_intSampleRate); // 9.4 = 4.7 + 4.7
|
||||
m_intNumberSamplePerLineSignals = (int) ((12.0f/64.0f)*m_config.m_fltLineDuration * m_config.m_intSampleRate); // 12.0 = 7.3 + 4.7
|
||||
m_intNumberSaplesPerHSync = (int) ((9.6f/64.0f)*m_config.m_fltLineDuration * m_config.m_intSampleRate); // 9.4 = 4.7 + 4.7
|
||||
}
|
||||
|
||||
int ATVDemod::getSampleRate()
|
||||
{
|
||||
return m_objRunning.m_intSampleRate;
|
||||
return m_running.m_intSampleRate;
|
||||
}
|
||||
|
||||
int ATVDemod::getEffectiveSampleRate()
|
||||
{
|
||||
return m_objRFRunning.m_blndecimatorEnable ? m_objRunningPrivate.m_intTVSampleRate : m_objRunning.m_intSampleRate;
|
||||
return m_rfRunning.m_blndecimatorEnable ? m_runningPrivate.m_intTVSampleRate : m_running.m_intSampleRate;
|
||||
}
|
||||
|
||||
bool ATVDemod::getBFOLocked()
|
||||
{
|
||||
if ((m_objRFRunning.m_enmModulation == ATV_USB) || (m_objRFRunning.m_enmModulation == ATV_LSB))
|
||||
if ((m_rfRunning.m_enmModulation == ATV_USB) || (m_rfRunning.m_enmModulation == ATV_LSB))
|
||||
{
|
||||
return m_bfoPLL.locked();
|
||||
}
|
||||
|
@ -38,6 +38,7 @@
|
||||
#include "util/message.h"
|
||||
#include "atvscreen.h"
|
||||
|
||||
class DeviceSourceAPI;
|
||||
|
||||
class ATVDemod : public BasebandSampleSink
|
||||
{
|
||||
@ -146,8 +147,9 @@ public:
|
||||
{ }
|
||||
};
|
||||
|
||||
ATVDemod(BasebandSampleSink* objScopeSink);
|
||||
ATVDemod(DeviceSourceAPI *deviceAPI);
|
||||
~ATVDemod();
|
||||
void setScopeSink(BasebandSampleSink* scopeSink) { m_scopeSink = scopeSink; }
|
||||
|
||||
void configure(MessageQueue* objMessageQueue,
|
||||
float fltLineDurationUs,
|
||||
@ -339,13 +341,15 @@ private:
|
||||
bool m_start;
|
||||
};
|
||||
|
||||
DeviceSourceAPI* m_deviceAPI;
|
||||
|
||||
//*************** SCOPE ***************
|
||||
|
||||
BasebandSampleSink* m_objScopeSink;
|
||||
SampleVector m_objScopeSampleBuffer;
|
||||
BasebandSampleSink* m_scopeSink;
|
||||
SampleVector m_scopeSampleBuffer;
|
||||
|
||||
//*************** ATV PARAMETERS ***************
|
||||
ATVScreen * m_objRegisteredATVScreen;
|
||||
ATVScreen * m_registeredATVScreen;
|
||||
|
||||
//int m_intNumberSamplePerLine;
|
||||
int m_intNumberSamplePerTop;
|
||||
@ -411,14 +415,14 @@ private:
|
||||
|
||||
//QElapsedTimer m_objTimer;
|
||||
|
||||
ATVConfig m_objRunning;
|
||||
ATVConfig m_objConfig;
|
||||
ATVConfig m_running;
|
||||
ATVConfig m_config;
|
||||
|
||||
ATVRFConfig m_objRFRunning;
|
||||
ATVRFConfig m_objRFConfig;
|
||||
ATVRFConfig m_rfRunning;
|
||||
ATVRFConfig m_rfConfig;
|
||||
|
||||
ATVConfigPrivate m_objRunningPrivate;
|
||||
ATVConfigPrivate m_objConfigPrivate;
|
||||
ATVConfigPrivate m_runningPrivate;
|
||||
ATVConfigPrivate m_configPrivate;
|
||||
|
||||
QMutex m_objSettingsMutex;
|
||||
|
||||
@ -429,17 +433,17 @@ private:
|
||||
|
||||
inline void processHSkip(float& fltVal, int& intVal)
|
||||
{
|
||||
m_objRegisteredATVScreen->setDataColor(m_intColIndex - m_intNumberSaplesPerHSync + m_intNumberSamplePerTop, intVal, intVal, intVal);
|
||||
m_registeredATVScreen->setDataColor(m_intColIndex - m_intNumberSaplesPerHSync + m_intNumberSamplePerTop, intVal, intVal, intVal);
|
||||
|
||||
// Horizontal Synchro detection
|
||||
|
||||
// Floor Detection 0
|
||||
if (fltVal < m_objRunning.m_fltVoltLevelSynchroTop)
|
||||
if (fltVal < m_running.m_fltVoltLevelSynchroTop)
|
||||
{
|
||||
m_intSynchroPoints++;
|
||||
}
|
||||
// Black detection 0.3
|
||||
else if (fltVal > m_objRunning.m_fltVoltLevelSynchroBlack)
|
||||
else if (fltVal > m_running.m_fltVoltLevelSynchroBlack)
|
||||
{
|
||||
m_intSynchroPoints = 0;
|
||||
}
|
||||
@ -450,11 +454,11 @@ private:
|
||||
|
||||
if (m_blnSynchroDetected)
|
||||
{
|
||||
if (m_intSampleIndex >= (3 * m_objRunningPrivate.m_intNumberSamplePerLine)/2) // first after skip
|
||||
if (m_intSampleIndex >= (3 * m_runningPrivate.m_intNumberSamplePerLine)/2) // first after skip
|
||||
{
|
||||
//qDebug("VSync: %d %d %d", m_intColIndex, m_intSampleIndex, m_intLineIndex);
|
||||
m_intAvgColIndex = m_intColIndex;
|
||||
m_objRegisteredATVScreen->renderImage(0);
|
||||
m_registeredATVScreen->renderImage(0);
|
||||
|
||||
m_intImageIndex++;
|
||||
m_intLineIndex = 0;
|
||||
@ -468,25 +472,25 @@ private:
|
||||
m_intSampleIndex++;
|
||||
}
|
||||
|
||||
if (m_intColIndex < m_objRunningPrivate.m_intNumberSamplePerLine + m_intNumberSamplePerTop - 1)
|
||||
if (m_intColIndex < m_runningPrivate.m_intNumberSamplePerLine + m_intNumberSamplePerTop - 1)
|
||||
{
|
||||
m_intColIndex++;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_objRunning.m_blnHSync && (m_intLineIndex == 0))
|
||||
if (m_running.m_blnHSync && (m_intLineIndex == 0))
|
||||
{
|
||||
//qDebug("HCorr: %d", m_intAvgColIndex);
|
||||
m_intColIndex = m_intNumberSamplePerTop + (m_objRunningPrivate.m_intNumberSamplePerLine - m_intAvgColIndex)/2; // amortizing factor 1/2
|
||||
m_intColIndex = m_intNumberSamplePerTop + (m_runningPrivate.m_intNumberSamplePerLine - m_intAvgColIndex)/2; // amortizing factor 1/2
|
||||
}
|
||||
else
|
||||
{
|
||||
m_intColIndex = m_intNumberSamplePerTop;
|
||||
}
|
||||
|
||||
if ((m_objRFRunning.m_enmModulation == ATV_AM)
|
||||
|| (m_objRFRunning.m_enmModulation == ATV_USB)
|
||||
|| (m_objRFRunning.m_enmModulation == ATV_LSB))
|
||||
if ((m_rfRunning.m_enmModulation == ATV_AM)
|
||||
|| (m_rfRunning.m_enmModulation == ATV_USB)
|
||||
|| (m_rfRunning.m_enmModulation == ATV_LSB))
|
||||
{
|
||||
m_fltAmpMin = m_fltEffMin;
|
||||
m_fltAmpMax = m_fltEffMax;
|
||||
@ -502,7 +506,7 @@ private:
|
||||
m_fltEffMax = -2000000.0f;
|
||||
}
|
||||
|
||||
m_objRegisteredATVScreen->selectRow(m_intRowIndex);
|
||||
m_registeredATVScreen->selectRow(m_intRowIndex);
|
||||
m_intLineIndex++;
|
||||
m_intRowIndex++;
|
||||
}
|
||||
@ -510,18 +514,18 @@ private:
|
||||
|
||||
inline void processClassic(float& fltVal, int& intVal)
|
||||
{
|
||||
int intSynchroTimeSamples= (3 * m_objRunningPrivate.m_intNumberSamplePerLine)/4;
|
||||
float fltSynchroTrameLevel = 0.5f*((float)intSynchroTimeSamples) * m_objRunning.m_fltVoltLevelSynchroBlack;
|
||||
int intSynchroTimeSamples= (3 * m_runningPrivate.m_intNumberSamplePerLine)/4;
|
||||
float fltSynchroTrameLevel = 0.5f*((float)intSynchroTimeSamples) * m_running.m_fltVoltLevelSynchroBlack;
|
||||
|
||||
// Horizontal Synchro detection
|
||||
|
||||
// Floor Detection 0
|
||||
if (fltVal < m_objRunning.m_fltVoltLevelSynchroTop)
|
||||
if (fltVal < m_running.m_fltVoltLevelSynchroTop)
|
||||
{
|
||||
m_intSynchroPoints++;
|
||||
}
|
||||
// Black detection 0.3
|
||||
else if (fltVal > m_objRunning.m_fltVoltLevelSynchroBlack)
|
||||
else if (fltVal > m_running.m_fltVoltLevelSynchroBlack)
|
||||
{
|
||||
m_intSynchroPoints = 0;
|
||||
}
|
||||
@ -534,7 +538,7 @@ private:
|
||||
|
||||
if (m_blnSynchroDetected)
|
||||
{
|
||||
m_intAvgColIndex = m_intSampleIndex - m_intColIndex - (m_intColIndex < m_objRunningPrivate.m_intNumberSamplePerLine/2 ? 150 : 0);
|
||||
m_intAvgColIndex = m_intSampleIndex - m_intColIndex - (m_intColIndex < m_runningPrivate.m_intNumberSamplePerLine/2 ? 150 : 0);
|
||||
//qDebug("HSync: %d %d %d", m_intSampleIndex, m_intColIndex, m_intAvgColIndex);
|
||||
m_intSampleIndex = 0;
|
||||
}
|
||||
@ -543,14 +547,14 @@ private:
|
||||
m_intSampleIndex++;
|
||||
}
|
||||
|
||||
if (!m_objRunning.m_blnHSync && (m_intColIndex >= m_objRunningPrivate.m_intNumberSamplePerLine)) // H Sync not active
|
||||
if (!m_running.m_blnHSync && (m_intColIndex >= m_runningPrivate.m_intNumberSamplePerLine)) // H Sync not active
|
||||
{
|
||||
m_intColIndex = 0;
|
||||
blnNewLine = true;
|
||||
}
|
||||
else if (m_intColIndex >= m_objRunningPrivate.m_intNumberSamplePerLine + m_intNumberSamplePerTop) // No valid H sync
|
||||
else if (m_intColIndex >= m_runningPrivate.m_intNumberSamplePerLine + m_intNumberSamplePerTop) // No valid H sync
|
||||
{
|
||||
if (m_objRunning.m_blnHSync && (m_intLineIndex == 0))
|
||||
if (m_running.m_blnHSync && (m_intLineIndex == 0))
|
||||
{
|
||||
//qDebug("HSync: %d %d", m_intColIndex, m_intAvgColIndex);
|
||||
m_intColIndex = m_intNumberSamplePerTop + m_intAvgColIndex/4; // amortizing 1/4
|
||||
@ -565,9 +569,9 @@ private:
|
||||
|
||||
if (blnNewLine)
|
||||
{
|
||||
if ((m_objRFRunning.m_enmModulation == ATV_AM)
|
||||
|| (m_objRFRunning.m_enmModulation == ATV_USB)
|
||||
|| (m_objRFRunning.m_enmModulation == ATV_LSB))
|
||||
if ((m_rfRunning.m_enmModulation == ATV_AM)
|
||||
|| (m_rfRunning.m_enmModulation == ATV_USB)
|
||||
|| (m_rfRunning.m_enmModulation == ATV_LSB))
|
||||
{
|
||||
m_fltAmpMin = m_fltEffMin;
|
||||
m_fltAmpMax = m_fltEffMax;
|
||||
@ -590,7 +594,7 @@ private:
|
||||
|
||||
if (m_intRowIndex < m_intNumberOfLines)
|
||||
{
|
||||
m_objRegisteredATVScreen->selectRow(m_intRowIndex - m_intNumberOfSyncLines);
|
||||
m_registeredATVScreen->selectRow(m_intRowIndex - m_intNumberOfSyncLines);
|
||||
}
|
||||
|
||||
m_intLineIndex++;
|
||||
@ -599,12 +603,12 @@ private:
|
||||
// Filling pixels
|
||||
|
||||
// +4 is to compensate shift due to hsync amortizing factor of 1/4
|
||||
m_objRegisteredATVScreen->setDataColor(m_intColIndex - m_intNumberSaplesPerHSync + m_intNumberSamplePerTop + 4, intVal, intVal, intVal);
|
||||
m_registeredATVScreen->setDataColor(m_intColIndex - m_intNumberSaplesPerHSync + m_intNumberSamplePerTop + 4, intVal, intVal, intVal);
|
||||
m_intColIndex++;
|
||||
|
||||
// Vertical sync and image rendering
|
||||
|
||||
if ((m_objRunning.m_blnVSync) && (m_intLineIndex < m_intNumberOfLines)) // VSync activated and lines in range
|
||||
if ((m_running.m_blnVSync) && (m_intLineIndex < m_intNumberOfLines)) // VSync activated and lines in range
|
||||
{
|
||||
if (m_intColIndex >= intSynchroTimeSamples)
|
||||
{
|
||||
@ -618,7 +622,7 @@ private:
|
||||
|
||||
if ((m_intLineIndex % 2 == 0) || !m_interleaved) // even => odd image
|
||||
{
|
||||
m_objRegisteredATVScreen->renderImage(0);
|
||||
m_registeredATVScreen->renderImage(0);
|
||||
m_intRowIndex = 1;
|
||||
}
|
||||
else
|
||||
@ -626,7 +630,7 @@ private:
|
||||
m_intRowIndex = 0;
|
||||
}
|
||||
|
||||
m_objRegisteredATVScreen->selectRow(m_intRowIndex - m_intNumberOfSyncLines);
|
||||
m_registeredATVScreen->selectRow(m_intRowIndex - m_intNumberOfSyncLines);
|
||||
m_intLineIndex = 0;
|
||||
m_intImageIndex++;
|
||||
}
|
||||
@ -643,9 +647,9 @@ private:
|
||||
{
|
||||
if (m_intImageIndex % 2 == 1) // odd image
|
||||
{
|
||||
m_objRegisteredATVScreen->renderImage(0);
|
||||
m_registeredATVScreen->renderImage(0);
|
||||
|
||||
if (m_objRFRunning.m_enmModulation == ATV_AM)
|
||||
if (m_rfRunning.m_enmModulation == ATV_AM)
|
||||
{
|
||||
m_fltAmpMin = m_fltEffMin;
|
||||
m_fltAmpMax = m_fltEffMax;
|
||||
@ -668,7 +672,7 @@ private:
|
||||
m_intRowIndex = 0;
|
||||
}
|
||||
|
||||
m_objRegisteredATVScreen->selectRow(m_intRowIndex - m_intNumberOfSyncLines);
|
||||
m_registeredATVScreen->selectRow(m_intRowIndex - m_intNumberOfSyncLines);
|
||||
m_intLineIndex = 0;
|
||||
m_intImageIndex++;
|
||||
}
|
||||
|
@ -61,12 +61,12 @@ QString ATVDemodGUI::getName() const
|
||||
|
||||
qint64 ATVDemodGUI::getCenterFrequency() const
|
||||
{
|
||||
return m_objChannelMarker.getCenterFrequency();
|
||||
return m_channelMarker.getCenterFrequency();
|
||||
}
|
||||
|
||||
void ATVDemodGUI::setCenterFrequency(qint64 intCenterFrequency)
|
||||
{
|
||||
m_objChannelMarker.setCenterFrequency(intCenterFrequency);
|
||||
m_channelMarker.setCenterFrequency(intCenterFrequency);
|
||||
applySettings();
|
||||
}
|
||||
|
||||
@ -105,8 +105,8 @@ QByteArray ATVDemodGUI::serialize() const
|
||||
{
|
||||
SimpleSerializer s(1);
|
||||
|
||||
s.writeS32(1, m_objChannelMarker.getCenterFrequency());
|
||||
s.writeU32(2, m_objChannelMarker.getColor().rgb());
|
||||
s.writeS32(1, m_channelMarker.getCenterFrequency());
|
||||
s.writeU32(2, m_channelMarker.getColor().rgb());
|
||||
s.writeS32(3, ui->synchLevel->value());
|
||||
s.writeS32(4, ui->blackLevel->value());
|
||||
s.writeS32(5, ui->lineTime->value());
|
||||
@ -144,10 +144,10 @@ bool ATVDemodGUI::deserialize(const QByteArray& arrData)
|
||||
bool booltmp;
|
||||
|
||||
blockApplySettings(true);
|
||||
m_objChannelMarker.blockSignals(true);
|
||||
m_channelMarker.blockSignals(true);
|
||||
|
||||
d.readS32(1, &tmp, 0);
|
||||
m_objChannelMarker.setCenterFrequency(tmp);
|
||||
m_channelMarker.setCenterFrequency(tmp);
|
||||
|
||||
// if (d.readU32(2, &u32tmp)) {
|
||||
// m_objChannelMarker.setColor(u32tmp);
|
||||
@ -189,7 +189,7 @@ bool ATVDemodGUI::deserialize(const QByteArray& arrData)
|
||||
ui->standard->setCurrentIndex(tmp);
|
||||
|
||||
blockApplySettings(false);
|
||||
m_objChannelMarker.blockSignals(false);
|
||||
m_channelMarker.blockSignals(false);
|
||||
|
||||
lineTimeUpdate();
|
||||
topTimeUpdate();
|
||||
@ -211,7 +211,7 @@ bool ATVDemodGUI::handleMessage(const Message& objMessage)
|
||||
int nbPointsPerLine = ((ATVDemod::MsgReportEffectiveSampleRate&)objMessage).getNbPointsPerLine();
|
||||
ui->channelSampleRateText->setText(tr("%1k").arg(sampleRate/1000.0f, 0, 'f', 2));
|
||||
ui->nbPointsPerLineText->setText(tr("%1p").arg(nbPointsPerLine));
|
||||
m_objScopeVis->setSampleRate(sampleRate);
|
||||
m_scopeVis->setSampleRate(sampleRate);
|
||||
setRFFiltersSlidersRange(sampleRate);
|
||||
lineTimeUpdate();
|
||||
topTimeUpdate();
|
||||
@ -242,7 +242,7 @@ void ATVDemodGUI::handleSourceMessages()
|
||||
{
|
||||
Message* message;
|
||||
|
||||
while ((message = m_objATVDemod->getOutputMessageQueue()->pop()) != 0)
|
||||
while ((message = getInputMessageQueue()->pop()) != 0)
|
||||
{
|
||||
if (handleMessage(*message))
|
||||
{
|
||||
@ -261,7 +261,7 @@ void ATVDemodGUI::onMenuDoubleClicked()
|
||||
{
|
||||
m_blnBasicSettingsShown = true;
|
||||
BasicChannelSettingsWidget* bcsw = new BasicChannelSettingsWidget(
|
||||
&m_objChannelMarker, this);
|
||||
&m_channelMarker, this);
|
||||
bcsw->show();
|
||||
}
|
||||
}
|
||||
@ -270,9 +270,9 @@ ATVDemodGUI::ATVDemodGUI(PluginAPI* objPluginAPI, DeviceSourceAPI *objDeviceAPI,
|
||||
QWidget* objParent) :
|
||||
RollupWidget(objParent),
|
||||
ui(new Ui::ATVDemodGUI),
|
||||
m_objPluginAPI(objPluginAPI),
|
||||
m_objDeviceAPI(objDeviceAPI),
|
||||
m_objChannelMarker(this),
|
||||
m_pluginAPI(objPluginAPI),
|
||||
m_deviceAPI(objDeviceAPI),
|
||||
m_channelMarker(this),
|
||||
m_blnBasicSettingsShown(false),
|
||||
m_blnDoApplySettings(true),
|
||||
m_objMagSqAverage(40, 0),
|
||||
@ -283,42 +283,44 @@ ATVDemodGUI::ATVDemodGUI(PluginAPI* objPluginAPI, DeviceSourceAPI *objDeviceAPI,
|
||||
connect(this, SIGNAL(widgetRolled(QWidget*,bool)), this, SLOT(onWidgetRolled(QWidget*,bool)));
|
||||
connect(this, SIGNAL(menuDoubleClickEvent()), this, SLOT(onMenuDoubleClicked()));
|
||||
|
||||
m_objScopeVis = new ScopeVisNG(ui->glScope);
|
||||
m_objATVDemod = new ATVDemod(m_objScopeVis);
|
||||
m_objATVDemod->setATVScreen(ui->screenTV);
|
||||
m_scopeVis = new ScopeVisNG(ui->glScope);
|
||||
m_atvDemod = new ATVDemod(m_deviceAPI);
|
||||
m_atvDemod->setScopeSink(m_scopeVis);
|
||||
m_atvDemod->setMessageQueueToGUI(getInputMessageQueue());
|
||||
m_atvDemod->setATVScreen(ui->screenTV);
|
||||
|
||||
m_objChannelizer = new DownChannelizer(m_objATVDemod);
|
||||
m_objThreadedChannelizer = new ThreadedBasebandSampleSink(m_objChannelizer, this);
|
||||
m_objDeviceAPI->addThreadedSink(m_objThreadedChannelizer);
|
||||
m_channelizer = new DownChannelizer(m_atvDemod);
|
||||
m_threadedChannelizer = new ThreadedBasebandSampleSink(m_channelizer, this);
|
||||
m_deviceAPI->addThreadedSink(m_threadedChannelizer);
|
||||
|
||||
ui->glScope->connectTimer(m_objPluginAPI->getMainWindow()->getMasterTimer());
|
||||
connect(&m_objPluginAPI->getMainWindow()->getMasterTimer(), SIGNAL(timeout()), this, SLOT(tick())); // 50 ms
|
||||
ui->glScope->connectTimer(m_pluginAPI->getMainWindow()->getMasterTimer());
|
||||
connect(&m_pluginAPI->getMainWindow()->getMasterTimer(), SIGNAL(timeout()), this, SLOT(tick())); // 50 ms
|
||||
|
||||
ui->deltaFrequencyLabel->setText(QString("%1f").arg(QChar(0x94, 0x03)));
|
||||
ui->deltaFrequency->setColorMapper(ColorMapper(ColorMapper::GrayGold));
|
||||
ui->deltaFrequency->setValueRange(false, 7, -9999999, 9999999);
|
||||
|
||||
connect(m_objChannelizer, SIGNAL(inputSampleRateChanged()), this, SLOT(channelSampleRateChanged()));
|
||||
connect(m_channelizer, SIGNAL(inputSampleRateChanged()), this, SLOT(channelSampleRateChanged()));
|
||||
|
||||
//m_objPluginAPI->addThreadedSink(m_objThreadedChannelizer);
|
||||
m_objChannelMarker.setColor(Qt::white);
|
||||
m_objChannelMarker.setMovable(false);
|
||||
m_objChannelMarker.setBandwidth(6000000);
|
||||
m_objChannelMarker.setCenterFrequency(0);
|
||||
m_objChannelMarker.setVisible(true);
|
||||
setTitleColor(m_objChannelMarker.getColor());
|
||||
m_channelMarker.setColor(Qt::white);
|
||||
m_channelMarker.setMovable(false);
|
||||
m_channelMarker.setBandwidth(6000000);
|
||||
m_channelMarker.setCenterFrequency(0);
|
||||
m_channelMarker.setVisible(true);
|
||||
setTitleColor(m_channelMarker.getColor());
|
||||
|
||||
connect(&m_objChannelMarker, SIGNAL(changed()), this, SLOT(viewChanged()));
|
||||
connect(&m_channelMarker, SIGNAL(changed()), this, SLOT(viewChanged()));
|
||||
|
||||
m_objDeviceAPI->registerChannelInstance(m_strChannelID, this);
|
||||
m_objDeviceAPI->addChannelMarker(&m_objChannelMarker);
|
||||
m_objDeviceAPI->addRollupWidget(this);
|
||||
m_deviceAPI->registerChannelInstance(m_strChannelID, this);
|
||||
m_deviceAPI->addChannelMarker(&m_channelMarker);
|
||||
m_deviceAPI->addRollupWidget(this);
|
||||
|
||||
//ui->screenTV->connectTimer(m_objPluginAPI->getMainWindow()->getMasterTimer());
|
||||
|
||||
m_objMagSqAverage.resize(4, 1.0);
|
||||
|
||||
ui->scopeGUI->setBuddies(m_objScopeVis->getInputMessageQueue(), m_objScopeVis, ui->glScope);
|
||||
ui->scopeGUI->setBuddies(m_scopeVis->getInputMessageQueue(), m_scopeVis, ui->glScope);
|
||||
|
||||
resetToDefaults(); // does applySettings()
|
||||
|
||||
@ -337,7 +339,7 @@ ATVDemodGUI::ATVDemodGUI(PluginAPI* objPluginAPI, DeviceSourceAPI *objDeviceAPI,
|
||||
ui->scopeGUI->changeTrigger(0, triggerData);
|
||||
ui->scopeGUI->focusOnTrigger(0); // re-focus to take changes into account in the GUI
|
||||
|
||||
connect(m_objATVDemod->getOutputMessageQueue(), SIGNAL(messageEnqueued()), this, SLOT(handleSourceMessages()));
|
||||
connect(getInputMessageQueue(), SIGNAL(messageEnqueued()), this, SLOT(handleSourceMessages()));
|
||||
|
||||
QChar delta = QChar(0x94, 0x03);
|
||||
ui->fmDeviationLabel->setText(delta);
|
||||
@ -345,12 +347,12 @@ ATVDemodGUI::ATVDemodGUI(PluginAPI* objPluginAPI, DeviceSourceAPI *objDeviceAPI,
|
||||
|
||||
ATVDemodGUI::~ATVDemodGUI()
|
||||
{
|
||||
m_objDeviceAPI->removeChannelInstance(this);
|
||||
m_objDeviceAPI->removeThreadedSink(m_objThreadedChannelizer);
|
||||
delete m_objThreadedChannelizer;
|
||||
delete m_objChannelizer;
|
||||
delete m_objATVDemod;
|
||||
delete m_objScopeVis;
|
||||
m_deviceAPI->removeChannelInstance(this);
|
||||
m_deviceAPI->removeThreadedSink(m_threadedChannelizer);
|
||||
delete m_threadedChannelizer;
|
||||
delete m_channelizer;
|
||||
delete m_atvDemod;
|
||||
delete m_scopeVis;
|
||||
delete ui;
|
||||
}
|
||||
|
||||
@ -363,13 +365,13 @@ void ATVDemodGUI::applySettings()
|
||||
{
|
||||
if (m_blnDoApplySettings)
|
||||
{
|
||||
ui->deltaFrequency->setValue(m_objChannelMarker.getCenterFrequency());
|
||||
ui->deltaFrequency->setValue(m_channelMarker.getCenterFrequency());
|
||||
|
||||
m_objChannelizer->configure(m_objChannelizer->getInputMessageQueue(),
|
||||
m_objChannelizer->getInputSampleRate(), // always use maximum available bandwidth
|
||||
m_objChannelMarker.getCenterFrequency());
|
||||
m_channelizer->configure(m_channelizer->getInputMessageQueue(),
|
||||
m_channelizer->getInputSampleRate(), // always use maximum available bandwidth
|
||||
m_channelMarker.getCenterFrequency());
|
||||
|
||||
m_objATVDemod->configure(m_objATVDemod->getInputMessageQueue(),
|
||||
m_atvDemod->configure(m_atvDemod->getInputMessageQueue(),
|
||||
getNominalLineTime(ui->nbLines->currentIndex(), ui->fps->currentIndex()) + ui->lineTime->value() * m_fltLineTimeMultiplier,
|
||||
getNominalLineTime(ui->nbLines->currentIndex(), ui->fps->currentIndex()) * (4.7f / 64.0f) + ui->topTime->value() * m_fltTopTimeMultiplier,
|
||||
getFps(ui->fps->currentIndex()),
|
||||
@ -384,8 +386,8 @@ void ATVDemodGUI::applySettings()
|
||||
ui->screenTabWidget->currentIndex());
|
||||
|
||||
qDebug() << "ATVDemodGUI::applySettings:"
|
||||
<< " m_objChannelizer.inputSampleRate: " << m_objChannelizer->getInputSampleRate()
|
||||
<< " m_objATVDemod.sampleRate: " << m_objATVDemod->getSampleRate();
|
||||
<< " m_objChannelizer.inputSampleRate: " << m_channelizer->getInputSampleRate()
|
||||
<< " m_objATVDemod.sampleRate: " << m_atvDemod->getSampleRate();
|
||||
}
|
||||
}
|
||||
|
||||
@ -393,7 +395,7 @@ void ATVDemodGUI::applyRFSettings()
|
||||
{
|
||||
if (m_blnDoApplySettings)
|
||||
{
|
||||
m_objATVDemod->configureRF(m_objATVDemod->getInputMessageQueue(),
|
||||
m_atvDemod->configureRF(m_atvDemod->getInputMessageQueue(),
|
||||
(ATVDemod::ATVModulation) ui->modulation->currentIndex(),
|
||||
ui->rfBW->value() * m_rfSliderDivisor * 1.0f,
|
||||
ui->rfOppBW->value() * m_rfSliderDivisor * 1.0f,
|
||||
@ -410,26 +412,26 @@ void ATVDemodGUI::setChannelMarkerBandwidth()
|
||||
|
||||
if (ui->rfFiltering->isChecked()) // FFT filter
|
||||
{
|
||||
m_objChannelMarker.setBandwidth(ui->rfBW->value()*m_rfSliderDivisor);
|
||||
m_objChannelMarker.setOppositeBandwidth(ui->rfOppBW->value()*m_rfSliderDivisor);
|
||||
m_channelMarker.setBandwidth(ui->rfBW->value()*m_rfSliderDivisor);
|
||||
m_channelMarker.setOppositeBandwidth(ui->rfOppBW->value()*m_rfSliderDivisor);
|
||||
|
||||
if (ui->modulation->currentIndex() == (int) ATVDemod::ATV_LSB) {
|
||||
m_objChannelMarker.setSidebands(ChannelMarker::vlsb);
|
||||
m_channelMarker.setSidebands(ChannelMarker::vlsb);
|
||||
} else if (ui->modulation->currentIndex() == (int) ATVDemod::ATV_USB) {
|
||||
m_objChannelMarker.setSidebands(ChannelMarker::vusb);
|
||||
m_channelMarker.setSidebands(ChannelMarker::vusb);
|
||||
} else {
|
||||
m_objChannelMarker.setSidebands(ChannelMarker::vusb);
|
||||
m_channelMarker.setSidebands(ChannelMarker::vusb);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ui->decimatorEnable->isChecked()) {
|
||||
m_objChannelMarker.setBandwidth(ui->rfBW->value()*m_rfSliderDivisor);
|
||||
m_channelMarker.setBandwidth(ui->rfBW->value()*m_rfSliderDivisor);
|
||||
} else {
|
||||
m_objChannelMarker.setBandwidth(m_objChannelizer->getInputSampleRate());
|
||||
m_channelMarker.setBandwidth(m_channelizer->getInputSampleRate());
|
||||
}
|
||||
|
||||
m_objChannelMarker.setSidebands(ChannelMarker::dsb);
|
||||
m_channelMarker.setSidebands(ChannelMarker::dsb);
|
||||
}
|
||||
|
||||
m_blnDoApplySettings = true;
|
||||
@ -463,14 +465,14 @@ void ATVDemodGUI::setRFFiltersSlidersRange(int sampleRate)
|
||||
void ATVDemodGUI::leaveEvent(QEvent*)
|
||||
{
|
||||
blockApplySettings(true);
|
||||
m_objChannelMarker.setHighlighted(false);
|
||||
m_channelMarker.setHighlighted(false);
|
||||
blockApplySettings(false);
|
||||
}
|
||||
|
||||
void ATVDemodGUI::enterEvent(QEvent*)
|
||||
{
|
||||
blockApplySettings(true);
|
||||
m_objChannelMarker.setHighlighted(true);
|
||||
m_channelMarker.setHighlighted(true);
|
||||
blockApplySettings(false);
|
||||
}
|
||||
|
||||
@ -482,13 +484,13 @@ void ATVDemodGUI::tick()
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_objATVDemod)
|
||||
if (m_atvDemod)
|
||||
{
|
||||
m_objMagSqAverage.feed(m_objATVDemod->getMagSq());
|
||||
m_objMagSqAverage.feed(m_atvDemod->getMagSq());
|
||||
double magSqDB = CalcDb::dbPower(m_objMagSqAverage.average() / (1<<30));
|
||||
ui->channePowerText->setText(tr("%1 dB").arg(magSqDB, 0, 'f', 1));
|
||||
|
||||
if (m_objATVDemod->getBFOLocked()) {
|
||||
if (m_atvDemod->getBFOLocked()) {
|
||||
ui->bfoLockedLabel->setStyleSheet("QLabel { background-color : green; }");
|
||||
} else {
|
||||
ui->bfoLockedLabel->setStyleSheet("QLabel { background:rgb(79,79,79); }");
|
||||
@ -573,7 +575,7 @@ void ATVDemodGUI::on_reset_clicked(bool checked __attribute__((unused)))
|
||||
|
||||
void ATVDemodGUI::on_modulation_currentIndexChanged(int index __attribute__((unused)))
|
||||
{
|
||||
setRFFiltersSlidersRange(m_objATVDemod->getEffectiveSampleRate());
|
||||
setRFFiltersSlidersRange(m_atvDemod->getEffectiveSampleRate());
|
||||
setChannelMarkerBandwidth();
|
||||
applyRFSettings();
|
||||
}
|
||||
@ -594,7 +596,7 @@ void ATVDemodGUI::on_rfOppBW_valueChanged(int value)
|
||||
|
||||
void ATVDemodGUI::on_rfFiltering_toggled(bool checked __attribute__((unused)))
|
||||
{
|
||||
setRFFiltersSlidersRange(m_objATVDemod->getEffectiveSampleRate());
|
||||
setRFFiltersSlidersRange(m_atvDemod->getEffectiveSampleRate());
|
||||
setChannelMarkerBandwidth();
|
||||
applyRFSettings();
|
||||
}
|
||||
@ -607,7 +609,7 @@ void ATVDemodGUI::on_decimatorEnable_toggled(bool checked __attribute__((unused)
|
||||
|
||||
void ATVDemodGUI::on_deltaFrequency_changed(qint64 value)
|
||||
{
|
||||
m_objChannelMarker.setCenterFrequency(value);
|
||||
m_channelMarker.setCenterFrequency(value);
|
||||
}
|
||||
|
||||
void ATVDemodGUI::on_bfo_valueChanged(int value)
|
||||
@ -632,10 +634,10 @@ void ATVDemodGUI::lineTimeUpdate()
|
||||
float nominalLineTime = getNominalLineTime(ui->nbLines->currentIndex(), ui->fps->currentIndex());
|
||||
int lineTimeScaleFactor = (int) std::log10(nominalLineTime);
|
||||
|
||||
if (m_objATVDemod->getEffectiveSampleRate() == 0) {
|
||||
if (m_atvDemod->getEffectiveSampleRate() == 0) {
|
||||
m_fltLineTimeMultiplier = std::pow(10.0, lineTimeScaleFactor-3);
|
||||
} else {
|
||||
m_fltLineTimeMultiplier = 1.0f / m_objATVDemod->getEffectiveSampleRate();
|
||||
m_fltLineTimeMultiplier = 1.0f / m_atvDemod->getEffectiveSampleRate();
|
||||
}
|
||||
|
||||
float lineTime = nominalLineTime + m_fltLineTimeMultiplier * ui->lineTime->value();
|
||||
@ -657,10 +659,10 @@ void ATVDemodGUI::topTimeUpdate()
|
||||
float nominalTopTime = getNominalLineTime(ui->nbLines->currentIndex(), ui->fps->currentIndex()) * (4.7f / 64.0f);
|
||||
int topTimeScaleFactor = (int) std::log10(nominalTopTime);
|
||||
|
||||
if (m_objATVDemod->getEffectiveSampleRate() == 0) {
|
||||
if (m_atvDemod->getEffectiveSampleRate() == 0) {
|
||||
m_fltTopTimeMultiplier = std::pow(10.0, topTimeScaleFactor-3);
|
||||
} else {
|
||||
m_fltTopTimeMultiplier = 1.0f / m_objATVDemod->getEffectiveSampleRate();
|
||||
m_fltTopTimeMultiplier = 1.0f / m_atvDemod->getEffectiveSampleRate();
|
||||
}
|
||||
|
||||
float topTime = nominalTopTime + m_fltTopTimeMultiplier * ui->topTime->value();
|
||||
|
@ -18,10 +18,10 @@
|
||||
#ifndef INCLUDE_ATVDEMODGUI_H
|
||||
#define INCLUDE_ATVDEMODGUI_H
|
||||
|
||||
#include <plugin/plugininstancegui.h>
|
||||
#include "gui/rollupwidget.h"
|
||||
#include "dsp/channelmarker.h"
|
||||
#include "dsp/movingaverage.h"
|
||||
#include "plugin/plugininstanceui.h"
|
||||
#include "util/messagequeue.h"
|
||||
|
||||
class PluginAPI;
|
||||
@ -37,7 +37,7 @@ namespace Ui
|
||||
class ATVDemodGUI;
|
||||
}
|
||||
|
||||
class ATVDemodGUI : public RollupWidget, public PluginInstanceUI
|
||||
class ATVDemodGUI : public RollupWidget, public PluginInstanceGUI
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
@ -89,12 +89,12 @@ private slots:
|
||||
|
||||
private:
|
||||
Ui::ATVDemodGUI* ui;
|
||||
PluginAPI* m_objPluginAPI;
|
||||
DeviceSourceAPI* m_objDeviceAPI;
|
||||
ChannelMarker m_objChannelMarker;
|
||||
ThreadedBasebandSampleSink* m_objThreadedChannelizer;
|
||||
DownChannelizer* m_objChannelizer;
|
||||
ATVDemod* m_objATVDemod;
|
||||
PluginAPI* m_pluginAPI;
|
||||
DeviceSourceAPI* m_deviceAPI;
|
||||
ChannelMarker m_channelMarker;
|
||||
ThreadedBasebandSampleSink* m_threadedChannelizer;
|
||||
DownChannelizer* m_channelizer;
|
||||
ATVDemod* m_atvDemod;
|
||||
|
||||
bool m_blnBasicSettingsShown;
|
||||
bool m_blnDoApplySettings;
|
||||
@ -102,7 +102,7 @@ private:
|
||||
MovingAverage<double> m_objMagSqAverage;
|
||||
int m_intTickCount;
|
||||
|
||||
ScopeVisNG* m_objScopeVis;
|
||||
ScopeVisNG* m_scopeVis;
|
||||
|
||||
float m_fltLineTimeMultiplier;
|
||||
float m_fltTopTimeMultiplier;
|
||||
|
@ -26,7 +26,7 @@
|
||||
const PluginDescriptor ATVDemodPlugin::m_ptrPluginDescriptor =
|
||||
{
|
||||
QString("ATV Demodulator"),
|
||||
QString("3.5.0"),
|
||||
QString("3.7.3"),
|
||||
QString("(c) F4HKW for F4EXB / SDRAngel"),
|
||||
QString("https://github.com/f4exb/sdrangel"),
|
||||
true,
|
||||
@ -53,7 +53,7 @@ void ATVDemodPlugin::initPlugin(PluginAPI* ptrPluginAPI)
|
||||
m_ptrPluginAPI->registerRxChannel(ATVDemodGUI::m_strChannelID, this);
|
||||
}
|
||||
|
||||
PluginInstanceUI* ATVDemodPlugin::createRxChannel(const QString& strChannelName, DeviceSourceAPI *ptrDeviceAPI)
|
||||
PluginInstanceGUI* ATVDemodPlugin::createRxChannel(const QString& strChannelName, DeviceSourceAPI *ptrDeviceAPI)
|
||||
{
|
||||
if(strChannelName == ATVDemodGUI::m_strChannelID)
|
||||
{
|
||||
|
@ -35,7 +35,7 @@ public:
|
||||
const PluginDescriptor& getPluginDescriptor() const;
|
||||
void initPlugin(PluginAPI* ptrPluginAPI);
|
||||
|
||||
PluginInstanceUI* createRxChannel(const QString& strChannelName, DeviceSourceAPI *ptrDeviceAPI);
|
||||
PluginInstanceGUI* createRxChannel(const QString& strChannelName, DeviceSourceAPI *ptrDeviceAPI);
|
||||
|
||||
private:
|
||||
static const PluginDescriptor m_ptrPluginDescriptor;
|
||||
|
@ -3,6 +3,7 @@ project(bfm)
|
||||
set(bfm_SOURCES
|
||||
bfmdemod.cpp
|
||||
bfmdemodgui.cpp
|
||||
bfmdemodsettings.cpp
|
||||
bfmplugin.cpp
|
||||
rdsdemod.cpp
|
||||
rdsdecoder.cpp
|
||||
@ -13,6 +14,7 @@ set(bfm_SOURCES
|
||||
set(bfm_HEADERS
|
||||
bfmdemod.h
|
||||
bfmdemodgui.h
|
||||
bfmdemodsettings.h
|
||||
bfmplugin.h
|
||||
rdsdemod.h
|
||||
rdsdecoder.h
|
||||
|
@ -15,63 +15,77 @@
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "../../channelrx/demodbfm/bfmdemod.h"
|
||||
|
||||
#include <QTime>
|
||||
#include <QDebug>
|
||||
#include <stdio.h>
|
||||
#include <complex.h>
|
||||
|
||||
#include "audio/audiooutput.h"
|
||||
#include "dsp/dspengine.h"
|
||||
#include "dsp/pidcontroller.h"
|
||||
#include "bfmdemod.h"
|
||||
|
||||
#include <dsp/downchannelizer.h>
|
||||
#include "dsp/threadedbasebandsamplesink.h"
|
||||
#include "device/devicesourceapi.h"
|
||||
|
||||
#include "rdsparser.h"
|
||||
#include "bfmdemod.h"
|
||||
|
||||
MESSAGE_CLASS_DEFINITION(BFMDemod::MsgConfigureChannelizer, Message)
|
||||
MESSAGE_CLASS_DEFINITION(BFMDemod::MsgReportChannelSampleRateChanged, Message)
|
||||
MESSAGE_CLASS_DEFINITION(BFMDemod::MsgConfigureBFMDemod, Message)
|
||||
|
||||
const Real BFMDemod::default_deemphasis = 50.0; // 50 us
|
||||
const int BFMDemod::m_udpBlockSize = 512;
|
||||
|
||||
BFMDemod::BFMDemod(BasebandSampleSink* sampleSink, RDSParser *rdsParser) :
|
||||
m_sampleSink(sampleSink),
|
||||
BFMDemod::BFMDemod(DeviceSourceAPI *deviceAPI) :
|
||||
m_deviceAPI(deviceAPI),
|
||||
m_audioFifo(250000),
|
||||
m_settingsMutex(QMutex::Recursive),
|
||||
m_pilotPLL(19000/384000, 50/384000, 0.01),
|
||||
m_rdsParser(rdsParser),
|
||||
m_deemphasisFilterX(default_deemphasis * 48000 * 1.0e-6),
|
||||
m_deemphasisFilterY(default_deemphasis * 48000 * 1.0e-6),
|
||||
m_fmExcursion(default_excursion)
|
||||
{
|
||||
setObjectName("BFMDemod");
|
||||
|
||||
m_config.m_inputSampleRate = 384000;
|
||||
m_config.m_inputFrequencyOffset = 0;
|
||||
m_config.m_rfBandwidth = 180000;
|
||||
m_config.m_afBandwidth = 15000;
|
||||
m_config.m_squelch = -60.0;
|
||||
m_config.m_volume = 2.0;
|
||||
m_config.m_audioSampleRate = DSPEngine::instance()->getAudioSampleRate(); // normally 48 kHz
|
||||
m_deemphasisFilterX.configure(default_deemphasis * m_config.m_audioSampleRate * 1.0e-6);
|
||||
m_deemphasisFilterY.configure(default_deemphasis * m_config.m_audioSampleRate * 1.0e-6);
|
||||
m_rfFilter = new fftfilt(-50000.0 / 384000.0, 50000.0 / 384000.0, filtFftLen);
|
||||
m_phaseDiscri.setFMScaling(384000/m_fmExcursion);
|
||||
|
||||
apply();
|
||||
|
||||
m_audioBuffer.resize(16384);
|
||||
m_audioBufferFill = 0;
|
||||
|
||||
// m_movingAverage.resize(16, 0);
|
||||
m_magsq = 0.0f;
|
||||
m_magsq = 0.0f;
|
||||
m_magsqSum = 0.0f;
|
||||
m_magsqPeak = 0.0f;
|
||||
m_magsqCount = 0;
|
||||
|
||||
m_squelchLevel = 0;
|
||||
m_squelchState = 0;
|
||||
|
||||
m_interpolatorDistance = 0.0f;
|
||||
m_interpolatorDistanceRemain = 0.0f;
|
||||
|
||||
m_interpolatorRDSDistance = 0.0f;
|
||||
m_interpolatorRDSDistanceRemain = 0.0f;
|
||||
|
||||
m_interpolatorStereoDistance = 0.0f;
|
||||
m_interpolatorStereoDistanceRemain = 0.0f;
|
||||
|
||||
m_sampleSink = 0;
|
||||
m_m1Arg = 0;
|
||||
|
||||
m_rfFilter = new fftfilt(-50000.0 / 384000.0, 50000.0 / 384000.0, filtFftLen);
|
||||
|
||||
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_deemphasisFilterX.configure(default_deemphasis * m_settings.m_audioSampleRate * 1.0e-6);
|
||||
m_deemphasisFilterY.configure(default_deemphasis * m_settings.m_audioSampleRate * 1.0e-6);
|
||||
m_phaseDiscri.setFMScaling(384000/m_fmExcursion);
|
||||
|
||||
m_audioBuffer.resize(16384);
|
||||
m_audioBufferFill = 0;
|
||||
|
||||
DSPEngine::instance()->addAudioSink(&m_audioFifo);
|
||||
m_udpBufferAudio = new UDPSink<AudioSample>(this, m_udpBlockSize, m_config.m_udpPort);
|
||||
m_udpBufferAudio = new UDPSink<AudioSample>(this, m_udpBlockSize, m_settings.m_udpPort);
|
||||
|
||||
applySettings(m_settings, true);
|
||||
}
|
||||
|
||||
BFMDemod::~BFMDemod()
|
||||
@ -83,35 +97,10 @@ BFMDemod::~BFMDemod()
|
||||
|
||||
DSPEngine::instance()->removeAudioSink(&m_audioFifo);
|
||||
delete m_udpBufferAudio;
|
||||
}
|
||||
|
||||
void BFMDemod::configure(MessageQueue* messageQueue,
|
||||
Real rfBandwidth,
|
||||
Real afBandwidth,
|
||||
Real volume,
|
||||
Real squelch,
|
||||
bool audioStereo,
|
||||
bool lsbStereo,
|
||||
bool showPilot,
|
||||
bool rdsActive,
|
||||
bool copyAudioToUDP,
|
||||
const QString& udpAddress,
|
||||
quint16 udpPort,
|
||||
bool force)
|
||||
{
|
||||
Message* cmd = MsgConfigureBFMDemod::create(rfBandwidth,
|
||||
afBandwidth,
|
||||
volume,
|
||||
squelch,
|
||||
audioStereo,
|
||||
lsbStereo,
|
||||
showPilot,
|
||||
rdsActive,
|
||||
copyAudioToUDP,
|
||||
udpAddress,
|
||||
udpPort,
|
||||
force);
|
||||
messageQueue->push(cmd);
|
||||
m_deviceAPI->removeThreadedSink(m_threadedChannelizer);
|
||||
delete m_threadedChannelizer;
|
||||
delete m_channelizer;
|
||||
}
|
||||
|
||||
void BFMDemod::feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end, bool firstOfBurst __attribute__((unused)))
|
||||
@ -149,7 +138,7 @@ void BFMDemod::feed(const SampleVector::const_iterator& begin, const SampleVecto
|
||||
// m_movingAverage.feed(msq);
|
||||
|
||||
if(m_magsq >= m_squelchLevel) {
|
||||
m_squelchState = m_running.m_rfBandwidth / 20; // decay rate
|
||||
m_squelchState = m_settings.m_rfBandwidth / 20; // decay rate
|
||||
}
|
||||
|
||||
if(m_squelchState > 0)
|
||||
@ -164,12 +153,12 @@ void BFMDemod::feed(const SampleVector::const_iterator& begin, const SampleVecto
|
||||
demod = 0;
|
||||
}
|
||||
|
||||
if (!m_running.m_showPilot)
|
||||
if (!m_settings.m_showPilot)
|
||||
{
|
||||
m_sampleBuffer.push_back(Sample(demod * (1<<15), 0.0));
|
||||
}
|
||||
|
||||
if (m_running.m_rdsActive)
|
||||
if (m_settings.m_rdsActive)
|
||||
{
|
||||
//Complex r(demod * 2.0 * std::cos(3.0 * m_pilotPLLSamples[3]), 0.0);
|
||||
Complex r(demod * 2.0 * std::cos(3.0 * m_pilotPLLSamples[3]), 0.0);
|
||||
@ -182,10 +171,7 @@ void BFMDemod::feed(const SampleVector::const_iterator& begin, const SampleVecto
|
||||
{
|
||||
if (m_rdsDecoder.frameSync(bit))
|
||||
{
|
||||
if (m_rdsParser)
|
||||
{
|
||||
m_rdsParser->parseGroup(m_rdsDecoder.getGroup());
|
||||
}
|
||||
m_rdsParser.parseGroup(m_rdsDecoder.getGroup());
|
||||
}
|
||||
}
|
||||
|
||||
@ -197,16 +183,16 @@ void BFMDemod::feed(const SampleVector::const_iterator& begin, const SampleVecto
|
||||
|
||||
// Process stereo if stereo mode is selected
|
||||
|
||||
if (m_running.m_audioStereo)
|
||||
if (m_settings.m_audioStereo)
|
||||
{
|
||||
m_pilotPLL.process(demod, m_pilotPLLSamples);
|
||||
|
||||
if (m_running.m_showPilot)
|
||||
if (m_settings.m_showPilot)
|
||||
{
|
||||
m_sampleBuffer.push_back(Sample(m_pilotPLLSamples[1] * (1<<15), 0.0)); // debug 38 kHz pilot
|
||||
}
|
||||
|
||||
if (m_running.m_lsbStereo)
|
||||
if (m_settings.m_lsbStereo)
|
||||
{
|
||||
// 1.17 * 0.7 = 0.819
|
||||
Complex s(demod * m_pilotPLLSamples[1], demod * m_pilotPLLSamples[2]);
|
||||
@ -233,32 +219,32 @@ void BFMDemod::feed(const SampleVector::const_iterator& begin, const SampleVecto
|
||||
|
||||
if (m_interpolator.decimate(&m_interpolatorDistanceRemain, e, &ci))
|
||||
{
|
||||
if (m_running.m_audioStereo)
|
||||
if (m_settings.m_audioStereo)
|
||||
{
|
||||
Real deemph_l, deemph_r; // Pre-emphasis is applied on each channel before multiplexing
|
||||
m_deemphasisFilterX.process(ci.real() + sampleStereo, deemph_l);
|
||||
m_deemphasisFilterY.process(ci.real() - sampleStereo, deemph_r);
|
||||
if (m_running.m_lsbStereo)
|
||||
if (m_settings.m_lsbStereo)
|
||||
{
|
||||
m_audioBuffer[m_audioBufferFill].l = (qint16)(deemph_l * (1<<12) * m_running.m_volume);
|
||||
m_audioBuffer[m_audioBufferFill].r = (qint16)(deemph_r * (1<<12) * m_running.m_volume);
|
||||
if (m_running.m_copyAudioToUDP) m_udpBufferAudio->write(m_audioBuffer[m_audioBufferFill]);
|
||||
m_audioBuffer[m_audioBufferFill].l = (qint16)(deemph_l * (1<<12) * m_settings.m_volume);
|
||||
m_audioBuffer[m_audioBufferFill].r = (qint16)(deemph_r * (1<<12) * m_settings.m_volume);
|
||||
if (m_settings.m_copyAudioToUDP) m_udpBufferAudio->write(m_audioBuffer[m_audioBufferFill]);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_audioBuffer[m_audioBufferFill].l = (qint16)(deemph_l * (1<<12) * m_running.m_volume);
|
||||
m_audioBuffer[m_audioBufferFill].r = (qint16)(deemph_r * (1<<12) * m_running.m_volume);
|
||||
if (m_running.m_copyAudioToUDP) m_udpBufferAudio->write(m_audioBuffer[m_audioBufferFill]);
|
||||
m_audioBuffer[m_audioBufferFill].l = (qint16)(deemph_l * (1<<12) * m_settings.m_volume);
|
||||
m_audioBuffer[m_audioBufferFill].r = (qint16)(deemph_r * (1<<12) * m_settings.m_volume);
|
||||
if (m_settings.m_copyAudioToUDP) m_udpBufferAudio->write(m_audioBuffer[m_audioBufferFill]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Real deemph;
|
||||
m_deemphasisFilterX.process(ci.real(), deemph);
|
||||
quint16 sample = (qint16)(deemph * (1<<12) * m_running.m_volume);
|
||||
quint16 sample = (qint16)(deemph * (1<<12) * m_settings.m_volume);
|
||||
m_audioBuffer[m_audioBufferFill].l = sample;
|
||||
m_audioBuffer[m_audioBufferFill].r = sample;
|
||||
if (m_running.m_copyAudioToUDP) m_udpBufferAudio->write(m_audioBuffer[m_audioBufferFill]);
|
||||
if (m_settings.m_copyAudioToUDP) m_udpBufferAudio->write(m_audioBuffer[m_audioBufferFill]);
|
||||
}
|
||||
|
||||
++m_audioBufferFill;
|
||||
@ -313,54 +299,58 @@ void BFMDemod::stop()
|
||||
{
|
||||
}
|
||||
|
||||
void BFMDemod::channelSampleRateChanged()
|
||||
{
|
||||
MsgReportChannelSampleRateChanged *msg = MsgReportChannelSampleRateChanged::create(getSampleRate());
|
||||
getMessageQueueToGUI()->push(msg);
|
||||
}
|
||||
|
||||
bool BFMDemod::handleMessage(const Message& cmd)
|
||||
{
|
||||
if (DownChannelizer::MsgChannelizerNotification::match(cmd))
|
||||
{
|
||||
DownChannelizer::MsgChannelizerNotification& notif = (DownChannelizer::MsgChannelizerNotification&) cmd;
|
||||
|
||||
m_config.m_inputSampleRate = notif.getSampleRate();
|
||||
m_config.m_inputFrequencyOffset = notif.getFrequencyOffset();
|
||||
BFMDemodSettings settings = m_settings;
|
||||
|
||||
apply();
|
||||
settings.m_inputSampleRate = notif.getSampleRate();
|
||||
settings.m_inputFrequencyOffset = notif.getFrequencyOffset();
|
||||
|
||||
qDebug() << "BFMDemod::handleMessage: MsgChannelizerNotification: m_inputSampleRate: " << m_config.m_inputSampleRate
|
||||
<< " m_inputFrequencyOffset: " << m_config.m_inputFrequencyOffset;
|
||||
applySettings(settings);
|
||||
|
||||
qDebug() << "BFMDemod::handleMessage: MsgChannelizerNotification:"
|
||||
<< " m_inputSampleRate: " << settings.m_inputSampleRate
|
||||
<< " m_inputFrequencyOffset: " << settings.m_inputFrequencyOffset;
|
||||
|
||||
return true;
|
||||
}
|
||||
else if (MsgConfigureBFMDemod::match(cmd))
|
||||
{
|
||||
MsgConfigureBFMDemod& cfg = (MsgConfigureBFMDemod&) cmd;
|
||||
else if (MsgConfigureBFMDemod::match(cmd))
|
||||
{
|
||||
MsgConfigureBFMDemod& cfg = (MsgConfigureBFMDemod&) cmd;
|
||||
|
||||
m_config.m_rfBandwidth = cfg.getRFBandwidth();
|
||||
m_config.m_afBandwidth = cfg.getAFBandwidth();
|
||||
m_config.m_volume = cfg.getVolume();
|
||||
m_config.m_squelch = cfg.getSquelch();
|
||||
m_config.m_audioStereo = cfg.getAudioStereo();
|
||||
m_config.m_lsbStereo = cfg.getLsbStereo();
|
||||
m_config.m_showPilot = cfg.getShowPilot();
|
||||
m_config.m_rdsActive = cfg.getRDSActive();
|
||||
m_config.m_copyAudioToUDP= cfg.getCopyAudioToUDP();
|
||||
m_config.m_udpAddress = cfg.getUDPAddress();
|
||||
m_config.m_udpPort = cfg.getUDPPort();
|
||||
BFMDemodSettings settings = cfg.getSettings();
|
||||
|
||||
apply(cfg.getForce());
|
||||
// These settings are set with DownChannelizer::MsgChannelizerNotification
|
||||
settings.m_inputSampleRate = m_settings.m_inputSampleRate;
|
||||
settings.m_inputFrequencyOffset = m_settings.m_inputFrequencyOffset;
|
||||
|
||||
qDebug() << "BFMDemod::handleMessage: MsgConfigureBFMDemod: m_rfBandwidth: " << m_config.m_rfBandwidth
|
||||
<< " m_afBandwidth: " << m_config.m_afBandwidth
|
||||
<< " m_volume: " << m_config.m_volume
|
||||
<< " m_squelch: " << m_config.m_squelch
|
||||
<< " m_audioStereo: " << m_config.m_audioStereo
|
||||
<< " m_lsbStereo: " << m_config.m_lsbStereo
|
||||
<< " m_showPilot: " << m_config.m_showPilot
|
||||
<< " m_rdsActive: " << m_config.m_rdsActive
|
||||
<< " m_copyAudioToUDP: " << m_config.m_copyAudioToUDP
|
||||
<< " m_udpAddress: " << m_config.m_udpAddress
|
||||
<< " m_udpPort: " << m_config.m_udpPort;
|
||||
applySettings(settings, cfg.getForce());
|
||||
|
||||
return true;
|
||||
}
|
||||
qDebug() << "BFMDemod::handleMessage: MsgConfigureBFMDemod:"
|
||||
<< " m_rfBandwidth: " << settings.m_rfBandwidth
|
||||
<< " m_volume: " << settings.m_volume
|
||||
<< " m_squelch: " << settings.m_squelch
|
||||
<< " m_audioStereo: " << settings.m_audioStereo
|
||||
<< " m_lsbStereo: " << settings.m_lsbStereo
|
||||
<< " m_showPilot: " << settings.m_showPilot
|
||||
<< " m_rdsActive: " << settings.m_rdsActive
|
||||
<< " m_copyAudioToUDP: " << settings.m_copyAudioToUDP
|
||||
<< " m_udpAddress: " << settings.m_udpAddress
|
||||
<< " m_udpPort: " << settings.m_udpPort
|
||||
<< " force: " << cfg.getForce();
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
qDebug() << "BFMDemod::handleMessage: none";
|
||||
@ -376,87 +366,87 @@ bool BFMDemod::handleMessage(const Message& cmd)
|
||||
}
|
||||
}
|
||||
|
||||
void BFMDemod::apply(bool force)
|
||||
void BFMDemod::applySettings(const BFMDemodSettings& settings, bool force)
|
||||
{
|
||||
if ((m_config.m_inputSampleRate != m_running.m_inputSampleRate)
|
||||
|| (m_config.m_audioStereo && (m_config.m_audioStereo != m_running.m_audioStereo)) || force)
|
||||
{
|
||||
m_pilotPLL.configure(19000.0/m_config.m_inputSampleRate, 50.0/m_config.m_inputSampleRate, 0.01);
|
||||
}
|
||||
|
||||
if((m_config.m_inputFrequencyOffset != m_running.m_inputFrequencyOffset) ||
|
||||
(m_config.m_inputSampleRate != m_running.m_inputSampleRate) || force)
|
||||
{
|
||||
qDebug() << "BFMDemod::handleMessage: m_nco.setFreq";
|
||||
m_nco.setFreq(-m_config.m_inputFrequencyOffset, m_config.m_inputSampleRate);
|
||||
}
|
||||
|
||||
if((m_config.m_inputSampleRate != m_running.m_inputSampleRate) ||
|
||||
(m_config.m_afBandwidth != m_running.m_afBandwidth) || force)
|
||||
{
|
||||
m_settingsMutex.lock();
|
||||
qDebug() << "BFMDemod::handleMessage: m_interpolator.create";
|
||||
|
||||
m_interpolator.create(16, m_config.m_inputSampleRate, m_config.m_afBandwidth);
|
||||
m_interpolatorDistanceRemain = (Real) m_config.m_inputSampleRate / m_config.m_audioSampleRate;
|
||||
m_interpolatorDistance = (Real) m_config.m_inputSampleRate / (Real) m_config.m_audioSampleRate;
|
||||
|
||||
m_interpolatorStereo.create(16, m_config.m_inputSampleRate, m_config.m_afBandwidth);
|
||||
m_interpolatorStereoDistanceRemain = (Real) m_config.m_inputSampleRate / m_config.m_audioSampleRate;
|
||||
m_interpolatorStereoDistance = (Real) m_config.m_inputSampleRate / (Real) m_config.m_audioSampleRate;
|
||||
|
||||
m_interpolatorRDS.create(4, m_config.m_inputSampleRate, 600.0);
|
||||
m_interpolatorRDSDistanceRemain = (Real) m_config.m_inputSampleRate / 250000.0;
|
||||
m_interpolatorRDSDistance = (Real) m_config.m_inputSampleRate / 250000.0;
|
||||
|
||||
m_settingsMutex.unlock();
|
||||
}
|
||||
|
||||
if((m_config.m_inputSampleRate != m_running.m_inputSampleRate) ||
|
||||
(m_config.m_rfBandwidth != m_running.m_rfBandwidth) ||
|
||||
(m_config.m_inputFrequencyOffset != m_running.m_inputFrequencyOffset) || force)
|
||||
{
|
||||
m_settingsMutex.lock();
|
||||
Real lowCut = -(m_config.m_rfBandwidth / 2.0) / m_config.m_inputSampleRate;
|
||||
Real hiCut = (m_config.m_rfBandwidth / 2.0) / m_config.m_inputSampleRate;
|
||||
m_rfFilter->create_filter(lowCut, hiCut);
|
||||
m_phaseDiscri.setFMScaling(m_config.m_inputSampleRate / m_fmExcursion);
|
||||
m_settingsMutex.unlock();
|
||||
|
||||
qDebug() << "BFMDemod::handleMessage: m_rfFilter->create_filter: sampleRate: "
|
||||
<< m_config.m_inputSampleRate
|
||||
<< " lowCut: " << lowCut * m_config.m_inputSampleRate
|
||||
<< " hiCut: " << hiCut * m_config.m_inputSampleRate;
|
||||
}
|
||||
|
||||
if ((m_config.m_afBandwidth != m_running.m_afBandwidth) ||
|
||||
(m_config.m_audioSampleRate != m_running.m_audioSampleRate) || force)
|
||||
{
|
||||
m_settingsMutex.lock();
|
||||
qDebug() << "BFMDemod::handleMessage: m_lowpass.create";
|
||||
m_lowpass.create(21, m_config.m_audioSampleRate, m_config.m_afBandwidth);
|
||||
m_settingsMutex.unlock();
|
||||
}
|
||||
|
||||
if ((m_config.m_squelch != m_running.m_squelch) || force)
|
||||
{
|
||||
qDebug() << "BFMDemod::handleMessage: set m_squelchLevel";
|
||||
m_squelchLevel = std::pow(10.0, m_config.m_squelch / 20.0);
|
||||
m_squelchLevel *= m_squelchLevel;
|
||||
}
|
||||
|
||||
if ((m_config.m_audioSampleRate != m_running.m_audioSampleRate) || force)
|
||||
{
|
||||
m_deemphasisFilterX.configure(default_deemphasis * m_config.m_audioSampleRate * 1.0e-6);
|
||||
m_deemphasisFilterY.configure(default_deemphasis * m_config.m_audioSampleRate * 1.0e-6);
|
||||
}
|
||||
|
||||
if ((m_config.m_udpAddress != m_running.m_udpAddress)
|
||||
|| (m_config.m_udpPort != m_running.m_udpPort) || force)
|
||||
if ((settings.m_inputSampleRate != m_settings.m_inputSampleRate)
|
||||
|| (settings.m_audioStereo && (settings.m_audioStereo != m_settings.m_audioStereo)) || force)
|
||||
{
|
||||
m_udpBufferAudio->setAddress(m_config.m_udpAddress);
|
||||
m_udpBufferAudio->setPort(m_config.m_udpPort);
|
||||
m_pilotPLL.configure(19000.0/settings.m_inputSampleRate, 50.0/settings.m_inputSampleRate, 0.01);
|
||||
}
|
||||
|
||||
m_running = m_config;
|
||||
if((settings.m_inputFrequencyOffset != m_settings.m_inputFrequencyOffset) ||
|
||||
(settings.m_inputSampleRate != m_settings.m_inputSampleRate) || force)
|
||||
{
|
||||
qDebug() << "BFMDemod::handleMessage: m_nco.setFreq";
|
||||
m_nco.setFreq(-settings.m_inputFrequencyOffset, settings.m_inputSampleRate);
|
||||
}
|
||||
|
||||
if((settings.m_inputSampleRate != m_settings.m_inputSampleRate) ||
|
||||
(settings.m_afBandwidth != m_settings.m_afBandwidth) || force)
|
||||
{
|
||||
m_settingsMutex.lock();
|
||||
qDebug() << "BFMDemod::handleMessage: m_interpolator.create";
|
||||
|
||||
m_interpolator.create(16, settings.m_inputSampleRate, settings.m_afBandwidth);
|
||||
m_interpolatorDistanceRemain = (Real) settings.m_inputSampleRate / settings.m_audioSampleRate;
|
||||
m_interpolatorDistance = (Real) settings.m_inputSampleRate / (Real) settings.m_audioSampleRate;
|
||||
|
||||
m_interpolatorStereo.create(16, settings.m_inputSampleRate, settings.m_afBandwidth);
|
||||
m_interpolatorStereoDistanceRemain = (Real) settings.m_inputSampleRate / settings.m_audioSampleRate;
|
||||
m_interpolatorStereoDistance = (Real) settings.m_inputSampleRate / (Real) settings.m_audioSampleRate;
|
||||
|
||||
m_interpolatorRDS.create(4, settings.m_inputSampleRate, 600.0);
|
||||
m_interpolatorRDSDistanceRemain = (Real) settings.m_inputSampleRate / 250000.0;
|
||||
m_interpolatorRDSDistance = (Real) settings.m_inputSampleRate / 250000.0;
|
||||
|
||||
m_settingsMutex.unlock();
|
||||
}
|
||||
|
||||
if((settings.m_inputSampleRate != m_settings.m_inputSampleRate) ||
|
||||
(settings.m_rfBandwidth != m_settings.m_rfBandwidth) ||
|
||||
(settings.m_inputFrequencyOffset != m_settings.m_inputFrequencyOffset) || force)
|
||||
{
|
||||
m_settingsMutex.lock();
|
||||
Real lowCut = -(settings.m_rfBandwidth / 2.0) / settings.m_inputSampleRate;
|
||||
Real hiCut = (settings.m_rfBandwidth / 2.0) / settings.m_inputSampleRate;
|
||||
m_rfFilter->create_filter(lowCut, hiCut);
|
||||
m_phaseDiscri.setFMScaling(settings.m_inputSampleRate / m_fmExcursion);
|
||||
m_settingsMutex.unlock();
|
||||
|
||||
qDebug() << "BFMDemod::handleMessage: m_rfFilter->create_filter: sampleRate: "
|
||||
<< settings.m_inputSampleRate
|
||||
<< " lowCut: " << lowCut * settings.m_inputSampleRate
|
||||
<< " hiCut: " << hiCut * settings.m_inputSampleRate;
|
||||
}
|
||||
|
||||
if ((settings.m_afBandwidth != m_settings.m_afBandwidth) ||
|
||||
(settings.m_audioSampleRate != m_settings.m_audioSampleRate) || force)
|
||||
{
|
||||
m_settingsMutex.lock();
|
||||
qDebug() << "BFMDemod::handleMessage: m_lowpass.create";
|
||||
m_lowpass.create(21, settings.m_audioSampleRate, settings.m_afBandwidth);
|
||||
m_settingsMutex.unlock();
|
||||
}
|
||||
|
||||
if ((settings.m_squelch != m_settings.m_squelch) || force)
|
||||
{
|
||||
qDebug() << "BFMDemod::handleMessage: set m_squelchLevel";
|
||||
m_squelchLevel = std::pow(10.0, settings.m_squelch / 20.0);
|
||||
m_squelchLevel *= m_squelchLevel;
|
||||
}
|
||||
|
||||
if ((settings.m_audioSampleRate != m_settings.m_audioSampleRate) || force)
|
||||
{
|
||||
m_deemphasisFilterX.configure(default_deemphasis * settings.m_audioSampleRate * 1.0e-6);
|
||||
m_deemphasisFilterY.configure(default_deemphasis * settings.m_audioSampleRate * 1.0e-6);
|
||||
}
|
||||
|
||||
if ((settings.m_udpAddress != m_settings.m_udpAddress)
|
||||
|| (settings.m_udpPort != m_settings.m_udpPort) || force)
|
||||
{
|
||||
m_udpBufferAudio->setAddress(const_cast<QString&>(settings.m_udpAddress));
|
||||
m_udpBufferAudio->setPort(settings.m_udpPort);
|
||||
}
|
||||
|
||||
m_settings = settings;
|
||||
}
|
||||
|
@ -33,31 +33,88 @@
|
||||
#include "util/message.h"
|
||||
#include "util/udpsink.h"
|
||||
|
||||
#include "rdsparser.h"
|
||||
#include "rdsdecoder.h"
|
||||
#include "rdsdemod.h"
|
||||
#include "bfmdemodsettings.h"
|
||||
|
||||
class RDSParser;
|
||||
class DeviceSourceAPI;
|
||||
class ThreadedBasebandSampleSink;
|
||||
class DownChannelizer;
|
||||
|
||||
class BFMDemod : public BasebandSampleSink {
|
||||
public:
|
||||
BFMDemod(BasebandSampleSink* sampleSink, RDSParser* rdsParser);
|
||||
class MsgConfigureBFMDemod : public Message {
|
||||
MESSAGE_CLASS_DECLARATION
|
||||
|
||||
public:
|
||||
const BFMDemodSettings& getSettings() const { return m_settings; }
|
||||
bool getForce() const { return m_force; }
|
||||
|
||||
static MsgConfigureBFMDemod* create(const BFMDemodSettings& settings, bool force)
|
||||
{
|
||||
return new MsgConfigureBFMDemod(settings, force);
|
||||
}
|
||||
|
||||
private:
|
||||
BFMDemodSettings m_settings;
|
||||
bool m_force;
|
||||
|
||||
MsgConfigureBFMDemod(const BFMDemodSettings& 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 MsgReportChannelSampleRateChanged : public Message {
|
||||
MESSAGE_CLASS_DECLARATION
|
||||
|
||||
public:
|
||||
int getSampleRate() const { return m_sampleRate; }
|
||||
|
||||
static MsgReportChannelSampleRateChanged* create(int sampleRate)
|
||||
{
|
||||
return new MsgReportChannelSampleRateChanged(sampleRate);
|
||||
}
|
||||
|
||||
private:
|
||||
int m_sampleRate;
|
||||
|
||||
MsgReportChannelSampleRateChanged(int sampleRate) :
|
||||
Message(),
|
||||
m_sampleRate(sampleRate)
|
||||
{ }
|
||||
};
|
||||
|
||||
BFMDemod(DeviceSourceAPI *deviceAPI);
|
||||
virtual ~BFMDemod();
|
||||
void setSampleSink(BasebandSampleSink* sampleSink) { m_sampleSink = sampleSink; }
|
||||
|
||||
void configure(MessageQueue* messageQueue,
|
||||
Real rfBandwidth,
|
||||
Real afBandwidth,
|
||||
Real volume,
|
||||
Real squelch,
|
||||
bool audioStereo,
|
||||
bool lsbStereo,
|
||||
bool showPilot,
|
||||
bool rdsActive,
|
||||
bool copyAudioUDP,
|
||||
const QString& m_udpAddress,
|
||||
quint16 udpPort,
|
||||
bool force = false);
|
||||
|
||||
int getSampleRate() const { return m_config.m_inputSampleRate; }
|
||||
int getSampleRate() const { return m_settings.m_inputSampleRate; }
|
||||
virtual void feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end, bool po);
|
||||
virtual void start();
|
||||
virtual void stop();
|
||||
@ -85,134 +142,22 @@ public:
|
||||
m_magsqCount = 0;
|
||||
}
|
||||
|
||||
RDSParser& getRDSParser() { return m_rdsParser; }
|
||||
|
||||
private slots:
|
||||
void channelSampleRateChanged();
|
||||
|
||||
private:
|
||||
class MsgConfigureBFMDemod : public Message {
|
||||
MESSAGE_CLASS_DECLARATION
|
||||
|
||||
public:
|
||||
Real getRFBandwidth() const { return m_rfBandwidth; }
|
||||
Real getAFBandwidth() const { return m_afBandwidth; }
|
||||
Real getVolume() const { return m_volume; }
|
||||
Real getSquelch() const { return m_squelch; }
|
||||
bool getAudioStereo() const { return m_audioStereo; }
|
||||
bool getLsbStereo() const { return m_lsbStereo; }
|
||||
bool getShowPilot() const { return m_showPilot; }
|
||||
bool getRDSActive() const { return m_rdsActive; }
|
||||
bool getCopyAudioToUDP() const { return m_copyAudioToUDP; }
|
||||
const QString& getUDPAddress() const { return m_udpAddress; }
|
||||
quint16 getUDPPort() const { return m_udpPort; }
|
||||
bool getForce() const { return m_force; }
|
||||
|
||||
static MsgConfigureBFMDemod* create(Real rfBandwidth,
|
||||
Real afBandwidth,
|
||||
Real volume,
|
||||
Real squelch,
|
||||
bool audioStereo,
|
||||
bool lsbStereo,
|
||||
bool showPilot,
|
||||
bool rdsActive,
|
||||
bool copyAudioToUDP,
|
||||
const QString& udpAddress,
|
||||
quint16 udpPort,
|
||||
bool force)
|
||||
{
|
||||
return new MsgConfigureBFMDemod(rfBandwidth,
|
||||
afBandwidth,
|
||||
volume,
|
||||
squelch,
|
||||
audioStereo,
|
||||
lsbStereo,
|
||||
showPilot,
|
||||
rdsActive,
|
||||
copyAudioToUDP,
|
||||
udpAddress,
|
||||
udpPort,
|
||||
force);
|
||||
}
|
||||
|
||||
private:
|
||||
Real m_rfBandwidth;
|
||||
Real m_afBandwidth;
|
||||
Real m_volume;
|
||||
Real m_squelch;
|
||||
bool m_audioStereo;
|
||||
bool m_lsbStereo;
|
||||
bool m_showPilot;
|
||||
bool m_rdsActive;
|
||||
bool m_copyAudioToUDP;
|
||||
QString m_udpAddress;
|
||||
quint16 m_udpPort;
|
||||
bool m_force;
|
||||
|
||||
MsgConfigureBFMDemod(Real rfBandwidth,
|
||||
Real afBandwidth,
|
||||
Real volume,
|
||||
Real squelch,
|
||||
bool audioStereo,
|
||||
bool lsbStereo,
|
||||
bool showPilot,
|
||||
bool rdsActive,
|
||||
bool copyAudioToUDP,
|
||||
const QString& udpAddress,
|
||||
quint16 udpPort,
|
||||
bool force) :
|
||||
Message(),
|
||||
m_rfBandwidth(rfBandwidth),
|
||||
m_afBandwidth(afBandwidth),
|
||||
m_volume(volume),
|
||||
m_squelch(squelch),
|
||||
m_audioStereo(audioStereo),
|
||||
m_lsbStereo(lsbStereo),
|
||||
m_showPilot(showPilot),
|
||||
m_rdsActive(rdsActive),
|
||||
m_copyAudioToUDP(copyAudioToUDP),
|
||||
m_udpAddress(udpAddress),
|
||||
m_udpPort(udpPort),
|
||||
m_force(force)
|
||||
{ }
|
||||
};
|
||||
|
||||
enum RateState {
|
||||
RSInitialFill,
|
||||
RSRunning
|
||||
};
|
||||
|
||||
struct Config {
|
||||
int m_inputSampleRate;
|
||||
qint64 m_inputFrequencyOffset;
|
||||
Real m_rfBandwidth;
|
||||
Real m_afBandwidth;
|
||||
Real m_squelch;
|
||||
Real m_volume;
|
||||
quint32 m_audioSampleRate;
|
||||
bool m_audioStereo;
|
||||
bool m_lsbStereo;
|
||||
bool m_showPilot;
|
||||
bool m_rdsActive;
|
||||
bool m_copyAudioToUDP;
|
||||
QString m_udpAddress;
|
||||
quint16 m_udpPort;
|
||||
DeviceSourceAPI *m_deviceAPI;
|
||||
ThreadedBasebandSampleSink* m_threadedChannelizer;
|
||||
DownChannelizer* m_channelizer;
|
||||
|
||||
Config() :
|
||||
m_inputSampleRate(-1),
|
||||
m_inputFrequencyOffset(0),
|
||||
m_rfBandwidth(-1),
|
||||
m_afBandwidth(-1),
|
||||
m_squelch(0),
|
||||
m_volume(0),
|
||||
m_audioSampleRate(0),
|
||||
m_audioStereo(false),
|
||||
m_lsbStereo(false),
|
||||
m_showPilot(false),
|
||||
m_rdsActive(false),
|
||||
m_copyAudioToUDP(false),
|
||||
m_udpAddress("127.0.0.1"),
|
||||
m_udpPort(9999)
|
||||
{ }
|
||||
};
|
||||
|
||||
Config m_config;
|
||||
Config m_running;
|
||||
BFMDemodSettings m_settings;
|
||||
|
||||
NCO m_nco;
|
||||
Interpolator m_interpolator; //!< Interpolator between fixed demod bandwidth and audio bandwidth (rational)
|
||||
@ -254,7 +199,7 @@ private:
|
||||
|
||||
RDSDemod m_rdsDemod;
|
||||
RDSDecoder m_rdsDecoder;
|
||||
RDSParser *m_rdsParser;
|
||||
RDSParser m_rdsParser;
|
||||
|
||||
LowPassFilterRC m_deemphasisFilterX;
|
||||
LowPassFilterRC m_deemphasisFilterY;
|
||||
@ -268,7 +213,7 @@ private:
|
||||
|
||||
static const int m_udpBlockSize;
|
||||
|
||||
void apply(bool force = false);
|
||||
void applySettings(const BFMDemodSettings& settings, bool force = false);
|
||||
};
|
||||
|
||||
#endif // INCLUDE_BFMDEMOD_H
|
||||
|
@ -37,26 +37,13 @@
|
||||
#include "gui/basicchannelsettingsdialog.h"
|
||||
#include "mainwindow.h"
|
||||
|
||||
#include "bfmdemodsettings.h"
|
||||
#include "bfmdemod.h"
|
||||
#include "rdstmc.h"
|
||||
#include "ui_bfmdemodgui.h"
|
||||
|
||||
const QString BFMDemodGUI::m_channelID = "sdrangel.channel.bfm";
|
||||
|
||||
const int BFMDemodGUI::m_rfBW[] = {
|
||||
80000, 100000, 120000, 140000, 160000, 180000, 200000, 220000, 250000
|
||||
};
|
||||
|
||||
//int requiredBW(int rfBW)
|
||||
//{
|
||||
// if (rfBW <= 48000)
|
||||
// return 48000;
|
||||
// else if (rfBW < 100000)
|
||||
// return 96000;
|
||||
// else
|
||||
// return 384000;
|
||||
//}
|
||||
|
||||
BFMDemodGUI* BFMDemodGUI::create(PluginAPI* pluginAPI, DeviceSourceAPI *deviceAPI)
|
||||
{
|
||||
BFMDemodGUI* gui = new BFMDemodGUI(pluginAPI, deviceAPI);
|
||||
@ -91,119 +78,65 @@ void BFMDemodGUI::setCenterFrequency(qint64 centerFrequency)
|
||||
|
||||
void BFMDemodGUI::resetToDefaults()
|
||||
{
|
||||
blockApplySettings(true);
|
||||
m_settings.resetToDefaults();
|
||||
displaySettings();
|
||||
|
||||
ui->rfBW->setValue(4);
|
||||
ui->afBW->setValue(3);
|
||||
ui->volume->setValue(20);
|
||||
ui->squelch->setValue(-40);
|
||||
ui->deltaFrequency->setValue(0);
|
||||
ui->copyAudioToUDP->setChecked(false);
|
||||
m_channelMarker.setTitle("Broadcast FM Demod");
|
||||
m_channelMarker.setColor(QColor(80, 120, 228));
|
||||
m_channelMarker.setBandwidth(12500);
|
||||
m_channelMarker.setCenterFrequency(0);
|
||||
m_channelMarker.setUDPAddress("127.0.0.1");
|
||||
m_channelMarker.setUDPSendPort(9999);
|
||||
setTitleColor(m_channelMarker.getColor());
|
||||
blockApplySettings(true);
|
||||
ui->g00AltFrequenciesBox->setEnabled(false);
|
||||
ui->g14MappedFrequencies->setEnabled(false);
|
||||
ui->g14AltFrequencies->setEnabled(false);
|
||||
|
||||
blockApplySettings(false);
|
||||
|
||||
applySettings();
|
||||
}
|
||||
|
||||
QByteArray BFMDemodGUI::serialize() const
|
||||
{
|
||||
SimpleSerializer s(1);
|
||||
s.writeS32(1, m_channelMarker.getCenterFrequency());
|
||||
s.writeS32(2, ui->rfBW->value());
|
||||
s.writeS32(3, ui->afBW->value());
|
||||
s.writeS32(4, ui->volume->value());
|
||||
s.writeS32(5, ui->squelch->value());
|
||||
s.writeU32(7, m_channelMarker.getColor().rgb());
|
||||
s.writeBlob(8, ui->spectrumGUI->serialize());
|
||||
s.writeBool(9, ui->audioStereo->isChecked());
|
||||
s.writeBool(10, ui->lsbStereo->isChecked());
|
||||
s.writeBlob(11, m_channelMarker.serialize());
|
||||
return s.final();
|
||||
return m_settings.serialize();
|
||||
}
|
||||
|
||||
bool BFMDemodGUI::deserialize(const QByteArray& data)
|
||||
{
|
||||
SimpleDeserializer d(data);
|
||||
|
||||
if (!d.isValid())
|
||||
{
|
||||
resetToDefaults();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (d.getVersion() == 1)
|
||||
{
|
||||
QByteArray bytetmp;
|
||||
qint32 tmp;
|
||||
quint32 u32tmp;
|
||||
bool booltmp;
|
||||
QString strtmp;
|
||||
|
||||
blockApplySettings(true);
|
||||
m_channelMarker.blockSignals(true);
|
||||
|
||||
d.readBlob(11, &bytetmp);
|
||||
m_channelMarker.deserialize(bytetmp);
|
||||
|
||||
d.readS32(1, &tmp, 0);
|
||||
m_channelMarker.setCenterFrequency(tmp);
|
||||
|
||||
d.readS32(2, &tmp, 4);
|
||||
ui->rfBW->setValue(tmp);
|
||||
ui->rfBWText->setText(QString("%1 kHz").arg(m_rfBW[tmp] / 1000.0));
|
||||
m_channelMarker.setBandwidth(m_rfBW[tmp]);
|
||||
|
||||
d.readS32(3, &tmp, 3);
|
||||
ui->afBW->setValue(tmp);
|
||||
|
||||
d.readS32(4, &tmp, 20);
|
||||
ui->volume->setValue(tmp);
|
||||
|
||||
d.readS32(5, &tmp, -40);
|
||||
ui->squelch->setValue(tmp);
|
||||
|
||||
if(d.readU32(7, &u32tmp))
|
||||
{
|
||||
m_channelMarker.setColor(u32tmp);
|
||||
}
|
||||
|
||||
d.readBlob(8, &bytetmp);
|
||||
ui->spectrumGUI->deserialize(bytetmp);
|
||||
|
||||
d.readBool(9, &booltmp, false);
|
||||
ui->audioStereo->setChecked(booltmp);
|
||||
|
||||
d.readBool(10, &booltmp, false);
|
||||
ui->lsbStereo->setChecked(booltmp);
|
||||
|
||||
this->setWindowTitle(m_channelMarker.getTitle());
|
||||
displayUDPAddress();
|
||||
|
||||
blockApplySettings(false);
|
||||
m_channelMarker.blockSignals(false);
|
||||
|
||||
applySettings(true);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
resetToDefaults();
|
||||
return false;
|
||||
}
|
||||
if(m_settings.deserialize(data)) {
|
||||
updateChannelMarker();
|
||||
displaySettings();
|
||||
applySettings(true);
|
||||
return true;
|
||||
} else {
|
||||
resetToDefaults();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool BFMDemodGUI::handleMessage(const Message& message __attribute__((unused)))
|
||||
bool BFMDemodGUI::handleMessage(const Message& message)
|
||||
{
|
||||
return false;
|
||||
if (BFMDemod::MsgReportChannelSampleRateChanged::match(message))
|
||||
{
|
||||
BFMDemod::MsgReportChannelSampleRateChanged& report = (BFMDemod::MsgReportChannelSampleRateChanged&) message;
|
||||
m_rate = report.getSampleRate();
|
||||
ui->glSpectrum->setCenterFrequency(m_rate / 4);
|
||||
ui->glSpectrum->setSampleRate(m_rate / 2);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void BFMDemodGUI::handleInputMessages()
|
||||
{
|
||||
Message* message;
|
||||
|
||||
while ((message = getInputMessageQueue()->pop()) != 0)
|
||||
{
|
||||
qDebug("BFMDemodGUI::handleInputMessages: message: %s", message->getIdentifier());
|
||||
|
||||
if (handleMessage(*message))
|
||||
{
|
||||
delete message;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BFMDemodGUI::channelMarkerChanged()
|
||||
@ -216,30 +149,36 @@ void BFMDemodGUI::channelMarkerChanged()
|
||||
void BFMDemodGUI::on_deltaFrequency_changed(qint64 value)
|
||||
{
|
||||
m_channelMarker.setCenterFrequency(value);
|
||||
m_settings.m_inputFrequencyOffset = m_channelMarker.getCenterFrequency();
|
||||
applySettings();
|
||||
}
|
||||
|
||||
void BFMDemodGUI::on_rfBW_valueChanged(int value)
|
||||
{
|
||||
ui->rfBWText->setText(QString("%1 kHz").arg(m_rfBW[value] / 1000.0));
|
||||
m_channelMarker.setBandwidth(m_rfBW[value]);
|
||||
ui->rfBWText->setText(QString("%1 kHz").arg(BFMDemodSettings::getRFBW(value) / 1000.0));
|
||||
m_channelMarker.setBandwidth(BFMDemodSettings::getRFBW(value));
|
||||
m_settings.m_rfBandwidth = BFMDemodSettings::getRFBW(value);
|
||||
applySettings();
|
||||
}
|
||||
|
||||
void BFMDemodGUI::on_afBW_valueChanged(int value)
|
||||
{
|
||||
ui->afBWText->setText(QString("%1 kHz").arg(value));
|
||||
m_settings.m_afBandwidth = value * 1000.0;
|
||||
applySettings();
|
||||
}
|
||||
|
||||
void BFMDemodGUI::on_volume_valueChanged(int value)
|
||||
{
|
||||
ui->volumeText->setText(QString("%1").arg(value / 10.0, 0, 'f', 1));
|
||||
m_settings.m_volume = value / 10.0;
|
||||
applySettings();
|
||||
}
|
||||
|
||||
void BFMDemodGUI::on_squelch_valueChanged(int value)
|
||||
{
|
||||
ui->squelchText->setText(QString("%1 dB").arg(value));
|
||||
m_settings.m_squelch = value;
|
||||
applySettings();
|
||||
}
|
||||
|
||||
@ -250,26 +189,31 @@ void BFMDemodGUI::on_audioStereo_toggled(bool stereo)
|
||||
ui->audioStereo->setStyleSheet("QToolButton { background:rgb(79,79,79); }");
|
||||
}
|
||||
|
||||
m_settings.m_audioStereo = stereo;
|
||||
applySettings();
|
||||
}
|
||||
|
||||
void BFMDemodGUI::on_lsbStereo_toggled(bool lsb __attribute__((unused)))
|
||||
void BFMDemodGUI::on_lsbStereo_toggled(bool lsb)
|
||||
{
|
||||
m_settings.m_lsbStereo = lsb;
|
||||
applySettings();
|
||||
}
|
||||
|
||||
void BFMDemodGUI::on_copyAudioToUDP_toggled(bool copy __attribute__((unused)))
|
||||
void BFMDemodGUI::on_copyAudioToUDP_toggled(bool copy)
|
||||
{
|
||||
m_settings.m_copyAudioToUDP = copy;
|
||||
applySettings();
|
||||
}
|
||||
|
||||
void BFMDemodGUI::on_showPilot_clicked()
|
||||
{
|
||||
m_settings.m_showPilot = ui->showPilot->isChecked();
|
||||
applySettings();
|
||||
}
|
||||
|
||||
void BFMDemodGUI::on_rds_clicked()
|
||||
{
|
||||
m_settings.m_rdsActive = ui->rds->isChecked();
|
||||
applySettings();
|
||||
}
|
||||
|
||||
@ -277,7 +221,7 @@ void BFMDemodGUI::on_clearData_clicked(bool checked __attribute__((unused)))
|
||||
{
|
||||
if (ui->rds->isChecked())
|
||||
{
|
||||
m_rdsParser.clearAllFields();
|
||||
m_bfmDemod->getRDSParser().clearAllFields();
|
||||
|
||||
ui->g14ProgServiceNames->clear();
|
||||
ui->g14MappedFrequencies->clear();
|
||||
@ -298,9 +242,9 @@ void BFMDemodGUI::on_g14ProgServiceNames_currentIndexChanged(int _index)
|
||||
if (index < m_g14ComboIndex.size())
|
||||
{
|
||||
unsigned int piKey = m_g14ComboIndex[index];
|
||||
RDSParser::freqs_map_t::const_iterator mIt = m_rdsParser.m_g14_mapped_freqs.find(piKey);
|
||||
RDSParser::freqs_map_t::const_iterator mIt = m_bfmDemod->getRDSParser().m_g14_mapped_freqs.find(piKey);
|
||||
|
||||
if (mIt != m_rdsParser.m_g14_mapped_freqs.end())
|
||||
if (mIt != m_bfmDemod->getRDSParser().m_g14_mapped_freqs.end())
|
||||
{
|
||||
ui->g14MappedFrequencies->clear();
|
||||
RDSParser::freqs_set_t::iterator sIt = (mIt->second).begin();
|
||||
@ -316,9 +260,9 @@ void BFMDemodGUI::on_g14ProgServiceNames_currentIndexChanged(int _index)
|
||||
ui->g14MappedFrequencies->setEnabled(ui->g14MappedFrequencies->count() > 0);
|
||||
}
|
||||
|
||||
mIt = m_rdsParser.m_g14_alt_freqs.find(piKey);
|
||||
mIt = m_bfmDemod->getRDSParser().m_g14_alt_freqs.find(piKey);
|
||||
|
||||
if (mIt != m_rdsParser.m_g14_alt_freqs.end())
|
||||
if (mIt != m_bfmDemod->getRDSParser().m_g14_alt_freqs.end())
|
||||
{
|
||||
ui->g14AltFrequencies->clear();
|
||||
RDSParser::freqs_set_t::iterator sIt = (mIt->second).begin();
|
||||
@ -354,7 +298,6 @@ void BFMDemodGUI::on_g14AltFrequencies_activated(int index __attribute__((unused
|
||||
changeFrequency(f);
|
||||
}
|
||||
|
||||
|
||||
void BFMDemodGUI::onWidgetRolled(QWidget* widget __attribute__((unused)), bool rollDown __attribute__((unused)))
|
||||
{
|
||||
}
|
||||
@ -385,13 +328,12 @@ BFMDemodGUI::BFMDemodGUI(PluginAPI* pluginAPI, DeviceSourceAPI *deviceAPI, QWidg
|
||||
setAttribute(Qt::WA_DeleteOnClose, true);
|
||||
connect(this, SIGNAL(widgetRolled(QWidget*,bool)), this, SLOT(onWidgetRolled(QWidget*,bool)));
|
||||
connect(this, SIGNAL(customContextMenuRequested(const QPoint &)), this, SLOT(onMenuDialogCalled(const QPoint &)));
|
||||
connect(getInputMessageQueue(), SIGNAL(messageEnqueued()), this, SLOT(handleInputMessages()));
|
||||
|
||||
m_spectrumVis = new SpectrumVis(ui->glSpectrum);
|
||||
m_bfmDemod = new BFMDemod(m_spectrumVis, &m_rdsParser);
|
||||
m_channelizer = new DownChannelizer(m_bfmDemod);
|
||||
m_threadedChannelizer = new ThreadedBasebandSampleSink(m_channelizer, this);
|
||||
connect(m_channelizer, SIGNAL(inputSampleRateChanged()), this, SLOT(channelSampleRateChanged()));
|
||||
m_deviceAPI->addThreadedSink(m_threadedChannelizer);
|
||||
m_bfmDemod = new BFMDemod(m_deviceAPI);
|
||||
m_bfmDemod->setMessageQueueToGUI(getInputMessageQueue());
|
||||
m_bfmDemod->setSampleSink(m_spectrumVis);
|
||||
|
||||
ui->glSpectrum->setCenterFrequency(m_rate / 4);
|
||||
ui->glSpectrum->setSampleRate(m_rate / 2);
|
||||
@ -401,16 +343,18 @@ BFMDemodGUI::BFMDemodGUI(PluginAPI* pluginAPI, DeviceSourceAPI *deviceAPI, QWidg
|
||||
m_spectrumVis->configure(m_spectrumVis->getInputMessageQueue(), 64, 10, FFTWindow::BlackmanHarris);
|
||||
connect(&m_pluginAPI->getMainWindow()->getMasterTimer(), SIGNAL(timeout()), this, SLOT(tick()));
|
||||
|
||||
//m_channelMarker = new ChannelMarker(this);
|
||||
m_channelMarker.setTitle("Broadcast FM Demod");
|
||||
m_channelMarker.setColor(QColor(80, 120, 228));
|
||||
m_channelMarker.setBandwidth(12500);
|
||||
m_channelMarker.setCenterFrequency(0);
|
||||
m_channelMarker.setUDPAddress("127.0.0.1");
|
||||
m_channelMarker.setUDPSendPort(9999);
|
||||
m_channelMarker.setVisible(true);
|
||||
m_channelMarker.setColor(m_settings.m_rgbColor);
|
||||
setTitleColor(m_channelMarker.getColor());
|
||||
|
||||
m_settings.setChannelMarker(&m_channelMarker);
|
||||
m_settings.setSpectrumGUI(ui->spectrumGUI);
|
||||
|
||||
connect(&m_channelMarker, SIGNAL(changed()), this, SLOT(channelMarkerChanged()));
|
||||
|
||||
m_deviceAPI->registerChannelInstance(m_channelID, this);
|
||||
@ -425,6 +369,7 @@ BFMDemodGUI::BFMDemodGUI(PluginAPI* pluginAPI, DeviceSourceAPI *deviceAPI, QWidg
|
||||
|
||||
rdsUpdateFixedFields();
|
||||
rdsUpdate(true);
|
||||
displaySettings();
|
||||
displayUDPAddress();
|
||||
applySettings(true);
|
||||
}
|
||||
@ -432,11 +377,7 @@ BFMDemodGUI::BFMDemodGUI(PluginAPI* pluginAPI, DeviceSourceAPI *deviceAPI, QWidg
|
||||
BFMDemodGUI::~BFMDemodGUI()
|
||||
{
|
||||
m_deviceAPI->removeChannelInstance(this);
|
||||
m_deviceAPI->removeThreadedSink(m_threadedChannelizer);
|
||||
delete m_threadedChannelizer;
|
||||
delete m_channelizer;
|
||||
delete m_bfmDemod;
|
||||
//delete m_channelMarker;
|
||||
delete ui;
|
||||
}
|
||||
|
||||
@ -445,6 +386,13 @@ void BFMDemodGUI::displayUDPAddress()
|
||||
ui->copyAudioToUDP->setToolTip(QString("Copy audio output to UDP %1:%2").arg(m_channelMarker.getUDPAddress()).arg(m_channelMarker.getUDPSendPort()));
|
||||
}
|
||||
|
||||
void BFMDemodGUI::updateChannelMarker()
|
||||
{
|
||||
m_channelMarker.blockSignals(true);
|
||||
this->setWindowTitle(m_channelMarker.getTitle());
|
||||
m_channelMarker.blockSignals(false);
|
||||
}
|
||||
|
||||
void BFMDemodGUI::blockApplySettings(bool block)
|
||||
{
|
||||
m_doApplySettings = !block;
|
||||
@ -456,28 +404,54 @@ void BFMDemodGUI::applySettings(bool force)
|
||||
{
|
||||
setTitleColor(m_channelMarker.getColor());
|
||||
|
||||
m_channelizer->configure(m_channelizer->getInputMessageQueue(),
|
||||
requiredBW(m_rfBW[ui->rfBW->value()]), // TODO: this is where requested sample rate is specified
|
||||
m_channelMarker.getCenterFrequency());
|
||||
BFMDemod::MsgConfigureChannelizer *msgChan = BFMDemod::MsgConfigureChannelizer::create(
|
||||
requiredBW(BFMDemodSettings::getRFBW(ui->rfBW->value())),
|
||||
m_channelMarker.getCenterFrequency());
|
||||
m_bfmDemod->getInputMessageQueue()->push(msgChan);
|
||||
|
||||
ui->deltaFrequency->setValue(m_channelMarker.getCenterFrequency());
|
||||
|
||||
m_bfmDemod->configure(m_bfmDemod->getInputMessageQueue(),
|
||||
m_rfBW[ui->rfBW->value()],
|
||||
ui->afBW->value() * 1000.0,
|
||||
ui->volume->value() / 10.0,
|
||||
ui->squelch->value(),
|
||||
ui->audioStereo->isChecked(),
|
||||
ui->lsbStereo->isChecked(),
|
||||
ui->showPilot->isChecked(),
|
||||
ui->rds->isChecked(),
|
||||
ui->copyAudioToUDP->isChecked(),
|
||||
m_channelMarker.getUDPAddress(),
|
||||
m_channelMarker.getUDPSendPort(),
|
||||
force);
|
||||
BFMDemod::MsgConfigureBFMDemod* msgConfig = BFMDemod::MsgConfigureBFMDemod::create( m_settings, force);
|
||||
m_bfmDemod->getInputMessageQueue()->push(msgConfig);
|
||||
}
|
||||
}
|
||||
|
||||
void BFMDemodGUI::displaySettings()
|
||||
{
|
||||
blockApplySettings(true);
|
||||
|
||||
ui->deltaFrequency->setValue(m_settings.m_inputFrequencyOffset);
|
||||
|
||||
ui->rfBW->setValue(BFMDemodSettings::getRFBWIndex(m_settings.m_rfBandwidth));
|
||||
ui->rfBWText->setText(QString("%1 kHz").arg(m_settings.m_rfBandwidth / 1000.0));
|
||||
m_channelMarker.setBandwidth(m_settings.m_rfBandwidth);
|
||||
|
||||
ui->afBW->setValue(m_settings.m_afBandwidth/1000.0);
|
||||
ui->afBWText->setText(QString("%1 kHz").arg(m_settings.m_afBandwidth/1000.0));
|
||||
|
||||
ui->volume->setValue(m_settings.m_volume * 10.0);
|
||||
ui->volumeText->setText(QString("%1").arg(m_settings.m_volume, 0, 'f', 1));
|
||||
|
||||
ui->squelch->setValue(m_settings.m_squelch);
|
||||
ui->squelchText->setText(QString("%1 dB").arg(m_settings.m_squelch));
|
||||
|
||||
ui->audioStereo->setChecked(m_settings.m_audioStereo);
|
||||
ui->lsbStereo->setChecked(m_settings.m_lsbStereo);
|
||||
ui->showPilot->setChecked(m_settings.m_showPilot);
|
||||
ui->rds->setChecked(m_settings.m_rdsActive);
|
||||
ui->copyAudioToUDP->setChecked(m_settings.m_copyAudioToUDP);
|
||||
|
||||
m_channelMarker.blockSignals(true);
|
||||
m_channelMarker.setCenterFrequency(m_settings.m_inputFrequencyOffset);
|
||||
m_channelMarker.setUDPAddress(m_settings.m_udpAddress);
|
||||
m_channelMarker.setUDPSendPort(m_settings.m_udpPort);
|
||||
m_channelMarker.setColor(m_settings.m_rgbColor);
|
||||
setTitleColor(m_settings.m_rgbColor);
|
||||
m_channelMarker.blockSignals(false);
|
||||
|
||||
blockApplySettings(false);
|
||||
}
|
||||
|
||||
void BFMDemodGUI::leaveEvent(QEvent*)
|
||||
{
|
||||
blockApplySettings(true);
|
||||
@ -541,38 +515,31 @@ void BFMDemodGUI::tick()
|
||||
//qDebug() << "Pilot lock: " << m_bfmDemod->getPilotLock() << ":" << m_bfmDemod->getPilotLevel(); TODO: update a GUI item with status
|
||||
}
|
||||
|
||||
void BFMDemodGUI::channelSampleRateChanged()
|
||||
{
|
||||
m_rate = m_bfmDemod->getSampleRate();
|
||||
ui->glSpectrum->setCenterFrequency(m_rate / 4);
|
||||
ui->glSpectrum->setSampleRate(m_rate / 2);
|
||||
}
|
||||
|
||||
void BFMDemodGUI::rdsUpdateFixedFields()
|
||||
{
|
||||
ui->g00Label->setText(m_rdsParser.rds_group_acronym_tags[0].c_str());
|
||||
ui->g01Label->setText(m_rdsParser.rds_group_acronym_tags[1].c_str());
|
||||
ui->g02Label->setText(m_rdsParser.rds_group_acronym_tags[2].c_str());
|
||||
ui->g03Label->setText(m_rdsParser.rds_group_acronym_tags[3].c_str());
|
||||
ui->g04Label->setText(m_rdsParser.rds_group_acronym_tags[4].c_str());
|
||||
//ui->g05Label->setText(m_rdsParser.rds_group_acronym_tags[5].c_str());
|
||||
//ui->g06Label->setText(m_rdsParser.rds_group_acronym_tags[6].c_str());
|
||||
//ui->g07Label->setText(m_rdsParser.rds_group_acronym_tags[7].c_str());
|
||||
ui->g08Label->setText(m_rdsParser.rds_group_acronym_tags[8].c_str());
|
||||
ui->g09Label->setText(m_rdsParser.rds_group_acronym_tags[9].c_str());
|
||||
ui->g14Label->setText(m_rdsParser.rds_group_acronym_tags[14].c_str());
|
||||
ui->g00Label->setText(m_bfmDemod->getRDSParser().rds_group_acronym_tags[0].c_str());
|
||||
ui->g01Label->setText(m_bfmDemod->getRDSParser().rds_group_acronym_tags[1].c_str());
|
||||
ui->g02Label->setText(m_bfmDemod->getRDSParser().rds_group_acronym_tags[2].c_str());
|
||||
ui->g03Label->setText(m_bfmDemod->getRDSParser().rds_group_acronym_tags[3].c_str());
|
||||
ui->g04Label->setText(m_bfmDemod->getRDSParser().rds_group_acronym_tags[4].c_str());
|
||||
//ui->g05Label->setText(m_bfmDemod->getRDSParser().rds_group_acronym_tags[5].c_str());
|
||||
//ui->g06Label->setText(m_bfmDemod->getRDSParser().rds_group_acronym_tags[6].c_str());
|
||||
//ui->g07Label->setText(m_bfmDemod->getRDSParser().rds_group_acronym_tags[7].c_str());
|
||||
ui->g08Label->setText(m_bfmDemod->getRDSParser().rds_group_acronym_tags[8].c_str());
|
||||
ui->g09Label->setText(m_bfmDemod->getRDSParser().rds_group_acronym_tags[9].c_str());
|
||||
ui->g14Label->setText(m_bfmDemod->getRDSParser().rds_group_acronym_tags[14].c_str());
|
||||
|
||||
ui->g00CountLabel->setText(m_rdsParser.rds_group_acronym_tags[0].c_str());
|
||||
ui->g01CountLabel->setText(m_rdsParser.rds_group_acronym_tags[1].c_str());
|
||||
ui->g02CountLabel->setText(m_rdsParser.rds_group_acronym_tags[2].c_str());
|
||||
ui->g03CountLabel->setText(m_rdsParser.rds_group_acronym_tags[3].c_str());
|
||||
ui->g04CountLabel->setText(m_rdsParser.rds_group_acronym_tags[4].c_str());
|
||||
ui->g05CountLabel->setText(m_rdsParser.rds_group_acronym_tags[5].c_str());
|
||||
ui->g06CountLabel->setText(m_rdsParser.rds_group_acronym_tags[6].c_str());
|
||||
ui->g07CountLabel->setText(m_rdsParser.rds_group_acronym_tags[7].c_str());
|
||||
ui->g08CountLabel->setText(m_rdsParser.rds_group_acronym_tags[8].c_str());
|
||||
ui->g09CountLabel->setText(m_rdsParser.rds_group_acronym_tags[9].c_str());
|
||||
ui->g14CountLabel->setText(m_rdsParser.rds_group_acronym_tags[14].c_str());
|
||||
ui->g00CountLabel->setText(m_bfmDemod->getRDSParser().rds_group_acronym_tags[0].c_str());
|
||||
ui->g01CountLabel->setText(m_bfmDemod->getRDSParser().rds_group_acronym_tags[1].c_str());
|
||||
ui->g02CountLabel->setText(m_bfmDemod->getRDSParser().rds_group_acronym_tags[2].c_str());
|
||||
ui->g03CountLabel->setText(m_bfmDemod->getRDSParser().rds_group_acronym_tags[3].c_str());
|
||||
ui->g04CountLabel->setText(m_bfmDemod->getRDSParser().rds_group_acronym_tags[4].c_str());
|
||||
ui->g05CountLabel->setText(m_bfmDemod->getRDSParser().rds_group_acronym_tags[5].c_str());
|
||||
ui->g06CountLabel->setText(m_bfmDemod->getRDSParser().rds_group_acronym_tags[6].c_str());
|
||||
ui->g07CountLabel->setText(m_bfmDemod->getRDSParser().rds_group_acronym_tags[7].c_str());
|
||||
ui->g08CountLabel->setText(m_bfmDemod->getRDSParser().rds_group_acronym_tags[8].c_str());
|
||||
ui->g09CountLabel->setText(m_bfmDemod->getRDSParser().rds_group_acronym_tags[9].c_str());
|
||||
ui->g14CountLabel->setText(m_bfmDemod->getRDSParser().rds_group_acronym_tags[14].c_str());
|
||||
}
|
||||
|
||||
void BFMDemodGUI::rdsUpdate(bool force)
|
||||
@ -591,21 +558,21 @@ void BFMDemodGUI::rdsUpdate(bool force)
|
||||
}
|
||||
|
||||
// PI group
|
||||
if (m_rdsParser.m_pi_updated || force)
|
||||
if (m_bfmDemod->getRDSParser().m_pi_updated || force)
|
||||
{
|
||||
ui->piLabel->setStyleSheet("QLabel { background-color : green; }");
|
||||
ui->piCountText->setNum((int) m_rdsParser.m_pi_count);
|
||||
QString pistring(str(boost::format("%04X") % m_rdsParser.m_pi_program_identification).c_str());
|
||||
ui->piCountText->setNum((int) m_bfmDemod->getRDSParser().m_pi_count);
|
||||
QString pistring(str(boost::format("%04X") % m_bfmDemod->getRDSParser().m_pi_program_identification).c_str());
|
||||
ui->piText->setText(pistring);
|
||||
|
||||
if (m_rdsParser.m_pi_traffic_program) {
|
||||
if (m_bfmDemod->getRDSParser().m_pi_traffic_program) {
|
||||
ui->piTPIndicator->setStyleSheet("QLabel { background-color : green; }");
|
||||
} else {
|
||||
ui->piTPIndicator->setStyleSheet("QLabel { background:rgb(79,79,79); }");
|
||||
}
|
||||
|
||||
ui->piType->setText(QString(m_rdsParser.pty_table[m_rdsParser.m_pi_program_type].c_str()));
|
||||
ui->piCoverage->setText(QString(m_rdsParser.coverage_area_codes[m_rdsParser.m_pi_area_coverage_index].c_str()));
|
||||
ui->piType->setText(QString(m_bfmDemod->getRDSParser().pty_table[m_bfmDemod->getRDSParser().m_pi_program_type].c_str()));
|
||||
ui->piCoverage->setText(QString(m_bfmDemod->getRDSParser().coverage_area_codes[m_bfmDemod->getRDSParser().m_pi_area_coverage_index].c_str()));
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -613,29 +580,29 @@ void BFMDemodGUI::rdsUpdate(bool force)
|
||||
}
|
||||
|
||||
// G0 group
|
||||
if (m_rdsParser.m_g0_updated || force)
|
||||
if (m_bfmDemod->getRDSParser().m_g0_updated || force)
|
||||
{
|
||||
ui->g00Label->setStyleSheet("QLabel { background-color : green; }");
|
||||
ui->g00CountText->setNum((int) m_rdsParser.m_g0_count);
|
||||
ui->g00CountText->setNum((int) m_bfmDemod->getRDSParser().m_g0_count);
|
||||
|
||||
if (m_rdsParser.m_g0_psn_bitmap == 0b1111) {
|
||||
ui->g00ProgServiceName->setText(QString(m_rdsParser.m_g0_program_service_name));
|
||||
if (m_bfmDemod->getRDSParser().m_g0_psn_bitmap == 0b1111) {
|
||||
ui->g00ProgServiceName->setText(QString(m_bfmDemod->getRDSParser().m_g0_program_service_name));
|
||||
}
|
||||
|
||||
if (m_rdsParser.m_g0_traffic_announcement) {
|
||||
if (m_bfmDemod->getRDSParser().m_g0_traffic_announcement) {
|
||||
ui->g00TrafficAnnouncement->setStyleSheet("QLabel { background-color : green; }");
|
||||
} else {
|
||||
ui->g00TrafficAnnouncement->setStyleSheet("QLabel { background:rgb(79,79,79); }");
|
||||
}
|
||||
|
||||
ui->g00MusicSpeech->setText(QString((m_rdsParser.m_g0_music_speech ? "Music" : "Speech")));
|
||||
ui->g00MonoStereo->setText(QString((m_rdsParser.m_g0_mono_stereo ? "Mono" : "Stereo")));
|
||||
ui->g00MusicSpeech->setText(QString((m_bfmDemod->getRDSParser().m_g0_music_speech ? "Music" : "Speech")));
|
||||
ui->g00MonoStereo->setText(QString((m_bfmDemod->getRDSParser().m_g0_mono_stereo ? "Mono" : "Stereo")));
|
||||
|
||||
if (m_rdsParser.m_g0_af_updated)
|
||||
if (m_bfmDemod->getRDSParser().m_g0_af_updated)
|
||||
{
|
||||
ui->g00AltFrequenciesBox->clear();
|
||||
|
||||
for (std::set<double>::iterator it = m_rdsParser.m_g0_alt_freq.begin(); it != m_rdsParser.m_g0_alt_freq.end(); ++it)
|
||||
for (std::set<double>::iterator it = m_bfmDemod->getRDSParser().m_g0_alt_freq.begin(); it != m_bfmDemod->getRDSParser().m_g0_alt_freq.end(); ++it)
|
||||
{
|
||||
if (*it > 76.0)
|
||||
{
|
||||
@ -654,20 +621,20 @@ void BFMDemodGUI::rdsUpdate(bool force)
|
||||
}
|
||||
|
||||
// G1 group
|
||||
if (m_rdsParser.m_g1_updated || force)
|
||||
if (m_bfmDemod->getRDSParser().m_g1_updated || force)
|
||||
{
|
||||
ui->g01Label->setStyleSheet("QLabel { background-color : green; }");
|
||||
ui->g01CountText->setNum((int) m_rdsParser.m_g1_count);
|
||||
ui->g01CountText->setNum((int) m_bfmDemod->getRDSParser().m_g1_count);
|
||||
|
||||
if ((m_rdsParser.m_g1_country_page_index >= 0) && (m_rdsParser.m_g1_country_index >= 0)) {
|
||||
ui->g01CountryCode->setText(QString((m_rdsParser.pi_country_codes[m_rdsParser.m_g1_country_page_index][m_rdsParser.m_g1_country_index]).c_str()));
|
||||
if ((m_bfmDemod->getRDSParser().m_g1_country_page_index >= 0) && (m_bfmDemod->getRDSParser().m_g1_country_index >= 0)) {
|
||||
ui->g01CountryCode->setText(QString((m_bfmDemod->getRDSParser().pi_country_codes[m_bfmDemod->getRDSParser().m_g1_country_page_index][m_bfmDemod->getRDSParser().m_g1_country_index]).c_str()));
|
||||
}
|
||||
|
||||
if (m_rdsParser.m_g1_language_index >= 0) {
|
||||
ui->g01Language->setText(QString(m_rdsParser.language_codes[m_rdsParser.m_g1_language_index].c_str()));
|
||||
if (m_bfmDemod->getRDSParser().m_g1_language_index >= 0) {
|
||||
ui->g01Language->setText(QString(m_bfmDemod->getRDSParser().language_codes[m_bfmDemod->getRDSParser().m_g1_language_index].c_str()));
|
||||
}
|
||||
|
||||
ui->g01DHM->setText(QString(str(boost::format("%id:%i:%i") % m_rdsParser.m_g1_pin_day % m_rdsParser.m_g1_pin_hour % m_rdsParser.m_g1_pin_minute).c_str()));
|
||||
ui->g01DHM->setText(QString(str(boost::format("%id:%i:%i") % m_bfmDemod->getRDSParser().m_g1_pin_day % m_bfmDemod->getRDSParser().m_g1_pin_hour % m_bfmDemod->getRDSParser().m_g1_pin_minute).c_str()));
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -675,11 +642,11 @@ void BFMDemodGUI::rdsUpdate(bool force)
|
||||
}
|
||||
|
||||
// G2 group
|
||||
if (m_rdsParser.m_g2_updated || force)
|
||||
if (m_bfmDemod->getRDSParser().m_g2_updated || force)
|
||||
{
|
||||
ui->g02Label->setStyleSheet("QLabel { background-color : green; }");
|
||||
ui->g02CountText->setNum((int) m_rdsParser.m_g2_count);
|
||||
ui->go2Text->setText(QString(m_rdsParser.m_g2_radiotext));
|
||||
ui->g02CountText->setNum((int) m_bfmDemod->getRDSParser().m_g2_count);
|
||||
ui->go2Text->setText(QString(m_bfmDemod->getRDSParser().m_g2_radiotext));
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -687,11 +654,11 @@ void BFMDemodGUI::rdsUpdate(bool force)
|
||||
}
|
||||
|
||||
// G3 group
|
||||
if (m_rdsParser.m_g3_updated || force)
|
||||
if (m_bfmDemod->getRDSParser().m_g3_updated || force)
|
||||
{
|
||||
ui->g03Label->setStyleSheet("QLabel { background-color : green; }");
|
||||
ui->g03CountText->setNum((int) m_rdsParser.m_g3_count);
|
||||
std::string g3str = str(boost::format("%02X%c %04X %04X") % m_rdsParser.m_g3_appGroup % (m_rdsParser.m_g3_groupB ? 'B' : 'A') % m_rdsParser.m_g3_message % m_rdsParser.m_g3_aid);
|
||||
ui->g03CountText->setNum((int) m_bfmDemod->getRDSParser().m_g3_count);
|
||||
std::string g3str = str(boost::format("%02X%c %04X %04X") % m_bfmDemod->getRDSParser().m_g3_appGroup % (m_bfmDemod->getRDSParser().m_g3_groupB ? 'B' : 'A') % m_bfmDemod->getRDSParser().m_g3_message % m_bfmDemod->getRDSParser().m_g3_aid);
|
||||
ui->g03Data->setText(QString(g3str.c_str()));
|
||||
}
|
||||
else
|
||||
@ -700,12 +667,12 @@ void BFMDemodGUI::rdsUpdate(bool force)
|
||||
}
|
||||
|
||||
// G4 group
|
||||
if (m_rdsParser.m_g4_updated || force)
|
||||
if (m_bfmDemod->getRDSParser().m_g4_updated || force)
|
||||
{
|
||||
ui->g04Label->setStyleSheet("QLabel { background-color : green; }");
|
||||
ui->g04CountText->setNum((int) m_rdsParser.m_g4_count);
|
||||
ui->g04CountText->setNum((int) m_bfmDemod->getRDSParser().m_g4_count);
|
||||
std::string time = str(boost::format("%02i.%02i.%4i, %02i:%02i (%+.1fh)")\
|
||||
% m_rdsParser.m_g4_day % m_rdsParser.m_g4_month % (1900 + m_rdsParser.m_g4_year) % m_rdsParser.m_g4_hours % m_rdsParser.m_g4_minutes % m_rdsParser.m_g4_local_time_offset);
|
||||
% m_bfmDemod->getRDSParser().m_g4_day % m_bfmDemod->getRDSParser().m_g4_month % (1900 + m_bfmDemod->getRDSParser().m_g4_year) % m_bfmDemod->getRDSParser().m_g4_hours % m_bfmDemod->getRDSParser().m_g4_minutes % m_bfmDemod->getRDSParser().m_g4_local_time_offset);
|
||||
ui->g04Time->setText(QString(time.c_str()));
|
||||
}
|
||||
else
|
||||
@ -714,42 +681,42 @@ void BFMDemodGUI::rdsUpdate(bool force)
|
||||
}
|
||||
|
||||
// G5 group
|
||||
if (m_rdsParser.m_g5_updated || force)
|
||||
if (m_bfmDemod->getRDSParser().m_g5_updated || force)
|
||||
{
|
||||
ui->g05CountText->setNum((int) m_rdsParser.m_g5_count);
|
||||
ui->g05CountText->setNum((int) m_bfmDemod->getRDSParser().m_g5_count);
|
||||
}
|
||||
|
||||
// G6 group
|
||||
if (m_rdsParser.m_g6_updated || force)
|
||||
if (m_bfmDemod->getRDSParser().m_g6_updated || force)
|
||||
{
|
||||
ui->g06CountText->setNum((int) m_rdsParser.m_g6_count);
|
||||
ui->g06CountText->setNum((int) m_bfmDemod->getRDSParser().m_g6_count);
|
||||
}
|
||||
|
||||
// G7 group
|
||||
if (m_rdsParser.m_g7_updated || force)
|
||||
if (m_bfmDemod->getRDSParser().m_g7_updated || force)
|
||||
{
|
||||
ui->g07CountText->setNum((int) m_rdsParser.m_g7_count);
|
||||
ui->g07CountText->setNum((int) m_bfmDemod->getRDSParser().m_g7_count);
|
||||
}
|
||||
|
||||
// G8 group
|
||||
if (m_rdsParser.m_g8_updated || force)
|
||||
if (m_bfmDemod->getRDSParser().m_g8_updated || force)
|
||||
{
|
||||
ui->g08Label->setStyleSheet("QLabel { background-color : green; }");
|
||||
ui->g08CountText->setNum((int) m_rdsParser.m_g8_count);
|
||||
ui->g08CountText->setNum((int) m_bfmDemod->getRDSParser().m_g8_count);
|
||||
|
||||
std::ostringstream os;
|
||||
os << (m_rdsParser.m_g8_sign ? "-" : "+") << m_rdsParser.m_g8_extent + 1;
|
||||
os << (m_bfmDemod->getRDSParser().m_g8_sign ? "-" : "+") << m_bfmDemod->getRDSParser().m_g8_extent + 1;
|
||||
ui->g08Extent->setText(QString(os.str().c_str()));
|
||||
int event_line = RDSTMC::get_tmc_event_code_index(m_rdsParser.m_g8_event, 1);
|
||||
int event_line = RDSTMC::get_tmc_event_code_index(m_bfmDemod->getRDSParser().m_g8_event, 1);
|
||||
ui->g08TMCEvent->setText(QString(RDSTMC::get_tmc_events(event_line, 1).c_str()));
|
||||
QString pistring(str(boost::format("%04X") % m_rdsParser.m_g8_location).c_str());
|
||||
QString pistring(str(boost::format("%04X") % m_bfmDemod->getRDSParser().m_g8_location).c_str());
|
||||
ui->g08Location->setText(pistring);
|
||||
|
||||
if (m_rdsParser.m_g8_label_index >= 0) {
|
||||
ui->g08Description->setText(QString(m_rdsParser.label_descriptions[m_rdsParser.m_g8_label_index].c_str()));
|
||||
if (m_bfmDemod->getRDSParser().m_g8_label_index >= 0) {
|
||||
ui->g08Description->setText(QString(m_bfmDemod->getRDSParser().label_descriptions[m_bfmDemod->getRDSParser().m_g8_label_index].c_str()));
|
||||
}
|
||||
|
||||
ui->g08Content->setNum(m_rdsParser.m_g8_content);
|
||||
ui->g08Content->setNum(m_bfmDemod->getRDSParser().m_g8_content);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -757,11 +724,11 @@ void BFMDemodGUI::rdsUpdate(bool force)
|
||||
}
|
||||
|
||||
// G9 group
|
||||
if (m_rdsParser.m_g9_updated || force)
|
||||
if (m_bfmDemod->getRDSParser().m_g9_updated || force)
|
||||
{
|
||||
ui->g09Label->setStyleSheet("QLabel { background-color : green; }");
|
||||
ui->g09CountText->setNum((int) m_rdsParser.m_g9_count);
|
||||
std::string g9str = str(boost::format("%02X %04X %04X %02X %04X") % m_rdsParser.m_g9_varA % m_rdsParser.m_g9_cA % m_rdsParser.m_g9_dA % m_rdsParser.m_g9_varB % m_rdsParser.m_g9_dB);
|
||||
ui->g09CountText->setNum((int) m_bfmDemod->getRDSParser().m_g9_count);
|
||||
std::string g9str = str(boost::format("%02X %04X %04X %02X %04X") % m_bfmDemod->getRDSParser().m_g9_varA % m_bfmDemod->getRDSParser().m_g9_cA % m_bfmDemod->getRDSParser().m_g9_dA % m_bfmDemod->getRDSParser().m_g9_varB % m_bfmDemod->getRDSParser().m_g9_dB);
|
||||
ui->g09Data->setText(QString(g9str.c_str()));
|
||||
}
|
||||
else
|
||||
@ -770,18 +737,18 @@ void BFMDemodGUI::rdsUpdate(bool force)
|
||||
}
|
||||
|
||||
// G14 group
|
||||
if (m_rdsParser.m_g14_updated || force)
|
||||
if (m_bfmDemod->getRDSParser().m_g14_updated || force)
|
||||
{
|
||||
ui->g14CountText->setNum((int) m_rdsParser.m_g14_count);
|
||||
ui->g14CountText->setNum((int) m_bfmDemod->getRDSParser().m_g14_count);
|
||||
|
||||
if (m_rdsParser.m_g14_data_available)
|
||||
if (m_bfmDemod->getRDSParser().m_g14_data_available)
|
||||
{
|
||||
ui->g14Label->setStyleSheet("QLabel { background-color : green; }");
|
||||
m_g14ComboIndex.clear();
|
||||
ui->g14ProgServiceNames->clear();
|
||||
|
||||
RDSParser::psns_map_t::iterator it = m_rdsParser.m_g14_program_service_names.begin();
|
||||
const RDSParser::psns_map_t::iterator itEnd = m_rdsParser.m_g14_program_service_names.end();
|
||||
RDSParser::psns_map_t::iterator it = m_bfmDemod->getRDSParser().m_g14_program_service_names.begin();
|
||||
const RDSParser::psns_map_t::iterator itEnd = m_bfmDemod->getRDSParser().m_g14_program_service_names.end();
|
||||
int i = 0;
|
||||
|
||||
for (; it != itEnd; ++it, i++)
|
||||
@ -797,12 +764,11 @@ void BFMDemodGUI::rdsUpdate(bool force)
|
||||
}
|
||||
}
|
||||
|
||||
m_rdsParser.clearUpdateFlags();
|
||||
m_bfmDemod->getRDSParser().clearUpdateFlags();
|
||||
}
|
||||
|
||||
void BFMDemodGUI::changeFrequency(qint64 f)
|
||||
{
|
||||
qint64 df = m_channelMarker.getCenterFrequency();
|
||||
qDebug() << "BFMDemodGUI::changeFrequency: " << f - df;
|
||||
// TODO: in the future it should be able to set the center frequency of the sample source this channel plugin is linked to
|
||||
}
|
||||
|
@ -18,16 +18,16 @@
|
||||
#ifndef INCLUDE_BFMDEMODGUI_H
|
||||
#define INCLUDE_BFMDEMODGUI_H
|
||||
|
||||
#include <plugin/plugininstancegui.h>
|
||||
#include "gui/rollupwidget.h"
|
||||
#include "dsp/channelmarker.h"
|
||||
#include "dsp/movingaverage.h"
|
||||
#include "plugin/plugininstanceui.h"
|
||||
#include "util/messagequeue.h"
|
||||
|
||||
#include "rdsparser.h"
|
||||
#include "bfmdemodsettings.h"
|
||||
|
||||
class PluginAPI;
|
||||
class DeviceSourceAPI;
|
||||
class RDSParser;
|
||||
|
||||
class ThreadedBasebandSampleSink;
|
||||
class DownChannelizer;
|
||||
@ -38,7 +38,7 @@ namespace Ui {
|
||||
class BFMDemodGUI;
|
||||
}
|
||||
|
||||
class BFMDemodGUI : public RollupWidget, public PluginInstanceUI {
|
||||
class BFMDemodGUI : public RollupWidget, public PluginInstanceGUI {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
@ -60,7 +60,6 @@ public:
|
||||
|
||||
private slots:
|
||||
void channelMarkerChanged();
|
||||
void channelSampleRateChanged();
|
||||
void on_deltaFrequency_changed(qint64 value);
|
||||
void on_rfBW_valueChanged(int value);
|
||||
void on_afBW_valueChanged(int value);
|
||||
@ -78,6 +77,7 @@ private slots:
|
||||
void on_g14AltFrequencies_activated(int index);
|
||||
void onWidgetRolled(QWidget* widget, bool rollDown);
|
||||
void onMenuDialogCalled(const QPoint& p);
|
||||
void handleInputMessages();
|
||||
void tick();
|
||||
|
||||
private:
|
||||
@ -85,13 +85,11 @@ private:
|
||||
PluginAPI* m_pluginAPI;
|
||||
DeviceSourceAPI* m_deviceAPI;
|
||||
ChannelMarker m_channelMarker;
|
||||
BFMDemodSettings m_settings;
|
||||
bool m_doApplySettings;
|
||||
int m_rdsTimerCount;
|
||||
|
||||
ThreadedBasebandSampleSink* m_threadedChannelizer;
|
||||
DownChannelizer* m_channelizer;
|
||||
SpectrumVis* m_spectrumVis;
|
||||
RDSParser m_rdsParser;
|
||||
|
||||
BFMDemod* m_bfmDemod;
|
||||
MovingAverage<double> m_channelPowerDbAvg;
|
||||
@ -99,14 +97,14 @@ private:
|
||||
std::vector<unsigned int> m_g14ComboIndex;
|
||||
MessageQueue m_inputMessageQueue;
|
||||
|
||||
static const int m_rfBW[];
|
||||
|
||||
explicit BFMDemodGUI(PluginAPI* pluginAPI, DeviceSourceAPI *deviceAPI, QWidget* parent = NULL);
|
||||
virtual ~BFMDemodGUI();
|
||||
|
||||
void blockApplySettings(bool block);
|
||||
void applySettings(bool force = false);
|
||||
void displaySettings();
|
||||
void displayUDPAddress();
|
||||
void updateChannelMarker();
|
||||
void rdsUpdate(bool force);
|
||||
void rdsUpdateFixedFields();
|
||||
|
||||
|
154
plugins/channelrx/demodbfm/bfmdemodsettings.cpp
Normal file
@ -0,0 +1,154 @@
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// 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 "bfmdemodsettings.h"
|
||||
|
||||
const int BFMDemodSettings::m_nbRFBW = 9;
|
||||
const int BFMDemodSettings::m_rfBW[] = {
|
||||
80000, 100000, 120000, 140000, 160000, 180000, 200000, 220000, 250000
|
||||
};
|
||||
|
||||
BFMDemodSettings::BFMDemodSettings() :
|
||||
m_channelMarker(0),
|
||||
m_spectrumGUI(0)
|
||||
{
|
||||
resetToDefaults();
|
||||
}
|
||||
|
||||
void BFMDemodSettings::resetToDefaults()
|
||||
{
|
||||
m_inputSampleRate = 384000;
|
||||
m_inputFrequencyOffset = 0;
|
||||
m_rfBandwidth = getRFBW(5);
|
||||
m_afBandwidth = 15000;
|
||||
m_volume = 2.0;
|
||||
m_squelch = -60.0;
|
||||
m_audioSampleRate = DSPEngine::instance()->getAudioSampleRate();
|
||||
m_audioStereo = false;
|
||||
m_lsbStereo = false;
|
||||
m_showPilot = false;
|
||||
m_rdsActive = false;
|
||||
m_copyAudioToUDP = false;
|
||||
m_udpAddress = "127.0.0.1";
|
||||
m_udpPort = 9999;
|
||||
m_rgbColor = QColor(80, 120, 228).rgb();
|
||||
}
|
||||
|
||||
QByteArray BFMDemodSettings::serialize() const
|
||||
{
|
||||
SimpleSerializer s(1);
|
||||
s.writeS32(1, m_inputFrequencyOffset);
|
||||
s.writeS32(2, getRFBWIndex(m_rfBandwidth));
|
||||
s.writeS32(3, m_afBandwidth/1000.0);
|
||||
s.writeS32(4, m_volume*10.0);
|
||||
s.writeS32(5, m_squelch);
|
||||
s.writeU32(7, m_rgbColor);
|
||||
|
||||
if (m_spectrumGUI) {
|
||||
s.writeBlob(8, m_spectrumGUI->serialize());
|
||||
}
|
||||
|
||||
s.writeBool(9, m_audioStereo);
|
||||
s.writeBool(10, m_lsbStereo);
|
||||
|
||||
if (m_channelMarker) {
|
||||
s.writeBlob(11, m_channelMarker->serialize());
|
||||
}
|
||||
|
||||
return s.final();
|
||||
}
|
||||
|
||||
bool BFMDemodSettings::deserialize(const QByteArray& data)
|
||||
{
|
||||
SimpleDeserializer d(data);
|
||||
|
||||
if(!d.isValid())
|
||||
{
|
||||
resetToDefaults();
|
||||
return false;
|
||||
}
|
||||
|
||||
if(d.getVersion() == 1)
|
||||
{
|
||||
QByteArray bytetmp;
|
||||
qint32 tmp;
|
||||
QString strtmp;
|
||||
|
||||
d.readS32(1, &tmp, 0);
|
||||
m_inputFrequencyOffset = tmp;
|
||||
d.readS32(2, &tmp, 4);
|
||||
m_rfBandwidth = getRFBW(tmp);
|
||||
d.readS32(3, &tmp, 3);
|
||||
m_afBandwidth = tmp * 1000.0;
|
||||
d.readS32(4, &tmp, 20);
|
||||
m_volume = tmp * 0.1;
|
||||
d.readS32(5, &tmp, -60);
|
||||
m_squelch = tmp;
|
||||
d.readU32(7, &m_rgbColor);
|
||||
|
||||
d.readBlob(8, &bytetmp);
|
||||
|
||||
if (m_spectrumGUI) {
|
||||
m_spectrumGUI->deserialize(bytetmp);
|
||||
}
|
||||
|
||||
d.readBool(9, &m_audioStereo, false);
|
||||
d.readBool(10, &m_lsbStereo, false);
|
||||
|
||||
d.readBlob(11, &bytetmp);
|
||||
|
||||
if (m_channelMarker) {
|
||||
m_channelMarker->deserialize(bytetmp);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
resetToDefaults();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
int BFMDemodSettings::getRFBW(int index)
|
||||
{
|
||||
if (index < 0) {
|
||||
return m_rfBW[0];
|
||||
} else if (index < m_nbRFBW) {
|
||||
return m_rfBW[index];
|
||||
} else {
|
||||
return m_rfBW[m_nbRFBW-1];
|
||||
}
|
||||
}
|
||||
|
||||
int BFMDemodSettings::getRFBWIndex(int rfbw)
|
||||
{
|
||||
for (int i = 0; i < m_nbRFBW; i++)
|
||||
{
|
||||
if (rfbw <= m_rfBW[i])
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return m_nbRFBW-1;
|
||||
}
|
58
plugins/channelrx/demodbfm/bfmdemodsettings.h
Normal file
@ -0,0 +1,58 @@
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// 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_DEMODBFM_BFMDEMODSETTINGS_H_
|
||||
#define PLUGINS_CHANNELRX_DEMODBFM_BFMDEMODSETTINGS_H_
|
||||
|
||||
class Serializable;
|
||||
|
||||
struct BFMDemodSettings
|
||||
{
|
||||
int m_inputSampleRate;
|
||||
qint64 m_inputFrequencyOffset;
|
||||
Real m_rfBandwidth;
|
||||
Real m_afBandwidth;
|
||||
Real m_volume;
|
||||
Real m_squelch;
|
||||
quint32 m_audioSampleRate;
|
||||
bool m_audioStereo;
|
||||
bool m_lsbStereo;
|
||||
bool m_showPilot;
|
||||
bool m_rdsActive;
|
||||
bool m_copyAudioToUDP;
|
||||
QString m_udpAddress;
|
||||
quint16 m_udpPort;
|
||||
quint32 m_rgbColor;
|
||||
|
||||
Serializable *m_channelMarker;
|
||||
Serializable *m_spectrumGUI;
|
||||
|
||||
static const int m_nbRFBW;
|
||||
static const int m_rfBW[];
|
||||
|
||||
BFMDemodSettings();
|
||||
void resetToDefaults();
|
||||
void setChannelMarker(Serializable *channelMarker) { m_channelMarker = channelMarker; }
|
||||
void setSpectrumGUI(Serializable *spectrumGUI) { m_spectrumGUI = spectrumGUI; }
|
||||
QByteArray serialize() const;
|
||||
bool deserialize(const QByteArray& data);
|
||||
|
||||
static int getRFBW(int index);
|
||||
static int getRFBWIndex(int rfbw);
|
||||
};
|
||||
|
||||
|
||||
#endif /* PLUGINS_CHANNELRX_DEMODBFM_BFMDEMODSETTINGS_H_ */
|
@ -24,7 +24,7 @@
|
||||
|
||||
const PluginDescriptor BFMPlugin::m_pluginDescriptor = {
|
||||
QString("Broadcast FM Demodulator"),
|
||||
QString("3.6.1"),
|
||||
QString("3.7.3"),
|
||||
QString("(c) Edouard Griffiths, F4EXB"),
|
||||
QString("https://github.com/f4exb/sdrangel"),
|
||||
true,
|
||||
@ -50,7 +50,7 @@ void BFMPlugin::initPlugin(PluginAPI* pluginAPI)
|
||||
m_pluginAPI->registerRxChannel(BFMDemodGUI::m_channelID, this);
|
||||
}
|
||||
|
||||
PluginInstanceUI* BFMPlugin::createRxChannel(const QString& channelName, DeviceSourceAPI *deviceAPI)
|
||||
PluginInstanceGUI* BFMPlugin::createRxChannel(const QString& channelName, DeviceSourceAPI *deviceAPI)
|
||||
{
|
||||
if(channelName == BFMDemodGUI::m_channelID)
|
||||
{
|
||||
|
@ -34,7 +34,7 @@ public:
|
||||
const PluginDescriptor& getPluginDescriptor() const;
|
||||
void initPlugin(PluginAPI* pluginAPI);
|
||||
|
||||
PluginInstanceUI* createRxChannel(const QString& channelName, DeviceSourceAPI *deviceAPI);
|
||||
PluginInstanceGUI* createRxChannel(const QString& channelName, DeviceSourceAPI *deviceAPI);
|
||||
|
||||
private:
|
||||
static const PluginDescriptor m_pluginDescriptor;
|
||||
|
@ -30,6 +30,7 @@ CONFIG(Debug):build_subdir = debug
|
||||
|
||||
SOURCES += bfmdemod.cpp\
|
||||
bfmdemodgui.cpp\
|
||||
bfmdemodsettings.cpp\
|
||||
bfmplugin.cpp\
|
||||
rdsdemod.cpp\
|
||||
rdsdecoder.cpp\
|
||||
@ -38,6 +39,7 @@ SOURCES += bfmdemod.cpp\
|
||||
|
||||
HEADERS += bfmdemod.h\
|
||||
bfmdemodgui.h\
|
||||
bfmdemodsettings.h\
|
||||
bfmplugin.h\
|
||||
rdsdemod.h\
|
||||
rdsdecoder.h\
|
||||
|
@ -22,6 +22,10 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#undef M_PI
|
||||
#define M_PI 3.14159265358979323846
|
||||
#undef M_PI_2
|
||||
#define M_PI_2 1.57079632679489661923
|
||||
|
||||
const Real RDSDemod::m_pllBeta = 50;
|
||||
const Real RDSDemod::m_fsc = 1187.5;
|
||||
@ -77,7 +81,7 @@ bool RDSDemod::process(Real demod, bool& bit)
|
||||
m_parms.clock_offset = 0;
|
||||
}*/
|
||||
|
||||
m_parms.subcarr_phi += (2 * M_PI * m_fsc) / (Real) m_srate;
|
||||
m_parms.subcarr_phi += (2 * M_PI * m_fsc) / (Real) m_srate;
|
||||
m_parms.clock_phi = m_parms.subcarr_phi + m_parms.clock_offset;
|
||||
|
||||
// Clock phase recovery
|
||||
|
@ -4,6 +4,8 @@ set(dsddemod_SOURCES
|
||||
dsddemod.cpp
|
||||
dsddemodgui.cpp
|
||||
dsddemodplugin.cpp
|
||||
dsddemodbaudrates.cpp
|
||||
dsddemodsettings.cpp
|
||||
dsddecoder.cpp
|
||||
)
|
||||
|
||||
@ -11,6 +13,8 @@ set(dsddemod_HEADERS
|
||||
dsddemod.h
|
||||
dsddemodgui.h
|
||||
dsddemodplugin.h
|
||||
dsddemodbaudrates.h
|
||||
dsddemodsettings.h
|
||||
dsddecoder.h
|
||||
)
|
||||
|
||||
|
@ -40,12 +40,16 @@ CONFIG(Debug):build_subdir = debug
|
||||
SOURCES = dsddecoder.cpp\
|
||||
dsddemod.cpp\
|
||||
dsddemodgui.cpp\
|
||||
dsddemodplugin.cpp
|
||||
dsddemodplugin.cpp\
|
||||
dsddemodbaudrates.cpp\
|
||||
dsddemodsettings.cpp
|
||||
|
||||
HEADERS = dsddecoder.h\
|
||||
dsddemod.h\
|
||||
dsddemodgui.h\
|
||||
dsddemodplugin.h
|
||||
dsddemodplugin.h\
|
||||
dsddemodbaudrates.h\
|
||||
dsddemodsettings.h
|
||||
|
||||
FORMS = dsddemodgui.ui
|
||||
|
||||
|
@ -15,51 +15,48 @@
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "../../channelrx/demoddsd/dsddemod.h"
|
||||
|
||||
#include <QTime>
|
||||
#include <QDebug>
|
||||
#include <stdio.h>
|
||||
#include <complex.h>
|
||||
|
||||
#include <dsp/downchannelizer.h>
|
||||
#include "audio/audiooutput.h"
|
||||
#include "dsp/pidcontroller.h"
|
||||
#include "dsp/dspengine.h"
|
||||
#include "dsddemodgui.h"
|
||||
#include "dsp/threadedbasebandsamplesink.h"
|
||||
#include <dsp/downchannelizer.h>
|
||||
#include <device/devicesourceapi.h>
|
||||
|
||||
#include "dsddemod.h"
|
||||
|
||||
MESSAGE_CLASS_DEFINITION(DSDDemod::MsgConfigureChannelizer, Message)
|
||||
MESSAGE_CLASS_DEFINITION(DSDDemod::MsgConfigureDSDDemod, Message)
|
||||
MESSAGE_CLASS_DEFINITION(DSDDemod::MsgConfigureMyPosition, Message)
|
||||
|
||||
const int DSDDemod::m_udpBlockSize = 512;
|
||||
|
||||
DSDDemod::DSDDemod(BasebandSampleSink* sampleSink) :
|
||||
m_sampleCount(0),
|
||||
m_squelchCount(0),
|
||||
m_squelchOpen(false),
|
||||
DSDDemod::DSDDemod(DeviceSourceAPI *deviceAPI) :
|
||||
m_deviceAPI(deviceAPI),
|
||||
m_interpolatorDistance(0.0f),
|
||||
m_interpolatorDistanceRemain(0.0f),
|
||||
m_sampleCount(0),
|
||||
m_squelchCount(0),
|
||||
m_squelchGate(0),
|
||||
m_squelchLevel(1e-4),
|
||||
m_squelchOpen(false),
|
||||
m_movingAverage(40, 0),
|
||||
m_fmExcursion(24),
|
||||
m_audioFifo1(48000),
|
||||
m_audioFifo1(48000),
|
||||
m_audioFifo2(48000),
|
||||
m_scope(sampleSink),
|
||||
m_scope(0),
|
||||
m_scopeEnabled(true),
|
||||
m_dsdDecoder(),
|
||||
m_settingsMutex(QMutex::Recursive)
|
||||
{
|
||||
setObjectName("DSDDemod");
|
||||
|
||||
m_config.m_inputSampleRate = 96000;
|
||||
m_config.m_inputFrequencyOffset = 0;
|
||||
m_config.m_rfBandwidth = 100;
|
||||
m_config.m_demodGain = 100;
|
||||
m_config.m_fmDeviation = 100;
|
||||
m_config.m_squelchGate = 5; // 10s of ms at 48000 Hz sample rate. Corresponds to 2400 for AGC attack
|
||||
m_config.m_squelch = -30.0;
|
||||
m_config.m_volume = 1.0;
|
||||
m_config.m_baudRate = 4800;
|
||||
m_config.m_audioMute = false;
|
||||
m_config.m_audioSampleRate = DSPEngine::instance()->getAudioSampleRate();
|
||||
m_config.m_enableCosineFiltering = false;
|
||||
|
||||
m_audioBuffer.resize(1<<14);
|
||||
m_audioBufferFill = 0;
|
||||
|
||||
@ -75,11 +72,15 @@ DSDDemod::DSDDemod(BasebandSampleSink* sampleSink) :
|
||||
DSPEngine::instance()->addAudioSink(&m_audioFifo1);
|
||||
DSPEngine::instance()->addAudioSink(&m_audioFifo2);
|
||||
|
||||
m_udpBufferAudio = new UDPSink<AudioSample>(this, m_udpBlockSize, m_config.m_udpPort);
|
||||
m_udpBufferAudio = new UDPSink<AudioSample>(this, m_udpBlockSize, m_settings.m_udpPort);
|
||||
m_audioFifo1.setUDPSink(m_udpBufferAudio);
|
||||
m_audioFifo2.setUDPSink(m_udpBufferAudio);
|
||||
|
||||
apply(true);
|
||||
m_channelizer = new DownChannelizer(this);
|
||||
m_threadedChannelizer = new ThreadedBasebandSampleSink(m_channelizer, this);
|
||||
m_deviceAPI->addThreadedSink(m_threadedChannelizer);
|
||||
|
||||
applySettings(m_settings, true);
|
||||
}
|
||||
|
||||
DSDDemod::~DSDDemod()
|
||||
@ -88,47 +89,10 @@ DSDDemod::~DSDDemod()
|
||||
DSPEngine::instance()->removeAudioSink(&m_audioFifo1);
|
||||
DSPEngine::instance()->removeAudioSink(&m_audioFifo2);
|
||||
delete m_udpBufferAudio;
|
||||
}
|
||||
|
||||
void DSDDemod::configure(MessageQueue* messageQueue,
|
||||
int rfBandwidth,
|
||||
int demodGain,
|
||||
int fmDeviation,
|
||||
int volume,
|
||||
int baudRate,
|
||||
int squelchGate,
|
||||
Real squelch,
|
||||
bool audioMute,
|
||||
bool enableCosineFiltering,
|
||||
bool syncOrConstellation,
|
||||
bool slot1On,
|
||||
bool slot2On,
|
||||
bool tdmaStereo,
|
||||
bool pllLock,
|
||||
bool udpCopyAudio,
|
||||
const QString& udpAddress,
|
||||
quint16 udpPort,
|
||||
bool force)
|
||||
{
|
||||
Message* cmd = MsgConfigureDSDDemod::create(rfBandwidth,
|
||||
demodGain,
|
||||
fmDeviation,
|
||||
volume,
|
||||
baudRate,
|
||||
squelchGate,
|
||||
squelch,
|
||||
audioMute,
|
||||
enableCosineFiltering,
|
||||
syncOrConstellation,
|
||||
slot1On,
|
||||
slot2On,
|
||||
tdmaStereo,
|
||||
pllLock,
|
||||
udpCopyAudio,
|
||||
udpAddress,
|
||||
udpPort,
|
||||
force);
|
||||
messageQueue->push(cmd);
|
||||
m_deviceAPI->removeThreadedSink(m_threadedChannelizer);
|
||||
delete m_threadedChannelizer;
|
||||
delete m_channelizer;
|
||||
}
|
||||
|
||||
void DSDDemod::configureMyPosition(MessageQueue* messageQueue, float myLatitude, float myLongitude)
|
||||
@ -168,7 +132,7 @@ void DSDDemod::feed(const SampleVector::const_iterator& begin, const SampleVecto
|
||||
|
||||
m_magsqCount++;
|
||||
|
||||
Real demod = 32768.0f * m_phaseDiscri.phaseDiscriminator(ci) * ((float) m_running.m_demodGain / 100.0f);
|
||||
Real demod = 32768.0f * m_phaseDiscri.phaseDiscriminator(ci) * m_settings.m_demodGain;
|
||||
m_sampleCount++;
|
||||
|
||||
// AF processing
|
||||
@ -205,7 +169,7 @@ void DSDDemod::feed(const SampleVector::const_iterator& begin, const SampleVecto
|
||||
|
||||
m_dsdDecoder.pushSample(sample);
|
||||
|
||||
if (m_running.m_enableCosineFiltering) { // show actual input to FSK demod
|
||||
if (m_settings.m_enableCosineFiltering) { // show actual input to FSK demod
|
||||
sample = m_dsdDecoder.getFilteredSample();
|
||||
}
|
||||
|
||||
@ -223,7 +187,7 @@ void DSDDemod::feed(const SampleVector::const_iterator& begin, const SampleVecto
|
||||
delayedSample = m_sampleBuffer[m_sampleBufferIndex - samplesPerSymbol];
|
||||
}
|
||||
|
||||
if (m_running.m_syncOrConstellation)
|
||||
if (m_settings.m_syncOrConstellation)
|
||||
{
|
||||
Sample s(sample, m_dsdDecoder.getSymbolSyncSample());
|
||||
m_scopeSampleBuffer.push_back(s);
|
||||
@ -236,30 +200,30 @@ void DSDDemod::feed(const SampleVector::const_iterator& begin, const SampleVecto
|
||||
|
||||
if (DSPEngine::instance()->hasDVSerialSupport())
|
||||
{
|
||||
if ((m_running.m_slot1On) && m_dsdDecoder.mbeDVReady1())
|
||||
if ((m_settings.m_slot1On) && m_dsdDecoder.mbeDVReady1())
|
||||
{
|
||||
if (!m_running.m_audioMute)
|
||||
if (!m_settings.m_audioMute)
|
||||
{
|
||||
DSPEngine::instance()->pushMbeFrame(
|
||||
m_dsdDecoder.getMbeDVFrame1(),
|
||||
m_dsdDecoder.getMbeRateIndex(),
|
||||
m_running.m_volume,
|
||||
m_running.m_tdmaStereo ? 1 : 3, // left or both channels
|
||||
m_settings.m_volume,
|
||||
m_settings.m_tdmaStereo ? 1 : 3, // left or both channels
|
||||
&m_audioFifo1);
|
||||
}
|
||||
|
||||
m_dsdDecoder.resetMbeDV1();
|
||||
}
|
||||
|
||||
if ((m_running.m_slot2On) && m_dsdDecoder.mbeDVReady2())
|
||||
if ((m_settings.m_slot2On) && m_dsdDecoder.mbeDVReady2())
|
||||
{
|
||||
if (!m_running.m_audioMute)
|
||||
if (!m_settings.m_audioMute)
|
||||
{
|
||||
DSPEngine::instance()->pushMbeFrame(
|
||||
m_dsdDecoder.getMbeDVFrame2(),
|
||||
m_dsdDecoder.getMbeRateIndex(),
|
||||
m_running.m_volume,
|
||||
m_running.m_tdmaStereo ? 2 : 3, // right or both channels
|
||||
m_settings.m_volume,
|
||||
m_settings.m_tdmaStereo ? 2 : 3, // right or both channels
|
||||
&m_audioFifo2);
|
||||
}
|
||||
|
||||
@ -269,9 +233,9 @@ void DSDDemod::feed(const SampleVector::const_iterator& begin, const SampleVecto
|
||||
|
||||
// if (DSPEngine::instance()->hasDVSerialSupport() && m_dsdDecoder.mbeDVReady1())
|
||||
// {
|
||||
// if (!m_running.m_audioMute)
|
||||
// if (!m_settings.m_audioMute)
|
||||
// {
|
||||
// DSPEngine::instance()->pushMbeFrame(m_dsdDecoder.getMbeDVFrame1(), m_dsdDecoder.getMbeRateIndex(), m_running.m_volume, &m_audioFifo1);
|
||||
// DSPEngine::instance()->pushMbeFrame(m_dsdDecoder.getMbeDVFrame1(), m_dsdDecoder.getMbeRateIndex(), m_settings.m_volume, &m_audioFifo1);
|
||||
// }
|
||||
//
|
||||
// m_dsdDecoder.resetMbeDV1();
|
||||
@ -283,14 +247,14 @@ void DSDDemod::feed(const SampleVector::const_iterator& begin, const SampleVecto
|
||||
|
||||
if (!DSPEngine::instance()->hasDVSerialSupport())
|
||||
{
|
||||
if (m_running.m_slot1On)
|
||||
if (m_settings.m_slot1On)
|
||||
{
|
||||
int nbAudioSamples;
|
||||
short *dsdAudio = m_dsdDecoder.getAudio1(nbAudioSamples);
|
||||
|
||||
if (nbAudioSamples > 0)
|
||||
{
|
||||
if (!m_running.m_audioMute) {
|
||||
if (!m_settings.m_audioMute) {
|
||||
m_audioFifo1.write((const quint8*) dsdAudio, nbAudioSamples, 10);
|
||||
}
|
||||
|
||||
@ -298,14 +262,14 @@ void DSDDemod::feed(const SampleVector::const_iterator& begin, const SampleVecto
|
||||
}
|
||||
}
|
||||
|
||||
if (m_running.m_slot2On)
|
||||
if (m_settings.m_slot2On)
|
||||
{
|
||||
int nbAudioSamples;
|
||||
short *dsdAudio = m_dsdDecoder.getAudio2(nbAudioSamples);
|
||||
|
||||
if (nbAudioSamples > 0)
|
||||
{
|
||||
if (!m_running.m_audioMute) {
|
||||
if (!m_settings.m_audioMute) {
|
||||
m_audioFifo2.write((const quint8*) dsdAudio, nbAudioSamples, 10);
|
||||
}
|
||||
|
||||
@ -318,7 +282,7 @@ void DSDDemod::feed(const SampleVector::const_iterator& begin, const SampleVecto
|
||||
//
|
||||
// if (nbAudioSamples > 0)
|
||||
// {
|
||||
// if (!m_running.m_audioMute) {
|
||||
// if (!m_settings.m_audioMute) {
|
||||
// uint res = m_audioFifo1.write((const quint8*) dsdAudio, nbAudioSamples, 10);
|
||||
// }
|
||||
//
|
||||
@ -354,60 +318,60 @@ bool DSDDemod::handleMessage(const Message& cmd)
|
||||
{
|
||||
DownChannelizer::MsgChannelizerNotification& notif = (DownChannelizer::MsgChannelizerNotification&) cmd;
|
||||
|
||||
m_config.m_inputSampleRate = notif.getSampleRate();
|
||||
m_config.m_inputFrequencyOffset = notif.getFrequencyOffset();
|
||||
DSDDemodSettings settings = m_settings;
|
||||
settings.m_inputSampleRate = notif.getSampleRate();
|
||||
settings.m_inputFrequencyOffset = notif.getFrequencyOffset();
|
||||
|
||||
apply();
|
||||
applySettings(settings);
|
||||
|
||||
qDebug() << "DSDDemod::handleMessage: MsgChannelizerNotification: m_inputSampleRate: " << m_config.m_inputSampleRate
|
||||
<< " m_inputFrequencyOffset: " << m_config.m_inputFrequencyOffset;
|
||||
qDebug() << "DSDDemod::handleMessage: MsgChannelizerNotification: m_inputSampleRate: " << settings.m_inputSampleRate
|
||||
<< " m_inputFrequencyOffset: " << settings.m_inputFrequencyOffset;
|
||||
|
||||
return true;
|
||||
}
|
||||
else if (MsgConfigureDSDDemod::match(cmd))
|
||||
{
|
||||
MsgConfigureDSDDemod& cfg = (MsgConfigureDSDDemod&) cmd;
|
||||
else if (MsgConfigureChannelizer::match(cmd))
|
||||
{
|
||||
MsgConfigureChannelizer& cfg = (MsgConfigureChannelizer&) cmd;
|
||||
|
||||
m_config.m_rfBandwidth = cfg.getRFBandwidth();
|
||||
m_config.m_demodGain = cfg.getDemodGain();
|
||||
m_config.m_fmDeviation = cfg.getFMDeviation();
|
||||
m_config.m_volume = cfg.getVolume();
|
||||
m_config.m_baudRate = cfg.getBaudRate();
|
||||
m_config.m_squelchGate = cfg.getSquelchGate();
|
||||
m_config.m_squelch = cfg.getSquelch();
|
||||
m_config.m_audioMute = cfg.getAudioMute();
|
||||
m_config.m_enableCosineFiltering = cfg.getEnableCosineFiltering();
|
||||
m_config.m_syncOrConstellation = cfg.getSyncOrConstellation();
|
||||
m_config.m_slot1On = cfg.getSlot1On();
|
||||
m_config.m_slot2On = cfg.getSlot2On();
|
||||
m_config.m_tdmaStereo = cfg.getTDMAStereo();
|
||||
m_config.m_pllLock = cfg.getPLLLock();
|
||||
m_config.m_udpCopyAudio = cfg.getUDPCopyAudio();
|
||||
m_config.m_udpAddress = cfg.getUDPAddress();
|
||||
m_config.m_udpPort = cfg.getUDPPort();
|
||||
m_channelizer->configure(m_channelizer->getInputMessageQueue(),
|
||||
cfg.getSampleRate(),
|
||||
cfg.getCenterFrequency());
|
||||
|
||||
apply();
|
||||
return true;
|
||||
}
|
||||
else if (MsgConfigureDSDDemod::match(cmd))
|
||||
{
|
||||
MsgConfigureDSDDemod& cfg = (MsgConfigureDSDDemod&) cmd;
|
||||
|
||||
qDebug() << "DSDDemod::handleMessage: MsgConfigureDSDDemod: m_rfBandwidth: " << m_config.m_rfBandwidth * 100
|
||||
<< " m_demodGain: " << m_config.m_demodGain / 100.0
|
||||
<< " m_fmDeviation: " << m_config.m_fmDeviation * 100
|
||||
<< " m_volume: " << m_config.m_volume / 10.0
|
||||
<< " m_baudRate: " << m_config.m_baudRate
|
||||
<< " m_squelchGate" << m_config.m_squelchGate
|
||||
<< " m_squelch: " << m_config.m_squelch
|
||||
<< " m_audioMute: " << m_config.m_audioMute
|
||||
<< " m_enableCosineFiltering: " << m_config.m_enableCosineFiltering
|
||||
<< " m_syncOrConstellation: " << m_config.m_syncOrConstellation
|
||||
<< " m_slot1On: " << m_config.m_slot1On
|
||||
<< " m_slot2On: " << m_config.m_slot2On
|
||||
<< " m_tdmaStereo: " << m_config.m_tdmaStereo
|
||||
<< " m_pllLock: " << m_config.m_pllLock
|
||||
<< " m_udpCopyAudio: " << m_config.m_udpCopyAudio
|
||||
<< " m_udpAddress: " << m_config.m_udpAddress
|
||||
<< " m_udpPort: " << m_config.m_udpPort;
|
||||
DSDDemodSettings settings = cfg.getSettings();
|
||||
|
||||
return true;
|
||||
}
|
||||
// These settings are set with DownChannelizer::MsgChannelizerNotification
|
||||
settings.m_inputSampleRate = m_settings.m_inputSampleRate;
|
||||
settings.m_inputFrequencyOffset = m_settings.m_inputFrequencyOffset;
|
||||
|
||||
applySettings(settings, cfg.getForce());
|
||||
|
||||
qDebug() << "DSDDemod::handleMessage: MsgConfigureDSDDemod: m_rfBandwidth: " << m_settings.m_rfBandwidth
|
||||
<< " m_fmDeviation: " << m_settings.m_fmDeviation
|
||||
<< " m_demodGain: " << m_settings.m_demodGain
|
||||
<< " m_volume: " << m_settings.m_volume
|
||||
<< " m_baudRate: " << m_settings.m_baudRate
|
||||
<< " m_squelchGate" << m_settings.m_squelchGate
|
||||
<< " m_squelch: " << m_settings.m_squelch
|
||||
<< " m_audioMute: " << m_settings.m_audioMute
|
||||
<< " m_enableCosineFiltering: " << m_settings.m_enableCosineFiltering
|
||||
<< " m_syncOrConstellation: " << m_settings.m_syncOrConstellation
|
||||
<< " m_slot1On: " << m_settings.m_slot1On
|
||||
<< " m_slot2On: " << m_settings.m_slot2On
|
||||
<< " m_tdmaStereo: " << m_settings.m_tdmaStereo
|
||||
<< " m_pllLock: " << m_settings.m_pllLock
|
||||
<< " m_udpCopyAudio: " << m_settings.m_udpCopyAudio
|
||||
<< " m_udpAddress: " << m_settings.m_udpAddress
|
||||
<< " m_udpPort: " << m_settings.m_udpPort
|
||||
<< " force: " << cfg.getForce();
|
||||
|
||||
return true;
|
||||
}
|
||||
else if (MsgConfigureMyPosition::match(cmd))
|
||||
{
|
||||
MsgConfigureMyPosition& cfg = (MsgConfigureMyPosition&) cmd;
|
||||
@ -420,82 +384,81 @@ bool DSDDemod::handleMessage(const Message& cmd)
|
||||
}
|
||||
}
|
||||
|
||||
void DSDDemod::apply(bool force)
|
||||
void DSDDemod::applySettings(DSDDemodSettings& settings, bool force)
|
||||
{
|
||||
if ((m_config.m_inputFrequencyOffset != m_running.m_inputFrequencyOffset) ||
|
||||
(m_config.m_inputSampleRate != m_running.m_inputSampleRate) || force)
|
||||
{
|
||||
m_nco.setFreq(-m_config.m_inputFrequencyOffset, m_config.m_inputSampleRate);
|
||||
}
|
||||
|
||||
if ((m_config.m_inputSampleRate != m_running.m_inputSampleRate) ||
|
||||
(m_config.m_rfBandwidth != m_running.m_rfBandwidth) || force)
|
||||
{
|
||||
m_settingsMutex.lock();
|
||||
m_interpolator.create(16, m_config.m_inputSampleRate, (m_config.m_rfBandwidth * 100) / 2.2);
|
||||
m_interpolatorDistanceRemain = 0;
|
||||
m_interpolatorDistance = (Real) m_config.m_inputSampleRate / (Real) m_config.m_audioSampleRate;
|
||||
m_phaseDiscri.setFMScaling((float) m_config.m_rfBandwidth / (float) m_config.m_fmDeviation);
|
||||
m_settingsMutex.unlock();
|
||||
}
|
||||
|
||||
if ((m_config.m_fmDeviation != m_running.m_fmDeviation) || force)
|
||||
{
|
||||
m_phaseDiscri.setFMScaling((float) m_config.m_rfBandwidth / (float) m_config.m_fmDeviation);
|
||||
}
|
||||
|
||||
if ((m_config.m_squelchGate != m_running.m_squelchGate) || force)
|
||||
{
|
||||
m_squelchGate = 480 * m_config.m_squelchGate; // gate is given in 10s of ms at 48000 Hz audio sample rate
|
||||
m_squelchCount = 0; // reset squelch open counter
|
||||
}
|
||||
|
||||
if ((m_config.m_squelch != m_running.m_squelch) || force)
|
||||
{
|
||||
// input is a value in tenths of dB
|
||||
m_squelchLevel = std::pow(10.0, m_config.m_squelch / 100.0);
|
||||
//m_squelchLevel *= m_squelchLevel;
|
||||
}
|
||||
|
||||
if ((m_config.m_volume != m_running.m_volume) || force)
|
||||
if ((settings.m_inputFrequencyOffset != m_settings.m_inputFrequencyOffset) ||
|
||||
(settings.m_inputSampleRate != m_settings.m_inputSampleRate) || force)
|
||||
{
|
||||
m_dsdDecoder.setAudioGain(m_config.m_volume / 10.0f);
|
||||
m_nco.setFreq(-settings.m_inputFrequencyOffset, settings.m_inputSampleRate);
|
||||
}
|
||||
|
||||
if ((m_config.m_baudRate != m_running.m_baudRate) || force)
|
||||
if ((settings.m_inputSampleRate != m_settings.m_inputSampleRate) ||
|
||||
(settings.m_rfBandwidth != m_settings.m_rfBandwidth) || force)
|
||||
{
|
||||
m_dsdDecoder.setBaudRate(m_config.m_baudRate);
|
||||
m_settingsMutex.lock();
|
||||
m_interpolator.create(16, settings.m_inputSampleRate, (settings.m_rfBandwidth) / 2.2);
|
||||
m_interpolatorDistanceRemain = 0;
|
||||
m_interpolatorDistance = (Real) settings.m_inputSampleRate / (Real) settings.m_audioSampleRate;
|
||||
m_phaseDiscri.setFMScaling((float) settings.m_rfBandwidth / (float) settings.m_fmDeviation);
|
||||
m_settingsMutex.unlock();
|
||||
}
|
||||
|
||||
if ((m_config.m_enableCosineFiltering != m_running.m_enableCosineFiltering) || force)
|
||||
if ((settings.m_fmDeviation != m_settings.m_fmDeviation) || force)
|
||||
{
|
||||
m_dsdDecoder.enableCosineFiltering(m_config.m_enableCosineFiltering);
|
||||
m_phaseDiscri.setFMScaling((float) settings.m_rfBandwidth / (float) settings.m_fmDeviation);
|
||||
}
|
||||
|
||||
if ((m_config.m_tdmaStereo != m_running.m_tdmaStereo) || force)
|
||||
if ((settings.m_squelchGate != m_settings.m_squelchGate) || force)
|
||||
{
|
||||
m_dsdDecoder.setTDMAStereo(m_config.m_tdmaStereo);
|
||||
m_squelchGate = 480 * settings.m_squelchGate; // gate is given in 10s of ms at 48000 Hz audio sample rate
|
||||
m_squelchCount = 0; // reset squelch open counter
|
||||
}
|
||||
|
||||
if ((m_config.m_pllLock != m_running.m_pllLock) || force)
|
||||
if ((settings.m_squelch != m_settings.m_squelch) || force)
|
||||
{
|
||||
m_dsdDecoder.setSymbolPLLLock(m_config.m_pllLock);
|
||||
// input is a value in dB
|
||||
m_squelchLevel = std::pow(10.0, settings.m_squelch / 10.0);
|
||||
}
|
||||
|
||||
if ((m_config.m_udpAddress != m_running.m_udpAddress)
|
||||
|| (m_config.m_udpPort != m_running.m_udpPort) || force)
|
||||
if ((settings.m_volume != m_settings.m_volume) || force)
|
||||
{
|
||||
m_udpBufferAudio->setAddress(m_config.m_udpAddress);
|
||||
m_udpBufferAudio->setPort(m_config.m_udpPort);
|
||||
m_dsdDecoder.setAudioGain(settings.m_volume);
|
||||
}
|
||||
|
||||
if ((m_config.m_udpCopyAudio != m_running.m_udpCopyAudio)
|
||||
|| (m_config.m_slot1On != m_running.m_slot1On)
|
||||
|| (m_config.m_slot2On != m_running.m_slot2On) || force)
|
||||
if ((settings.m_baudRate != m_settings.m_baudRate) || force)
|
||||
{
|
||||
m_audioFifo1.setCopyToUDP(m_config.m_slot1On && m_config.m_udpCopyAudio);
|
||||
m_audioFifo2.setCopyToUDP(m_config.m_slot2On && !m_config.m_slot1On && m_config.m_udpCopyAudio);
|
||||
m_dsdDecoder.setBaudRate(settings.m_baudRate);
|
||||
}
|
||||
|
||||
m_running = m_config;
|
||||
if ((settings.m_enableCosineFiltering != m_settings.m_enableCosineFiltering) || force)
|
||||
{
|
||||
m_dsdDecoder.enableCosineFiltering(settings.m_enableCosineFiltering);
|
||||
}
|
||||
|
||||
if ((settings.m_tdmaStereo != m_settings.m_tdmaStereo) || force)
|
||||
{
|
||||
m_dsdDecoder.setTDMAStereo(settings.m_tdmaStereo);
|
||||
}
|
||||
|
||||
if ((settings.m_pllLock != m_settings.m_pllLock) || force)
|
||||
{
|
||||
m_dsdDecoder.setSymbolPLLLock(settings.m_pllLock);
|
||||
}
|
||||
|
||||
if ((settings.m_udpAddress != m_settings.m_udpAddress)
|
||||
|| (settings.m_udpPort != m_settings.m_udpPort) || force)
|
||||
{
|
||||
m_udpBufferAudio->setAddress(settings.m_udpAddress);
|
||||
m_udpBufferAudio->setPort(settings.m_udpPort);
|
||||
}
|
||||
|
||||
if ((settings.m_udpCopyAudio != m_settings.m_udpCopyAudio)
|
||||
|| (settings.m_slot1On != m_settings.m_slot1On)
|
||||
|| (settings.m_slot2On != m_settings.m_slot2On) || force)
|
||||
{
|
||||
m_audioFifo1.setCopyToUDP(settings.m_slot1On && settings.m_udpCopyAudio);
|
||||
m_audioFifo2.setCopyToUDP(settings.m_slot2On && !settings.m_slot1On && settings.m_udpCopyAudio);
|
||||
}
|
||||
|
||||
m_settings = settings;
|
||||
}
|
||||
|
@ -33,34 +33,64 @@
|
||||
#include "util/message.h"
|
||||
#include "util/udpsink.h"
|
||||
|
||||
#include "dsddemodsettings.h"
|
||||
#include "dsddecoder.h"
|
||||
|
||||
class DSDDemodGUI;
|
||||
class DeviceSourceAPI;
|
||||
class ThreadedBasebandSampleSink;
|
||||
class DownChannelizer;
|
||||
|
||||
class DSDDemod : public BasebandSampleSink {
|
||||
public:
|
||||
DSDDemod(BasebandSampleSink* sampleSink);
|
||||
~DSDDemod();
|
||||
class MsgConfigureDSDDemod : public Message {
|
||||
MESSAGE_CLASS_DECLARATION
|
||||
|
||||
void configure(MessageQueue* messageQueue,
|
||||
int rfBandwidth,
|
||||
int demodGain,
|
||||
int volume,
|
||||
int baudRate,
|
||||
int fmDeviation,
|
||||
int squelchGate,
|
||||
Real squelch,
|
||||
bool audioMute,
|
||||
bool enableCosineFiltering,
|
||||
bool syncOrConstellation,
|
||||
bool slot1On,
|
||||
bool slot2On,
|
||||
bool tdmaStereo,
|
||||
bool pllLock,
|
||||
bool udpCopyAudio,
|
||||
const QString& udpAddress,
|
||||
quint16 udpPort,
|
||||
bool force);
|
||||
public:
|
||||
const DSDDemodSettings& getSettings() const { return m_settings; }
|
||||
bool getForce() const { return m_force; }
|
||||
|
||||
static MsgConfigureDSDDemod* create(const DSDDemodSettings& settings, bool force)
|
||||
{
|
||||
return new MsgConfigureDSDDemod(settings, force);
|
||||
}
|
||||
|
||||
private:
|
||||
DSDDemodSettings m_settings;
|
||||
bool m_force;
|
||||
|
||||
MsgConfigureDSDDemod(const DSDDemodSettings& 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)
|
||||
{ }
|
||||
};
|
||||
|
||||
DSDDemod(DeviceSourceAPI *deviceAPI);
|
||||
~DSDDemod();
|
||||
void setScopeSink(BasebandSampleSink* sampleSink) { m_scope = sampleSink; }
|
||||
|
||||
void configureMyPosition(MessageQueue* messageQueue, float myLatitude, float myLongitude);
|
||||
|
||||
@ -69,10 +99,6 @@ public:
|
||||
virtual void stop();
|
||||
virtual bool handleMessage(const Message& cmd);
|
||||
|
||||
void registerGUI(DSDDemodGUI *dsdDemodGUI) {
|
||||
m_dsdDemodGUI = dsdDemodGUI;
|
||||
}
|
||||
|
||||
double getMagSq() { return m_magsq; }
|
||||
bool getSquelchOpen() const { return m_squelchOpen; }
|
||||
|
||||
@ -113,180 +139,16 @@ private:
|
||||
{}
|
||||
};
|
||||
|
||||
class MsgConfigureDSDDemod : public Message {
|
||||
MESSAGE_CLASS_DECLARATION
|
||||
|
||||
public:
|
||||
int getRFBandwidth() const { return m_rfBandwidth; }
|
||||
int getDemodGain() const { return m_demodGain; }
|
||||
int getFMDeviation() const { return m_fmDeviation; }
|
||||
int getVolume() const { return m_volume; }
|
||||
int getBaudRate() const { return m_baudRate; }
|
||||
int getSquelchGate() const { return m_squelchGate; }
|
||||
Real getSquelch() const { return m_squelch; }
|
||||
bool getAudioMute() const { return m_audioMute; }
|
||||
bool getEnableCosineFiltering() const { return m_enableCosineFiltering; }
|
||||
bool getSyncOrConstellation() const { return m_syncOrConstellation; }
|
||||
bool getSlot1On() const { return m_slot1On; }
|
||||
bool getSlot2On() const { return m_slot2On; }
|
||||
bool getTDMAStereo() const { return m_tdmaStereo; }
|
||||
bool getPLLLock() const { return m_pllLock; }
|
||||
bool getUDPCopyAudio() const { return m_udpCopyAudio; }
|
||||
const QString& getUDPAddress() const { return m_udpAddress; }
|
||||
quint16 getUDPPort() const { return m_udpPort; }
|
||||
|
||||
static MsgConfigureDSDDemod* create(int rfBandwidth,
|
||||
int demodGain,
|
||||
int fmDeviation,
|
||||
int volume,
|
||||
int baudRate,
|
||||
int squelchGate,
|
||||
Real squelch,
|
||||
bool audioMute,
|
||||
bool enableCosineFiltering,
|
||||
bool syncOrConstellation,
|
||||
bool slot1On,
|
||||
bool slot2On,
|
||||
bool tdmaStereo,
|
||||
bool pllLock,
|
||||
bool udpCopyAudio,
|
||||
const QString& udpAddress,
|
||||
quint16 udpPort,
|
||||
bool force)
|
||||
{
|
||||
return new MsgConfigureDSDDemod(rfBandwidth,
|
||||
demodGain,
|
||||
fmDeviation,
|
||||
volume,
|
||||
baudRate,
|
||||
squelchGate,
|
||||
squelch,
|
||||
audioMute,
|
||||
enableCosineFiltering,
|
||||
syncOrConstellation,
|
||||
slot1On,
|
||||
slot2On,
|
||||
tdmaStereo,
|
||||
pllLock,
|
||||
udpCopyAudio,
|
||||
udpAddress,
|
||||
udpPort,
|
||||
force);
|
||||
}
|
||||
|
||||
private:
|
||||
Real m_rfBandwidth;
|
||||
Real m_demodGain;
|
||||
int m_fmDeviation;
|
||||
int m_volume;
|
||||
int m_baudRate;
|
||||
int m_squelchGate;
|
||||
Real m_squelch;
|
||||
bool m_audioMute;
|
||||
bool m_enableCosineFiltering;
|
||||
bool m_syncOrConstellation;
|
||||
bool m_slot1On;
|
||||
bool m_slot2On;
|
||||
bool m_tdmaStereo;
|
||||
bool m_pllLock;
|
||||
bool m_udpCopyAudio;
|
||||
QString m_udpAddress;
|
||||
quint16 m_udpPort;
|
||||
bool m_force;
|
||||
|
||||
MsgConfigureDSDDemod(int rfBandwidth,
|
||||
int demodGain,
|
||||
int fmDeviation,
|
||||
int volume,
|
||||
int baudRate,
|
||||
int squelchGate,
|
||||
Real squelch,
|
||||
bool audioMute,
|
||||
bool enableCosineFiltering,
|
||||
bool syncOrConstellation,
|
||||
bool slot1On,
|
||||
bool slot2On,
|
||||
bool tdmaStereo,
|
||||
bool pllLock,
|
||||
bool udpCopyAudio,
|
||||
const QString& udpAddress,
|
||||
quint16 udpPort,
|
||||
bool force) :
|
||||
Message(),
|
||||
m_rfBandwidth(rfBandwidth),
|
||||
m_demodGain(demodGain),
|
||||
m_fmDeviation(fmDeviation),
|
||||
m_volume(volume),
|
||||
m_baudRate(baudRate),
|
||||
m_squelchGate(squelchGate),
|
||||
m_squelch(squelch),
|
||||
m_audioMute(audioMute),
|
||||
m_enableCosineFiltering(enableCosineFiltering),
|
||||
m_syncOrConstellation(syncOrConstellation),
|
||||
m_slot1On(slot1On),
|
||||
m_slot2On(slot2On),
|
||||
m_tdmaStereo(tdmaStereo),
|
||||
m_pllLock(pllLock),
|
||||
m_udpCopyAudio(udpCopyAudio),
|
||||
m_udpAddress(udpAddress),
|
||||
m_udpPort(udpPort),
|
||||
m_force(force)
|
||||
{ }
|
||||
};
|
||||
|
||||
enum RateState {
|
||||
RSInitialFill,
|
||||
RSRunning
|
||||
};
|
||||
|
||||
struct Config {
|
||||
int m_inputSampleRate;
|
||||
qint64 m_inputFrequencyOffset;
|
||||
int m_rfBandwidth;
|
||||
int m_demodGain;
|
||||
int m_volume;
|
||||
int m_baudRate;
|
||||
int m_fmDeviation;
|
||||
int m_squelchGate;
|
||||
Real m_squelch;
|
||||
bool m_audioMute;
|
||||
quint32 m_audioSampleRate;
|
||||
bool m_enableCosineFiltering;
|
||||
bool m_syncOrConstellation;
|
||||
bool m_slot1On;
|
||||
bool m_slot2On;
|
||||
bool m_tdmaStereo;
|
||||
bool m_pllLock;
|
||||
bool m_udpCopyAudio;
|
||||
QString m_udpAddress;
|
||||
quint16 m_udpPort;
|
||||
DSDDemodSettings m_settings;
|
||||
|
||||
Config() :
|
||||
m_inputSampleRate(-1),
|
||||
m_inputFrequencyOffset(0),
|
||||
m_rfBandwidth(-1),
|
||||
m_demodGain(-1),
|
||||
m_volume(-1),
|
||||
m_baudRate(4800),
|
||||
m_fmDeviation(1),
|
||||
m_squelchGate(1),
|
||||
m_squelch(0),
|
||||
m_audioMute(false),
|
||||
m_audioSampleRate(0),
|
||||
m_enableCosineFiltering(false),
|
||||
m_syncOrConstellation(false),
|
||||
m_slot1On(false),
|
||||
m_slot2On(false),
|
||||
m_tdmaStereo(false),
|
||||
m_pllLock(true),
|
||||
m_udpCopyAudio(false),
|
||||
m_udpAddress("127.0.0.1"),
|
||||
m_udpPort(9999)
|
||||
{ }
|
||||
};
|
||||
|
||||
Config m_config;
|
||||
Config m_running;
|
||||
DeviceSourceAPI *m_deviceAPI;
|
||||
ThreadedBasebandSampleSink* m_threadedChannelizer;
|
||||
DownChannelizer* m_channelizer;
|
||||
|
||||
NCO m_nco;
|
||||
Interpolator m_interpolator;
|
||||
@ -299,7 +161,6 @@ private:
|
||||
double m_squelchLevel;
|
||||
bool m_squelchOpen;
|
||||
|
||||
Real m_lastArgument;
|
||||
MovingAverage<double> m_movingAverage;
|
||||
double m_magsq;
|
||||
double m_magsqSum;
|
||||
@ -320,7 +181,6 @@ private:
|
||||
bool m_scopeEnabled;
|
||||
|
||||
DSDDecoder m_dsdDecoder;
|
||||
DSDDemodGUI *m_dsdDemodGUI;
|
||||
QMutex m_settingsMutex;
|
||||
|
||||
PhaseDiscriminators m_phaseDiscri;
|
||||
@ -328,7 +188,7 @@ private:
|
||||
|
||||
static const int m_udpBlockSize;
|
||||
|
||||
void apply(bool force = false);
|
||||
void applySettings(DSDDemodSettings& settings, bool force = false);
|
||||
};
|
||||
|
||||
#endif // INCLUDE_DSDDEMOD_H
|
||||
|
50
plugins/channelrx/demoddsd/dsddemodbaudrates.cpp
Normal file
@ -0,0 +1,50 @@
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// Copyright (C) 2016 F4EXB //
|
||||
// written by Edouard Griffiths //
|
||||
// //
|
||||
// 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 "dsddemodbaudrates.h"
|
||||
|
||||
unsigned int DSDDemodBaudRates::m_rates[] = {2400, 4800};
|
||||
unsigned int DSDDemodBaudRates::m_nb_rates = 2;
|
||||
unsigned int DSDDemodBaudRates::m_defaultRateIndex = 1; // 4800 bauds
|
||||
|
||||
unsigned int DSDDemodBaudRates::getRate(unsigned int rate_index)
|
||||
{
|
||||
if (rate_index < m_nb_rates)
|
||||
{
|
||||
return m_rates[rate_index];
|
||||
}
|
||||
else
|
||||
{
|
||||
return m_rates[m_defaultRateIndex];
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int DSDDemodBaudRates::getRateIndex(unsigned int rate)
|
||||
{
|
||||
for (unsigned int i=0; i < m_nb_rates; i++)
|
||||
{
|
||||
if (rate == m_rates[i])
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return m_defaultRateIndex;
|
||||
}
|
||||
|
||||
|
||||
|
35
plugins/channelrx/demoddsd/dsddemodbaudrates.h
Normal file
@ -0,0 +1,35 @@
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// Copyright (C) 2016 F4EXB //
|
||||
// written by Edouard Griffiths //
|
||||
// //
|
||||
// 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_DEMODDSD_DSDDEMODBAUDRATES_H_
|
||||
#define PLUGINS_CHANNELRX_DEMODDSD_DSDDEMODBAUDRATES_H_
|
||||
|
||||
class DSDDemodBaudRates
|
||||
{
|
||||
public:
|
||||
static unsigned int getRate(unsigned int rate_index);
|
||||
static unsigned int getRateIndex(unsigned int rate);
|
||||
static unsigned int getDefaultRate() { return m_rates[m_defaultRateIndex]; }
|
||||
static unsigned int getDefaultRateIndex() { return m_defaultRateIndex; }
|
||||
static unsigned int getNbRates() { return m_nb_rates; }
|
||||
private:
|
||||
static unsigned int m_nb_rates;
|
||||
static unsigned int m_rates[2];
|
||||
static unsigned int m_defaultRateIndex;
|
||||
};
|
||||
|
||||
#endif /* PLUGINS_CHANNELRX_DEMODDSD_DSDDEMODBAUDRATES_H_ */
|
@ -34,14 +34,11 @@
|
||||
#include "dsp/dspengine.h"
|
||||
#include "mainwindow.h"
|
||||
|
||||
#include "dsddemodbaudrates.h"
|
||||
#include "dsddemod.h"
|
||||
|
||||
const QString DSDDemodGUI::m_channelID = "sdrangel.channel.dsddemod";
|
||||
|
||||
unsigned int DSDDemodBaudRates::m_rates[] = {2400, 4800};
|
||||
unsigned int DSDDemodBaudRates::m_nb_rates = 2;
|
||||
unsigned int DSDDemodBaudRates::m_defaultRateIndex = 1; // 4800 bauds
|
||||
|
||||
DSDDemodGUI* DSDDemodGUI::create(PluginAPI* pluginAPI, DeviceSourceAPI *deviceAPI)
|
||||
{
|
||||
DSDDemodGUI* gui = new DSDDemodGUI(pluginAPI, deviceAPI);
|
||||
@ -76,112 +73,31 @@ void DSDDemodGUI::setCenterFrequency(qint64 centerFrequency)
|
||||
|
||||
void DSDDemodGUI::resetToDefaults()
|
||||
{
|
||||
m_settings.resetToDefaults();
|
||||
blockApplySettings(true);
|
||||
|
||||
ui->rfBW->setValue(100); // x100 Hz
|
||||
ui->demodGain->setValue(100); // 100ths
|
||||
ui->fmDeviation->setValue(50); // x100 Hz
|
||||
ui->volume->setValue(20); // /10.0
|
||||
ui->baudRate->setCurrentIndex(DSDDemodBaudRates::getDefaultRateIndex());
|
||||
ui->squelchGate->setValue(5);
|
||||
ui->squelch->setValue(-40);
|
||||
ui->deltaFrequency->setValue(0);
|
||||
ui->symbolPLLLock->setChecked(true);
|
||||
|
||||
displaySettings();
|
||||
blockApplySettings(false);
|
||||
applySettings();
|
||||
}
|
||||
|
||||
QByteArray DSDDemodGUI::serialize() const
|
||||
{
|
||||
SimpleSerializer s(1);
|
||||
s.writeS32(1, m_channelMarker.getCenterFrequency());
|
||||
s.writeS32(2, ui->rfBW->value());
|
||||
s.writeS32(3, ui->demodGain->value());
|
||||
s.writeS32(4, ui->fmDeviation->value());
|
||||
s.writeS32(5, ui->squelch->value());
|
||||
s.writeU32(7, m_channelMarker.getColor().rgb());
|
||||
s.writeS32(8, ui->squelchGate->value());
|
||||
s.writeS32(9, ui->volume->value());
|
||||
s.writeBlob(10, ui->scopeGUI->serialize());
|
||||
s.writeS32(11, ui->baudRate->currentIndex());
|
||||
s.writeBool(12, m_enableCosineFiltering);
|
||||
s.writeBool(13, m_syncOrConstellation);
|
||||
s.writeBool(14, m_slot1On);
|
||||
s.writeBool(15, m_slot2On);
|
||||
s.writeBool(16, m_tdmaStereo);
|
||||
s.writeBlob(17, m_channelMarker.serialize());
|
||||
return s.final();
|
||||
return m_settings.serialize();
|
||||
}
|
||||
|
||||
bool DSDDemodGUI::deserialize(const QByteArray& data)
|
||||
{
|
||||
SimpleDeserializer d(data);
|
||||
|
||||
if (!d.isValid())
|
||||
{
|
||||
resetToDefaults();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (d.getVersion() == 1)
|
||||
{
|
||||
QByteArray bytetmp;
|
||||
QString strtmp;
|
||||
quint32 u32tmp;
|
||||
qint32 tmp;
|
||||
|
||||
blockApplySettings(true);
|
||||
m_channelMarker.blockSignals(true);
|
||||
|
||||
d.readBlob(17, &bytetmp);
|
||||
m_channelMarker.deserialize(bytetmp);
|
||||
|
||||
d.readS32(1, &tmp, 0);
|
||||
m_channelMarker.setCenterFrequency(tmp);
|
||||
d.readS32(2, &tmp, 4);
|
||||
ui->rfBW->setValue(tmp);
|
||||
d.readS32(3, &tmp, 3);
|
||||
ui->demodGain->setValue(tmp);
|
||||
d.readS32(4, &tmp, 20);
|
||||
ui->fmDeviation->setValue(tmp);
|
||||
d.readS32(5, &tmp, -40);
|
||||
ui->squelch->setValue(tmp);
|
||||
|
||||
if(d.readU32(7, &u32tmp))
|
||||
{
|
||||
m_channelMarker.setColor(u32tmp);
|
||||
}
|
||||
|
||||
d.readS32(8, &tmp, 5);
|
||||
ui->squelchGate->setValue(tmp);
|
||||
d.readS32(9, &tmp, 20);
|
||||
ui->volume->setValue(tmp);
|
||||
d.readBlob(10, &bytetmp);
|
||||
ui->scopeGUI->deserialize(bytetmp);
|
||||
d.readS32(11, &tmp, 20);
|
||||
ui->baudRate->setCurrentIndex(tmp);
|
||||
d.readBool(12, &m_enableCosineFiltering, false);
|
||||
d.readBool(13, &m_syncOrConstellation, false);
|
||||
d.readBool(14, &m_slot1On, false);
|
||||
d.readBool(15, &m_slot2On, false);
|
||||
d.readBool(16, &m_tdmaStereo, false);
|
||||
|
||||
this->setWindowTitle(m_channelMarker.getTitle());
|
||||
displayUDPAddress();
|
||||
|
||||
blockApplySettings(false);
|
||||
m_channelMarker.blockSignals(false);
|
||||
|
||||
updateMyPosition(); // we do it also here to be able to refresh with latest settings
|
||||
applySettings(true);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
resetToDefaults();
|
||||
return false;
|
||||
}
|
||||
if (m_settings.deserialize(data))
|
||||
{
|
||||
displaySettings();
|
||||
applySettings(true);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
resetToDefaults();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool DSDDemodGUI::handleMessage(const Message& message __attribute__((unused)))
|
||||
@ -192,79 +108,92 @@ bool DSDDemodGUI::handleMessage(const Message& message __attribute__((unused)))
|
||||
void DSDDemodGUI::on_deltaFrequency_changed(qint64 value)
|
||||
{
|
||||
m_channelMarker.setCenterFrequency(value);
|
||||
m_settings.m_inputFrequencyOffset = m_channelMarker.getCenterFrequency();
|
||||
applySettings();
|
||||
}
|
||||
|
||||
void DSDDemodGUI::on_rfBW_valueChanged(int value)
|
||||
{
|
||||
qDebug() << "DSDDemodGUI::on_rfBW_valueChanged" << value * 100;
|
||||
m_channelMarker.setBandwidth(value * 100);
|
||||
m_settings.m_rfBandwidth = value * 100.0;
|
||||
ui->rfBWText->setText(QString("%1k").arg(value / 10.0, 0, 'f', 1));
|
||||
applySettings();
|
||||
}
|
||||
|
||||
void DSDDemodGUI::on_demodGain_valueChanged(int value __attribute__((unused)))
|
||||
void DSDDemodGUI::on_demodGain_valueChanged(int value)
|
||||
{
|
||||
m_settings.m_demodGain = value / 100.0;
|
||||
ui->demodGainText->setText(QString("%1").arg(value / 100.0, 0, 'f', 2));
|
||||
applySettings();
|
||||
}
|
||||
|
||||
void DSDDemodGUI::on_fmDeviation_valueChanged(int value __attribute__((unused)))
|
||||
void DSDDemodGUI::on_fmDeviation_valueChanged(int value)
|
||||
{
|
||||
m_settings.m_fmDeviation = value * 100.0;
|
||||
ui->fmDeviationText->setText(QString("%1k").arg(value / 10.0, 0, 'f', 1));
|
||||
applySettings();
|
||||
}
|
||||
|
||||
void DSDDemodGUI::on_volume_valueChanged(int value __attribute__((unused)))
|
||||
void DSDDemodGUI::on_volume_valueChanged(int value)
|
||||
{
|
||||
m_settings.m_volume= value / 10.0;
|
||||
ui->volumeText->setText(QString("%1").arg(value / 10.0, 0, 'f', 1));
|
||||
applySettings();
|
||||
}
|
||||
|
||||
void DSDDemodGUI::on_baudRate_currentIndexChanged(int index __attribute__((unused)))
|
||||
void DSDDemodGUI::on_baudRate_currentIndexChanged(int index)
|
||||
{
|
||||
m_settings.m_baudRate = DSDDemodBaudRates::getRate(index);
|
||||
applySettings();
|
||||
}
|
||||
|
||||
void DSDDemodGUI::on_enableCosineFiltering_toggled(bool enable)
|
||||
{
|
||||
m_enableCosineFiltering = enable;
|
||||
m_settings.m_enableCosineFiltering = enable;
|
||||
applySettings();
|
||||
}
|
||||
|
||||
void DSDDemodGUI::on_syncOrConstellation_toggled(bool checked)
|
||||
{
|
||||
m_syncOrConstellation = checked;
|
||||
m_settings.m_syncOrConstellation = checked;
|
||||
applySettings();
|
||||
}
|
||||
|
||||
void DSDDemodGUI::on_slot1On_toggled(bool checked)
|
||||
{
|
||||
m_slot1On = checked;
|
||||
m_settings.m_slot1On = checked;
|
||||
applySettings();
|
||||
}
|
||||
|
||||
void DSDDemodGUI::on_slot2On_toggled(bool checked)
|
||||
{
|
||||
m_slot2On = checked;
|
||||
m_settings.m_slot2On = checked;
|
||||
applySettings();
|
||||
}
|
||||
|
||||
void DSDDemodGUI::on_tdmaStereoSplit_toggled(bool checked)
|
||||
{
|
||||
m_tdmaStereo = checked;
|
||||
m_settings.m_tdmaStereo = checked;
|
||||
applySettings();
|
||||
}
|
||||
|
||||
void DSDDemodGUI::on_squelchGate_valueChanged(int value __attribute__((unused)))
|
||||
void DSDDemodGUI::on_squelchGate_valueChanged(int value)
|
||||
{
|
||||
m_settings.m_squelchGate = value;
|
||||
ui->squelchGateText->setText(QString("%1").arg(value * 10.0, 0, 'f', 0));
|
||||
applySettings();
|
||||
}
|
||||
|
||||
void DSDDemodGUI::on_squelch_valueChanged(int value)
|
||||
{
|
||||
ui->squelchText->setText(QString("%1").arg(value / 10.0, 0, 'f', 1));
|
||||
m_settings.m_squelch = value / 10.0;
|
||||
applySettings();
|
||||
}
|
||||
|
||||
void DSDDemodGUI::on_audioMute_toggled(bool checked)
|
||||
{
|
||||
m_audioMute = checked;
|
||||
m_settings.m_audioMute = checked;
|
||||
applySettings();
|
||||
}
|
||||
|
||||
@ -275,11 +204,13 @@ void DSDDemodGUI::on_symbolPLLLock_toggled(bool checked)
|
||||
} else {
|
||||
ui->symbolPLLLock->setStyleSheet("QToolButton { background:rgb(53,53,53); }");
|
||||
}
|
||||
m_settings.m_pllLock = checked;
|
||||
applySettings();
|
||||
}
|
||||
|
||||
void DSDDemodGUI::on_udpOutput_toggled(bool checked __attribute__((unused)))
|
||||
void DSDDemodGUI::on_udpOutput_toggled(bool checked)
|
||||
{
|
||||
m_settings.m_udpCopyAudio = checked;
|
||||
applySettings();
|
||||
}
|
||||
|
||||
@ -322,8 +253,9 @@ DSDDemodGUI::DSDDemodGUI(PluginAPI* pluginAPI, DeviceSourceAPI *deviceAPI, QWidg
|
||||
connect(this, SIGNAL(customContextMenuRequested(const QPoint &)), this, SLOT(onMenuDialogCalled(const QPoint &)));
|
||||
|
||||
m_scopeVis = new ScopeVis(ui->glScope);
|
||||
m_dsdDemod = new DSDDemod(m_scopeVis);
|
||||
m_dsdDemod->registerGUI(this);
|
||||
m_dsdDemod = new DSDDemod(m_deviceAPI);
|
||||
m_dsdDemod->setScopeSink(m_scopeVis);
|
||||
m_dsdDemod->setMessageQueueToGUI(getInputMessageQueue());
|
||||
|
||||
ui->glScope->setSampleRate(48000);
|
||||
m_scopeVis->setSampleRate(48000);
|
||||
@ -339,11 +271,7 @@ DSDDemodGUI::DSDDemodGUI(PluginAPI* pluginAPI, DeviceSourceAPI *deviceAPI, QWidg
|
||||
ui->deltaFrequency->setValueRange(false, 7, -9999999, 9999999);
|
||||
ui->channelPowerMeter->setColorTheme(LevelMeterSignalDB::ColorGreenAndBlue);
|
||||
|
||||
m_channelizer = new DownChannelizer(m_dsdDemod);
|
||||
m_threadedChannelizer = new ThreadedBasebandSampleSink(m_channelizer, this);
|
||||
m_deviceAPI->addThreadedSink(m_threadedChannelizer);
|
||||
|
||||
//m_channelMarker = new ChannelMarker(this);
|
||||
m_channelMarker.setTitle(windowTitle());
|
||||
m_channelMarker.setColor(Qt::cyan);
|
||||
m_channelMarker.setBandwidth(10000);
|
||||
@ -358,7 +286,11 @@ DSDDemodGUI::DSDDemodGUI(PluginAPI* pluginAPI, DeviceSourceAPI *deviceAPI, QWidg
|
||||
|
||||
ui->scopeGUI->setBuddies(m_scopeVis->getInputMessageQueue(), m_scopeVis, ui->glScope);
|
||||
|
||||
m_settings.setChannelMarker(&m_channelMarker);
|
||||
m_settings.setScopeGUI(ui->scopeGUI);
|
||||
|
||||
updateMyPosition();
|
||||
displaySettings();
|
||||
displayUDPAddress();
|
||||
applySettings(true);
|
||||
}
|
||||
@ -366,11 +298,7 @@ DSDDemodGUI::DSDDemodGUI(PluginAPI* pluginAPI, DeviceSourceAPI *deviceAPI, QWidg
|
||||
DSDDemodGUI::~DSDDemodGUI()
|
||||
{
|
||||
m_deviceAPI->removeChannelInstance(this);
|
||||
m_deviceAPI->removeThreadedSink(m_threadedChannelizer);
|
||||
delete m_threadedChannelizer;
|
||||
delete m_channelizer;
|
||||
delete m_dsdDemod;
|
||||
//delete m_channelMarker;
|
||||
delete ui;
|
||||
}
|
||||
|
||||
@ -392,49 +320,65 @@ void DSDDemodGUI::displayUDPAddress()
|
||||
ui->udpOutput->setToolTip(QString("Copy audio output to UDP %1:%2").arg(m_channelMarker.getUDPAddress()).arg(m_channelMarker.getUDPSendPort()));
|
||||
}
|
||||
|
||||
void DSDDemodGUI::displaySettings()
|
||||
{
|
||||
blockApplySettings(true);
|
||||
|
||||
m_channelMarker.blockSignals(true);
|
||||
m_channelMarker.setCenterFrequency(m_settings.m_inputFrequencyOffset);
|
||||
m_channelMarker.setUDPAddress(m_settings.m_udpAddress);
|
||||
m_channelMarker.setUDPSendPort(m_settings.m_udpPort);
|
||||
m_channelMarker.setColor(m_settings.m_rgbColor);
|
||||
this->setWindowTitle(m_channelMarker.getTitle());
|
||||
setTitleColor(m_settings.m_rgbColor);
|
||||
m_channelMarker.blockSignals(false);
|
||||
|
||||
ui->deltaFrequency->setValue(m_channelMarker.getCenterFrequency());
|
||||
|
||||
ui->rfBW->setValue(m_settings.m_rfBandwidth / 100.0);
|
||||
ui->rfBWText->setText(QString("%1k").arg(ui->rfBW->value() / 10.0, 0, 'f', 1));
|
||||
|
||||
ui->fmDeviation->setValue(m_settings.m_fmDeviation / 100.0);
|
||||
ui->fmDeviationText->setText(QString("%1k").arg(ui->fmDeviation->value() / 10.0, 0, 'f', 1));
|
||||
|
||||
ui->squelch->setValue(m_settings.m_squelch * 10.0);
|
||||
ui->squelchText->setText(QString("%1").arg(ui->squelch->value() / 10.0, 0, 'f', 1));
|
||||
|
||||
ui->squelchGate->setValue(m_settings.m_squelchGate);
|
||||
ui->squelchGateText->setText(QString("%1").arg(ui->squelchGate->value() * 10.0, 0, 'f', 0));
|
||||
|
||||
ui->demodGain->setValue(m_settings.m_demodGain * 100.0);
|
||||
ui->demodGainText->setText(QString("%1").arg(ui->demodGain->value() / 100.0, 0, 'f', 2));
|
||||
|
||||
ui->volume->setValue(m_settings.m_volume * 10.0);
|
||||
ui->volumeText->setText(QString("%1").arg(ui->volume->value() / 10.0, 0, 'f', 1));
|
||||
|
||||
ui->enableCosineFiltering->setChecked(m_settings.m_enableCosineFiltering);
|
||||
ui->syncOrConstellation->setChecked(m_settings.m_syncOrConstellation);
|
||||
ui->slot1On->setChecked(m_settings.m_slot1On);
|
||||
ui->slot2On->setChecked(m_settings.m_slot2On);
|
||||
ui->tdmaStereoSplit->setChecked(m_settings.m_tdmaStereo);
|
||||
ui->audioMute->setChecked(m_settings.m_audioMute);
|
||||
ui->udpOutput->setChecked(m_settings.m_udpCopyAudio);
|
||||
ui->symbolPLLLock->setChecked(m_settings.m_pllLock);
|
||||
|
||||
ui->baudRate->setCurrentIndex(DSDDemodBaudRates::getRateIndex(m_settings.m_baudRate));
|
||||
|
||||
blockApplySettings(false);
|
||||
}
|
||||
|
||||
void DSDDemodGUI::applySettings(bool force)
|
||||
{
|
||||
if (m_doApplySettings)
|
||||
{
|
||||
qDebug() << "DSDDemodGUI::applySettings";
|
||||
|
||||
setTitleColor(m_channelMarker.getColor());
|
||||
DSDDemod::MsgConfigureChannelizer* channelConfigMsg = DSDDemod::MsgConfigureChannelizer::create(
|
||||
48000, m_channelMarker.getCenterFrequency());
|
||||
m_dsdDemod->getInputMessageQueue()->push(channelConfigMsg);
|
||||
|
||||
m_channelizer->configure(m_channelizer->getInputMessageQueue(),
|
||||
48000,
|
||||
m_channelMarker.getCenterFrequency());
|
||||
|
||||
ui->deltaFrequency->setValue(m_channelMarker.getCenterFrequency());
|
||||
ui->rfBWText->setText(QString("%1k").arg(ui->rfBW->value() / 10.0, 0, 'f', 1));
|
||||
ui->demodGainText->setText(QString("%1").arg(ui->demodGain->value() / 100.0, 0, 'f', 2));
|
||||
ui->fmDeviationText->setText(QString("%1k").arg(ui->fmDeviation->value() / 10.0, 0, 'f', 1));
|
||||
ui->squelchGateText->setText(QString("%1").arg(ui->squelchGate->value() * 10.0, 0, 'f', 0));
|
||||
ui->volumeText->setText(QString("%1").arg(ui->volume->value() / 10.0, 0, 'f', 1));
|
||||
ui->enableCosineFiltering->setChecked(m_enableCosineFiltering);
|
||||
ui->syncOrConstellation->setChecked(m_syncOrConstellation);
|
||||
ui->slot1On->setChecked(m_slot1On);
|
||||
ui->slot2On->setChecked(m_slot2On);
|
||||
ui->tdmaStereoSplit->setChecked(m_tdmaStereo);
|
||||
|
||||
m_dsdDemod->configure(m_dsdDemod->getInputMessageQueue(),
|
||||
ui->rfBW->value(),
|
||||
ui->demodGain->value(),
|
||||
ui->fmDeviation->value(),
|
||||
ui->volume->value(),
|
||||
DSDDemodBaudRates::getRate(ui->baudRate->currentIndex()),
|
||||
ui->squelchGate->value(), // in 10ths of ms
|
||||
ui->squelch->value(),
|
||||
ui->audioMute->isChecked(),
|
||||
m_enableCosineFiltering,
|
||||
m_syncOrConstellation,
|
||||
m_slot1On,
|
||||
m_slot2On,
|
||||
m_tdmaStereo,
|
||||
ui->symbolPLLLock->isChecked(),
|
||||
ui->udpOutput->isChecked(),
|
||||
m_channelMarker.getUDPAddress(),
|
||||
m_channelMarker.getUDPSendPort(),
|
||||
force);
|
||||
DSDDemod::MsgConfigureDSDDemod* message = DSDDemod::MsgConfigureDSDDemod::create( m_settings, force);
|
||||
m_dsdDemod->getInputMessageQueue()->push(message);
|
||||
}
|
||||
}
|
||||
|
||||
@ -683,28 +627,3 @@ void DSDDemodGUI::tick()
|
||||
|
||||
m_tickCount++;
|
||||
}
|
||||
|
||||
unsigned int DSDDemodBaudRates::getRate(unsigned int rate_index)
|
||||
{
|
||||
if (rate_index < m_nb_rates)
|
||||
{
|
||||
return m_rates[rate_index];
|
||||
}
|
||||
else
|
||||
{
|
||||
return m_rates[m_defaultRateIndex];
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int DSDDemodBaudRates::getRateIndex(unsigned int rate)
|
||||
{
|
||||
for (unsigned int i=0; i < m_nb_rates; i++)
|
||||
{
|
||||
if (rate == m_rates[i])
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return m_defaultRateIndex;
|
||||
}
|
||||
|
@ -18,20 +18,20 @@
|
||||
#ifndef INCLUDE_DSDDEMODGUI_H
|
||||
#define INCLUDE_DSDDEMODGUI_H
|
||||
|
||||
#include <plugin/plugininstancegui.h>
|
||||
#include <QMenu>
|
||||
|
||||
#include "gui/rollupwidget.h"
|
||||
#include "dsp/dsptypes.h"
|
||||
#include "dsp/channelmarker.h"
|
||||
#include "dsp/movingaverage.h"
|
||||
#include "plugin/plugininstanceui.h"
|
||||
#include "util/messagequeue.h"
|
||||
|
||||
#include "dsddemodsettings.h"
|
||||
|
||||
class PluginAPI;
|
||||
class DeviceSourceAPI;
|
||||
|
||||
class ThreadedBasebandSampleSink;
|
||||
class DownChannelizer;
|
||||
class ScopeVis;
|
||||
class DSDDemod;
|
||||
|
||||
@ -39,7 +39,7 @@ namespace Ui {
|
||||
class DSDDemodGUI;
|
||||
}
|
||||
|
||||
class DSDDemodGUI : public RollupWidget, public PluginInstanceUI {
|
||||
class DSDDemodGUI : public RollupWidget, public PluginInstanceGUI {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
@ -96,12 +96,11 @@ private:
|
||||
PluginAPI* m_pluginAPI;
|
||||
DeviceSourceAPI* m_deviceAPI;
|
||||
ChannelMarker m_channelMarker;
|
||||
DSDDemodSettings m_settings;
|
||||
bool m_doApplySettings;
|
||||
char m_formatStatusText[82+1]; //!< Fixed signal format dependent status text
|
||||
SignalFormat m_signalFormat;
|
||||
|
||||
ThreadedBasebandSampleSink* m_threadedChannelizer;
|
||||
DownChannelizer* m_channelizer;
|
||||
ScopeVis* m_scopeVis;
|
||||
|
||||
DSDDemod* m_dsdDemod;
|
||||
@ -124,6 +123,7 @@ private:
|
||||
|
||||
void blockApplySettings(bool block);
|
||||
void applySettings(bool force = false);
|
||||
void displaySettings();
|
||||
void updateMyPosition();
|
||||
void displayUDPAddress();
|
||||
|
||||
@ -131,18 +131,4 @@ private:
|
||||
void enterEvent(QEvent*);
|
||||
};
|
||||
|
||||
class DSDDemodBaudRates
|
||||
{
|
||||
public:
|
||||
static unsigned int getRate(unsigned int rate_index);
|
||||
static unsigned int getRateIndex(unsigned int rate);
|
||||
static unsigned int getDefaultRate() { return m_rates[m_defaultRateIndex]; }
|
||||
static unsigned int getDefaultRateIndex() { return m_defaultRateIndex; }
|
||||
static unsigned int getNbRates();
|
||||
private:
|
||||
static unsigned int m_nb_rates;
|
||||
static unsigned int m_rates[2];
|
||||
static unsigned int m_defaultRateIndex;
|
||||
};
|
||||
|
||||
#endif // INCLUDE_DSDDEMODGUI_H
|
||||
|
@ -24,7 +24,7 @@
|
||||
|
||||
const PluginDescriptor DSDDemodPlugin::m_pluginDescriptor = {
|
||||
QString("DSD Demodulator"),
|
||||
QString("3.6.1"),
|
||||
QString("3.7.3"),
|
||||
QString("(c) Edouard Griffiths, F4EXB"),
|
||||
QString("https://github.com/f4exb/sdrangel"),
|
||||
true,
|
||||
@ -50,7 +50,7 @@ void DSDDemodPlugin::initPlugin(PluginAPI* pluginAPI)
|
||||
m_pluginAPI->registerRxChannel(DSDDemodGUI::m_channelID, this);
|
||||
}
|
||||
|
||||
PluginInstanceUI* DSDDemodPlugin::createRxChannel(const QString& channelName, DeviceSourceAPI *deviceAPI)
|
||||
PluginInstanceGUI* DSDDemodPlugin::createRxChannel(const QString& channelName, DeviceSourceAPI *deviceAPI)
|
||||
{
|
||||
if(channelName == DSDDemodGUI::m_channelID)
|
||||
{
|
||||
|
@ -34,7 +34,7 @@ public:
|
||||
const PluginDescriptor& getPluginDescriptor() const;
|
||||
void initPlugin(PluginAPI* pluginAPI);
|
||||
|
||||
PluginInstanceUI* createRxChannel(const QString& channelName, DeviceSourceAPI *deviceAPI);
|
||||
PluginInstanceGUI* createRxChannel(const QString& channelName, DeviceSourceAPI *deviceAPI);
|
||||
|
||||
private:
|
||||
static const PluginDescriptor m_pluginDescriptor;
|
||||
|
144
plugins/channelrx/demoddsd/dsddemodsettings.cpp
Normal file
@ -0,0 +1,144 @@
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// Copyright (C) 2017 Edouard Griffiths, F4EXB. //
|
||||
// //
|
||||
// This program is free som_udpCopyAudioftware; 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 "dsddemodsettings.h"
|
||||
|
||||
DSDDemodSettings::DSDDemodSettings() :
|
||||
m_channelMarker(0),
|
||||
m_scopeGUI(0)
|
||||
{
|
||||
resetToDefaults();
|
||||
}
|
||||
|
||||
void DSDDemodSettings::resetToDefaults()
|
||||
{
|
||||
m_inputSampleRate = 96000;
|
||||
m_inputFrequencyOffset = 0;
|
||||
m_rfBandwidth = 12500.0;
|
||||
m_fmDeviation = 5000.0;
|
||||
m_demodGain = 1.25;
|
||||
m_volume = 2.0;
|
||||
m_baudRate = 4800;
|
||||
m_squelchGate = 5; // 10s of ms at 48000 Hz sample rate. Corresponds to 2400 for AGC attack
|
||||
m_squelch = -40.0;
|
||||
m_audioMute = false;
|
||||
m_audioSampleRate = DSPEngine::instance()->getAudioSampleRate();
|
||||
m_enableCosineFiltering = false;
|
||||
m_syncOrConstellation = false;
|
||||
m_slot1On = true;
|
||||
m_slot2On = false;
|
||||
m_tdmaStereo = false;
|
||||
m_pllLock = true;
|
||||
m_udpCopyAudio = false;
|
||||
m_udpAddress = "127.0.0.1";
|
||||
m_udpPort = 9999;
|
||||
m_rgbColor = QColor(0, 255, 255).rgb();
|
||||
}
|
||||
|
||||
QByteArray DSDDemodSettings::serialize() const
|
||||
{
|
||||
SimpleSerializer s(1);
|
||||
s.writeS32(1, m_inputFrequencyOffset);
|
||||
s.writeS32(2, m_rfBandwidth/100.0);
|
||||
s.writeS32(3, m_demodGain*100.0);
|
||||
s.writeS32(4, m_fmDeviation/100.0);
|
||||
s.writeS32(5, m_squelch*10.0);
|
||||
s.writeS32(6, m_inputSampleRate);
|
||||
s.writeU32(7, m_rgbColor);
|
||||
s.writeS32(8, m_squelchGate);
|
||||
s.writeS32(9, m_volume*10.0);
|
||||
|
||||
if (m_scopeGUI) {
|
||||
s.writeBlob(10, m_scopeGUI->serialize());
|
||||
}
|
||||
|
||||
s.writeS32(11, m_baudRate);
|
||||
s.writeBool(12, m_enableCosineFiltering);
|
||||
s.writeBool(13, m_syncOrConstellation);
|
||||
s.writeBool(14, m_slot1On);
|
||||
s.writeBool(15, m_slot2On);
|
||||
s.writeBool(16, m_tdmaStereo);
|
||||
|
||||
if (m_channelMarker) {
|
||||
s.writeBlob(17, m_channelMarker->serialize());
|
||||
}
|
||||
|
||||
return s.final();
|
||||
}
|
||||
|
||||
bool DSDDemodSettings::deserialize(const QByteArray& data)
|
||||
{
|
||||
SimpleDeserializer d(data);
|
||||
|
||||
if (!d.isValid())
|
||||
{
|
||||
resetToDefaults();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (d.getVersion() == 1)
|
||||
{
|
||||
QByteArray bytetmp;
|
||||
QString strtmp;
|
||||
qint32 tmp;
|
||||
|
||||
if (m_channelMarker) {
|
||||
d.readBlob(17, &bytetmp);
|
||||
m_channelMarker->deserialize(bytetmp);
|
||||
}
|
||||
|
||||
d.readS32(1, &tmp, 0);
|
||||
m_inputFrequencyOffset = tmp;
|
||||
d.readS32(2, &tmp, 125);
|
||||
m_rfBandwidth = tmp * 100.0;
|
||||
d.readS32(3, &tmp, 125);
|
||||
m_demodGain = tmp / 100.0;
|
||||
d.readS32(4, &tmp, 50);
|
||||
m_fmDeviation = tmp * 100.0;
|
||||
d.readS32(5, &tmp, -400);
|
||||
m_squelch = tmp / 10.0;
|
||||
d.readS32(6, &m_inputSampleRate, 96000);
|
||||
d.readU32(7, &m_rgbColor);
|
||||
d.readS32(8, &m_squelchGate, 5);
|
||||
d.readS32(9, &tmp, 20);
|
||||
m_volume = tmp / 10.0;
|
||||
|
||||
if (m_scopeGUI) {
|
||||
d.readBlob(10, &bytetmp);
|
||||
m_scopeGUI->deserialize(bytetmp);
|
||||
}
|
||||
|
||||
d.readS32(11, &m_baudRate, 4800);
|
||||
d.readBool(12, &m_enableCosineFiltering, false);
|
||||
d.readBool(13, &m_syncOrConstellation, false);
|
||||
d.readBool(14, &m_slot1On, false);
|
||||
d.readBool(15, &m_slot2On, false);
|
||||
d.readBool(16, &m_tdmaStereo, false);
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
resetToDefaults();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
60
plugins/channelrx/demoddsd/dsddemodsettings.h
Normal file
@ -0,0 +1,60 @@
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// 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_DEMODDSD_DSDDEMODSETTINGS_H_
|
||||
#define PLUGINS_CHANNELRX_DEMODDSD_DSDDEMODSETTINGS_H_
|
||||
|
||||
#include <QByteArray>
|
||||
|
||||
class Serializable;
|
||||
|
||||
struct DSDDemodSettings
|
||||
{
|
||||
int m_inputSampleRate;
|
||||
qint64 m_inputFrequencyOffset;
|
||||
Real m_rfBandwidth;
|
||||
Real m_fmDeviation;
|
||||
Real m_demodGain;
|
||||
Real m_volume;
|
||||
int m_baudRate;
|
||||
int m_squelchGate;
|
||||
Real m_squelch;
|
||||
bool m_audioMute;
|
||||
quint32 m_audioSampleRate;
|
||||
bool m_enableCosineFiltering;
|
||||
bool m_syncOrConstellation;
|
||||
bool m_slot1On;
|
||||
bool m_slot2On;
|
||||
bool m_tdmaStereo;
|
||||
bool m_pllLock;
|
||||
bool m_udpCopyAudio;
|
||||
QString m_udpAddress;
|
||||
quint16 m_udpPort;
|
||||
quint32 m_rgbColor;
|
||||
|
||||
Serializable *m_channelMarker;
|
||||
Serializable *m_scopeGUI;
|
||||
|
||||
DSDDemodSettings();
|
||||
void resetToDefaults();
|
||||
void setChannelMarker(Serializable *channelMarker) { m_channelMarker = channelMarker; }
|
||||
void setScopeGUI(Serializable *scopeGUI) { m_scopeGUI = scopeGUI; }
|
||||
QByteArray serialize() const;
|
||||
bool deserialize(const QByteArray& data);
|
||||
};
|
||||
|
||||
|
||||
#endif /* PLUGINS_CHANNELRX_DEMODDSD_DSDDEMODSETTINGS_H_ */
|
@ -1,9 +1,9 @@
|
||||
#ifndef INCLUDE_LoRaDEMODGUI_H
|
||||
#define INCLUDE_LoRaDEMODGUI_H
|
||||
|
||||
#include <plugin/plugininstancegui.h>
|
||||
#include "gui/rollupwidget.h"
|
||||
#include "dsp/channelmarker.h"
|
||||
#include "plugin/plugininstanceui.h"
|
||||
#include "util/messagequeue.h"
|
||||
|
||||
#define BANDWIDTHSTRING {7813,15625,20833,31250,62500}
|
||||
@ -19,7 +19,7 @@ namespace Ui {
|
||||
class LoRaDemodGUI;
|
||||
}
|
||||
|
||||
class LoRaDemodGUI : public RollupWidget, public PluginInstanceUI {
|
||||
class LoRaDemodGUI : public RollupWidget, public PluginInstanceGUI {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
@ -33,7 +33,7 @@ void LoRaPlugin::initPlugin(PluginAPI* pluginAPI)
|
||||
m_pluginAPI->registerRxChannel(LoRaDemodGUI::m_channelID, this);
|
||||
}
|
||||
|
||||
PluginInstanceUI* LoRaPlugin::createRxChannel(const QString& channelName, DeviceSourceAPI *deviceAPI)
|
||||
PluginInstanceGUI* LoRaPlugin::createRxChannel(const QString& channelName, DeviceSourceAPI *deviceAPI)
|
||||
{
|
||||
if(channelName == LoRaDemodGUI::m_channelID)
|
||||
{
|
||||
|
@ -17,7 +17,7 @@ public:
|
||||
const PluginDescriptor& getPluginDescriptor() const;
|
||||
void initPlugin(PluginAPI* pluginAPI);
|
||||
|
||||
PluginInstanceUI* createRxChannel(const QString& channelName, DeviceSourceAPI *deviceAPI);
|
||||
PluginInstanceGUI* createRxChannel(const QString& channelName, DeviceSourceAPI *deviceAPI);
|
||||
|
||||
private:
|
||||
static const PluginDescriptor m_pluginDescriptor;
|
||||
|
@ -1,11 +1,11 @@
|
||||
#ifndef INCLUDE_NFMDEMODGUI_H
|
||||
#define INCLUDE_NFMDEMODGUI_H
|
||||
|
||||
#include <plugin/plugininstancegui.h>
|
||||
#include "gui/rollupwidget.h"
|
||||
#include "dsp/dsptypes.h"
|
||||
#include "dsp/channelmarker.h"
|
||||
#include "dsp/movingaverage.h"
|
||||
#include "plugin/plugininstanceui.h"
|
||||
#include "util/messagequeue.h"
|
||||
|
||||
class PluginAPI;
|
||||
@ -19,7 +19,7 @@ namespace Ui {
|
||||
class NFMDemodGUI;
|
||||
}
|
||||
|
||||
class NFMDemodGUI : public RollupWidget, public PluginInstanceUI {
|
||||
class NFMDemodGUI : public RollupWidget, public PluginInstanceGUI {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
@ -33,7 +33,7 @@ void NFMPlugin::initPlugin(PluginAPI* pluginAPI)
|
||||
m_pluginAPI->registerRxChannel(NFMDemodGUI::m_channelID, this);
|
||||
}
|
||||
|
||||
PluginInstanceUI* NFMPlugin::createRxChannel(const QString& channelName, DeviceSourceAPI *deviceAPI)
|
||||
PluginInstanceGUI* NFMPlugin::createRxChannel(const QString& channelName, DeviceSourceAPI *deviceAPI)
|
||||
{
|
||||
if(channelName == NFMDemodGUI::m_channelID) {
|
||||
NFMDemodGUI* gui = NFMDemodGUI::create(m_pluginAPI, deviceAPI);
|
||||
|
@ -17,7 +17,7 @@ public:
|
||||
const PluginDescriptor& getPluginDescriptor() const;
|
||||
void initPlugin(PluginAPI* pluginAPI);
|
||||
|
||||
PluginInstanceUI* createRxChannel(const QString& channelName, DeviceSourceAPI *deviceAPI);
|
||||
PluginInstanceGUI* createRxChannel(const QString& channelName, DeviceSourceAPI *deviceAPI);
|
||||
|
||||
private:
|
||||
static const PluginDescriptor m_pluginDescriptor;
|
||||
|
@ -3,12 +3,14 @@ project(ssb)
|
||||
set(ssb_SOURCES
|
||||
ssbdemod.cpp
|
||||
ssbdemodgui.cpp
|
||||
ssbdemodsettings.cpp
|
||||
ssbplugin.cpp
|
||||
)
|
||||
|
||||
set(ssb_HEADERS
|
||||
ssbdemod.h
|
||||
ssbdemodgui.h
|
||||
ssbdemodsettings.h
|
||||
ssbplugin.h
|
||||
)
|
||||
|
||||
|
@ -25,10 +25,12 @@ CONFIG(Debug):build_subdir = debug
|
||||
|
||||
SOURCES += ssbdemod.cpp\
|
||||
ssbdemodgui.cpp\
|
||||
ssbdemodsettings.cpp\
|
||||
ssbplugin.cpp
|
||||
|
||||
HEADERS += ssbdemod.h\
|
||||
ssbdemodgui.h\
|
||||
ssbdemodsettings.h\
|
||||
ssbplugin.h
|
||||
|
||||
FORMS += ssbdemodgui.ui
|
||||
|
@ -16,19 +16,26 @@
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "ssbdemod.h"
|
||||
|
||||
#include <dsp/downchannelizer.h>
|
||||
#include <QTime>
|
||||
#include <QDebug>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "audio/audiooutput.h"
|
||||
#include "dsp/dspengine.h"
|
||||
#include <dsp/downchannelizer.h>
|
||||
#include "dsp/threadedbasebandsamplesink.h"
|
||||
#include "device/devicesourceapi.h"
|
||||
#include "util/db.h"
|
||||
|
||||
MESSAGE_CLASS_DEFINITION(SSBDemod::MsgConfigureSSBDemod, Message)
|
||||
#include "ssbdemod.h"
|
||||
|
||||
SSBDemod::SSBDemod(BasebandSampleSink* sampleSink) :
|
||||
MESSAGE_CLASS_DEFINITION(SSBDemod::MsgConfigureSSBDemod, Message)
|
||||
MESSAGE_CLASS_DEFINITION(SSBDemod::MsgConfigureSSBDemodPrivate, Message)
|
||||
MESSAGE_CLASS_DEFINITION(SSBDemod::MsgConfigureChannelizer, Message)
|
||||
|
||||
SSBDemod::SSBDemod(DeviceSourceAPI *deviceAPI) :
|
||||
m_deviceAPI(deviceAPI),
|
||||
m_audioBinaual(false),
|
||||
m_audioFlipChannels(false),
|
||||
m_dsb(false),
|
||||
@ -40,7 +47,7 @@ SSBDemod::SSBDemod(BasebandSampleSink* sampleSink) :
|
||||
m_agcPowerThreshold(1e-2),
|
||||
m_agcThresholdGate(0),
|
||||
m_audioActive(false),
|
||||
m_sampleSink(sampleSink),
|
||||
m_sampleSink(0),
|
||||
m_audioFifo(24000),
|
||||
m_settingsMutex(QMutex::Recursive)
|
||||
{
|
||||
@ -75,7 +82,13 @@ SSBDemod::SSBDemod(BasebandSampleSink* sampleSink) :
|
||||
SSBFilter = new fftfilt(m_LowCutoff / m_audioSampleRate, m_Bandwidth / m_audioSampleRate, ssbFftLen);
|
||||
DSBFilter = new fftfilt((2.0f * m_Bandwidth) / m_audioSampleRate, 2 * ssbFftLen);
|
||||
|
||||
m_channelizer = new DownChannelizer(this);
|
||||
m_threadedChannelizer = new ThreadedBasebandSampleSink(m_channelizer, this);
|
||||
m_deviceAPI->addThreadedSink(m_threadedChannelizer);
|
||||
|
||||
DSPEngine::instance()->addAudioSink(&m_audioFifo);
|
||||
|
||||
applySettings(m_settings, true);
|
||||
}
|
||||
|
||||
SSBDemod::~SSBDemod()
|
||||
@ -84,6 +97,10 @@ SSBDemod::~SSBDemod()
|
||||
if (DSBFilter) delete DSBFilter;
|
||||
|
||||
DSPEngine::instance()->removeAudioSink(&m_audioFifo);
|
||||
|
||||
m_deviceAPI->removeThreadedSink(m_threadedChannelizer);
|
||||
delete m_threadedChannelizer;
|
||||
delete m_channelizer;
|
||||
}
|
||||
|
||||
void SSBDemod::configure(MessageQueue* messageQueue,
|
||||
@ -101,7 +118,7 @@ void SSBDemod::configure(MessageQueue* messageQueue,
|
||||
int agcPowerThreshold,
|
||||
int agcThresholdGate)
|
||||
{
|
||||
Message* cmd = MsgConfigureSSBDemod::create(
|
||||
Message* cmd = MsgConfigureSSBDemodPrivate::create(
|
||||
Bandwidth,
|
||||
LowCutoff,
|
||||
volume,
|
||||
@ -262,10 +279,6 @@ void SSBDemod::stop()
|
||||
|
||||
bool SSBDemod::handleMessage(const Message& cmd)
|
||||
{
|
||||
float band, lowCutoff;
|
||||
|
||||
qDebug() << "SSBDemod::handleMessage";
|
||||
|
||||
if (DownChannelizer::MsgChannelizerNotification::match(cmd))
|
||||
{
|
||||
DownChannelizer::MsgChannelizerNotification& notif = (DownChannelizer::MsgChannelizerNotification&) cmd;
|
||||
@ -284,94 +297,48 @@ bool SSBDemod::handleMessage(const Message& cmd)
|
||||
|
||||
return true;
|
||||
}
|
||||
else if (MsgConfigureSSBDemod::match(cmd))
|
||||
{
|
||||
MsgConfigureSSBDemod& cfg = (MsgConfigureSSBDemod&) cmd;
|
||||
else if (MsgConfigureChannelizer::match(cmd))
|
||||
{
|
||||
MsgConfigureChannelizer& cfg = (MsgConfigureChannelizer&) cmd;
|
||||
|
||||
m_settingsMutex.lock();
|
||||
m_channelizer->configure(m_channelizer->getInputMessageQueue(),
|
||||
cfg.getSampleRate(),
|
||||
cfg.getCenterFrequency());
|
||||
|
||||
band = cfg.getBandwidth();
|
||||
lowCutoff = cfg.getLoCutoff();
|
||||
qDebug() << "SSBDemod::handleMessage: MsgConfigureChannelizer: sampleRate: " << cfg.getSampleRate()
|
||||
<< " centerFrequency: " << cfg.getCenterFrequency();
|
||||
|
||||
if (band < 0) {
|
||||
band = -band;
|
||||
lowCutoff = -lowCutoff;
|
||||
m_usb = false;
|
||||
} else
|
||||
m_usb = true;
|
||||
return true;
|
||||
}
|
||||
else if (MsgConfigureSSBDemod::match(cmd))
|
||||
{
|
||||
MsgConfigureSSBDemod& cfg = (MsgConfigureSSBDemod&) cmd;
|
||||
|
||||
if (band < 100.0f)
|
||||
{
|
||||
band = 100.0f;
|
||||
lowCutoff = 0;
|
||||
}
|
||||
m_Bandwidth = band;
|
||||
m_LowCutoff = lowCutoff;
|
||||
SSBDemodSettings settings = cfg.getSettings();
|
||||
|
||||
m_interpolator.create(16, m_sampleRate, band * 2.0f);
|
||||
SSBFilter->create_filter(m_LowCutoff / (float) m_audioSampleRate, m_Bandwidth / (float) m_audioSampleRate);
|
||||
DSBFilter->create_dsb_filter((2.0f * m_Bandwidth) / (float) m_audioSampleRate);
|
||||
// These settings are set with DownChannelizer::MsgChannelizerNotification
|
||||
settings.m_inputSampleRate = m_settings.m_inputSampleRate;
|
||||
settings.m_inputFrequencyOffset = m_settings.m_inputFrequencyOffset;
|
||||
|
||||
m_volume = cfg.getVolume();
|
||||
//m_volume *= 2.0; // for 327.68
|
||||
m_volume /= 4.0; // for 3276.8
|
||||
applySettings(settings, cfg.getForce());
|
||||
|
||||
m_spanLog2 = cfg.getSpanLog2();
|
||||
m_audioBinaual = cfg.getAudioBinaural();
|
||||
m_audioFlipChannels = cfg.getAudioFlipChannels();
|
||||
m_dsb = cfg.getDSB();
|
||||
m_audioMute = cfg.getAudioMute();
|
||||
m_agcActive = cfg.getAGC();
|
||||
qDebug() << "SSBDemod::handleMessage: MsgConfigureSSBDemod:"
|
||||
<< " m_rfBandwidth: " << settings.m_rfBandwidth
|
||||
<< " m_lowCutoff: " << settings.m_lowCutoff
|
||||
<< " m_volume: " << settings.m_volume
|
||||
<< " m_spanLog2: " << settings.m_spanLog2
|
||||
<< " m_audioBinaual: " << settings.m_audioBinaural
|
||||
<< " m_audioFlipChannels: " << settings.m_audioFlipChannels
|
||||
<< " m_dsb: " << settings.m_dsb
|
||||
<< " m_audioMute: " << settings.m_audioMute
|
||||
<< " m_agcActive: " << settings.m_agc
|
||||
<< " m_agcClamping: " << settings.m_agcClamping
|
||||
<< " m_agcTimeLog2: " << settings.m_agcTimeLog2
|
||||
<< " agcPowerThreshold: " << settings.m_agcPowerThreshold
|
||||
<< " agcThresholdGate: " << settings.m_agcThresholdGate;
|
||||
|
||||
int agcNbSamples = 48 * (1<<cfg.getAGCTimeLog2());
|
||||
m_agc.setThresholdEnable(cfg.getAGCPowerThershold() != -99);
|
||||
double agcPowerThreshold = CalcDb::powerFromdB(cfg.getAGCPowerThershold()) * (1<<30);
|
||||
int agcThresholdGate = 48 * cfg.getAGCThersholdGate(); // ms
|
||||
bool agcClamping = cfg.getAGCClamping();
|
||||
|
||||
if (m_agcNbSamples != agcNbSamples)
|
||||
{
|
||||
m_agc.resize(agcNbSamples, agcTarget);
|
||||
m_agc.setStepDownDelay(agcNbSamples);
|
||||
m_agcNbSamples = agcNbSamples;
|
||||
}
|
||||
|
||||
if (m_agcPowerThreshold != agcPowerThreshold)
|
||||
{
|
||||
m_agc.setThreshold(agcPowerThreshold);
|
||||
m_agcPowerThreshold = agcPowerThreshold;
|
||||
}
|
||||
|
||||
if (m_agcThresholdGate != agcThresholdGate)
|
||||
{
|
||||
m_agc.setGate(agcThresholdGate);
|
||||
m_agcThresholdGate = agcThresholdGate;
|
||||
}
|
||||
|
||||
if (m_agcClamping != agcClamping)
|
||||
{
|
||||
m_agc.setClamping(agcClamping);
|
||||
m_agcClamping = agcClamping;
|
||||
}
|
||||
|
||||
m_settingsMutex.unlock();
|
||||
|
||||
qDebug() << "SBDemod::handleMessage: MsgConfigureSSBDemod: m_Bandwidth: " << m_Bandwidth
|
||||
<< " m_LowCutoff: " << m_LowCutoff
|
||||
<< " m_volume: " << m_volume
|
||||
<< " m_spanLog2: " << m_spanLog2
|
||||
<< " m_audioBinaual: " << m_audioBinaual
|
||||
<< " m_audioFlipChannels: " << m_audioFlipChannels
|
||||
<< " m_dsb: " << m_dsb
|
||||
<< " m_audioMute: " << m_audioMute
|
||||
<< " m_agcActive: " << m_agcActive
|
||||
<< " m_agcClamping: " << m_agcClamping
|
||||
<< " agcNbSamples: " << agcNbSamples
|
||||
<< " agcPowerThreshold: " << agcPowerThreshold
|
||||
<< " agcThresholdGate: " << agcThresholdGate;
|
||||
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(m_sampleSink != 0)
|
||||
@ -384,3 +351,116 @@ bool SSBDemod::handleMessage(const Message& cmd)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SSBDemod::applySettings(const SSBDemodSettings& settings, bool force)
|
||||
{
|
||||
if ((m_settings.m_inputFrequencyOffset != settings.m_inputFrequencyOffset) ||
|
||||
(m_settings.m_inputSampleRate != settings.m_inputSampleRate) || force)
|
||||
{
|
||||
m_nco.setFreq(-settings.m_inputFrequencyOffset, settings.m_inputSampleRate);
|
||||
}
|
||||
|
||||
|
||||
if((m_settings.m_inputSampleRate != settings.m_inputSampleRate) ||
|
||||
(m_settings.m_rfBandwidth != settings.m_rfBandwidth) ||
|
||||
(m_settings.m_lowCutoff != settings.m_lowCutoff) ||
|
||||
(m_settings.m_audioSampleRate != settings.m_audioSampleRate) || force)
|
||||
{
|
||||
float band, lowCutoff;
|
||||
|
||||
band = settings.m_rfBandwidth;
|
||||
lowCutoff = settings.m_lowCutoff;
|
||||
m_audioSampleRate = settings.m_audioSampleRate;
|
||||
|
||||
if (band < 0) {
|
||||
band = -band;
|
||||
lowCutoff = -lowCutoff;
|
||||
m_usb = false;
|
||||
} else
|
||||
m_usb = true;
|
||||
|
||||
if (band < 100.0f)
|
||||
{
|
||||
band = 100.0f;
|
||||
lowCutoff = 0;
|
||||
}
|
||||
|
||||
m_Bandwidth = band;
|
||||
m_LowCutoff = lowCutoff;
|
||||
|
||||
m_settingsMutex.lock();
|
||||
m_interpolator.create(16, m_sampleRate, band * 2.0f);
|
||||
SSBFilter->create_filter(m_LowCutoff / (float) m_audioSampleRate, m_Bandwidth / (float) m_audioSampleRate);
|
||||
DSBFilter->create_dsb_filter((2.0f * m_Bandwidth) / (float) m_audioSampleRate);
|
||||
m_settingsMutex.unlock();
|
||||
}
|
||||
|
||||
if ((m_settings.m_volume != settings.m_volume) || force)
|
||||
{
|
||||
m_volume = settings.m_volume;
|
||||
m_volume /= 4.0; // for 3276.8
|
||||
}
|
||||
|
||||
if ((m_settings.m_agcTimeLog2 != settings.m_agcTimeLog2) ||
|
||||
(m_settings.m_agcPowerThreshold != settings.m_agcPowerThreshold) ||
|
||||
(m_settings.m_agcThresholdGate != settings.m_agcThresholdGate) ||
|
||||
(m_settings.m_agcClamping != settings.m_agcClamping) || force)
|
||||
{
|
||||
int agcNbSamples = 48 * (1<<settings.m_agcTimeLog2);
|
||||
m_agc.setThresholdEnable(settings.m_agcPowerThreshold != -99);
|
||||
double agcPowerThreshold = CalcDb::powerFromdB(settings.m_agcPowerThreshold) * (1<<30);
|
||||
int agcThresholdGate = 48 * settings.m_agcThresholdGate; // ms
|
||||
bool agcClamping = settings.m_agcClamping;
|
||||
|
||||
if (m_agcNbSamples != agcNbSamples)
|
||||
{
|
||||
m_settingsMutex.lock();
|
||||
m_agc.resize(agcNbSamples, agcTarget);
|
||||
m_agc.setStepDownDelay(agcNbSamples);
|
||||
m_agcNbSamples = agcNbSamples;
|
||||
m_settingsMutex.unlock();
|
||||
}
|
||||
|
||||
if (m_agcPowerThreshold != agcPowerThreshold)
|
||||
{
|
||||
m_agc.setThreshold(agcPowerThreshold);
|
||||
m_agcPowerThreshold = agcPowerThreshold;
|
||||
}
|
||||
|
||||
if (m_agcThresholdGate != agcThresholdGate)
|
||||
{
|
||||
m_agc.setGate(agcThresholdGate);
|
||||
m_agcThresholdGate = agcThresholdGate;
|
||||
}
|
||||
|
||||
if (m_agcClamping != agcClamping)
|
||||
{
|
||||
m_agc.setClamping(agcClamping);
|
||||
m_agcClamping = agcClamping;
|
||||
}
|
||||
|
||||
qDebug() << "SBDemod::applySettings: AGC:"
|
||||
<< " agcNbSamples: " << agcNbSamples
|
||||
<< " agcPowerThreshold: " << agcPowerThreshold
|
||||
<< " agcThresholdGate: " << agcThresholdGate
|
||||
<< " agcClamping: " << agcClamping;
|
||||
}
|
||||
|
||||
// TODO:
|
||||
// if ((m_settings.m_udpAddress != settings.m_udpAddress)
|
||||
// || (m_settings.m_udpPort != settings.m_udpPort) || force)
|
||||
// {
|
||||
// m_udpBufferAudio->setAddress(const_cast<QString&>(settings.m_udpAddress));
|
||||
// m_udpBufferAudio->setPort(settings.m_udpPort);
|
||||
// }
|
||||
|
||||
m_spanLog2 = settings.m_spanLog2;
|
||||
m_audioBinaual = settings.m_audioBinaural;
|
||||
m_audioFlipChannels = settings.m_audioFlipChannels;
|
||||
m_dsb = settings.m_dsb;
|
||||
m_audioMute = settings.m_audioMute;
|
||||
m_agcActive = settings.m_agc;
|
||||
|
||||
m_settings = settings;
|
||||
}
|
||||
|
||||
|
@ -18,9 +18,10 @@
|
||||
#ifndef INCLUDE_SSBDEMOD_H
|
||||
#define INCLUDE_SSBDEMOD_H
|
||||
|
||||
#include <dsp/basebandsamplesink.h>
|
||||
#include <QMutex>
|
||||
#include <vector>
|
||||
|
||||
#include <dsp/basebandsamplesink.h>
|
||||
#include "dsp/ncof.h"
|
||||
#include "dsp/interpolator.h"
|
||||
#include "dsp/fftfilt.h"
|
||||
@ -28,13 +29,66 @@
|
||||
#include "audio/audiofifo.h"
|
||||
#include "util/message.h"
|
||||
|
||||
#include "ssbdemodsettings.h"
|
||||
|
||||
#define ssbFftLen 1024
|
||||
#define agcTarget 3276.8 // -10 dB amplitude => -20 dB power: center of normal signal
|
||||
|
||||
class DeviceSourceAPI;
|
||||
class ThreadedBasebandSampleSink;
|
||||
class DownChannelizer;
|
||||
|
||||
class SSBDemod : public BasebandSampleSink {
|
||||
public:
|
||||
SSBDemod(BasebandSampleSink* sampleSink);
|
||||
class MsgConfigureSSBDemod : public Message {
|
||||
MESSAGE_CLASS_DECLARATION
|
||||
|
||||
public:
|
||||
const SSBDemodSettings& getSettings() const { return m_settings; }
|
||||
bool getForce() const { return m_force; }
|
||||
|
||||
static MsgConfigureSSBDemod* create(const SSBDemodSettings& settings, bool force)
|
||||
{
|
||||
return new MsgConfigureSSBDemod(settings, force);
|
||||
}
|
||||
|
||||
private:
|
||||
SSBDemodSettings m_settings;
|
||||
bool m_force;
|
||||
|
||||
MsgConfigureSSBDemod(const SSBDemodSettings& 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)
|
||||
{ }
|
||||
};
|
||||
|
||||
SSBDemod(DeviceSourceAPI *deviceAPI);
|
||||
virtual ~SSBDemod();
|
||||
void setSampleSink(BasebandSampleSink* sampleSink) { m_sampleSink = sampleSink; }
|
||||
|
||||
void configure(MessageQueue* messageQueue,
|
||||
Real Bandwidth,
|
||||
@ -71,7 +125,7 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
class MsgConfigureSSBDemod : public Message {
|
||||
class MsgConfigureSSBDemodPrivate : public Message {
|
||||
MESSAGE_CLASS_DECLARATION
|
||||
|
||||
public:
|
||||
@ -89,7 +143,7 @@ private:
|
||||
int getAGCPowerThershold() const { return m_agcPowerThreshold; }
|
||||
int getAGCThersholdGate() const { return m_agcThresholdGate; }
|
||||
|
||||
static MsgConfigureSSBDemod* create(Real Bandwidth,
|
||||
static MsgConfigureSSBDemodPrivate* create(Real Bandwidth,
|
||||
Real LowCutoff,
|
||||
Real volume,
|
||||
int spanLog2,
|
||||
@ -103,7 +157,7 @@ private:
|
||||
int agcPowerThreshold,
|
||||
int agcThresholdGate)
|
||||
{
|
||||
return new MsgConfigureSSBDemod(
|
||||
return new MsgConfigureSSBDemodPrivate(
|
||||
Bandwidth,
|
||||
LowCutoff,
|
||||
volume,
|
||||
@ -134,7 +188,7 @@ private:
|
||||
int m_agcPowerThreshold;
|
||||
int m_agcThresholdGate;
|
||||
|
||||
MsgConfigureSSBDemod(Real Bandwidth,
|
||||
MsgConfigureSSBDemodPrivate(Real Bandwidth,
|
||||
Real LowCutoff,
|
||||
Real volume,
|
||||
int spanLog2,
|
||||
@ -164,6 +218,11 @@ private:
|
||||
{ }
|
||||
};
|
||||
|
||||
DeviceSourceAPI *m_deviceAPI;
|
||||
ThreadedBasebandSampleSink* m_threadedChannelizer;
|
||||
DownChannelizer* m_channelizer;
|
||||
SSBDemodSettings m_settings;
|
||||
|
||||
Real m_Bandwidth;
|
||||
Real m_LowCutoff;
|
||||
Real m_volume;
|
||||
@ -204,6 +263,8 @@ private:
|
||||
quint32 m_audioSampleRate;
|
||||
|
||||
QMutex m_settingsMutex;
|
||||
|
||||
void applySettings(const SSBDemodSettings& settings, bool force = false);
|
||||
};
|
||||
|
||||
#endif // INCLUDE_SSBDEMOD_H
|
||||
|
@ -2,12 +2,9 @@
|
||||
#include "ssbdemodgui.h"
|
||||
|
||||
#include <device/devicesourceapi.h>
|
||||
#include <dsp/downchannelizer.h>
|
||||
#include <QDockWidget>
|
||||
#include <QMainWindow>
|
||||
|
||||
#include "dsp/threadedbasebandsamplesink.h"
|
||||
#include "ui_ssbdemodgui.h"
|
||||
#include "ui_ssbdemodgui.h"
|
||||
#include "dsp/spectrumvis.h"
|
||||
#include "gui/glspectrum.h"
|
||||
@ -50,113 +47,36 @@ qint64 SSBDemodGUI::getCenterFrequency() const
|
||||
void SSBDemodGUI::setCenterFrequency(qint64 centerFrequency)
|
||||
{
|
||||
m_channelMarker.setCenterFrequency(centerFrequency);
|
||||
m_settings.m_inputFrequencyOffset = m_channelMarker.getCenterFrequency();
|
||||
applySettings();
|
||||
}
|
||||
|
||||
void SSBDemodGUI::resetToDefaults()
|
||||
{
|
||||
blockApplySettings(true);
|
||||
|
||||
ui->BW->setValue(30);
|
||||
ui->volume->setValue(30);
|
||||
ui->deltaFrequency->setValue(0);
|
||||
ui->spanLog2->setValue(3);
|
||||
ui->agc->setChecked(false);
|
||||
ui->agcTimeLog2->setValue(7);
|
||||
ui->agcPowerThreshold->setValue(-40);
|
||||
ui->agcThresholdGate->setValue(4);
|
||||
|
||||
blockApplySettings(false);
|
||||
m_settings.resetToDefaults();
|
||||
}
|
||||
|
||||
QByteArray SSBDemodGUI::serialize() const
|
||||
{
|
||||
SimpleSerializer s(1);
|
||||
s.writeS32(1, m_channelMarker.getCenterFrequency());
|
||||
s.writeS32(2, ui->BW->value());
|
||||
s.writeS32(3, ui->volume->value());
|
||||
s.writeBlob(4, ui->spectrumGUI->serialize());
|
||||
s.writeU32(5, m_channelMarker.getColor().rgb());
|
||||
s.writeS32(6, ui->lowCut->value());
|
||||
s.writeS32(7, ui->spanLog2->value());
|
||||
s.writeBool(8, m_audioBinaural);
|
||||
s.writeBool(9, m_audioFlipChannels);
|
||||
s.writeBool(10, m_dsb);
|
||||
s.writeBool(11, ui->agc->isChecked());
|
||||
s.writeS32(12, ui->agcTimeLog2->value());
|
||||
s.writeS32(13, ui->agcPowerThreshold->value());
|
||||
s.writeS32(14, ui->agcThresholdGate->value());
|
||||
s.writeBool(15, ui->agcClamping->isChecked());
|
||||
return s.final();
|
||||
return m_settings.serialize();
|
||||
}
|
||||
|
||||
bool SSBDemodGUI::deserialize(const QByteArray& data)
|
||||
{
|
||||
SimpleDeserializer d(data);
|
||||
|
||||
if (!d.isValid())
|
||||
{
|
||||
resetToDefaults();
|
||||
applySettings();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (d.getVersion() == 1)
|
||||
{
|
||||
QByteArray bytetmp;
|
||||
quint32 u32tmp;
|
||||
qint32 tmp;
|
||||
bool booltmp;
|
||||
|
||||
blockApplySettings(true);
|
||||
m_channelMarker.blockSignals(true);
|
||||
|
||||
d.readS32(1, &tmp, 0);
|
||||
m_channelMarker.setCenterFrequency(tmp);
|
||||
d.readS32(2, &tmp, 30);
|
||||
ui->BW->setValue(tmp);
|
||||
d.readS32(3, &tmp, 30);
|
||||
ui->volume->setValue(tmp);
|
||||
d.readBlob(4, &bytetmp);
|
||||
ui->spectrumGUI->deserialize(bytetmp);
|
||||
if(d.readU32(5, &u32tmp))
|
||||
m_channelMarker.setColor(u32tmp);
|
||||
d.readS32(6, &tmp, 3);
|
||||
ui->lowCut->setValue(tmp);
|
||||
d.readS32(7, &tmp, 20);
|
||||
ui->spanLog2->setValue(tmp);
|
||||
setNewRate(tmp);
|
||||
d.readBool(8, &m_audioBinaural);
|
||||
ui->audioBinaural->setChecked(m_audioBinaural);
|
||||
d.readBool(9, &m_audioFlipChannels);
|
||||
ui->audioFlipChannels->setChecked(m_audioFlipChannels);
|
||||
d.readBool(10, &m_dsb);
|
||||
ui->dsb->setChecked(m_dsb);
|
||||
d.readBool(11, &booltmp, false);
|
||||
ui->agc->setChecked(booltmp);
|
||||
d.readS32(12, &tmp, 7);
|
||||
ui->agcTimeLog2->setValue(tmp);
|
||||
d.readS32(13, &tmp, -40);
|
||||
ui->agcPowerThreshold->setValue(tmp);
|
||||
d.readS32(14, &tmp, 4);
|
||||
ui->agcThresholdGate->setValue(tmp);
|
||||
d.readBool(15, &booltmp, false);
|
||||
ui->agcClamping->setChecked(booltmp);
|
||||
|
||||
if(m_settings.deserialize(data))
|
||||
{
|
||||
updateChannelMarker();
|
||||
displaySettings();
|
||||
|
||||
blockApplySettings(false);
|
||||
m_channelMarker.blockSignals(false);
|
||||
|
||||
applySettings();
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
resetToDefaults();
|
||||
applySettings();
|
||||
return false;
|
||||
}
|
||||
applySettings(true); // will have true
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_settings.resetToDefaults();
|
||||
displaySettings();
|
||||
applySettings(true); // will have true
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool SSBDemodGUI::handleMessage(const Message& message __attribute__((unused)))
|
||||
@ -172,18 +92,21 @@ void SSBDemodGUI::viewChanged()
|
||||
void SSBDemodGUI::on_audioBinaural_toggled(bool binaural)
|
||||
{
|
||||
m_audioBinaural = binaural;
|
||||
m_settings.m_audioBinaural = binaural;
|
||||
applySettings();
|
||||
}
|
||||
|
||||
void SSBDemodGUI::on_audioFlipChannels_toggled(bool flip)
|
||||
{
|
||||
m_audioFlipChannels = flip;
|
||||
m_settings.m_audioFlipChannels = flip;
|
||||
applySettings();
|
||||
}
|
||||
|
||||
void SSBDemodGUI::on_dsb_toggled(bool dsb)
|
||||
{
|
||||
m_dsb = dsb;
|
||||
m_settings.m_dsb = dsb;
|
||||
|
||||
if (m_dsb)
|
||||
{
|
||||
@ -220,6 +143,8 @@ void SSBDemodGUI::on_dsb_toggled(bool dsb)
|
||||
void SSBDemodGUI::on_deltaFrequency_changed(qint64 value)
|
||||
{
|
||||
m_channelMarker.setCenterFrequency(value);
|
||||
m_settings.m_inputFrequencyOffset = m_channelMarker.getCenterFrequency();
|
||||
applySettings();
|
||||
}
|
||||
|
||||
void SSBDemodGUI::on_BW_valueChanged(int value)
|
||||
@ -236,6 +161,7 @@ void SSBDemodGUI::on_BW_valueChanged(int value)
|
||||
ui->BWText->setText(tr("%1k").arg(s));
|
||||
}
|
||||
|
||||
m_settings.m_rfBandwidth = value * 100;
|
||||
on_lowCut_valueChanged(m_channelMarker.getLowCutoff()/100);
|
||||
setNewRate(m_spanLog2);
|
||||
}
|
||||
@ -279,22 +205,26 @@ void SSBDemodGUI::on_lowCut_valueChanged(int value)
|
||||
QString s = QString::number(lowCutoff/1000.0, 'f', 1);
|
||||
ui->lowCutText->setText(tr("%1k").arg(s));
|
||||
ui->lowCut->setValue(lowCutoff/100);
|
||||
m_settings.m_lowCutoff = lowCutoff;
|
||||
applySettings();
|
||||
}
|
||||
|
||||
void SSBDemodGUI::on_volume_valueChanged(int value)
|
||||
{
|
||||
ui->volumeText->setText(QString("%1").arg(value / 10.0, 0, 'f', 1));
|
||||
m_settings.m_volume = value / 10.0;
|
||||
applySettings();
|
||||
}
|
||||
|
||||
void SSBDemodGUI::on_agc_toggled(bool checked __attribute((__unused__)))
|
||||
void SSBDemodGUI::on_agc_toggled(bool checked)
|
||||
{
|
||||
m_settings.m_agc = checked;
|
||||
applySettings();
|
||||
}
|
||||
|
||||
void SSBDemodGUI::on_agcClamping_toggled(bool checked __attribute((__unused__)))
|
||||
void SSBDemodGUI::on_agcClamping_toggled(bool checked)
|
||||
{
|
||||
m_settings.m_agcClamping = checked;
|
||||
applySettings();
|
||||
}
|
||||
|
||||
@ -302,12 +232,14 @@ void SSBDemodGUI::on_agcTimeLog2_valueChanged(int value)
|
||||
{
|
||||
QString s = QString::number((1<<value), 'f', 0);
|
||||
ui->agcTimeText->setText(s);
|
||||
m_settings.m_agcTimeLog2 = value;
|
||||
applySettings();
|
||||
}
|
||||
|
||||
void SSBDemodGUI::on_agcPowerThreshold_valueChanged(int value)
|
||||
{
|
||||
displayAGCPowerThreshold(value);
|
||||
m_settings.m_agcPowerThreshold = value;
|
||||
applySettings();
|
||||
}
|
||||
|
||||
@ -315,12 +247,14 @@ void SSBDemodGUI::on_agcThresholdGate_valueChanged(int value)
|
||||
{
|
||||
QString s = QString::number(value, 'f', 0);
|
||||
ui->agcThresholdGateText->setText(s);
|
||||
m_settings.m_agcThresholdGate = value;
|
||||
applySettings();
|
||||
}
|
||||
|
||||
void SSBDemodGUI::on_audioMute_toggled(bool checked)
|
||||
{
|
||||
m_audioMute = checked;
|
||||
m_settings.m_audioMute = checked;
|
||||
applySettings();
|
||||
}
|
||||
|
||||
@ -328,6 +262,7 @@ void SSBDemodGUI::on_spanLog2_valueChanged(int value)
|
||||
{
|
||||
if (setNewRate(value))
|
||||
{
|
||||
m_settings.m_spanLog2 = value;
|
||||
applySettings();
|
||||
}
|
||||
|
||||
@ -373,10 +308,9 @@ SSBDemodGUI::SSBDemodGUI(PluginAPI* pluginAPI, DeviceSourceAPI *deviceAPI, QWidg
|
||||
connect(this, SIGNAL(menuDoubleClickEvent()), this, SLOT(onMenuDoubleClicked()));
|
||||
|
||||
m_spectrumVis = new SpectrumVis(ui->glSpectrum);
|
||||
m_ssbDemod = new SSBDemod(m_spectrumVis);
|
||||
m_channelizer = new DownChannelizer(m_ssbDemod);
|
||||
m_threadedChannelizer = new ThreadedBasebandSampleSink(m_channelizer, this);
|
||||
m_deviceAPI->addThreadedSink(m_threadedChannelizer);
|
||||
m_ssbDemod = new SSBDemod(m_deviceAPI);
|
||||
m_ssbDemod->setMessageQueueToGUI(getInputMessageQueue());
|
||||
m_ssbDemod->setSampleSink(m_spectrumVis);
|
||||
|
||||
ui->deltaFrequencyLabel->setText(QString("%1f").arg(QChar(0x94, 0x03)));
|
||||
ui->deltaFrequency->setColorMapper(ColorMapper(ColorMapper::GrayGold));
|
||||
@ -389,13 +323,11 @@ SSBDemodGUI::SSBDemodGUI(PluginAPI* pluginAPI, DeviceSourceAPI *deviceAPI, QWidg
|
||||
|
||||
connect(&m_pluginAPI->getMainWindow()->getMasterTimer(), SIGNAL(timeout()), this, SLOT(tick()));
|
||||
|
||||
//m_channelMarker = new ChannelMarker(this);
|
||||
m_channelMarker.setColor(Qt::green);
|
||||
m_channelMarker.setBandwidth(m_rate);
|
||||
m_channelMarker.setSidebands(ChannelMarker::usb);
|
||||
m_channelMarker.setCenterFrequency(0);
|
||||
m_channelMarker.setVisible(true);
|
||||
|
||||
m_settings.setChannelMarker(&m_channelMarker);
|
||||
m_settings.setSpectrumGUI(ui->spectrumGUI);
|
||||
|
||||
connect(&m_channelMarker, SIGNAL(changed()), this, SLOT(viewChanged()));
|
||||
|
||||
m_deviceAPI->registerChannelInstance(m_channelID, this);
|
||||
@ -404,21 +336,16 @@ SSBDemodGUI::SSBDemodGUI(PluginAPI* pluginAPI, DeviceSourceAPI *deviceAPI, QWidg
|
||||
|
||||
ui->spectrumGUI->setBuddies(m_spectrumVis->getInputMessageQueue(), m_spectrumVis, ui->glSpectrum);
|
||||
|
||||
resetToDefaults();
|
||||
displaySettings();
|
||||
applySettings();
|
||||
applySettings(true);
|
||||
setNewRate(m_spanLog2);
|
||||
}
|
||||
|
||||
SSBDemodGUI::~SSBDemodGUI()
|
||||
{
|
||||
m_deviceAPI->removeChannelInstance(this);
|
||||
m_deviceAPI->removeThreadedSink(m_threadedChannelizer);
|
||||
delete m_threadedChannelizer;
|
||||
delete m_channelizer;
|
||||
delete m_ssbDemod;
|
||||
delete m_spectrumVis;
|
||||
//delete m_channelMarker;
|
||||
delete ui;
|
||||
}
|
||||
|
||||
@ -454,7 +381,6 @@ bool SSBDemodGUI::setNewRate(int spanLog2)
|
||||
m_channelMarker.setLowCutoff(m_rate);
|
||||
}
|
||||
|
||||
|
||||
QString s = QString::number(m_rate/1000.0, 'f', 1);
|
||||
|
||||
if (m_dsb)
|
||||
@ -504,41 +430,101 @@ void SSBDemodGUI::blockApplySettings(bool block)
|
||||
m_doApplySettings = !block;
|
||||
}
|
||||
|
||||
void SSBDemodGUI::applySettings()
|
||||
void SSBDemodGUI::applySettings(bool force)
|
||||
{
|
||||
if (m_doApplySettings)
|
||||
{
|
||||
setTitleColor(m_channelMarker.getColor());
|
||||
ui->deltaFrequency->setValue(m_channelMarker.getCenterFrequency());
|
||||
|
||||
m_channelizer->configure(m_channelizer->getInputMessageQueue(),
|
||||
48000,
|
||||
m_channelMarker.getCenterFrequency());
|
||||
SSBDemod::MsgConfigureChannelizer* channelConfigMsg = SSBDemod::MsgConfigureChannelizer::create(
|
||||
48000, m_channelMarker.getCenterFrequency());
|
||||
m_ssbDemod->getInputMessageQueue()->push(channelConfigMsg);
|
||||
|
||||
m_ssbDemod->configure(m_ssbDemod->getInputMessageQueue(),
|
||||
ui->BW->value() * 100.0,
|
||||
ui->lowCut->value() * 100.0,
|
||||
ui->volume->value() / 10.0,
|
||||
m_spanLog2,
|
||||
m_audioBinaural,
|
||||
m_audioFlipChannels,
|
||||
m_dsb,
|
||||
ui->audioMute->isChecked(),
|
||||
ui->agc->isChecked(),
|
||||
ui->agcClamping->isChecked(),
|
||||
ui->agcTimeLog2->value(),
|
||||
ui->agcPowerThreshold->value(),
|
||||
ui->agcThresholdGate->value());
|
||||
SSBDemod::MsgConfigureSSBDemod* message = SSBDemod::MsgConfigureSSBDemod::create( m_settings, force);
|
||||
m_ssbDemod->getInputMessageQueue()->push(message);
|
||||
}
|
||||
}
|
||||
|
||||
void SSBDemodGUI::displaySettings()
|
||||
{
|
||||
QString s = QString::number((1<<ui->agcTimeLog2->value()), 'f', 0);
|
||||
m_channelMarker.blockSignals(true);
|
||||
m_channelMarker.setCenterFrequency(m_settings.m_inputFrequencyOffset);
|
||||
m_channelMarker.setBandwidth(m_settings.m_rfBandwidth * 2);
|
||||
m_channelMarker.setLowCutoff(m_settings.m_lowCutoff);
|
||||
m_channelMarker.setUDPAddress(m_settings.m_udpAddress);
|
||||
m_channelMarker.setUDPSendPort(m_settings.m_udpPort);
|
||||
m_channelMarker.setColor(m_settings.m_rgbColor);
|
||||
setTitleColor(m_settings.m_rgbColor);
|
||||
|
||||
if (m_settings.m_dsb) {
|
||||
m_channelMarker.setSidebands(ChannelMarker::dsb);
|
||||
} else {
|
||||
if (m_settings.m_rfBandwidth < 0) {
|
||||
m_channelMarker.setSidebands(ChannelMarker::lsb);
|
||||
} else {
|
||||
m_channelMarker.setSidebands(ChannelMarker::usb);
|
||||
}
|
||||
}
|
||||
|
||||
m_channelMarker.blockSignals(false);
|
||||
|
||||
blockApplySettings(true);
|
||||
|
||||
ui->agc->setChecked(m_settings.m_agc);
|
||||
ui->agcClamping->setChecked(m_settings.m_agcClamping);
|
||||
ui->audioBinaural->setChecked(m_settings.m_audioBinaural);
|
||||
ui->audioFlipChannels->setChecked(m_settings.m_audioFlipChannels);
|
||||
ui->audioMute->setChecked(m_settings.m_audioMute);
|
||||
ui->deltaFrequency->setValue(m_channelMarker.getCenterFrequency());
|
||||
ui->dsb->setChecked(m_settings.m_dsb);
|
||||
ui->spanLog2->setValue(m_settings.m_spanLog2);
|
||||
|
||||
ui->BW->setValue(m_settings.m_rfBandwidth / 100.0);
|
||||
QString s = QString::number(m_settings.m_rfBandwidth/1000.0, 'f', 1);
|
||||
|
||||
if (m_settings.m_dsb)
|
||||
{
|
||||
ui->BWText->setText(tr("%1%2k").arg(QChar(0xB1, 0x00)).arg(s));
|
||||
}
|
||||
else
|
||||
{
|
||||
ui->BWText->setText(tr("%1k").arg(s));
|
||||
}
|
||||
|
||||
ui->lowCut->setValue(m_settings.m_lowCutoff / 100.0);
|
||||
ui->lowCutText->setText(tr("%1k").arg(m_settings.m_lowCutoff / 1000.0));
|
||||
|
||||
ui->volume->setValue(m_settings.m_volume * 10.0);
|
||||
ui->volumeText->setText(QString("%1").arg(m_settings.m_volume, 0, 'f', 1));
|
||||
|
||||
ui->agcTimeLog2->setValue(m_settings.m_agcTimeLog2);
|
||||
s = QString::number((1<<ui->agcTimeLog2->value()), 'f', 0);
|
||||
ui->agcTimeText->setText(s);
|
||||
|
||||
ui->agcPowerThreshold->setValue(m_settings.m_agcPowerThreshold);
|
||||
displayAGCPowerThreshold(ui->agcPowerThreshold->value());
|
||||
|
||||
ui->agcThresholdGate->setValue(m_settings.m_agcThresholdGate);
|
||||
s = QString::number(ui->agcThresholdGate->value(), 'f', 0);
|
||||
ui->agcThresholdGateText->setText(s);
|
||||
|
||||
blockApplySettings(false);
|
||||
}
|
||||
|
||||
void SSBDemodGUI::displayUDPAddress()
|
||||
{
|
||||
//TODO: ui->copyAudioToUDP->setToolTip(QString("Copy audio output to UDP %1:%2").arg(m_channelMarker.getUDPAddress()).arg(m_channelMarker.getUDPSendPort()));
|
||||
}
|
||||
|
||||
void SSBDemodGUI::updateChannelMarker()
|
||||
{
|
||||
m_channelMarker.blockSignals(true);
|
||||
|
||||
//m_channelMarker.deserialize(m_settings.m_channelMarkerBytes);
|
||||
this->setWindowTitle(m_channelMarker.getTitle());
|
||||
|
||||
m_channelMarker.blockSignals(false);
|
||||
}
|
||||
|
||||
void SSBDemodGUI::displayAGCPowerThreshold(int value)
|
||||
|
@ -1,18 +1,17 @@
|
||||
#ifndef INCLUDE_SSBDEMODGUI_H
|
||||
#define INCLUDE_SSBDEMODGUI_H
|
||||
|
||||
#include <plugin/plugininstancegui.h>
|
||||
#include "gui/rollupwidget.h"
|
||||
#include "dsp/channelmarker.h"
|
||||
#include "dsp/movingaverage.h"
|
||||
#include "plugin/plugininstanceui.h"
|
||||
#include "util/messagequeue.h"
|
||||
#include "ssbdemodsettings.h"
|
||||
|
||||
class PluginAPI;
|
||||
class DeviceSourceAPI;
|
||||
|
||||
class AudioFifo;
|
||||
class ThreadedBasebandSampleSink;
|
||||
class DownChannelizer;
|
||||
class SSBDemod;
|
||||
class SpectrumVis;
|
||||
|
||||
@ -20,7 +19,7 @@ namespace Ui {
|
||||
class SSBDemodGUI;
|
||||
}
|
||||
|
||||
class SSBDemodGUI : public RollupWidget, public PluginInstanceUI {
|
||||
class SSBDemodGUI : public RollupWidget, public PluginInstanceGUI {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
@ -65,6 +64,7 @@ private:
|
||||
PluginAPI* m_pluginAPI;
|
||||
DeviceSourceAPI* m_deviceAPI;
|
||||
ChannelMarker m_channelMarker;
|
||||
SSBDemodSettings m_settings;
|
||||
bool m_basicSettingsShown;
|
||||
bool m_doApplySettings;
|
||||
int m_rate;
|
||||
@ -76,8 +76,6 @@ private:
|
||||
bool m_squelchOpen;
|
||||
uint32_t m_tickCount;
|
||||
|
||||
ThreadedBasebandSampleSink* m_threadedChannelizer;
|
||||
DownChannelizer* m_channelizer;
|
||||
SSBDemod* m_ssbDemod;
|
||||
SpectrumVis* m_spectrumVis;
|
||||
MessageQueue m_inputMessageQueue;
|
||||
@ -89,8 +87,10 @@ private:
|
||||
bool setNewRate(int spanLog2);
|
||||
|
||||
void blockApplySettings(bool block);
|
||||
void applySettings();
|
||||
void applySettings(bool force = false);
|
||||
void displaySettings();
|
||||
void displayUDPAddress();
|
||||
void updateChannelMarker();
|
||||
|
||||
void displayAGCPowerThreshold(int value);
|
||||
|
||||
|
124
plugins/channelrx/demodssb/ssbdemodsettings.cpp
Normal file
@ -0,0 +1,124 @@
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// 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 "ssbdemodsettings.h"
|
||||
|
||||
SSBDemodSettings::SSBDemodSettings() :
|
||||
m_channelMarker(0),
|
||||
m_spectrumGUI(0)
|
||||
{
|
||||
resetToDefaults();
|
||||
}
|
||||
|
||||
void SSBDemodSettings::resetToDefaults()
|
||||
{
|
||||
m_audioBinaural = false;
|
||||
m_audioFlipChannels = false;
|
||||
m_dsb = false;
|
||||
m_audioMute = false;
|
||||
m_agc = false;
|
||||
m_agcClamping = false;
|
||||
m_agcPowerThreshold = -40;
|
||||
m_agcThresholdGate = 4;
|
||||
m_agcTimeLog2 = 7;
|
||||
m_rfBandwidth = 3000;
|
||||
m_lowCutoff = 300;
|
||||
m_volume = 3.0;
|
||||
m_spanLog2 = 3;
|
||||
m_inputSampleRate = 96000;
|
||||
m_inputFrequencyOffset = 0;
|
||||
m_audioSampleRate = DSPEngine::instance()->getAudioSampleRate();
|
||||
m_rgbColor = QColor(0, 255, 0).rgb();
|
||||
}
|
||||
|
||||
QByteArray SSBDemodSettings::serialize() const
|
||||
{
|
||||
SimpleSerializer s(1);
|
||||
s.writeS32(1, m_inputFrequencyOffset);
|
||||
s.writeS32(2, m_rfBandwidth / 100.0);
|
||||
s.writeS32(3, m_volume * 10.0);
|
||||
|
||||
if (m_spectrumGUI) {
|
||||
s.writeBlob(4, m_spectrumGUI->serialize());
|
||||
}
|
||||
|
||||
s.writeU32(5, m_rgbColor);
|
||||
s.writeS32(6, m_lowCutoff / 100.0);
|
||||
s.writeS32(7, m_spanLog2);
|
||||
s.writeBool(8, m_audioBinaural);
|
||||
s.writeBool(9, m_audioFlipChannels);
|
||||
s.writeBool(10, m_dsb);
|
||||
s.writeBool(11, m_agc);
|
||||
s.writeS32(12, m_agcTimeLog2);
|
||||
s.writeS32(13, m_agcPowerThreshold);
|
||||
s.writeS32(14, m_agcThresholdGate);
|
||||
s.writeBool(15, m_agcClamping);
|
||||
return s.final();
|
||||
}
|
||||
|
||||
bool SSBDemodSettings::deserialize(const QByteArray& data)
|
||||
{
|
||||
SimpleDeserializer d(data);
|
||||
|
||||
if(!d.isValid())
|
||||
{
|
||||
resetToDefaults();
|
||||
return false;
|
||||
}
|
||||
|
||||
if(d.getVersion() == 1)
|
||||
{
|
||||
QByteArray bytetmp;
|
||||
qint32 tmp;
|
||||
QString strtmp;
|
||||
|
||||
d.readS32(1, &m_inputFrequencyOffset, 0);
|
||||
d.readS32(2, &tmp, 30);
|
||||
m_rfBandwidth = tmp * 100.0;
|
||||
d.readS32(3, &tmp, 30);
|
||||
m_volume = tmp / 10.0;
|
||||
|
||||
if (m_spectrumGUI) {
|
||||
d.readBlob(4, &bytetmp);
|
||||
m_spectrumGUI->deserialize(bytetmp);
|
||||
}
|
||||
|
||||
d.readU32(5, &m_rgbColor);
|
||||
d.readS32(6, &tmp, 30);
|
||||
m_lowCutoff = tmp * 100.0;
|
||||
d.readS32(7, &m_spanLog2, 3);
|
||||
d.readBool(8, &m_audioBinaural, false);
|
||||
d.readBool(9, &m_audioFlipChannels, false);
|
||||
d.readBool(10, &m_dsb, false);
|
||||
d.readBool(11, &m_agc, false);
|
||||
d.readS32(12, &m_agcTimeLog2, 7);
|
||||
d.readS32(13, &m_agcPowerThreshold, -40);
|
||||
d.readS32(14, &m_agcThresholdGate, 4);
|
||||
d.readBool(15, &m_agcClamping, false);
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
resetToDefaults();
|
||||
return false;
|
||||
}
|
||||
}
|
58
plugins/channelrx/demodssb/ssbdemodsettings.h
Normal file
@ -0,0 +1,58 @@
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// 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_DEMODSSB_SSBDEMODSETTINGS_H_
|
||||
#define PLUGINS_CHANNELRX_DEMODSSB_SSBDEMODSETTINGS_H_
|
||||
|
||||
#include <QByteArray>
|
||||
|
||||
class Serializable;
|
||||
|
||||
struct SSBDemodSettings
|
||||
{
|
||||
int m_inputSampleRate;
|
||||
qint32 m_inputFrequencyOffset;
|
||||
quint32 m_audioSampleRate;
|
||||
Real m_rfBandwidth;
|
||||
Real m_lowCutoff;
|
||||
Real m_volume;
|
||||
int m_spanLog2;
|
||||
bool m_audioBinaural;
|
||||
bool m_audioFlipChannels;
|
||||
bool m_dsb;
|
||||
bool m_audioMute;
|
||||
bool m_agc;
|
||||
bool m_agcClamping;
|
||||
int m_agcTimeLog2;
|
||||
int m_agcPowerThreshold;
|
||||
int m_agcThresholdGate;
|
||||
QString m_udpAddress;
|
||||
quint16 m_udpPort;
|
||||
quint32 m_rgbColor;
|
||||
|
||||
Serializable *m_channelMarker;
|
||||
Serializable *m_spectrumGUI;
|
||||
|
||||
SSBDemodSettings();
|
||||
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_DEMODSSB_SSBDEMODSETTINGS_H_ */
|
@ -7,7 +7,7 @@
|
||||
|
||||
const PluginDescriptor SSBPlugin::m_pluginDescriptor = {
|
||||
QString("SSB Demodulator"),
|
||||
QString("3.5.4"),
|
||||
QString("3.7.3"),
|
||||
QString("(c) Edouard Griffiths, F4EXB"),
|
||||
QString("https://github.com/f4exb/sdrangel"),
|
||||
true,
|
||||
@ -33,7 +33,7 @@ void SSBPlugin::initPlugin(PluginAPI* pluginAPI)
|
||||
m_pluginAPI->registerRxChannel(SSBDemodGUI::m_channelID, this);
|
||||
}
|
||||
|
||||
PluginInstanceUI* SSBPlugin::createRxChannel(const QString& channelName, DeviceSourceAPI *deviceAPI)
|
||||
PluginInstanceGUI* SSBPlugin::createRxChannel(const QString& channelName, DeviceSourceAPI *deviceAPI)
|
||||
{
|
||||
if(channelName == SSBDemodGUI::m_channelID)
|
||||
{
|
||||
|
@ -17,7 +17,7 @@ public:
|
||||
const PluginDescriptor& getPluginDescriptor() const;
|
||||
void initPlugin(PluginAPI* pluginAPI);
|
||||
|
||||
PluginInstanceUI* createRxChannel(const QString& channelName, DeviceSourceAPI *deviceAPI);
|
||||
PluginInstanceGUI* createRxChannel(const QString& channelName, DeviceSourceAPI *deviceAPI);
|
||||
|
||||
private:
|
||||
static const PluginDescriptor m_pluginDescriptor;
|
||||
|
@ -1,10 +1,10 @@
|
||||
#ifndef INCLUDE_WFMDEMODGUI_H
|
||||
#define INCLUDE_WFMDEMODGUI_H
|
||||
|
||||
#include <plugin/plugininstancegui.h>
|
||||
#include "gui/rollupwidget.h"
|
||||
#include "dsp/channelmarker.h"
|
||||
#include "dsp/movingaverage.h"
|
||||
#include "plugin/plugininstanceui.h"
|
||||
#include "util/messagequeue.h"
|
||||
|
||||
class PluginAPI;
|
||||
@ -18,7 +18,7 @@ namespace Ui {
|
||||
class WFMDemodGUI;
|
||||
}
|
||||
|
||||
class WFMDemodGUI : public RollupWidget, public PluginInstanceUI {
|
||||
class WFMDemodGUI : public RollupWidget, public PluginInstanceGUI {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
@ -33,7 +33,7 @@ void WFMPlugin::initPlugin(PluginAPI* pluginAPI)
|
||||
m_pluginAPI->registerRxChannel(WFMDemodGUI::m_channelID, this);
|
||||
}
|
||||
|
||||
PluginInstanceUI* WFMPlugin::createRxChannel(const QString& channelName, DeviceSourceAPI *deviceAPI)
|
||||
PluginInstanceGUI* WFMPlugin::createRxChannel(const QString& channelName, DeviceSourceAPI *deviceAPI)
|
||||
{
|
||||
if(channelName == WFMDemodGUI::m_channelID)
|
||||
{
|
||||
|
@ -17,7 +17,7 @@ public:
|
||||
const PluginDescriptor& getPluginDescriptor() const;
|
||||
void initPlugin(PluginAPI* pluginAPI);
|
||||
|
||||
PluginInstanceUI* createRxChannel(const QString& channelName, DeviceSourceAPI *deviceAPI);
|
||||
PluginInstanceGUI* createRxChannel(const QString& channelName, DeviceSourceAPI *deviceAPI);
|
||||
|
||||
private:
|
||||
static const PluginDescriptor m_pluginDescriptor;
|
||||
|
@ -1,12 +1,12 @@
|
||||
#ifndef INCLUDE_TCPSRCGUI_H
|
||||
#define INCLUDE_TCPSRCGUI_H
|
||||
|
||||
#include <plugin/plugininstancegui.h>
|
||||
#include <QHostAddress>
|
||||
|
||||
#include "gui/rollupwidget.h"
|
||||
#include "dsp/channelmarker.h"
|
||||
#include "dsp/movingaverage.h"
|
||||
#include "plugin/plugininstanceui.h"
|
||||
#include "util/messagequeue.h"
|
||||
|
||||
#include "tcpsrc.h"
|
||||
@ -22,7 +22,7 @@ namespace Ui {
|
||||
class TCPSrcGUI;
|
||||
}
|
||||
|
||||
class TCPSrcGUI : public RollupWidget, public PluginInstanceUI {
|
||||
class TCPSrcGUI : public RollupWidget, public PluginInstanceGUI {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
@ -33,7 +33,7 @@ void TCPSrcPlugin::initPlugin(PluginAPI* pluginAPI)
|
||||
m_pluginAPI->registerRxChannel(TCPSrcGUI::m_channelID, this);
|
||||
}
|
||||
|
||||
PluginInstanceUI* TCPSrcPlugin::createRxChannel(const QString& channelName, DeviceSourceAPI *deviceAPI)
|
||||
PluginInstanceGUI* TCPSrcPlugin::createRxChannel(const QString& channelName, DeviceSourceAPI *deviceAPI)
|
||||
{
|
||||
if(channelName == TCPSrcGUI::m_channelID)
|
||||
{
|
||||
|
@ -17,7 +17,7 @@ public:
|
||||
const PluginDescriptor& getPluginDescriptor() const;
|
||||
void initPlugin(PluginAPI* pluginAPI);
|
||||
|
||||
PluginInstanceUI* createRxChannel(const QString& channelName, DeviceSourceAPI *deviceAPI);
|
||||
PluginInstanceGUI* createRxChannel(const QString& channelName, DeviceSourceAPI *deviceAPI);
|
||||
|
||||
private:
|
||||
static const PluginDescriptor m_pluginDescriptor;
|
||||
|
@ -476,7 +476,7 @@ void UDPSrc::apply(bool force)
|
||||
m_outMovingAverage.resize(m_config.m_outputSampleRate * 0.01, 1e-10); // 10 ms
|
||||
}
|
||||
|
||||
if ((m_config.m_audioActive != m_config.m_audioActive) || force)
|
||||
if ((m_config.m_audioActive != m_running.m_audioActive) || force)
|
||||
{
|
||||
if (m_config.m_audioActive)
|
||||
{
|
||||
|
@ -18,11 +18,11 @@
|
||||
#ifndef INCLUDE_UDPSRCGUI_H
|
||||
#define INCLUDE_UDPSRCGUI_H
|
||||
|
||||
#include <plugin/plugininstancegui.h>
|
||||
#include <QHostAddress>
|
||||
#include "gui/rollupwidget.h"
|
||||
#include "dsp/channelmarker.h"
|
||||
#include "dsp/movingaverage.h"
|
||||
#include "plugin/plugininstanceui.h"
|
||||
#include "util/messagequeue.h"
|
||||
|
||||
#include "udpsrc.h"
|
||||
@ -38,7 +38,7 @@ namespace Ui {
|
||||
class UDPSrcGUI;
|
||||
}
|
||||
|
||||
class UDPSrcGUI : public RollupWidget, public PluginInstanceUI {
|
||||
class UDPSrcGUI : public RollupWidget, public PluginInstanceGUI {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
@ -50,7 +50,7 @@ void UDPSrcPlugin::initPlugin(PluginAPI* pluginAPI)
|
||||
m_pluginAPI->registerRxChannel(UDPSrcGUI::m_channelID, this);
|
||||
}
|
||||
|
||||
PluginInstanceUI* UDPSrcPlugin::createRxChannel(const QString& channelName, DeviceSourceAPI *deviceAPI)
|
||||
PluginInstanceGUI* UDPSrcPlugin::createRxChannel(const QString& channelName, DeviceSourceAPI *deviceAPI)
|
||||
{
|
||||
if(channelName == UDPSrcGUI::m_channelID)
|
||||
{
|
||||
|
@ -34,7 +34,7 @@ public:
|
||||
const PluginDescriptor& getPluginDescriptor() const;
|
||||
void initPlugin(PluginAPI* pluginAPI);
|
||||
|
||||
PluginInstanceUI* createRxChannel(const QString& channelName, DeviceSourceAPI *deviceAPI);
|
||||
PluginInstanceGUI* createRxChannel(const QString& channelName, DeviceSourceAPI *deviceAPI);
|
||||
|
||||
private:
|
||||
static const PluginDescriptor m_pluginDescriptor;
|
||||
|
@ -338,7 +338,7 @@ bool AMMod::handleMessage(const Message& cmd)
|
||||
|
||||
MsgReportFileSourceStreamTiming *report;
|
||||
report = MsgReportFileSourceStreamTiming::create(samplesCount);
|
||||
getOutputMessageQueue()->push(report);
|
||||
getMessageQueueToGUI()->push(report);
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -415,7 +415,7 @@ void AMMod::openFileStream()
|
||||
|
||||
MsgReportFileSourceStreamData *report;
|
||||
report = MsgReportFileSourceStreamData::create(m_sampleRate, m_recordLength);
|
||||
getOutputMessageQueue()->push(report);
|
||||
getMessageQueueToGUI()->push(report);
|
||||
}
|
||||
|
||||
void AMMod::seekFileStream(int seekPercentage)
|
||||
|
@ -178,7 +178,7 @@ void AMModGUI::handleSourceMessages()
|
||||
{
|
||||
Message* message;
|
||||
|
||||
while ((message = m_amMod->getOutputMessageQueue()->pop()) != 0)
|
||||
while ((message = getInputMessageQueue()->pop()) != 0)
|
||||
{
|
||||
if (handleMessage(*message))
|
||||
{
|
||||
@ -339,6 +339,7 @@ AMModGUI::AMModGUI(PluginAPI* pluginAPI, DeviceSinkAPI *deviceAPI, QWidget* pare
|
||||
connect(this, SIGNAL(menuDoubleClickEvent()), this, SLOT(onMenuDoubleClicked()));
|
||||
|
||||
m_amMod = new AMMod();
|
||||
m_amMod->setMessageQueueToGUI(getInputMessageQueue());
|
||||
m_channelizer = new UpChannelizer(m_amMod);
|
||||
m_threadedChannelizer = new ThreadedBasebandSampleSource(m_channelizer, this);
|
||||
//m_pluginAPI->addThreadedSink(m_threadedChannelizer);
|
||||
@ -372,7 +373,7 @@ AMModGUI::AMModGUI(PluginAPI* pluginAPI, DeviceSinkAPI *deviceAPI, QWidget* pare
|
||||
|
||||
applySettings();
|
||||
|
||||
connect(m_amMod->getOutputMessageQueue(), SIGNAL(messageEnqueued()), this, SLOT(handleSourceMessages()));
|
||||
connect(getInputMessageQueue(), SIGNAL(messageEnqueued()), this, SLOT(handleSourceMessages()));
|
||||
connect(m_amMod, SIGNAL(levelChanged(qreal, qreal, int)), ui->volumeMeter, SLOT(levelChanged(qreal, qreal, int)));
|
||||
}
|
||||
|
||||
|
@ -17,10 +17,10 @@
|
||||
#ifndef PLUGINS_CHANNELTX_MODAM_AMMODGUI_H_
|
||||
#define PLUGINS_CHANNELTX_MODAM_AMMODGUI_H_
|
||||
|
||||
#include <plugin/plugininstancegui.h>
|
||||
#include "gui/rollupwidget.h"
|
||||
#include "dsp/channelmarker.h"
|
||||
#include "dsp/movingaverage.h"
|
||||
#include "plugin/plugininstanceui.h"
|
||||
#include "util/messagequeue.h"
|
||||
|
||||
#include "ammod.h"
|
||||
@ -36,7 +36,7 @@ namespace Ui {
|
||||
class AMModGUI;
|
||||
}
|
||||
|
||||
class AMModGUI : public RollupWidget, public PluginInstanceUI {
|
||||
class AMModGUI : public RollupWidget, public PluginInstanceGUI {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
@ -49,7 +49,7 @@ void AMModPlugin::initPlugin(PluginAPI* pluginAPI)
|
||||
m_pluginAPI->registerTxChannel(AMModGUI::m_channelID, this);
|
||||
}
|
||||
|
||||
PluginInstanceUI* AMModPlugin::createTxChannel(const QString& channelName, DeviceSinkAPI *deviceAPI)
|
||||
PluginInstanceGUI* AMModPlugin::createTxChannel(const QString& channelName, DeviceSinkAPI *deviceAPI)
|
||||
{
|
||||
if(channelName == AMModGUI::m_channelID)
|
||||
{
|
||||
|
@ -33,7 +33,7 @@ public:
|
||||
const PluginDescriptor& getPluginDescriptor() const;
|
||||
void initPlugin(PluginAPI* pluginAPI);
|
||||
|
||||
PluginInstanceUI* createTxChannel(const QString& channelName, DeviceSinkAPI *deviceAPI);
|
||||
PluginInstanceGUI* createTxChannel(const QString& channelName, DeviceSinkAPI *deviceAPI);
|
||||
|
||||
private:
|
||||
static const PluginDescriptor m_pluginDescriptor;
|
||||
|
@ -385,16 +385,20 @@ void ATVMod::pullVideo(Real& sample)
|
||||
time_t start, end;
|
||||
cv::Mat frame;
|
||||
|
||||
MsgReportCameraData *report;
|
||||
report = MsgReportCameraData::create(
|
||||
camera.m_cameraNumber,
|
||||
0.0f,
|
||||
camera.m_videoFPSManual,
|
||||
camera.m_videoFPSManualEnable,
|
||||
camera.m_videoWidth,
|
||||
camera.m_videoHeight,
|
||||
1); // open splash screen on GUI side
|
||||
getOutputMessageQueue()->push(report);
|
||||
if (getMessageQueueToGUI())
|
||||
{
|
||||
MsgReportCameraData *report;
|
||||
report = MsgReportCameraData::create(
|
||||
camera.m_cameraNumber,
|
||||
0.0f,
|
||||
camera.m_videoFPSManual,
|
||||
camera.m_videoFPSManualEnable,
|
||||
camera.m_videoWidth,
|
||||
camera.m_videoHeight,
|
||||
1); // open splash screen on GUI side
|
||||
getMessageQueueToGUI()->push(report);
|
||||
}
|
||||
|
||||
int nbFrames = 0;
|
||||
|
||||
time(&start);
|
||||
@ -414,15 +418,19 @@ void ATVMod::pullVideo(Real& sample)
|
||||
camera.m_videoFPSCount = camera.m_videoFPSq;
|
||||
camera.m_videoPrevFPSCount = 0;
|
||||
|
||||
report = MsgReportCameraData::create(
|
||||
camera.m_cameraNumber,
|
||||
camera.m_videoFPS,
|
||||
camera.m_videoFPSManual,
|
||||
camera.m_videoFPSManualEnable,
|
||||
camera.m_videoWidth,
|
||||
camera.m_videoHeight,
|
||||
2); // close splash screen on GUI side
|
||||
getOutputMessageQueue()->push(report);
|
||||
if (getMessageQueueToGUI())
|
||||
{
|
||||
MsgReportCameraData *report;
|
||||
report = MsgReportCameraData::create(
|
||||
camera.m_cameraNumber,
|
||||
camera.m_videoFPS,
|
||||
camera.m_videoFPSManual,
|
||||
camera.m_videoFPSManualEnable,
|
||||
camera.m_videoWidth,
|
||||
camera.m_videoHeight,
|
||||
2); // close splash screen on GUI side
|
||||
getMessageQueueToGUI()->push(report);
|
||||
}
|
||||
}
|
||||
else if (camera.m_videoFPS == 0.0f) // Hideous hack for windows
|
||||
{
|
||||
@ -431,16 +439,19 @@ void ATVMod::pullVideo(Real& sample)
|
||||
camera.m_videoFPSCount = camera.m_videoFPSq;
|
||||
camera.m_videoPrevFPSCount = 0;
|
||||
|
||||
MsgReportCameraData *report;
|
||||
report = MsgReportCameraData::create(
|
||||
camera.m_cameraNumber,
|
||||
camera.m_videoFPS,
|
||||
camera.m_videoFPSManual,
|
||||
camera.m_videoFPSManualEnable,
|
||||
camera.m_videoWidth,
|
||||
camera.m_videoHeight,
|
||||
0);
|
||||
getOutputMessageQueue()->push(report);
|
||||
if (getMessageQueueToGUI())
|
||||
{
|
||||
MsgReportCameraData *report;
|
||||
report = MsgReportCameraData::create(
|
||||
camera.m_cameraNumber,
|
||||
camera.m_videoFPS,
|
||||
camera.m_videoFPSManual,
|
||||
camera.m_videoFPSManualEnable,
|
||||
camera.m_videoWidth,
|
||||
camera.m_videoHeight,
|
||||
0);
|
||||
getMessageQueueToGUI()->push(report);
|
||||
}
|
||||
}
|
||||
|
||||
int fpsIncrement = (int) camera.m_videoFPSCount - camera.m_videoPrevFPSCount;
|
||||
@ -601,9 +612,12 @@ bool ATVMod::handleMessage(const Message& cmd)
|
||||
framesCount = 0;
|
||||
}
|
||||
|
||||
MsgReportVideoFileSourceStreamTiming *report;
|
||||
report = MsgReportVideoFileSourceStreamTiming::create(framesCount);
|
||||
getOutputMessageQueue()->push(report);
|
||||
if (getMessageQueueToGUI())
|
||||
{
|
||||
MsgReportVideoFileSourceStreamTiming *report;
|
||||
report = MsgReportVideoFileSourceStreamTiming::create(framesCount);
|
||||
getMessageQueueToGUI()->push(report);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -615,16 +629,20 @@ bool ATVMod::handleMessage(const Message& cmd)
|
||||
if (index < m_cameras.size())
|
||||
{
|
||||
m_cameraIndex = index;
|
||||
MsgReportCameraData *report;
|
||||
report = MsgReportCameraData::create(
|
||||
m_cameras[m_cameraIndex].m_cameraNumber,
|
||||
m_cameras[m_cameraIndex].m_videoFPS,
|
||||
m_cameras[m_cameraIndex].m_videoFPSManual,
|
||||
m_cameras[m_cameraIndex].m_videoFPSManualEnable,
|
||||
m_cameras[m_cameraIndex].m_videoWidth,
|
||||
m_cameras[m_cameraIndex].m_videoHeight,
|
||||
0);
|
||||
getOutputMessageQueue()->push(report);
|
||||
|
||||
if (getMessageQueueToGUI())
|
||||
{
|
||||
MsgReportCameraData *report;
|
||||
report = MsgReportCameraData::create(
|
||||
m_cameras[m_cameraIndex].m_cameraNumber,
|
||||
m_cameras[m_cameraIndex].m_videoFPS,
|
||||
m_cameras[m_cameraIndex].m_videoFPSManual,
|
||||
m_cameras[m_cameraIndex].m_videoFPSManualEnable,
|
||||
m_cameras[m_cameraIndex].m_videoWidth,
|
||||
m_cameras[m_cameraIndex].m_videoHeight,
|
||||
0);
|
||||
getMessageQueueToGUI()->push(report);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -721,9 +739,12 @@ void ATVMod::apply(bool force)
|
||||
applyStandard(); // set all timings
|
||||
m_settingsMutex.unlock();
|
||||
|
||||
MsgReportEffectiveSampleRate *report;
|
||||
report = MsgReportEffectiveSampleRate::create(m_tvSampleRate, m_pointsPerLine);
|
||||
getOutputMessageQueue()->push(report);
|
||||
if (getMessageQueueToGUI())
|
||||
{
|
||||
MsgReportEffectiveSampleRate *report;
|
||||
report = MsgReportEffectiveSampleRate::create(m_tvSampleRate, m_pointsPerLine);
|
||||
getMessageQueueToGUI()->push(report);
|
||||
}
|
||||
}
|
||||
|
||||
if ((m_config.m_outputSampleRate != m_running.m_outputSampleRate)
|
||||
@ -977,9 +998,12 @@ void ATVMod::openVideo(const QString& fileName)
|
||||
calculateVideoSizes();
|
||||
m_videoEOF = false;
|
||||
|
||||
MsgReportVideoFileSourceStreamData *report;
|
||||
report = MsgReportVideoFileSourceStreamData::create(m_videoFPS, m_videoLength);
|
||||
getOutputMessageQueue()->push(report);
|
||||
if (getMessageQueueToGUI())
|
||||
{
|
||||
MsgReportVideoFileSourceStreamData *report;
|
||||
report = MsgReportVideoFileSourceStreamData::create(m_videoFPS, m_videoLength);
|
||||
getMessageQueueToGUI()->push(report);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1114,16 +1138,20 @@ void ATVMod::getCameraNumbers(std::vector<int>& numbers)
|
||||
if (m_cameras.size() > 0)
|
||||
{
|
||||
m_cameraIndex = 0;
|
||||
MsgReportCameraData *report;
|
||||
report = MsgReportCameraData::create(
|
||||
m_cameras[0].m_cameraNumber,
|
||||
m_cameras[0].m_videoFPS,
|
||||
m_cameras[0].m_videoFPSManual,
|
||||
m_cameras[0].m_videoFPSManualEnable,
|
||||
m_cameras[0].m_videoWidth,
|
||||
m_cameras[0].m_videoHeight,
|
||||
0);
|
||||
getOutputMessageQueue()->push(report);
|
||||
|
||||
if (getMessageQueueToGUI())
|
||||
{
|
||||
MsgReportCameraData *report;
|
||||
report = MsgReportCameraData::create(
|
||||
m_cameras[0].m_cameraNumber,
|
||||
m_cameras[0].m_videoFPS,
|
||||
m_cameras[0].m_videoFPSManual,
|
||||
m_cameras[0].m_videoFPSManualEnable,
|
||||
m_cameras[0].m_videoWidth,
|
||||
m_cameras[0].m_videoHeight,
|
||||
0);
|
||||
getMessageQueueToGUI()->push(report);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -363,7 +363,7 @@ void ATVModGUI::handleSourceMessages()
|
||||
{
|
||||
Message* message;
|
||||
|
||||
while ((message = m_atvMod->getOutputMessageQueue()->pop()) != 0)
|
||||
while ((message = getInputMessageQueue()->pop()) != 0)
|
||||
{
|
||||
if (handleMessage(*message))
|
||||
{
|
||||
@ -622,6 +622,7 @@ ATVModGUI::ATVModGUI(PluginAPI* pluginAPI, DeviceSinkAPI *deviceAPI, QWidget* pa
|
||||
connect(this, SIGNAL(menuDoubleClickEvent()), this, SLOT(onMenuDoubleClicked()));
|
||||
|
||||
m_atvMod = new ATVMod();
|
||||
m_atvMod->setMessageQueueToGUI(getInputMessageQueue());
|
||||
m_channelizer = new UpChannelizer(m_atvMod);
|
||||
m_threadedChannelizer = new ThreadedBasebandSampleSource(m_channelizer, this);
|
||||
//m_pluginAPI->addThreadedSink(m_threadedChannelizer);
|
||||
@ -648,7 +649,7 @@ ATVModGUI::ATVModGUI(PluginAPI* pluginAPI, DeviceSinkAPI *deviceAPI, QWidget* pa
|
||||
|
||||
resetToDefaults();
|
||||
|
||||
connect(m_atvMod->getOutputMessageQueue(), SIGNAL(messageEnqueued()), this, SLOT(handleSourceMessages()));
|
||||
connect(getInputMessageQueue(), SIGNAL(messageEnqueued()), this, SLOT(handleSourceMessages()));
|
||||
connect(m_atvMod, SIGNAL(levelChanged(qreal, qreal, int)), ui->volumeMeter, SLOT(levelChanged(qreal, qreal, int)));
|
||||
|
||||
std::vector<int> cameraNumbers;
|
||||
|
@ -17,10 +17,10 @@
|
||||
#ifndef PLUGINS_CHANNELTX_MODTV_ATVMODGUI_H_
|
||||
#define PLUGINS_CHANNELTX_MODTV_ATVMODGUI_H_
|
||||
|
||||
#include <plugin/plugininstancegui.h>
|
||||
#include "gui/rollupwidget.h"
|
||||
#include "dsp/channelmarker.h"
|
||||
#include "dsp/movingaverage.h"
|
||||
#include "plugin/plugininstanceui.h"
|
||||
#include "util/messagequeue.h"
|
||||
|
||||
#include "atvmod.h"
|
||||
@ -37,7 +37,7 @@ namespace Ui {
|
||||
class ATVModGUI;
|
||||
}
|
||||
|
||||
class ATVModGUI : public RollupWidget, public PluginInstanceUI {
|
||||
class ATVModGUI : public RollupWidget, public PluginInstanceGUI {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
@ -23,7 +23,7 @@
|
||||
|
||||
const PluginDescriptor ATVModPlugin::m_pluginDescriptor = {
|
||||
QString("ATV Modulator"),
|
||||
QString("3.5.0"),
|
||||
QString("3.7.3"),
|
||||
QString("(c) Edouard Griffiths, F4EXB"),
|
||||
QString("https://github.com/f4exb/sdrangel"),
|
||||
true,
|
||||
@ -49,7 +49,7 @@ void ATVModPlugin::initPlugin(PluginAPI* pluginAPI)
|
||||
m_pluginAPI->registerTxChannel(ATVModGUI::m_channelID, this);
|
||||
}
|
||||
|
||||
PluginInstanceUI* ATVModPlugin::createTxChannel(const QString& channelName, DeviceSinkAPI *deviceAPI)
|
||||
PluginInstanceGUI* ATVModPlugin::createTxChannel(const QString& channelName, DeviceSinkAPI *deviceAPI)
|
||||
{
|
||||
if(channelName == ATVModGUI::m_channelID)
|
||||
{
|
||||
|
@ -33,7 +33,7 @@ public:
|
||||
const PluginDescriptor& getPluginDescriptor() const;
|
||||
void initPlugin(PluginAPI* pluginAPI);
|
||||
|
||||
PluginInstanceUI* createTxChannel(const QString& channelName, DeviceSinkAPI *deviceAPI);
|
||||
PluginInstanceGUI* createTxChannel(const QString& channelName, DeviceSinkAPI *deviceAPI);
|
||||
|
||||
private:
|
||||
static const PluginDescriptor m_pluginDescriptor;
|
||||
|
@ -367,7 +367,7 @@ bool NFMMod::handleMessage(const Message& cmd)
|
||||
|
||||
MsgReportFileSourceStreamTiming *report;
|
||||
report = MsgReportFileSourceStreamTiming::create(samplesCount);
|
||||
getOutputMessageQueue()->push(report);
|
||||
getMessageQueueToGUI()->push(report);
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -462,7 +462,7 @@ void NFMMod::openFileStream()
|
||||
|
||||
MsgReportFileSourceStreamData *report;
|
||||
report = MsgReportFileSourceStreamData::create(m_sampleRate, m_recordLength);
|
||||
getOutputMessageQueue()->push(report);
|
||||
getMessageQueueToGUI()->push(report);
|
||||
}
|
||||
|
||||
void NFMMod::seekFileStream(int seekPercentage)
|
||||
|