Merge with v7
1
.github/workflows/sdrangel.yml
vendored
@ -6,6 +6,7 @@ on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
- v7
|
||||
tags:
|
||||
- 'v*'
|
||||
pull_request:
|
||||
|
@ -14,10 +14,10 @@ set(CMAKE_CXX_EXTENSIONS OFF)
|
||||
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||
|
||||
# configure version
|
||||
set(sdrangel_VERSION_MAJOR "6")
|
||||
set(sdrangel_VERSION_MINOR "20")
|
||||
set(sdrangel_VERSION_PATCH "3")
|
||||
set(sdrangel_VERSION_SUFFIX "")
|
||||
set(sdrangel_VERSION_MAJOR "7")
|
||||
set(sdrangel_VERSION_MINOR "0")
|
||||
set(sdrangel_VERSION_PATCH "0")
|
||||
set(sdrangel_VERSION_SUFFIX "alpha.4")
|
||||
|
||||
# SDRAngel cmake options
|
||||
option(DEBUG_OUTPUT "Print debug messages" OFF)
|
||||
|
10
app/main.cpp
@ -49,20 +49,20 @@ static int runQtApplication(int argc, char* argv[], qtwebapp::LoggerWithFile *lo
|
||||
qApp->setStyle(QStyleFactory::create("fusion"));
|
||||
|
||||
QPalette palette;
|
||||
palette.setColor(QPalette::Window, QColor(53,53,53));
|
||||
palette.setColor(QPalette::Window, QColor(64,64,64));
|
||||
palette.setColor(QPalette::WindowText, Qt::white);
|
||||
palette.setColor(QPalette::Base, QColor(25,25,25));
|
||||
palette.setColor(QPalette::AlternateBase, QColor(53,53,53));
|
||||
palette.setColor(QPalette::ToolTipBase, Qt::white);
|
||||
palette.setColor(QPalette::ToolTipText, Qt::black);
|
||||
palette.setColor(QPalette::Text, Qt::white);
|
||||
palette.setColor(QPalette::Button, QColor(0x40, 0x40, 0x40));
|
||||
palette.setColor(QPalette::Button, QColor(64,64,64));
|
||||
palette.setColor(QPalette::ButtonText, Qt::white);
|
||||
palette.setColor(QPalette::BrightText, Qt::red);
|
||||
|
||||
palette.setColor(QPalette::Light, QColor(53,53,53).lighter(125).lighter());
|
||||
palette.setColor(QPalette::Mid, QColor(53,53,53).lighter(125));
|
||||
palette.setColor(QPalette::Dark, QColor(53,53,53).lighter(125).darker());
|
||||
palette.setColor(QPalette::Light, QColor(64,64,64).lighter(125).lighter());
|
||||
palette.setColor(QPalette::Mid, QColor(64,64,64).lighter(125));
|
||||
palette.setColor(QPalette::Dark, QColor(64,64,64).lighter(125).darker());
|
||||
|
||||
palette.setColor(QPalette::Link, QColor(0,0xa0,0xa0));
|
||||
palette.setColor(QPalette::LinkVisited, QColor(0,0xa0,0xa0).lighter());
|
||||
|
@ -45,8 +45,8 @@ void DeviceUSRP::enumOriginDevices(const QString& hardwareId, PluginInterface::O
|
||||
for(unsigned i = 0; i != dev_addrs.size(); i++)
|
||||
{
|
||||
QString id = QString::fromStdString(dev_addrs[i].to_string());
|
||||
QString name = QString::fromStdString(dev_addrs[i].get("name"));
|
||||
QString serial = QString::fromStdString(dev_addrs[i].get("serial"));
|
||||
QString name = QString::fromStdString(dev_addrs[i].get("name", "N/A"));
|
||||
QString serial = QString::fromStdString(dev_addrs[i].get("serial", "N/A"));
|
||||
QString displayedName(QString("%1[%2:$1] %3").arg(name).arg(i).arg(serial));
|
||||
|
||||
qDebug() << "DeviceUSRP::enumOriginDevices: found USRP device " << displayedName;
|
||||
|
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 22 KiB |
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 9.9 KiB |
BIN
doc/img/ChannelWindow.png
Normal file
After Width: | Height: | Size: 31 KiB |
BIN
doc/img/ChannelWindow.xcf
Normal file
BIN
doc/img/ChannelWindow_bottom.png
Normal file
After Width: | Height: | Size: 5.1 KiB |
BIN
doc/img/ChannelWindow_bottom.xcf
Normal file
BIN
doc/img/ChannelWindow_top.png
Normal file
After Width: | Height: | Size: 9.0 KiB |
BIN
doc/img/ChannelWindow_top.xcf
Normal file
BIN
doc/img/Configurations.png
Normal file
After Width: | Height: | Size: 26 KiB |
BIN
doc/img/Configurations.xcf
Normal file
BIN
doc/img/DeviceWindow.png
Normal file
After Width: | Height: | Size: 30 KiB |
BIN
doc/img/DeviceWindow.xcf
Normal file
BIN
doc/img/DeviceWindow_bottom.png
Normal file
After Width: | Height: | Size: 3.0 KiB |
BIN
doc/img/DeviceWindow_bottom.xcf
Normal file
BIN
doc/img/DeviceWindow_top.png
Normal file
After Width: | Height: | Size: 11 KiB |
BIN
doc/img/DeviceWindow_top.xcf
Normal file
BIN
doc/img/FeatureWindow.png
Normal file
After Width: | Height: | Size: 30 KiB |
BIN
doc/img/FeatureWindow.xcf
Normal file
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 17 KiB |
BIN
doc/img/MainSpectrum.png
Normal file
After Width: | Height: | Size: 113 KiB |
BIN
doc/img/MainSpectrum.xcf
Normal file
BIN
doc/img/MainWindow.png
Normal file
After Width: | Height: | Size: 17 KiB |
Before Width: | Height: | Size: 7.0 KiB After Width: | Height: | Size: 6.7 KiB |
Before Width: | Height: | Size: 58 KiB After Width: | Height: | Size: 55 KiB |
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 5.8 KiB After Width: | Height: | Size: 5.1 KiB |
Before Width: | Height: | Size: 8.1 KiB After Width: | Height: | Size: 5.0 KiB |
BIN
doc/img/MainWindow_spectrum_gui_D.png
Normal file
After Width: | Height: | Size: 4.3 KiB |
BIN
doc/img/MainWindow_spectrum_gui_D.xcf
Normal file
BIN
doc/img/MainWindow_spectrum_gui_narrow.png
Normal file
After Width: | Height: | Size: 72 KiB |
BIN
doc/img/MainWindow_spectrum_gui_wide.png
Normal file
After Width: | Height: | Size: 131 KiB |
Before Width: | Height: | Size: 46 KiB After Width: | Height: | Size: 27 KiB |
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 10 KiB |
BIN
doc/img/Workspace_create_feature.png
Normal file
After Width: | Height: | Size: 7.6 KiB |
BIN
doc/img/Workspace_create_rx.png
Normal file
After Width: | Height: | Size: 11 KiB |
BIN
doc/img/Workspace_top.png
Normal file
After Width: | Height: | Size: 11 KiB |
BIN
doc/img/Workspace_top.xcf
Normal file
BIN
doc/img/Workspaces.png
Normal file
After Width: | Height: | Size: 53 KiB |
BIN
doc/img/Workspaces.xcf
Normal file
BIN
doc/img/channel.xcf
Normal file
BIN
doc/img/corner.xcf
Normal file
BIN
doc/img/cross.xcf
Normal file
BIN
doc/img/dock.xcf
Normal file
BIN
doc/img/exit.xcf
Normal file
BIN
doc/img/exit_round.xcf
Normal file
BIN
doc/img/gear.xcf
Normal file
BIN
doc/img/help.xcf
Normal file
BIN
doc/img/hide.xcf
Normal file
BIN
doc/img/mimo.xcf
Normal file
BIN
doc/img/rxtx.xcf
Normal file
BIN
doc/img/shrink.xcf
Normal file
BIN
doc/img/tiles.xcf
Normal file
BIN
doc/img/tool.xcf
Normal file
@ -22,6 +22,7 @@
|
||||
#include <QNetworkReply>
|
||||
|
||||
#include "SWGChannelSettings.h"
|
||||
#include "SWGWorkspaceInfo.h"
|
||||
|
||||
#include "device/deviceapi.h"
|
||||
#include "dsp/hbfilterchainconverter.h"
|
||||
@ -80,6 +81,18 @@ BeamSteeringCWMod::~BeamSteeringCWMod()
|
||||
delete m_thread;
|
||||
}
|
||||
|
||||
void BeamSteeringCWMod::setDeviceAPI(DeviceAPI *deviceAPI)
|
||||
{
|
||||
if (deviceAPI != m_deviceAPI)
|
||||
{
|
||||
m_deviceAPI->removeChannelSinkAPI(this);
|
||||
m_deviceAPI->removeMIMOChannel(this);
|
||||
m_deviceAPI = deviceAPI;
|
||||
m_deviceAPI->addMIMOChannel(this);
|
||||
m_deviceAPI->addChannelSinkAPI(this);
|
||||
}
|
||||
}
|
||||
|
||||
void BeamSteeringCWMod::startSources()
|
||||
{
|
||||
qDebug("BeamSteeringCWMod::startSources");
|
||||
@ -271,6 +284,15 @@ int BeamSteeringCWMod::webapiSettingsGet(
|
||||
return 200;
|
||||
}
|
||||
|
||||
int BeamSteeringCWMod::webapiWorkspaceGet(
|
||||
SWGSDRangel::SWGWorkspaceInfo& response,
|
||||
QString& errorMessage)
|
||||
{
|
||||
(void) errorMessage;
|
||||
response.setIndex(m_settings.m_workspaceIndex);
|
||||
return 200;
|
||||
}
|
||||
|
||||
int BeamSteeringCWMod::webapiSettingsPutPatch(
|
||||
bool force,
|
||||
const QStringList& channelSettingsKeys,
|
||||
|
@ -88,8 +88,10 @@ public:
|
||||
BeamSteeringCWMod(DeviceAPI *deviceAPI);
|
||||
virtual ~BeamSteeringCWMod();
|
||||
virtual void destroy() { delete this; }
|
||||
virtual void setDeviceAPI(DeviceAPI *deviceAPI);
|
||||
virtual DeviceAPI *getDeviceAPI() { return m_deviceAPI; }
|
||||
|
||||
virtual void startSinks() {}
|
||||
virtual void startSinks() {}
|
||||
virtual void stopSinks() {}
|
||||
virtual void startSources(); //!< thread start()
|
||||
virtual void stopSources(); //!< thread exit() and wait()
|
||||
@ -132,6 +134,10 @@ public:
|
||||
SWGSDRangel::SWGChannelSettings& response,
|
||||
QString& errorMessage);
|
||||
|
||||
virtual int webapiWorkspaceGet(
|
||||
SWGSDRangel::SWGWorkspaceInfo& query,
|
||||
QString& errorMessage);
|
||||
|
||||
static void webapiFormatChannelSettings(
|
||||
SWGSDRangel::SWGChannelSettings& response,
|
||||
const BeamSteeringCWModSettings& settings);
|
||||
|
@ -16,6 +16,7 @@
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <QLocale>
|
||||
#include <QResizeEvent>
|
||||
|
||||
#include "device/deviceuiset.h"
|
||||
#include "gui/basicchannelsettingsdialog.h"
|
||||
@ -61,6 +62,14 @@ bool BeamSteeringCWModGUI::deserialize(const QByteArray& data)
|
||||
}
|
||||
}
|
||||
|
||||
void BeamSteeringCWModGUI::resizeEvent(QResizeEvent* size)
|
||||
{
|
||||
int maxWidth = getRollupContents()->maximumWidth();
|
||||
int minHeight = getRollupContents()->minimumHeight() + getAdditionalHeight();
|
||||
resize(width() < maxWidth ? width() : maxWidth, minHeight);
|
||||
size->accept();
|
||||
}
|
||||
|
||||
bool BeamSteeringCWModGUI::handleMessage(const Message& message)
|
||||
{
|
||||
if (BeamSteeringCWMod::MsgBasebandNotification::match(message))
|
||||
@ -96,11 +105,13 @@ BeamSteeringCWModGUI::BeamSteeringCWModGUI(PluginAPI* pluginAPI, DeviceUISet *de
|
||||
m_centerFrequency(435000000),
|
||||
m_tickCount(0)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
setAttribute(Qt::WA_DeleteOnClose, true);
|
||||
setStreamIndicator("M");
|
||||
|
||||
connect(this, SIGNAL(widgetRolled(QWidget*,bool)), this, SLOT(onWidgetRolled(QWidget*,bool)));
|
||||
m_helpURL = "plugins/channelmimo/beamSteeringcwmod/readme.md";
|
||||
RollupContents *rollupContents = getRollupContents();
|
||||
ui->setupUi(rollupContents);
|
||||
setSizePolicy(rollupContents->sizePolicy());
|
||||
rollupContents->arrangeRollups();
|
||||
connect(rollupContents, SIGNAL(widgetRolled(QWidget*,bool)), this, SLOT(onWidgetRolled(QWidget*,bool)));
|
||||
connect(this, SIGNAL(customContextMenuRequested(const QPoint &)), this, SLOT(onMenuDialogCalled(const QPoint &)));
|
||||
|
||||
m_bsCWSource = (BeamSteeringCWMod*) mimoChannel;
|
||||
@ -113,7 +124,7 @@ BeamSteeringCWModGUI::BeamSteeringCWModGUI(PluginAPI* pluginAPI, DeviceUISet *de
|
||||
m_channelMarker.addStreamIndex(1);
|
||||
m_channelMarker.setColor(m_settings.m_rgbColor);
|
||||
m_channelMarker.setCenterFrequency(0);
|
||||
m_channelMarker.setTitle("Beam Steering CW Source");
|
||||
m_channelMarker.setTitle("BeamSteeringCWMod");
|
||||
m_channelMarker.setSourceOrSinkStream(false);
|
||||
m_channelMarker.blockSignals(false);
|
||||
m_channelMarker.setVisible(true); // activate signal on the last setting only
|
||||
@ -122,11 +133,11 @@ BeamSteeringCWModGUI::BeamSteeringCWModGUI(PluginAPI* pluginAPI, DeviceUISet *de
|
||||
m_settings.setRollupState(&m_rollupState);
|
||||
|
||||
m_deviceUISet->addChannelMarker(&m_channelMarker);
|
||||
m_deviceUISet->addRollupWidget(this);
|
||||
|
||||
connect(getInputMessageQueue(), SIGNAL(messageEnqueued()), this, SLOT(handleSourceMessages()));
|
||||
|
||||
displaySettings();
|
||||
makeUIConnections();
|
||||
displayRateAndShift();
|
||||
applySettings(true);
|
||||
}
|
||||
@ -164,12 +175,13 @@ void BeamSteeringCWModGUI::displaySettings()
|
||||
|
||||
setTitleColor(m_settings.m_rgbColor);
|
||||
setWindowTitle(m_channelMarker.getTitle());
|
||||
setTitle(m_channelMarker.getTitle());
|
||||
|
||||
blockApplySettings(true);
|
||||
ui->interpolationFactor->setCurrentIndex(m_settings.m_log2Interp);
|
||||
applyInterpolation();
|
||||
ui->steeringDegreesText->setText(tr("%1").arg(m_settings.m_steerDegrees));
|
||||
restoreState(m_rollupState);
|
||||
getRollupContents()->restoreState(m_rollupState);
|
||||
blockApplySettings(false);
|
||||
}
|
||||
|
||||
@ -212,7 +224,7 @@ void BeamSteeringCWModGUI::onWidgetRolled(QWidget* widget, bool rollDown)
|
||||
(void) widget;
|
||||
(void) rollDown;
|
||||
|
||||
saveState(m_rollupState);
|
||||
getRollupContents()->saveState(m_rollupState);
|
||||
applySettings();
|
||||
}
|
||||
|
||||
@ -226,6 +238,7 @@ void BeamSteeringCWModGUI::onMenuDialogCalled(const QPoint &p)
|
||||
dialog.setReverseAPIPort(m_settings.m_reverseAPIPort);
|
||||
dialog.setReverseAPIDeviceIndex(m_settings.m_reverseAPIDeviceIndex);
|
||||
dialog.setReverseAPIChannelIndex(m_settings.m_reverseAPIChannelIndex);
|
||||
dialog.setDefaultTitle(m_displayedName);
|
||||
|
||||
dialog.move(p);
|
||||
dialog.exec();
|
||||
@ -239,6 +252,7 @@ void BeamSteeringCWModGUI::onMenuDialogCalled(const QPoint &p)
|
||||
m_settings.m_reverseAPIChannelIndex = dialog.getReverseAPIChannelIndex();
|
||||
|
||||
setWindowTitle(m_settings.m_title);
|
||||
setTitle(m_channelMarker.getTitle());
|
||||
setTitleColor(m_settings.m_rgbColor);
|
||||
|
||||
applySettings();
|
||||
@ -303,3 +317,11 @@ void BeamSteeringCWModGUI::tick()
|
||||
m_tickCount = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void BeamSteeringCWModGUI::makeUIConnections()
|
||||
{
|
||||
QObject::connect(ui->channelOutput, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &BeamSteeringCWModGUI::on_channelOutput_currentIndexChanged);
|
||||
QObject::connect(ui->interpolationFactor, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &BeamSteeringCWModGUI::on_interpolationFactor_currentIndexChanged);
|
||||
QObject::connect(ui->position, &QSlider::valueChanged, this, &BeamSteeringCWModGUI::on_position_valueChanged);
|
||||
QObject::connect(ui->steeringDegrees, &QSlider::valueChanged, this, &BeamSteeringCWModGUI::on_steeringDegrees_valueChanged);
|
||||
}
|
||||
|
@ -48,6 +48,17 @@ public:
|
||||
QByteArray serialize() const;
|
||||
bool deserialize(const QByteArray& data);
|
||||
virtual MessageQueue *getInputMessageQueue() { return &m_inputMessageQueue; }
|
||||
virtual void setWorkspaceIndex(int index) { m_settings.m_workspaceIndex = index; };
|
||||
virtual int getWorkspaceIndex() const { return m_settings.m_workspaceIndex; };
|
||||
virtual void setGeometryBytes(const QByteArray& blob) { m_settings.m_geometryBytes = blob; };
|
||||
virtual QByteArray getGeometryBytes() const { return m_settings.m_geometryBytes; };
|
||||
virtual QString getTitle() const { return m_settings.m_title; };
|
||||
virtual QColor getTitleColor() const { return m_settings.m_rgbColor; };
|
||||
virtual void zetHidden(bool hidden) { m_settings.m_hidden = hidden; }
|
||||
virtual bool getHidden() const { return m_settings.m_hidden; }
|
||||
virtual ChannelMarker& getChannelMarker() { return m_channelMarker; }
|
||||
virtual int getStreamIndex() const { return -1; }
|
||||
virtual void setStreamIndex(int streamIndex) { (void) streamIndex; }
|
||||
|
||||
private:
|
||||
Ui::BeamSteeringCWModGUI* ui;
|
||||
@ -74,6 +85,7 @@ private:
|
||||
void displaySettings();
|
||||
void displayRateAndShift();
|
||||
bool handleMessage(const Message& message);
|
||||
void makeUIConnections();
|
||||
|
||||
void leaveEvent(QEvent*);
|
||||
void enterEvent(QEvent*);
|
||||
@ -81,6 +93,9 @@ private:
|
||||
void applyInterpolation();
|
||||
void applyPosition();
|
||||
|
||||
protected:
|
||||
void resizeEvent(QResizeEvent* size);
|
||||
|
||||
private slots:
|
||||
void handleSourceMessages();
|
||||
void on_channelOutput_currentIndexChanged(int index);
|
||||
|
@ -1,13 +1,13 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>BeamSteeringCWModGUI</class>
|
||||
<widget class="RollupWidget" name="BeamSteeringCWModGUI">
|
||||
<widget class="RollupContents" name="BeamSteeringCWModGUI">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>320</width>
|
||||
<height>102</height>
|
||||
<width>360</width>
|
||||
<height>100</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
@ -18,16 +18,10 @@
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>320</width>
|
||||
<width>360</width>
|
||||
<height>100</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>320</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Liberation Sans</family>
|
||||
@ -40,12 +34,24 @@
|
||||
<widget class="QWidget" name="settingsContainer" native="true">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>10</x>
|
||||
<y>10</y>
|
||||
<width>301</width>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>358</width>
|
||||
<height>91</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>358</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Settings</string>
|
||||
</property>
|
||||
@ -326,9 +332,9 @@
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>RollupWidget</class>
|
||||
<class>RollupContents</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>gui/rollupwidget.h</header>
|
||||
<header>gui/rollupcontents.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
|
@ -43,6 +43,8 @@ void BeamSteeringCWModSettings::resetToDefaults()
|
||||
m_reverseAPIPort = 8888;
|
||||
m_reverseAPIDeviceIndex = 0;
|
||||
m_reverseAPIChannelIndex = 0;
|
||||
m_workspaceIndex = 0;
|
||||
m_hidden = false;
|
||||
}
|
||||
|
||||
QByteArray BeamSteeringCWModSettings::serialize() const
|
||||
@ -64,6 +66,10 @@ QByteArray BeamSteeringCWModSettings::serialize() const
|
||||
s.writeBlob(15, m_rollupState->serialize());
|
||||
}
|
||||
|
||||
s.writeS32(16, m_workspaceIndex);
|
||||
s.writeBlob(17, m_geometryBytes);
|
||||
s.writeBool(18, m_hidden);
|
||||
|
||||
return s.final();
|
||||
}
|
||||
|
||||
@ -114,6 +120,10 @@ bool BeamSteeringCWModSettings::deserialize(const QByteArray& data)
|
||||
m_rollupState->deserialize(bytetmp);
|
||||
}
|
||||
|
||||
d.readS32(16, &m_workspaceIndex);
|
||||
d.readBlob(17, &m_geometryBytes);
|
||||
d.readBool(18, &m_hidden, false);
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
|
@ -36,6 +36,9 @@ struct BeamSteeringCWModSettings
|
||||
uint16_t m_reverseAPIPort;
|
||||
uint16_t m_reverseAPIDeviceIndex;
|
||||
uint16_t m_reverseAPIChannelIndex;
|
||||
int m_workspaceIndex;
|
||||
QByteArray m_geometryBytes;
|
||||
bool m_hidden;
|
||||
|
||||
Serializable *m_channelMarker;
|
||||
Serializable *m_rollupState;
|
||||
|
@ -8,6 +8,8 @@ This MIMO transmission only (MO) plugin can be used to drive a 2 channel MO devi
|
||||
|
||||
<h2>Interface</h2>
|
||||
|
||||
The top and bottom bars of the channel window are described [here](../../../sdrgui/channel/readme.md)
|
||||
|
||||
![Beam steering CW plugin GUI](../../../doc/img/BeamsteeringCWMod_plugin.png)
|
||||
|
||||
<h3>1: Channel output</h3>
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include <QNetworkReply>
|
||||
|
||||
#include "SWGChannelSettings.h"
|
||||
#include "SWGWorkspaceInfo.h"
|
||||
|
||||
#include "device/deviceapi.h"
|
||||
#include "dsp/hbfilterchainconverter.h"
|
||||
@ -82,6 +83,18 @@ Interferometer::~Interferometer()
|
||||
delete m_thread;
|
||||
}
|
||||
|
||||
void Interferometer::setDeviceAPI(DeviceAPI *deviceAPI)
|
||||
{
|
||||
if (deviceAPI != m_deviceAPI)
|
||||
{
|
||||
m_deviceAPI->removeChannelSinkAPI(this);
|
||||
m_deviceAPI->removeMIMOChannel(this);
|
||||
m_deviceAPI = deviceAPI;
|
||||
m_deviceAPI->addMIMOChannel(this);
|
||||
m_deviceAPI->addChannelSinkAPI(this);
|
||||
}
|
||||
}
|
||||
|
||||
void Interferometer::startSinks()
|
||||
{
|
||||
if (m_deviceSampleRate != 0) {
|
||||
@ -293,6 +306,15 @@ int Interferometer::webapiSettingsGet(
|
||||
return 200;
|
||||
}
|
||||
|
||||
int Interferometer::webapiWorkspaceGet(
|
||||
SWGSDRangel::SWGWorkspaceInfo& response,
|
||||
QString& errorMessage)
|
||||
{
|
||||
(void) errorMessage;
|
||||
response.setIndex(m_settings.m_workspaceIndex);
|
||||
return 200;
|
||||
}
|
||||
|
||||
int Interferometer::webapiSettingsPutPatch(
|
||||
bool force,
|
||||
const QStringList& channelSettingsKeys,
|
||||
|
@ -88,6 +88,8 @@ public:
|
||||
Interferometer(DeviceAPI *deviceAPI);
|
||||
virtual ~Interferometer();
|
||||
virtual void destroy() { delete this; }
|
||||
virtual void setDeviceAPI(DeviceAPI *deviceAPI);
|
||||
virtual DeviceAPI *getDeviceAPI() { return m_deviceAPI; }
|
||||
|
||||
virtual void startSinks(); //!< thread start()
|
||||
virtual void stopSinks(); //!< thread exit() and wait()
|
||||
@ -136,6 +138,10 @@ public:
|
||||
SWGSDRangel::SWGChannelSettings& response,
|
||||
QString& errorMessage);
|
||||
|
||||
virtual int webapiWorkspaceGet(
|
||||
SWGSDRangel::SWGWorkspaceInfo& query,
|
||||
QString& errorMessage);
|
||||
|
||||
static void webapiFormatChannelSettings(
|
||||
SWGSDRangel::SWGChannelSettings& response,
|
||||
const InterferometerSettings& settings);
|
||||
|
@ -106,11 +106,13 @@ InterferometerGUI::InterferometerGUI(PluginAPI* pluginAPI, DeviceUISet *deviceUI
|
||||
m_centerFrequency(435000000),
|
||||
m_tickCount(0)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
setAttribute(Qt::WA_DeleteOnClose, true);
|
||||
setStreamIndicator("M");
|
||||
|
||||
connect(this, SIGNAL(widgetRolled(QWidget*,bool)), this, SLOT(onWidgetRolled(QWidget*,bool)));
|
||||
m_helpURL = "plugins/channelmimo/interferometer/readme.md";
|
||||
RollupContents *rollupContents = getRollupContents();
|
||||
ui->setupUi(rollupContents);
|
||||
setSizePolicy(rollupContents->sizePolicy());
|
||||
rollupContents->arrangeRollups();
|
||||
connect(rollupContents, SIGNAL(widgetRolled(QWidget*,bool)), this, SLOT(onWidgetRolled(QWidget*,bool)));
|
||||
connect(this, SIGNAL(customContextMenuRequested(const QPoint &)), this, SLOT(onMenuDialogCalled(const QPoint &)));
|
||||
|
||||
m_interferometer = (Interferometer*) channelMIMO;
|
||||
@ -146,7 +148,6 @@ InterferometerGUI::InterferometerGUI(PluginAPI* pluginAPI, DeviceUISet *deviceUI
|
||||
m_settings.setSpectrumGUI(ui->spectrumGUI);
|
||||
|
||||
m_deviceUISet->addChannelMarker(&m_channelMarker);
|
||||
m_deviceUISet->addRollupWidget(this);
|
||||
|
||||
ui->spectrumGUI->setBuddies(m_spectrumVis, ui->glSpectrum);
|
||||
ui->scopeGUI->setBuddies(m_scopeVis->getInputMessageQueue(), m_scopeVis, ui->glScope);
|
||||
@ -157,6 +158,7 @@ InterferometerGUI::InterferometerGUI(PluginAPI* pluginAPI, DeviceUISet *deviceUI
|
||||
connect(getInputMessageQueue(), SIGNAL(messageEnqueued()), this, SLOT(handleSourceMessages()));
|
||||
|
||||
displaySettings();
|
||||
makeUIConnections();
|
||||
displayRateAndShift();
|
||||
applySettings(true);
|
||||
}
|
||||
@ -196,13 +198,14 @@ void InterferometerGUI::displaySettings()
|
||||
|
||||
setTitleColor(m_settings.m_rgbColor);
|
||||
setWindowTitle(m_channelMarker.getTitle());
|
||||
setTitle(m_channelMarker.getTitle());
|
||||
|
||||
blockApplySettings(true);
|
||||
ui->decimationFactor->setCurrentIndex(m_settings.m_log2Decim);
|
||||
applyDecimation();
|
||||
ui->phaseCorrection->setValue(m_settings.m_phase);
|
||||
ui->phaseCorrectionText->setText(tr("%1").arg(m_settings.m_phase));
|
||||
restoreState(m_rollupState);
|
||||
getRollupContents()->restoreState(m_rollupState);
|
||||
blockApplySettings(false);
|
||||
}
|
||||
|
||||
@ -247,7 +250,18 @@ void InterferometerGUI::onWidgetRolled(QWidget* widget, bool rollDown)
|
||||
(void) widget;
|
||||
(void) rollDown;
|
||||
|
||||
saveState(m_rollupState);
|
||||
RollupContents *rollupContents = getRollupContents();
|
||||
|
||||
if (rollupContents->hasExpandableWidgets()) {
|
||||
setSizePolicy(sizePolicy().horizontalPolicy(), QSizePolicy::Expanding);
|
||||
} else {
|
||||
setSizePolicy(sizePolicy().horizontalPolicy(), QSizePolicy::Fixed);
|
||||
}
|
||||
|
||||
int h = rollupContents->height() + getAdditionalHeight();
|
||||
resize(width(), h);
|
||||
|
||||
rollupContents->saveState(m_rollupState);
|
||||
applySettings();
|
||||
}
|
||||
|
||||
@ -261,6 +275,7 @@ void InterferometerGUI::onMenuDialogCalled(const QPoint &p)
|
||||
dialog.setReverseAPIPort(m_settings.m_reverseAPIPort);
|
||||
dialog.setReverseAPIDeviceIndex(m_settings.m_reverseAPIDeviceIndex);
|
||||
dialog.setReverseAPIChannelIndex(m_settings.m_reverseAPIChannelIndex);
|
||||
dialog.setDefaultTitle(m_displayedName);
|
||||
|
||||
dialog.move(p);
|
||||
dialog.exec();
|
||||
@ -274,6 +289,7 @@ void InterferometerGUI::onMenuDialogCalled(const QPoint &p)
|
||||
m_settings.m_reverseAPIChannelIndex = dialog.getReverseAPIChannelIndex();
|
||||
|
||||
setWindowTitle(m_settings.m_title);
|
||||
setTitle(m_channelMarker.getTitle());
|
||||
setTitleColor(m_settings.m_rgbColor);
|
||||
|
||||
applySettings();
|
||||
@ -338,3 +354,11 @@ void InterferometerGUI::tick()
|
||||
m_tickCount = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void InterferometerGUI::makeUIConnections()
|
||||
{
|
||||
QObject::connect(ui->decimationFactor, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &InterferometerGUI::on_decimationFactor_currentIndexChanged);
|
||||
QObject::connect(ui->position, &QSlider::valueChanged, this, &InterferometerGUI::on_position_valueChanged);
|
||||
QObject::connect(ui->phaseCorrection, &QSlider::valueChanged, this, &InterferometerGUI::on_phaseCorrection_valueChanged);
|
||||
QObject::connect(ui->correlationType, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &InterferometerGUI::on_correlationType_currentIndexChanged);
|
||||
}
|
||||
|
@ -47,6 +47,17 @@ public:
|
||||
virtual QByteArray serialize() const;
|
||||
virtual bool deserialize(const QByteArray& data);
|
||||
virtual MessageQueue* getInputMessageQueue();
|
||||
virtual void setWorkspaceIndex(int index) { m_settings.m_workspaceIndex = index; };
|
||||
virtual int getWorkspaceIndex() const { return m_settings.m_workspaceIndex; };
|
||||
virtual void setGeometryBytes(const QByteArray& blob) { m_settings.m_geometryBytes = blob; };
|
||||
virtual QByteArray getGeometryBytes() const { return m_settings.m_geometryBytes; };
|
||||
virtual QString getTitle() const { return m_settings.m_title; };
|
||||
virtual QColor getTitleColor() const { return m_settings.m_rgbColor; };
|
||||
virtual void zetHidden(bool hidden) { m_settings.m_hidden = hidden; }
|
||||
virtual bool getHidden() const { return m_settings.m_hidden; }
|
||||
virtual ChannelMarker& getChannelMarker() { return m_channelMarker; }
|
||||
virtual int getStreamIndex() const { return -1; }
|
||||
virtual void setStreamIndex(int streamIndex) { (void) streamIndex; }
|
||||
|
||||
private:
|
||||
Ui::InterferometerGUI* ui;
|
||||
@ -76,6 +87,7 @@ private:
|
||||
void displaySettings();
|
||||
void displayRateAndShift();
|
||||
bool handleMessage(const Message& message);
|
||||
void makeUIConnections();
|
||||
|
||||
void leaveEvent(QEvent*);
|
||||
void enterEvent(QEvent*);
|
||||
|
@ -1,15 +1,21 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>InterferometerGUI</class>
|
||||
<widget class="RollupWidget" name="InterferometerGUI">
|
||||
<widget class="RollupContents" name="InterferometerGUI">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>739</width>
|
||||
<height>778</height>
|
||||
<width>720</width>
|
||||
<height>770</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>720</width>
|
||||
@ -30,10 +36,16 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>10</y>
|
||||
<width>631</width>
|
||||
<width>718</width>
|
||||
<height>81</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>718</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Settings</string>
|
||||
</property>
|
||||
@ -352,9 +364,15 @@
|
||||
<height>284</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>716</width>
|
||||
<width>718</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
@ -379,6 +397,12 @@
|
||||
</property>
|
||||
<item>
|
||||
<widget class="GLSpectrum" name="glSpectrum" native="true">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>200</width>
|
||||
@ -407,9 +431,15 @@
|
||||
<height>334</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>716</width>
|
||||
<width>718</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
@ -434,6 +464,12 @@
|
||||
</property>
|
||||
<item>
|
||||
<widget class="GLScope" name="glScope" native="true">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>200</width>
|
||||
@ -456,9 +492,9 @@
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>RollupWidget</class>
|
||||
<class>RollupContents</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>gui/rollupwidget.h</header>
|
||||
<header>gui/rollupcontents.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
|
@ -44,6 +44,8 @@ void InterferometerSettings::resetToDefaults()
|
||||
m_reverseAPIPort = 8888;
|
||||
m_reverseAPIDeviceIndex = 0;
|
||||
m_reverseAPIChannelIndex = 0;
|
||||
m_workspaceIndex = 0;
|
||||
m_hidden = false;
|
||||
}
|
||||
|
||||
QByteArray InterferometerSettings::serialize() const
|
||||
@ -61,6 +63,9 @@ QByteArray InterferometerSettings::serialize() const
|
||||
s.writeU32(10, m_reverseAPIDeviceIndex);
|
||||
s.writeU32(11, m_reverseAPIChannelIndex);
|
||||
s.writeS32(12, m_phase);
|
||||
s.writeS32(13,m_workspaceIndex);
|
||||
s.writeBlob(14, m_geometryBytes);
|
||||
s.writeBool(15, m_hidden);
|
||||
|
||||
if (m_spectrumGUI) {
|
||||
s.writeBlob(20, m_spectrumGUI->serialize());
|
||||
@ -117,6 +122,9 @@ bool InterferometerSettings::deserialize(const QByteArray& data)
|
||||
m_reverseAPIChannelIndex = utmp > 99 ? 99 : utmp;
|
||||
d.readS32(12, &tmp, 0);
|
||||
m_phase = tmp < -180 ? -180 : tmp > 180 ? 180 : tmp;
|
||||
d.readS32(13, &m_workspaceIndex);
|
||||
d.readBlob(14, &m_geometryBytes);
|
||||
d.readBool(15, &m_hidden, false);
|
||||
|
||||
if (m_spectrumGUI)
|
||||
{
|
||||
|
@ -48,6 +48,9 @@ struct InterferometerSettings
|
||||
uint16_t m_reverseAPIPort;
|
||||
uint16_t m_reverseAPIDeviceIndex;
|
||||
uint16_t m_reverseAPIChannelIndex;
|
||||
int m_workspaceIndex;
|
||||
QByteArray m_geometryBytes;
|
||||
bool m_hidden;
|
||||
|
||||
Serializable *m_channelMarker;
|
||||
Serializable *m_spectrumGUI;
|
||||
|
@ -6,11 +6,13 @@ This MIMO reception only (MI) plugin can be used to study phase difference betwe
|
||||
|
||||
<h2>Interface</h2>
|
||||
|
||||
The top and bottom bars of the channel window are described [here](../../../sdrgui/channel/readme.md)
|
||||
|
||||
![Interferometer plugin GUI](../../../doc/img/Interferometer_plugin.png)
|
||||
|
||||
The interface is divided in 3 sections that will be detailed next:
|
||||
- A: settings. These are the plugin controls
|
||||
- B: spectrum (frequency domain). This is a spectrum display analogous to other spectrum displays. Its input varies depending on the correlation function selected
|
||||
- B: spectrum (frequency domain). This is a spectrum display analogous to other spectrum displays. Its input varies depending on the correlation function selected. Details on the spectrum view and controls can be found [here](../../../sdrgui/gui/spectrum.md)
|
||||
- C: scope (time domain). This is a scope display analogous to other scope displays. Its input varies depending on the correlation function selected. For FFT type correlation this is not a time domain but a frequency domain display transposed to time analogous to a frequency sweep.
|
||||
|
||||
<h2>A. Settings section</h2>
|
||||
|
@ -2,7 +2,7 @@ project(demod)
|
||||
|
||||
if (Qt5Quick_FOUND AND Qt5QuickWidgets_FOUND AND Qt5Positioning_FOUND)
|
||||
add_subdirectory(demodadsb)
|
||||
add_subdirectory(demodvor)
|
||||
# add_subdirectory(demodvormc)
|
||||
endif()
|
||||
|
||||
add_subdirectory(demodam)
|
||||
@ -15,7 +15,7 @@ add_subdirectory(localsink)
|
||||
add_subdirectory(filesink)
|
||||
add_subdirectory(freqtracker)
|
||||
add_subdirectory(demodchirpchat)
|
||||
add_subdirectory(demodvorsc)
|
||||
add_subdirectory(demodvor)
|
||||
add_subdirectory(demodpacket)
|
||||
add_subdirectory(demodais)
|
||||
add_subdirectory(demodpager)
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include <stdio.h>
|
||||
|
||||
#include "SWGChannelSettings.h"
|
||||
#include "SWGWorkspaceInfo.h"
|
||||
#include "SWGChannelAnalyzerSettings.h"
|
||||
|
||||
#include "device/deviceapi.h"
|
||||
@ -92,6 +93,23 @@ ChannelAnalyzer::~ChannelAnalyzer()
|
||||
qDebug("ChannelAnalyzer::~ChannelAnalyzer: done");
|
||||
}
|
||||
|
||||
void ChannelAnalyzer::setDeviceAPI(DeviceAPI *deviceAPI)
|
||||
{
|
||||
if (deviceAPI != m_deviceAPI)
|
||||
{
|
||||
m_deviceAPI->removeChannelSinkAPI(this);
|
||||
m_deviceAPI->removeChannelSink(this);
|
||||
m_deviceAPI = deviceAPI;
|
||||
m_deviceAPI->addChannelSink(this);
|
||||
m_deviceAPI->addChannelSinkAPI(this);
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t ChannelAnalyzer::getNumberOfDeviceStreams() const
|
||||
{
|
||||
return m_deviceAPI->getNbSourceStreams();
|
||||
}
|
||||
|
||||
int ChannelAnalyzer::getChannelSampleRate()
|
||||
{
|
||||
DeviceSampleSource *source = m_deviceAPI->getSampleSource();
|
||||
@ -100,7 +118,6 @@ int ChannelAnalyzer::getChannelSampleRate()
|
||||
m_basebandSampleRate = source->getSampleRate();
|
||||
}
|
||||
|
||||
qDebug("ChannelAnalyzer::getChannelSampleRate: %d", m_basebandSampleRate);
|
||||
return m_basebandSampleRate;
|
||||
}
|
||||
|
||||
@ -317,6 +334,15 @@ int ChannelAnalyzer::webapiSettingsGet(
|
||||
return 200;
|
||||
}
|
||||
|
||||
int ChannelAnalyzer::webapiWorkspaceGet(
|
||||
SWGSDRangel::SWGWorkspaceInfo& response,
|
||||
QString& errorMessage)
|
||||
{
|
||||
(void) errorMessage;
|
||||
response.setIndex(m_settings.m_workspaceIndex);
|
||||
return 200;
|
||||
}
|
||||
|
||||
int ChannelAnalyzer::webapiSettingsPutPatch(
|
||||
bool force,
|
||||
const QStringList& channelSettingsKeys,
|
||||
|
@ -64,6 +64,8 @@ public:
|
||||
ChannelAnalyzer(DeviceAPI *deviceAPI);
|
||||
virtual ~ChannelAnalyzer();
|
||||
virtual void destroy() { delete this; }
|
||||
virtual void setDeviceAPI(DeviceAPI *deviceAPI);
|
||||
virtual DeviceAPI *getDeviceAPI() { return m_deviceAPI; }
|
||||
SpectrumVis *getSpectrumVis() { return &m_spectrumVis; }
|
||||
ScopeVis *getScopeVis() { return &m_scopeVis; }
|
||||
void setScopeVis(ScopeVis *scopeVis) { m_basebandSink->setScopeVis(scopeVis); }
|
||||
@ -94,6 +96,7 @@ public:
|
||||
|
||||
virtual int getNbSinkStreams() const { return 1; }
|
||||
virtual int getNbSourceStreams() const { return 0; }
|
||||
uint32_t getNumberOfDeviceStreams() const;
|
||||
|
||||
virtual qint64 getStreamCenterFrequency(int streamIndex, bool sinkElseSource) const
|
||||
{
|
||||
@ -106,6 +109,10 @@ public:
|
||||
SWGSDRangel::SWGChannelSettings& response,
|
||||
QString& errorMessage);
|
||||
|
||||
virtual int webapiWorkspaceGet(
|
||||
SWGSDRangel::SWGWorkspaceInfo& response,
|
||||
QString& errorMessage);
|
||||
|
||||
virtual int webapiSettingsPutPatch(
|
||||
bool force,
|
||||
const QStringList& channelSettingsKeys,
|
||||
|
@ -76,6 +76,7 @@ void ChannelAnalyzerGUI::displaySettings()
|
||||
|
||||
setTitleColor(m_settings.m_rgbColor);
|
||||
setWindowTitle(m_channelMarker.getTitle());
|
||||
setTitle(m_channelMarker.getTitle());
|
||||
|
||||
blockApplySettings(true);
|
||||
|
||||
@ -97,7 +98,8 @@ void ChannelAnalyzerGUI::displaySettings()
|
||||
QString rolloffStr = QString::number(m_settings.m_rrcRolloff/100.0, 'f', 2);
|
||||
ui->rrcRolloffText->setText(rolloffStr);
|
||||
|
||||
restoreState(m_rollupState);
|
||||
getRollupContents()->restoreState(m_rollupState);
|
||||
updateAbsoluteCenterFrequency();
|
||||
blockApplySettings(false);
|
||||
}
|
||||
|
||||
@ -181,7 +183,7 @@ void ChannelAnalyzerGUI::setPLLVisibility()
|
||||
else
|
||||
ui->pllPskOrder->setCurrentIndex(i);
|
||||
ui->pllPskOrder->blockSignals(false);
|
||||
arrangeRollups();
|
||||
getRollupContents()->arrangeRollups();
|
||||
}
|
||||
|
||||
void ChannelAnalyzerGUI::setSpectrumDisplay()
|
||||
@ -232,6 +234,10 @@ bool ChannelAnalyzerGUI::handleMessage(const Message& message)
|
||||
{
|
||||
DSPSignalNotification& cmd = (DSPSignalNotification&) message;
|
||||
m_basebandSampleRate = cmd.getSampleRate();
|
||||
m_deviceCenterFrequency = cmd.getCenterFrequency();
|
||||
ui->deltaFrequency->setValueRange(false, 8, -m_basebandSampleRate/2, m_basebandSampleRate/2);
|
||||
ui->deltaFrequencyLabel->setToolTip(tr("Range %1 %L2 Hz").arg(QChar(0xB1)).arg(m_basebandSampleRate/2));
|
||||
updateAbsoluteCenterFrequency();
|
||||
qDebug("ChannelAnalyzerGUI::handleMessage: DSPSignalNotification: m_basebandSampleRate: %d", m_basebandSampleRate);
|
||||
setSinkSampleRate();
|
||||
|
||||
@ -274,6 +280,7 @@ void ChannelAnalyzerGUI::channelMarkerChangedByCursor()
|
||||
{
|
||||
ui->deltaFrequency->setValue(m_channelMarker.getCenterFrequency());
|
||||
m_settings.m_inputFrequencyOffset = m_channelMarker.getCenterFrequency();
|
||||
updateAbsoluteCenterFrequency();
|
||||
applySettings();
|
||||
}
|
||||
|
||||
@ -387,6 +394,7 @@ void ChannelAnalyzerGUI::on_deltaFrequency_changed(qint64 value)
|
||||
{
|
||||
m_channelMarker.setCenterFrequency(value);
|
||||
m_settings.m_inputFrequencyOffset = m_channelMarker.getCenterFrequency();
|
||||
updateAbsoluteCenterFrequency();
|
||||
applySettings();
|
||||
}
|
||||
|
||||
@ -450,7 +458,18 @@ void ChannelAnalyzerGUI::onWidgetRolled(QWidget* widget, bool rollDown)
|
||||
(void) widget;
|
||||
(void) rollDown;
|
||||
|
||||
saveState(m_rollupState);
|
||||
RollupContents *rollupContents = getRollupContents();
|
||||
|
||||
if (rollupContents->hasExpandableWidgets()) {
|
||||
setSizePolicy(sizePolicy().horizontalPolicy(), QSizePolicy::Expanding);
|
||||
} else {
|
||||
setSizePolicy(sizePolicy().horizontalPolicy(), QSizePolicy::Fixed);
|
||||
}
|
||||
|
||||
int h = rollupContents->height() + getAdditionalHeight();
|
||||
resize(width(), h);
|
||||
|
||||
rollupContents->saveState(m_rollupState);
|
||||
applySettings();
|
||||
}
|
||||
|
||||
@ -464,10 +483,17 @@ void ChannelAnalyzerGUI::onMenuDialogCalled(const QPoint& p)
|
||||
dialog.setReverseAPIPort(m_settings.m_reverseAPIPort);
|
||||
dialog.setReverseAPIDeviceIndex(m_settings.m_reverseAPIDeviceIndex);
|
||||
dialog.setReverseAPIChannelIndex(m_settings.m_reverseAPIChannelIndex);
|
||||
dialog.setDefaultTitle(m_displayedName);
|
||||
|
||||
if (m_deviceUISet->m_deviceMIMOEngine)
|
||||
{
|
||||
dialog.setNumberOfStreams(m_channelAnalyzer->getNumberOfDeviceStreams());
|
||||
dialog.setStreamIndex(m_settings.m_streamIndex);
|
||||
}
|
||||
|
||||
dialog.move(p);
|
||||
dialog.exec();
|
||||
|
||||
m_settings.m_inputFrequencyOffset = m_channelMarker.getCenterFrequency();
|
||||
m_settings.m_rgbColor = m_channelMarker.getColor().rgb();
|
||||
m_settings.m_title = m_channelMarker.getTitle();
|
||||
m_settings.m_useReverseAPI = dialog.useReverseAPI();
|
||||
@ -477,8 +503,17 @@ void ChannelAnalyzerGUI::onMenuDialogCalled(const QPoint& p)
|
||||
m_settings.m_reverseAPIChannelIndex = dialog.getReverseAPIChannelIndex();
|
||||
|
||||
setWindowTitle(m_settings.m_title);
|
||||
setTitle(m_channelMarker.getTitle());
|
||||
setTitleColor(m_settings.m_rgbColor);
|
||||
|
||||
if (m_deviceUISet->m_deviceMIMOEngine)
|
||||
{
|
||||
m_settings.m_streamIndex = dialog.getSelectedStreamIndex();
|
||||
m_channelMarker.clearStreamIndexes();
|
||||
m_channelMarker.addStreamIndex(m_settings.m_streamIndex);
|
||||
updateIndexLabel();
|
||||
}
|
||||
|
||||
applySettings();
|
||||
}
|
||||
|
||||
@ -494,11 +529,13 @@ ChannelAnalyzerGUI::ChannelAnalyzerGUI(PluginAPI* pluginAPI, DeviceUISet *device
|
||||
m_doApplySettings(true),
|
||||
m_basebandSampleRate(48000)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
m_helpURL = "plugins/channelrx/chanalyzer/readme.md";
|
||||
setAttribute(Qt::WA_DeleteOnClose, true);
|
||||
connect(this, SIGNAL(widgetRolled(QWidget*,bool)), this, SLOT(onWidgetRolled(QWidget*,bool)));
|
||||
|
||||
m_helpURL = "plugins/channelrx/chanalyzer/readme.md";
|
||||
RollupContents *rollupContents = getRollupContents();
|
||||
ui->setupUi(rollupContents);
|
||||
setSizePolicy(rollupContents->sizePolicy());
|
||||
rollupContents->arrangeRollups();
|
||||
connect(rollupContents, SIGNAL(widgetRolled(QWidget*,bool)), this, SLOT(onWidgetRolled(QWidget*,bool)));
|
||||
connect(this, SIGNAL(customContextMenuRequested(const QPoint &)), this, SLOT(onMenuDialogCalled(const QPoint &)));
|
||||
|
||||
m_channelAnalyzer = (ChannelAnalyzer*) rxChannel;
|
||||
@ -540,7 +577,6 @@ ChannelAnalyzerGUI::ChannelAnalyzerGUI(PluginAPI* pluginAPI, DeviceUISet *device
|
||||
setTitleColor(m_channelMarker.getColor());
|
||||
|
||||
m_deviceUISet->addChannelMarker(&m_channelMarker);
|
||||
m_deviceUISet->addRollupWidget(this);
|
||||
|
||||
ui->spectrumGUI->setBuddies(m_spectrumVis, ui->glSpectrum);
|
||||
ui->scopeGUI->setBuddies(m_scopeVis->getInputMessageQueue(), m_scopeVis, ui->glScope);
|
||||
@ -555,6 +591,7 @@ ChannelAnalyzerGUI::ChannelAnalyzerGUI(PluginAPI* pluginAPI, DeviceUISet *device
|
||||
connect(getInputMessageQueue(), SIGNAL(messageEnqueued()), this, SLOT(handleInputMessages()));
|
||||
|
||||
displaySettings();
|
||||
makeUIConnections();
|
||||
applySettings(true);
|
||||
}
|
||||
|
||||
@ -671,13 +708,39 @@ void ChannelAnalyzerGUI::applySettings(bool force)
|
||||
}
|
||||
}
|
||||
|
||||
void ChannelAnalyzerGUI::leaveEvent(QEvent*)
|
||||
void ChannelAnalyzerGUI::leaveEvent(QEvent* event)
|
||||
{
|
||||
m_channelMarker.setHighlighted(false);
|
||||
ChannelGUI::leaveEvent(event);
|
||||
}
|
||||
|
||||
void ChannelAnalyzerGUI::enterEvent(QEvent*)
|
||||
void ChannelAnalyzerGUI::enterEvent(QEvent* event)
|
||||
{
|
||||
m_channelMarker.setHighlighted(true);
|
||||
ChannelGUI::enterEvent(event);
|
||||
}
|
||||
|
||||
void ChannelAnalyzerGUI::makeUIConnections()
|
||||
{
|
||||
QObject::connect(ui->deltaFrequency, &ValueDialZ::changed, this, &ChannelAnalyzerGUI::on_deltaFrequency_changed);
|
||||
QObject::connect(ui->rationalDownSamplerRate, &ValueDial::changed, this, &ChannelAnalyzerGUI::on_rationalDownSamplerRate_changed);
|
||||
QObject::connect(ui->pll, &QToolButton::toggled, this, &ChannelAnalyzerGUI::on_pll_toggled);
|
||||
QObject::connect(ui->pllType, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &ChannelAnalyzerGUI::on_pllType_currentIndexChanged);
|
||||
QObject::connect(ui->pllPskOrder, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &ChannelAnalyzerGUI::on_pllPskOrder_currentIndexChanged);
|
||||
QObject::connect(ui->pllBandwidth, &QDial::valueChanged, this, &ChannelAnalyzerGUI::on_pllBandwidth_valueChanged);
|
||||
QObject::connect(ui->pllDampingFactor, &QDial::valueChanged, this, &ChannelAnalyzerGUI::on_pllDampingFactor_valueChanged);
|
||||
QObject::connect(ui->pllLoopGain, &QDial::valueChanged, this, &ChannelAnalyzerGUI::on_pllLoopGain_valueChanged);
|
||||
QObject::connect(ui->log2Decim, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &ChannelAnalyzerGUI::on_log2Decim_currentIndexChanged);
|
||||
QObject::connect(ui->useRationalDownsampler, &ButtonSwitch::toggled, this, &ChannelAnalyzerGUI::on_useRationalDownsampler_toggled);
|
||||
QObject::connect(ui->signalSelect, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &ChannelAnalyzerGUI::on_signalSelect_currentIndexChanged);
|
||||
QObject::connect(ui->rrcFilter, &ButtonSwitch::toggled, this, &ChannelAnalyzerGUI::on_rrcFilter_toggled);
|
||||
QObject::connect(ui->rrcRolloff, &QDial::valueChanged, this, &ChannelAnalyzerGUI::on_rrcRolloff_valueChanged);
|
||||
QObject::connect(ui->BW, &QSlider::valueChanged, this, &ChannelAnalyzerGUI::on_BW_valueChanged);
|
||||
QObject::connect(ui->lowCut, &QSlider::valueChanged, this, &ChannelAnalyzerGUI::on_lowCut_valueChanged);
|
||||
QObject::connect(ui->ssb, &QCheckBox::toggled, this, &ChannelAnalyzerGUI::on_ssb_toggled);
|
||||
}
|
||||
|
||||
void ChannelAnalyzerGUI::updateAbsoluteCenterFrequency()
|
||||
{
|
||||
setStatusFrequency(m_deviceCenterFrequency + m_settings.m_inputFrequencyOffset);
|
||||
}
|
||||
|
@ -49,6 +49,17 @@ public:
|
||||
QByteArray serialize() const;
|
||||
bool deserialize(const QByteArray& data);
|
||||
virtual MessageQueue *getInputMessageQueue() { return &m_inputMessageQueue; }
|
||||
virtual void setWorkspaceIndex(int index) { m_settings.m_workspaceIndex = index; };
|
||||
virtual int getWorkspaceIndex() const { return m_settings.m_workspaceIndex; };
|
||||
virtual void setGeometryBytes(const QByteArray& blob) { m_settings.m_geometryBytes = blob; };
|
||||
virtual QByteArray getGeometryBytes() const { return m_settings.m_geometryBytes; };
|
||||
virtual QString getTitle() const { return m_settings.m_title; };
|
||||
virtual QColor getTitleColor() const { return m_settings.m_rgbColor; };
|
||||
virtual void zetHidden(bool hidden) { m_settings.m_hidden = hidden; }
|
||||
virtual bool getHidden() const { return m_settings.m_hidden; }
|
||||
virtual ChannelMarker& getChannelMarker() { return m_channelMarker; }
|
||||
virtual int getStreamIndex() const { return m_settings.m_streamIndex; }
|
||||
virtual void setStreamIndex(int streamIndex) { m_settings.m_streamIndex = streamIndex; }
|
||||
|
||||
public slots:
|
||||
void channelMarkerChangedByCursor();
|
||||
@ -61,6 +72,7 @@ private:
|
||||
ChannelMarker m_channelMarker;
|
||||
RollupState m_rollupState;
|
||||
ChannelAnalyzerSettings m_settings;
|
||||
qint64 m_deviceCenterFrequency;
|
||||
bool m_doApplySettings;
|
||||
int m_basebandSampleRate; //!< sample rate after final in-channel decimation (spanlog2)
|
||||
MovingAverageUtil<double, double, 40> m_channelPowerAvg;
|
||||
@ -84,6 +96,8 @@ private:
|
||||
void setPLLVisibility();
|
||||
void setSpectrumDisplay();
|
||||
bool handleMessage(const Message& message);
|
||||
void makeUIConnections();
|
||||
void updateAbsoluteCenterFrequency();
|
||||
|
||||
void leaveEvent(QEvent*);
|
||||
void enterEvent(QEvent*);
|
||||
|
@ -1,12 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>ChannelAnalyzerGUI</class>
|
||||
<widget class="RollupWidget" name="ChannelAnalyzerGUI">
|
||||
<widget class="RollupContents" name="ChannelAnalyzerGUI">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>739</width>
|
||||
<width>720</width>
|
||||
<height>778</height>
|
||||
</rect>
|
||||
</property>
|
||||
@ -36,10 +36,16 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>524</width>
|
||||
<width>718</width>
|
||||
<height>101</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>718</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Settings</string>
|
||||
</property>
|
||||
@ -861,9 +867,15 @@
|
||||
<height>284</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>716</width>
|
||||
<width>718</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
@ -888,6 +900,12 @@
|
||||
</property>
|
||||
<item>
|
||||
<widget class="GLSpectrum" name="glSpectrum" native="true">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>200</width>
|
||||
@ -916,9 +934,15 @@
|
||||
<height>334</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>716</width>
|
||||
<width>718</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
@ -943,6 +967,12 @@
|
||||
</property>
|
||||
<item>
|
||||
<widget class="GLScope" name="glScope" native="true">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>200</width>
|
||||
@ -965,9 +995,20 @@
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>RollupWidget</class>
|
||||
<class>ValueDial</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>gui/rollupwidget.h</header>
|
||||
<header>gui/valuedial.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>ButtonSwitch</class>
|
||||
<extends>QToolButton</extends>
|
||||
<header>gui/buttonswitch.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>RollupContents</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>gui/rollupcontents.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
@ -976,23 +1017,6 @@
|
||||
<header>gui/valuedialz.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>GLScope</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>gui/glscope.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>GLScopeGUI</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>gui/glscopegui.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>ButtonSwitch</class>
|
||||
<extends>QToolButton</extends>
|
||||
<header>gui/buttonswitch.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>GLSpectrum</class>
|
||||
<extends>QWidget</extends>
|
||||
@ -1006,9 +1030,15 @@
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>ValueDial</class>
|
||||
<class>GLScope</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>gui/valuedial.h</header>
|
||||
<header>gui/glscope.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>GLScopeGUI</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>gui/glscopegui.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
|
@ -59,6 +59,8 @@ void ChannelAnalyzerSettings::resetToDefaults()
|
||||
m_reverseAPIPort = 8888;
|
||||
m_reverseAPIDeviceIndex = 0;
|
||||
m_reverseAPIChannelIndex = 0;
|
||||
m_workspaceIndex = 0;
|
||||
m_hidden = false;
|
||||
}
|
||||
|
||||
QByteArray ChannelAnalyzerSettings::serialize() const
|
||||
@ -105,6 +107,9 @@ QByteArray ChannelAnalyzerSettings::serialize() const
|
||||
s.writeU32(26, m_reverseAPIDeviceIndex);
|
||||
s.writeU32(27, m_reverseAPIChannelIndex);
|
||||
s.writeS32(28, m_streamIndex);
|
||||
s.writeS32(29, m_workspaceIndex);
|
||||
s.writeBlob(30, m_geometryBytes);
|
||||
s.writeBool(31, m_hidden);
|
||||
|
||||
return s.final();
|
||||
}
|
||||
@ -179,6 +184,9 @@ bool ChannelAnalyzerSettings::deserialize(const QByteArray& data)
|
||||
d.readU32(27, &utmp, 0);
|
||||
m_reverseAPIChannelIndex = utmp > 99 ? 99 : utmp;
|
||||
d.readS32(28, &m_streamIndex, 0);
|
||||
d.readS32(29, &m_workspaceIndex, 0);
|
||||
d.readBlob(30, &m_geometryBytes);
|
||||
d.readBool(31, &m_hidden, false);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -60,6 +60,9 @@ struct ChannelAnalyzerSettings
|
||||
uint16_t m_reverseAPIPort;
|
||||
uint16_t m_reverseAPIDeviceIndex;
|
||||
uint16_t m_reverseAPIChannelIndex;
|
||||
int m_workspaceIndex;
|
||||
QByteArray m_geometryBytes;
|
||||
bool m_hidden;
|
||||
|
||||
ChannelAnalyzerSettings();
|
||||
void resetToDefaults();
|
||||
|
@ -24,6 +24,8 @@ The same waveforms can be used to trigger the scope trace
|
||||
|
||||
<h2>B. General interface</h2>
|
||||
|
||||
The top and bottom bars of the channel window are described [here](../../../sdrgui/channel/readme.md)
|
||||
|
||||
![Channel Analyzer NG plugin GUI](../../../doc/img/ChAnalyzerNG_plugin.png)
|
||||
|
||||
The interface is essentially divided in the following sections
|
||||
@ -36,7 +38,7 @@ The interface is essentially divided in the following sections
|
||||
|
||||
Note 1: the scope trace is updated continuously for sweep times of 1 second or more else the display is refreshed only when the trace finishes.
|
||||
|
||||
Note 2: the spectrum view (Channel spectrum) is not presented here.
|
||||
Note 2: details on the spectrum view and controls can be found [here](../../../sdrgui/gui/spectrum.md)
|
||||
|
||||
<h2>C. Channel controls</h2>
|
||||
|
||||
|
@ -31,6 +31,7 @@
|
||||
#include <QThread>
|
||||
|
||||
#include "SWGChannelSettings.h"
|
||||
#include "SWGWorkspaceInfo.h"
|
||||
#include "SWGADSBDemodSettings.h"
|
||||
#include "SWGChannelReport.h"
|
||||
#include "SWGADSBDemodReport.h"
|
||||
@ -109,6 +110,18 @@ ADSBDemod::~ADSBDemod()
|
||||
delete m_thread;
|
||||
}
|
||||
|
||||
void ADSBDemod::setDeviceAPI(DeviceAPI *deviceAPI)
|
||||
{
|
||||
if (deviceAPI != m_deviceAPI)
|
||||
{
|
||||
m_deviceAPI->removeChannelSinkAPI(this);
|
||||
m_deviceAPI->removeChannelSink(this);
|
||||
m_deviceAPI = deviceAPI;
|
||||
m_deviceAPI->addChannelSink(this);
|
||||
m_deviceAPI->addChannelSinkAPI(this);
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t ADSBDemod::getNumberOfDeviceStreams() const
|
||||
{
|
||||
return m_deviceAPI->getNbSourceStreams();
|
||||
@ -362,6 +375,15 @@ int ADSBDemod::webapiSettingsGet(
|
||||
return 200;
|
||||
}
|
||||
|
||||
int ADSBDemod::webapiWorkspaceGet(
|
||||
SWGSDRangel::SWGWorkspaceInfo& response,
|
||||
QString& errorMessage)
|
||||
{
|
||||
(void) errorMessage;
|
||||
response.setIndex(m_settings.m_workspaceIndex);
|
||||
return 200;
|
||||
}
|
||||
|
||||
int ADSBDemod::webapiSettingsPutPatch(
|
||||
bool force,
|
||||
const QStringList& channelSettingsKeys,
|
||||
|
@ -65,6 +65,8 @@ public:
|
||||
ADSBDemod(DeviceAPI *deviceAPI);
|
||||
virtual ~ADSBDemod();
|
||||
virtual void destroy() { delete this; }
|
||||
virtual void setDeviceAPI(DeviceAPI *deviceAPI);
|
||||
virtual DeviceAPI *getDeviceAPI() { return m_deviceAPI; }
|
||||
|
||||
using BasebandSampleSink::feed;
|
||||
virtual void feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end, bool po);
|
||||
@ -96,6 +98,10 @@ public:
|
||||
SWGSDRangel::SWGChannelSettings& response,
|
||||
QString& errorMessage);
|
||||
|
||||
virtual int webapiWorkspaceGet(
|
||||
SWGSDRangel::SWGWorkspaceInfo& response,
|
||||
QString& errorMessage);
|
||||
|
||||
virtual int webapiSettingsPutPatch(
|
||||
bool force,
|
||||
const QStringList& channelSettingsKeys,
|
||||
|
@ -2132,7 +2132,7 @@ QString ADSBDemodGUI::subAircraftString(Aircraft *aircraft, const QString &strin
|
||||
|
||||
bool ADSBDemodGUI::handleMessage(const Message& message)
|
||||
{
|
||||
if (DSPSignalNotification::match(message))
|
||||
if (DSPSignalNotification::match(message))
|
||||
{
|
||||
DSPSignalNotification& notif = (DSPSignalNotification&) message;
|
||||
int sr = notif.getSampleRate();
|
||||
@ -2143,7 +2143,12 @@ if (DSPSignalNotification::match(message))
|
||||
} else {
|
||||
ui->warning->setText("");
|
||||
}
|
||||
arrangeRollups();
|
||||
getRollupContents()->arrangeRollups();
|
||||
m_deviceCenterFrequency = notif.getCenterFrequency();
|
||||
m_basebandSampleRate = sr;
|
||||
ui->deltaFrequency->setValueRange(false, 7, -sr/2, sr/2);
|
||||
ui->deltaFrequencyLabel->setToolTip(tr("Range %1 %L2 Hz").arg(QChar(0xB1)).arg(sr/2));
|
||||
updateAbsoluteCenterFrequency();
|
||||
return true;
|
||||
}
|
||||
else if (ADSBDemodReport::MsgReportADSB::match(message))
|
||||
@ -2211,6 +2216,7 @@ void ADSBDemodGUI::on_deltaFrequency_changed(qint64 value)
|
||||
{
|
||||
m_channelMarker.setCenterFrequency(value);
|
||||
m_settings.m_inputFrequencyOffset = m_channelMarker.getCenterFrequency();
|
||||
updateAbsoluteCenterFrequency();
|
||||
applySettings();
|
||||
}
|
||||
|
||||
@ -2759,7 +2765,18 @@ void ADSBDemodGUI::onWidgetRolled(QWidget* widget, bool rollDown)
|
||||
(void) widget;
|
||||
(void) rollDown;
|
||||
|
||||
saveState(m_rollupState);
|
||||
RollupContents *rollupContents = getRollupContents();
|
||||
|
||||
if (rollupContents->hasExpandableWidgets()) {
|
||||
setSizePolicy(sizePolicy().horizontalPolicy(), QSizePolicy::Expanding);
|
||||
} else {
|
||||
setSizePolicy(sizePolicy().horizontalPolicy(), QSizePolicy::Fixed);
|
||||
}
|
||||
|
||||
int h = rollupContents->height() + getAdditionalHeight();
|
||||
resize(width(), h);
|
||||
|
||||
rollupContents->saveState(m_rollupState);
|
||||
applySettings();
|
||||
}
|
||||
|
||||
@ -2773,10 +2790,17 @@ void ADSBDemodGUI::onMenuDialogCalled(const QPoint &p)
|
||||
dialog.setReverseAPIPort(m_settings.m_reverseAPIPort);
|
||||
dialog.setReverseAPIDeviceIndex(m_settings.m_reverseAPIDeviceIndex);
|
||||
dialog.setReverseAPIChannelIndex(m_settings.m_reverseAPIChannelIndex);
|
||||
dialog.setDefaultTitle(m_displayedName);
|
||||
|
||||
if (m_deviceUISet->m_deviceMIMOEngine)
|
||||
{
|
||||
dialog.setNumberOfStreams(m_adsbDemod->getNumberOfDeviceStreams());
|
||||
dialog.setStreamIndex(m_settings.m_streamIndex);
|
||||
}
|
||||
|
||||
dialog.move(p);
|
||||
dialog.exec();
|
||||
|
||||
m_settings.m_inputFrequencyOffset = m_channelMarker.getCenterFrequency();
|
||||
m_settings.m_rgbColor = m_channelMarker.getColor().rgb();
|
||||
m_settings.m_title = m_channelMarker.getTitle();
|
||||
m_settings.m_useReverseAPI = dialog.useReverseAPI();
|
||||
@ -2786,22 +2810,17 @@ void ADSBDemodGUI::onMenuDialogCalled(const QPoint &p)
|
||||
m_settings.m_reverseAPIChannelIndex = dialog.getReverseAPIChannelIndex();
|
||||
|
||||
setWindowTitle(m_settings.m_title);
|
||||
setTitle(m_channelMarker.getTitle());
|
||||
setTitleColor(m_settings.m_rgbColor);
|
||||
|
||||
applySettings();
|
||||
}
|
||||
else if ((m_contextMenuType == ContextMenuStreamSettings) && (m_deviceUISet->m_deviceMIMOEngine))
|
||||
{
|
||||
DeviceStreamSelectionDialog dialog(this);
|
||||
dialog.setNumberOfStreams(m_adsbDemod->getNumberOfDeviceStreams());
|
||||
dialog.setStreamIndex(m_settings.m_streamIndex);
|
||||
dialog.move(p);
|
||||
dialog.exec();
|
||||
if (m_deviceUISet->m_deviceMIMOEngine)
|
||||
{
|
||||
m_settings.m_streamIndex = dialog.getSelectedStreamIndex();
|
||||
m_channelMarker.clearStreamIndexes();
|
||||
m_channelMarker.addStreamIndex(m_settings.m_streamIndex);
|
||||
updateIndexLabel();
|
||||
}
|
||||
|
||||
m_settings.m_streamIndex = dialog.getSelectedStreamIndex();
|
||||
m_channelMarker.clearStreamIndexes();
|
||||
m_channelMarker.addStreamIndex(m_settings.m_streamIndex);
|
||||
displayStreamIndex();
|
||||
applySettings();
|
||||
}
|
||||
|
||||
@ -3674,6 +3693,8 @@ ADSBDemodGUI::ADSBDemodGUI(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, Baseb
|
||||
m_pluginAPI(pluginAPI),
|
||||
m_deviceUISet(deviceUISet),
|
||||
m_channelMarker(this),
|
||||
m_deviceCenterFrequency(0),
|
||||
m_basebandSampleRate(1),
|
||||
m_basicSettingsShown(false),
|
||||
m_doApplySettings(true),
|
||||
m_tickCount(0),
|
||||
@ -3684,8 +3705,13 @@ ADSBDemodGUI::ADSBDemodGUI(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, Baseb
|
||||
m_highlightAircraft(nullptr),
|
||||
m_progressDialog(nullptr)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
setAttribute(Qt::WA_DeleteOnClose, true);
|
||||
m_helpURL = "plugins/channelrx/demodadsb/readme.md";
|
||||
RollupContents *rollupContents = getRollupContents();
|
||||
ui->setupUi(rollupContents);
|
||||
setSizePolicy(rollupContents->sizePolicy());
|
||||
rollupContents->arrangeRollups();
|
||||
connect(rollupContents, SIGNAL(widgetRolled(QWidget*,bool)), this, SLOT(onWidgetRolled(QWidget*,bool)));
|
||||
|
||||
m_osmPort = 0; // Pick a free port
|
||||
m_templateServer = new ADSBOSMTemplateServer("q2RVNAe3eFKCH4XsrE3r", m_osmPort);
|
||||
@ -3696,9 +3722,6 @@ ADSBDemodGUI::ADSBDemodGUI(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, Baseb
|
||||
ui->map->rootContext()->setContextProperty("navAidModel", &m_navAidModel);
|
||||
ui->map->setSource(QUrl(QStringLiteral("qrc:/map/map.qml")));
|
||||
|
||||
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(&m_dlm, &HttpDownloadManager::downloadComplete, this, &ADSBDemodGUI::downloadFinished);
|
||||
|
||||
@ -3731,7 +3754,6 @@ ADSBDemodGUI::ADSBDemodGUI(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, Baseb
|
||||
m_settings.setRollupState(&m_rollupState);
|
||||
|
||||
m_deviceUISet->addChannelMarker(&m_channelMarker);
|
||||
m_deviceUISet->addRollupWidget(this);
|
||||
|
||||
connect(&m_channelMarker, SIGNAL(changedByCursor()), this, SLOT(channelMarkerChangedByCursor()));
|
||||
connect(&m_channelMarker, SIGNAL(highlightedByCursor()), this, SLOT(channelMarkerHighlightedByCursor()));
|
||||
@ -3829,6 +3851,7 @@ ADSBDemodGUI::ADSBDemodGUI(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, Baseb
|
||||
|
||||
updateDeviceSetList();
|
||||
displaySettings();
|
||||
makeUIConnections();
|
||||
applySettings(true);
|
||||
|
||||
connect(&m_importTimer, &QTimer::timeout, this, &ADSBDemodGUI::import);
|
||||
@ -3903,6 +3926,7 @@ void ADSBDemodGUI::displaySettings()
|
||||
|
||||
setTitleColor(m_settings.m_rgbColor);
|
||||
setWindowTitle(m_channelMarker.getTitle());
|
||||
setTitle(m_channelMarker.getTitle());
|
||||
|
||||
blockApplySettings(true);
|
||||
|
||||
@ -3940,7 +3964,7 @@ void ADSBDemodGUI::displaySettings()
|
||||
ui->logFilename->setToolTip(QString(".csv log filename: %1").arg(m_settings.m_logFilename));
|
||||
ui->logEnable->setChecked(m_settings.m_logEnabled);
|
||||
|
||||
displayStreamIndex();
|
||||
updateIndexLabel();
|
||||
|
||||
QFont font(m_settings.m_tableFontName, m_settings.m_tableFontSize);
|
||||
ui->adsbData->setFont(font);
|
||||
@ -3989,27 +4013,20 @@ void ADSBDemodGUI::displaySettings()
|
||||
applyMapSettings();
|
||||
applyImportSettings();
|
||||
|
||||
restoreState(m_rollupState);
|
||||
getRollupContents()->restoreState(m_rollupState);
|
||||
blockApplySettings(false);
|
||||
}
|
||||
|
||||
void ADSBDemodGUI::displayStreamIndex()
|
||||
{
|
||||
if (m_deviceUISet->m_deviceMIMOEngine) {
|
||||
setStreamIndicator(tr("%1").arg(m_settings.m_streamIndex));
|
||||
} else {
|
||||
setStreamIndicator("S"); // single channel indicator
|
||||
}
|
||||
}
|
||||
|
||||
void ADSBDemodGUI::leaveEvent(QEvent*)
|
||||
void ADSBDemodGUI::leaveEvent(QEvent* event)
|
||||
{
|
||||
m_channelMarker.setHighlighted(false);
|
||||
ChannelGUI::leaveEvent(event);
|
||||
}
|
||||
|
||||
void ADSBDemodGUI::enterEvent(QEvent*)
|
||||
void ADSBDemodGUI::enterEvent(QEvent* event)
|
||||
{
|
||||
m_channelMarker.setHighlighted(true);
|
||||
ChannelGUI::enterEvent(event);
|
||||
}
|
||||
|
||||
void ADSBDemodGUI::blockApplySettings(bool block)
|
||||
@ -4659,3 +4676,36 @@ void ADSBDemodGUI::preferenceChanged(int elementType)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ADSBDemodGUI::makeUIConnections()
|
||||
{
|
||||
QObject::connect(ui->deltaFrequency, &ValueDialZ::changed, this, &ADSBDemodGUI::on_deltaFrequency_changed);
|
||||
QObject::connect(ui->rfBW, &QSlider::valueChanged, this, &ADSBDemodGUI::on_rfBW_valueChanged);
|
||||
QObject::connect(ui->threshold, &QDial::valueChanged, this, &ADSBDemodGUI::on_threshold_valueChanged);
|
||||
QObject::connect(ui->phaseSteps, &QDial::valueChanged, this, &ADSBDemodGUI::on_phaseSteps_valueChanged);
|
||||
QObject::connect(ui->tapsPerPhase, &QDial::valueChanged, this, &ADSBDemodGUI::on_tapsPerPhase_valueChanged);
|
||||
QObject::connect(ui->adsbData, &QTableWidget::cellClicked, this, &ADSBDemodGUI::on_adsbData_cellClicked);
|
||||
QObject::connect(ui->adsbData, &QTableWidget::cellDoubleClicked, this, &ADSBDemodGUI::on_adsbData_cellDoubleClicked);
|
||||
QObject::connect(ui->spb, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &ADSBDemodGUI::on_spb_currentIndexChanged);
|
||||
QObject::connect(ui->correlateFullPreamble, &ButtonSwitch::clicked, this, &ADSBDemodGUI::on_correlateFullPreamble_clicked);
|
||||
QObject::connect(ui->demodModeS, &ButtonSwitch::clicked, this, &ADSBDemodGUI::on_demodModeS_clicked);
|
||||
QObject::connect(ui->feed, &ButtonSwitch::clicked, this, &ADSBDemodGUI::on_feed_clicked);
|
||||
QObject::connect(ui->notifications, &QToolButton::clicked, this, &ADSBDemodGUI::on_notifications_clicked);
|
||||
QObject::connect(ui->flightInfo, &QToolButton::clicked, this, &ADSBDemodGUI::on_flightInfo_clicked);
|
||||
QObject::connect(ui->findOnMapFeature, &QToolButton::clicked, this, &ADSBDemodGUI::on_findOnMapFeature_clicked);
|
||||
QObject::connect(ui->getOSNDB, &QToolButton::clicked, this, &ADSBDemodGUI::on_getOSNDB_clicked);
|
||||
QObject::connect(ui->getAirportDB, &QToolButton::clicked, this, &ADSBDemodGUI::on_getAirportDB_clicked);
|
||||
QObject::connect(ui->getAirspacesDB, &QToolButton::clicked, this, &ADSBDemodGUI::on_getAirspacesDB_clicked);
|
||||
QObject::connect(ui->flightPaths, &ButtonSwitch::clicked, this, &ADSBDemodGUI::on_flightPaths_clicked);
|
||||
QObject::connect(ui->allFlightPaths, &ButtonSwitch::clicked, this, &ADSBDemodGUI::on_allFlightPaths_clicked);
|
||||
QObject::connect(ui->device, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &ADSBDemodGUI::on_device_currentIndexChanged);
|
||||
QObject::connect(ui->displaySettings, &QToolButton::clicked, this, &ADSBDemodGUI::on_displaySettings_clicked);
|
||||
QObject::connect(ui->logEnable, &ButtonSwitch::clicked, this, &ADSBDemodGUI::on_logEnable_clicked);
|
||||
QObject::connect(ui->logFilename, &QToolButton::clicked, this, &ADSBDemodGUI::on_logFilename_clicked);
|
||||
QObject::connect(ui->logOpen, &QToolButton::clicked, this, &ADSBDemodGUI::on_logOpen_clicked);
|
||||
}
|
||||
|
||||
void ADSBDemodGUI::updateAbsoluteCenterFrequency()
|
||||
{
|
||||
setStatusFrequency(m_deviceCenterFrequency + m_settings.m_inputFrequencyOffset);
|
||||
}
|
||||
|
@ -752,6 +752,18 @@ public:
|
||||
QByteArray serialize() const;
|
||||
bool deserialize(const QByteArray& data);
|
||||
virtual MessageQueue *getInputMessageQueue() { return &m_inputMessageQueue; }
|
||||
virtual void setWorkspaceIndex(int index) { m_settings.m_workspaceIndex = index; };
|
||||
virtual int getWorkspaceIndex() const { return m_settings.m_workspaceIndex; };
|
||||
virtual void setGeometryBytes(const QByteArray& blob) { m_settings.m_geometryBytes = blob; };
|
||||
virtual QByteArray getGeometryBytes() const { return m_settings.m_geometryBytes; };
|
||||
virtual QString getTitle() const { return m_settings.m_title; };
|
||||
virtual QColor getTitleColor() const { return m_settings.m_rgbColor; };
|
||||
virtual void zetHidden(bool hidden) { m_settings.m_hidden = hidden; }
|
||||
virtual bool getHidden() const { return m_settings.m_hidden; }
|
||||
virtual ChannelMarker& getChannelMarker() { return m_channelMarker; }
|
||||
virtual int getStreamIndex() const { return m_settings.m_streamIndex; }
|
||||
virtual void setStreamIndex(int streamIndex) { m_settings.m_streamIndex = streamIndex; }
|
||||
|
||||
void highlightAircraft(Aircraft *aircraft);
|
||||
void targetAircraft(Aircraft *aircraft);
|
||||
void target(const QString& name, float az, float el, float range);
|
||||
@ -776,6 +788,8 @@ private:
|
||||
ChannelMarker m_channelMarker;
|
||||
RollupState m_rollupState;
|
||||
ADSBDemodSettings m_settings;
|
||||
qint64 m_deviceCenterFrequency;
|
||||
int m_basebandSampleRate;
|
||||
bool m_basicSettingsShown;
|
||||
bool m_doApplySettings;
|
||||
|
||||
@ -836,8 +850,10 @@ private:
|
||||
void blockApplySettings(bool block);
|
||||
void applySettings(bool force = false);
|
||||
void displaySettings();
|
||||
void displayStreamIndex();
|
||||
bool handleMessage(const Message& message);
|
||||
void makeUIConnections();
|
||||
void updateAbsoluteCenterFrequency();
|
||||
|
||||
void updatePosition(Aircraft *aircraft);
|
||||
bool updateLocalPosition(Aircraft *aircraft, double latitude, double longitude, bool surfacePosition);
|
||||
void sendToMap(Aircraft *aircraft, QList<SWGSDRangel::SWGMapAnimation *> *animations);
|
||||
|
@ -1,12 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>ADSBDemodGUI</class>
|
||||
<widget class="RollupWidget" name="ADSBDemodGUI">
|
||||
<widget class="RollupContents" name="ADSBDemodGUI">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>604</width>
|
||||
<width>600</width>
|
||||
<height>1046</height>
|
||||
</rect>
|
||||
</property>
|
||||
@ -18,7 +18,7 @@
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>350</width>
|
||||
<width>600</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
@ -35,13 +35,13 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>600</width>
|
||||
<width>598</width>
|
||||
<height>141</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>600</width>
|
||||
<width>598</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
@ -758,7 +758,7 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>140</y>
|
||||
<width>600</width>
|
||||
<width>598</width>
|
||||
<height>600</height>
|
||||
</rect>
|
||||
</property>
|
||||
@ -770,7 +770,7 @@
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>600</width>
|
||||
<width>598</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
@ -1269,17 +1269,17 @@
|
||||
<extends>QWidget</extends>
|
||||
<header location="global">QtQuickWidgets/QQuickWidget</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>RollupWidget</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>gui/rollupwidget.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>ButtonSwitch</class>
|
||||
<extends>QToolButton</extends>
|
||||
<header>gui/buttonswitch.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>RollupContents</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>gui/rollupcontents.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>ValueDialZ</class>
|
||||
<extends>QWidget</extends>
|
||||
|
@ -96,6 +96,8 @@ void ADSBDemodSettings::resetToDefaults()
|
||||
m_displayPhotos = true;
|
||||
m_verboseModelMatching = false;
|
||||
m_airfieldElevation = 0;
|
||||
m_workspaceIndex = 0;
|
||||
m_hidden = false;
|
||||
}
|
||||
|
||||
QByteArray ADSBDemodSettings::serialize() const
|
||||
@ -172,6 +174,9 @@ QByteArray ADSBDemodSettings::serialize() const
|
||||
s.writeString(56, m_importMaxLatitude);
|
||||
s.writeString(57, m_importMinLongitude);
|
||||
s.writeString(58, m_importMaxLongitude);
|
||||
s.writeS32(59, m_workspaceIndex);
|
||||
s.writeBlob(60, m_geometryBytes);
|
||||
s.writeBool(61, m_hidden);
|
||||
|
||||
for (int i = 0; i < ADSBDEMOD_COLUMNS; i++) {
|
||||
s.writeS32(100 + i, m_columnIndexes[i]);
|
||||
@ -298,6 +303,9 @@ bool ADSBDemodSettings::deserialize(const QByteArray& data)
|
||||
d.readString(56, &m_importMaxLatitude, "");
|
||||
d.readString(57, &m_importMinLongitude, "");
|
||||
d.readString(58, &m_importMaxLongitude, "");
|
||||
d.readS32(59, &m_workspaceIndex, 0);
|
||||
d.readBlob(60, &m_geometryBytes);
|
||||
d.readBool(61, &m_hidden, false);
|
||||
|
||||
for (int i = 0; i < ADSBDEMOD_COLUMNS; i++) {
|
||||
d.readS32(100 + i, &m_columnIndexes[i], i);
|
||||
|
@ -116,6 +116,10 @@ struct ADSBDemodSettings
|
||||
uint16_t m_reverseAPIPort;
|
||||
uint16_t m_reverseAPIDeviceIndex;
|
||||
uint16_t m_reverseAPIChannelIndex;
|
||||
int m_workspaceIndex;
|
||||
QByteArray m_geometryBytes;
|
||||
bool m_hidden;
|
||||
|
||||
int m_columnIndexes[ADSBDEMOD_COLUMNS];//!< How the columns are ordered in the table
|
||||
int m_columnSizes[ADSBDEMOD_COLUMNS]; //!< Size of the coumns in the table
|
||||
|
||||
|
@ -2,6 +2,8 @@
|
||||
|
||||
<h2>Introduction</h2>
|
||||
|
||||
The top and bottom bars of the device window are described [here](../../../sdrgui/device/readme.md)
|
||||
|
||||
The ADS-B demodulator plugin can be used to receive and display ADS-B aircraft information. This is information about an aircraft, such as position, altitude, heading and speed, broadcast by aircraft on 1090MHz, in the 1090ES (Extended Squitter) format. 1090ES frames have a chip rate of 2Mchip/s, so the baseband sample rate should be set to be greater than 2MSa/s.
|
||||
|
||||
As well as displaying information received via ADS-B, the plugin can also combine information from a number of databases to display more information about the aircraft and flight.
|
||||
@ -14,6 +16,8 @@ The ADS-B plugin can send aicraft for display on the [Map Feature](../../feature
|
||||
|
||||
<h2>Interface</h2>
|
||||
|
||||
The top and bottom bars of the channel window are described [here](../../../sdrgui/channel/readme.md)
|
||||
|
||||
![ADS-B Demodulator plugin settings](../../../doc/img/ADSBDemod_plugin_settings.png)
|
||||
|
||||
<h3>1: Frequency shift from center frequency of reception value</h3>
|
||||
|