1
0
mirror of https://github.com/f4exb/sdrangel.git synced 2024-11-26 09:48:45 -05:00

Merge branch 'f4exb:master' into mac_package

This commit is contained in:
srcejon 2022-05-26 10:08:16 +01:00 committed by GitHub
commit e59b00dfd5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
142 changed files with 8964 additions and 13332 deletions

View File

@ -1,3 +1,23 @@
sdrangel (7.2.1-1) unstable; urgency=medium
* AMBE feature: fixed many errors preventing build on Windows and MacOS. Issue #1254
-- Edouard Griffiths, F4EXB <f4exb06@gmail.com> Thu, 26 May 2022 03:12:00 +0200
sdrangel (7.2.0-1) unstable; urgency=medium
* Support hardware AMBE decoding wih a new feature plugin. Implements #1254
-- Edouard Griffiths, F4EXB <f4exb06@gmail.com> Wed, 25 May 2022 16:35:36 +0200
sdrangel (7.1.0-1) unstable; urgency=medium
* Support LimeRFE wtih a new feature plugin. Implements #1251
* Fixed auto stack workspaces status save/restore
* Fix typing errors in readme's. PR #1253
-- Edouard Griffiths, F4EXB <f4exb06@gmail.com> Sun, 22 May 2022 22:24:21 +0200
sdrangel (7.0.1-1) unstable; urgency=medium
* Added ability to build a package for MacOS. PR #1249
@ -9,7 +29,7 @@ sdrangel (7.0.1-1) unstable; urgency=medium
* Save/restore auto-stack function in workspaces. Part of #1250
* Fixed ButtonSwitch background color with stylesheets
-- Edouard Griffiths, F4EXB <f4exb06@gmail.com> Thu, 19 May 2022 26:02:31 +0200
-- Edouard Griffiths, F4EXB <f4exb06@gmail.com> Thu, 19 May 2022 16:02:31 +0200
sdrangel (7.0.0-1) unstable; urgency=medium

View File

@ -15,7 +15,7 @@ set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
# configure version
set(sdrangel_VERSION_MAJOR "7")
set(sdrangel_VERSION_MINOR "0")
set(sdrangel_VERSION_MINOR "2")
set(sdrangel_VERSION_PATCH "1")
set(sdrangel_VERSION_SUFFIX "")
@ -393,7 +393,7 @@ else()
find_package(Codec2)
find_package(CM256cc)
find_package(LibMbe)
find_package(SerialDV REQUIRED)
find_package(SerialDV)
find_package(LibDSDcc)
find_package(Sgp4)
find_package(AptDec)

20
debian/changelog vendored
View File

@ -1,3 +1,23 @@
sdrangel (7.2.1-1) unstable; urgency=medium
* AMBE feature: fixed many errors preventing build on Windows and MacOS. Issue #1254
-- Edouard Griffiths, F4EXB <f4exb06@gmail.com> Thu, 26 May 2022 03:12:00 +0200
sdrangel (7.2.0-1) unstable; urgency=medium
* Support hardware AMBE decoding wih a new feature plugin. Implements #1254
-- Edouard Griffiths, F4EXB <f4exb06@gmail.com> Wed, 25 May 2022 16:35:36 +0200
sdrangel (7.1.0-1) unstable; urgency=medium
* Support LimeRFE wtih a new feature plugin. Implements #1251
* Fixed auto stack workspaces status save/restore
* Fix typing errors in readme's. PR #1253
-- Edouard Griffiths, F4EXB <f4exb06@gmail.com> Sun, 22 May 2022 22:24:21 +0200
sdrangel (7.0.1-1) unstable; urgency=medium
* Added ability to build a package for MacOS. PR #1249

BIN
doc/img/AMBE_plugin.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

BIN
doc/img/AMBE_plugin.xcf Normal file

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 128 KiB

After

Width:  |  Height:  |  Size: 131 KiB

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

BIN
doc/img/LimeRFE_plugin.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

BIN
doc/img/LimeRFE_plugin.xcf Normal file

Binary file not shown.

View File

Before

Width:  |  Height:  |  Size: 9.1 KiB

After

Width:  |  Height:  |  Size: 9.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

View File

Before

Width:  |  Height:  |  Size: 9.8 KiB

After

Width:  |  Height:  |  Size: 9.8 KiB

View File

Before

Width:  |  Height:  |  Size: 9.2 KiB

After

Width:  |  Height:  |  Size: 9.2 KiB

View File

@ -68,7 +68,7 @@ UDP port number to forward received messages to.
<h3>12: UDP format</h3>
The format the messages are forwared via UDP in. This can be either binary (which is useful for SDRangel's PERTester feature) or NMEA (which is useful for 3rd party applications such as OpenCPN).
The format the messages are forwarded via UDP in. This can be either binary (which is useful for SDRangel's PERTester feature) or NMEA (which is useful for 3rd party applications such as OpenCPN).
<h3>13: Start/stop Logging Messages to .csv File</h3>

View File

@ -39,6 +39,7 @@
#include "dsp/dspcommands.h"
#include "device/deviceapi.h"
#include "feature/feature.h"
#include "feature/featureset.h"
#include "settings/serializable.h"
#include "util/db.h"
#include "maincore.h"
@ -46,6 +47,8 @@
#include "dsddemod.h"
MESSAGE_CLASS_DEFINITION(DSDDemod::MsgConfigureDSDDemod, Message)
MESSAGE_CLASS_DEFINITION(DSDDemod::MsgQueryAvailableAMBEFeatures, Message)
MESSAGE_CLASS_DEFINITION(DSDDemod::MsgReportAvailableAMBEFeatures, Message)
const char* const DSDDemod::m_channelIdURI = "sdrangel.channel.dsddemod";
const char* const DSDDemod::m_channelId = "DSDDemod";
@ -82,6 +85,20 @@ DSDDemod::DSDDemod(DeviceAPI *deviceAPI) :
this,
&DSDDemod::handleIndexInDeviceSetChanged
);
QObject::connect(
MainCore::instance(),
&MainCore::featureAdded,
this,
&DSDDemod::handleFeatureAdded
);
QObject::connect(
MainCore::instance(),
&MainCore::featureRemoved,
this,
&DSDDemod::handleFeatureRemoved
);
scanAvailableAMBEFeatures();
}
DSDDemod::~DSDDemod()
@ -176,6 +193,11 @@ bool DSDDemod::handleMessage(const Message& cmd)
return true;
}
else if (MsgQueryAvailableAMBEFeatures::match(cmd))
{
notifyUpdateAMBEFeatures();
return true;
}
else
{
return false;
@ -219,6 +241,8 @@ void DSDDemod::applySettings(const DSDDemodSettings& settings, bool force)
<< " m_traceStroke: " << settings.m_traceStroke
<< " m_traceDecay: " << settings.m_traceDecay
<< " m_streamIndex: " << settings.m_streamIndex
<< " m_ambeFeatureIndex: " << settings.m_ambeFeatureIndex
<< " m_connectAMBE: " << settings.m_connectAMBE
<< " force: " << force;
QList<QString> reverseAPIKeys;
@ -280,6 +304,30 @@ void DSDDemod::applySettings(const DSDDemodSettings& settings, bool force)
if ((settings.m_audioDeviceName != m_settings.m_audioDeviceName) || force) {
reverseAPIKeys.append("audioDeviceName");
}
if ((settings.m_ambeFeatureIndex != m_settings.m_ambeFeatureIndex) || force) {
reverseAPIKeys.append("ambeFeatureIndex");
}
if ((settings.m_connectAMBE != m_settings.m_connectAMBE) || force) {
reverseAPIKeys.append("connectAMBE");
}
if ((m_settings.m_connectAMBE != settings.m_connectAMBE)
|| (m_settings.m_ambeFeatureIndex != settings.m_ambeFeatureIndex) || force)
{
if (settings.m_connectAMBE)
{
for (const auto& feature : m_availableAMBEFeatures)
{
if (feature.m_featureIndex == settings.m_ambeFeatureIndex) {
m_basebandSink->setAMBEFeature(feature.m_feature);
}
}
}
else
{
m_basebandSink->setAMBEFeature(nullptr);
}
}
if (m_settings.m_streamIndex != settings.m_streamIndex)
{
@ -339,6 +387,32 @@ bool DSDDemod::deserialize(const QByteArray& data)
}
}
void DSDDemod::scanAvailableAMBEFeatures()
{
MainCore *mainCore = MainCore::instance();
int nbFeatures = mainCore->getFeatureeSets()[0]->getNumberOfFeatures();
m_availableAMBEFeatures.clear();
for (int i = 0; i < nbFeatures; i++)
{
Feature *feature = mainCore->getFeatureeSets()[0]->getFeatureAt(i);
if (feature->getURI() == "sdrangel.feature.ambe") {
m_availableAMBEFeatures[feature] = DSDDemodSettings::AvailableAMBEFeature{i, feature};
}
}
}
void DSDDemod::notifyUpdateAMBEFeatures()
{
if (getMessageQueueToGUI())
{
MsgReportAvailableAMBEFeatures *msg = MsgReportAvailableAMBEFeatures::create();
msg->getFeatures() = m_availableAMBEFeatures.values();
getMessageQueueToGUI()->push(msg);
}
}
void DSDDemod::sendSampleRateToDemodAnalyzer()
{
QList<ObjectPipe*> pipes;
@ -492,6 +566,12 @@ void DSDDemod::webapiUpdateChannelSettings(
if (channelSettingsKeys.contains("reverseAPIChannelIndex")) {
settings.m_reverseAPIChannelIndex = response.getDsdDemodSettings()->getReverseApiChannelIndex();
}
if (channelSettingsKeys.contains("ambeFeatureIndex")) {
settings.m_ambeFeatureIndex = response.getDsdDemodSettings()->getAmbeFeatureIndex();
}
if (channelSettingsKeys.contains("connectAMBE")) {
settings.m_connectAMBE = response.getDsdDemodSettings()->getConnectAmbe() != 0;
}
if (settings.m_channelMarker && channelSettingsKeys.contains("channelMarker")) {
settings.m_channelMarker->updateFrom(channelSettingsKeys, response.getDsdDemodSettings()->getChannelMarker());
}
@ -558,6 +638,8 @@ void DSDDemod::webapiFormatChannelSettings(SWGSDRangel::SWGChannelSettings& resp
response.getDsdDemodSettings()->setReverseApiPort(settings.m_reverseAPIPort);
response.getDsdDemodSettings()->setReverseApiDeviceIndex(settings.m_reverseAPIDeviceIndex);
response.getDsdDemodSettings()->setReverseApiChannelIndex(settings.m_reverseAPIChannelIndex);
response.getDsdDemodSettings()->setAmbeFeatureIndex(settings.m_ambeFeatureIndex);
response.getDsdDemodSettings()->setConnectAmbe(settings.m_connectAMBE ? 1 : 0);
if (settings.m_channelMarker)
{
@ -744,6 +826,12 @@ void DSDDemod::webapiFormatChannelSettings(
if (channelSettingsKeys.contains("streamIndex") || force) {
swgDSDDemodSettings->setStreamIndex(settings.m_streamIndex);
}
if (channelSettingsKeys.contains("ambeFeatureIndex") || force) {
swgDSDDemodSettings->setAmbeFeatureIndex(settings.m_ambeFeatureIndex);
}
if (channelSettingsKeys.contains("connectAMBE") || force) {
swgDSDDemodSettings->setConnectAmbe(settings.m_connectAMBE ? 1 : 0);
}
if (settings.m_channelMarker && (channelSettingsKeys.contains("channelMarker") || force))
{
@ -794,3 +882,40 @@ void DSDDemod::handleIndexInDeviceSetChanged(int index)
m_basebandSink->setFifoLabel(fifoLabel);
m_basebandSink->setAudioFifoLabel(fifoLabel);
}
void DSDDemod::handleFeatureAdded(int featureSetIndex, Feature *feature)
{
if (featureSetIndex != 0) {
return;
}
if ((feature->getURI() == "sdrangel.feature.ambe") && !m_availableAMBEFeatures.contains(feature))
{
m_availableAMBEFeatures[feature] = DSDDemodSettings::AvailableAMBEFeature{feature->getIndexInFeatureSet(), feature};
if (m_settings.m_connectAMBE && (m_settings.m_ambeFeatureIndex == feature->getIndexInFeatureSet())) {
m_basebandSink->setAMBEFeature(feature);
}
notifyUpdateAMBEFeatures();
}
}
void DSDDemod::handleFeatureRemoved(int featureSetIndex, Feature *feature)
{
if (featureSetIndex != 0) {
return;
}
if (m_availableAMBEFeatures.contains(feature))
{
if (m_settings.m_ambeFeatureIndex == m_availableAMBEFeatures[feature].m_featureIndex)
{
m_settings.m_connectAMBE = false;
m_basebandSink->setAMBEFeature(nullptr);
}
m_availableAMBEFeatures.remove(feature);
notifyUpdateAMBEFeatures();
}
}

View File

@ -62,6 +62,38 @@ public:
{ }
};
class MsgQueryAvailableAMBEFeatures : public Message {
MESSAGE_CLASS_DECLARATION
public:
static MsgQueryAvailableAMBEFeatures* create() {
return new MsgQueryAvailableAMBEFeatures();
}
protected:
MsgQueryAvailableAMBEFeatures() :
Message()
{ }
};
class MsgReportAvailableAMBEFeatures : public Message {
MESSAGE_CLASS_DECLARATION
public:
QList<DSDDemodSettings::AvailableAMBEFeature>& getFeatures() { return m_availableFeatures; }
static MsgReportAvailableAMBEFeatures* create() {
return new MsgReportAvailableAMBEFeatures();
}
private:
QList<DSDDemodSettings::AvailableAMBEFeature> m_availableFeatures;
MsgReportAvailableAMBEFeatures() :
Message()
{}
};
DSDDemod(DeviceAPI *deviceAPI);
virtual ~DSDDemod();
virtual void destroy() { delete this; }
@ -140,6 +172,7 @@ private:
DSDDemodBaseband *m_basebandSink;
DSDDemodSettings m_settings;
int m_basebandSampleRate; //!< stored from device message used when starting baseband sink
QHash<Feature*, DSDDemodSettings::AvailableAMBEFeature> m_availableAMBEFeatures;
QNetworkAccessManager *m_networkManager;
QNetworkRequest m_networkRequest;
@ -148,6 +181,8 @@ private:
virtual bool handleMessage(const Message& cmd);
void applySettings(const DSDDemodSettings& settings, bool force = false);
void scanAvailableAMBEFeatures();
void notifyUpdateAMBEFeatures();
void sendSampleRateToDemodAnalyzer();
void webapiFormatChannelReport(SWGSDRangel::SWGChannelReport& response);
void webapiReverseSendSettings(QList<QString>& channelSettingsKeys, const DSDDemodSettings& settings, bool force);
@ -167,6 +202,8 @@ private:
private slots:
void networkManagerFinished(QNetworkReply *reply);
void handleIndexInDeviceSetChanged(int index);
void handleFeatureAdded(int featureSetIndex, Feature *feature);
void handleFeatureRemoved(int featureSetIndex, Feature *feature);
};
#endif // INCLUDE_DSDDEMOD_H

View File

@ -29,6 +29,7 @@
class DownChannelizer;
class ChannelAPI;
class Feature;
class DSDDemodBaseband : public QObject
{
@ -75,6 +76,7 @@ public:
void setChannel(ChannelAPI *channel);
void setFifoLabel(const QString& label) { m_sampleFifo.setLabel(label); }
void setAudioFifoLabel(const QString& label) { m_sink.setAudioFifoLabel(label); }
void setAMBEFeature(Feature *ambeFeature) { m_sink.setAmbeFeature(ambeFeature); }
private:
SampleSinkFifo m_sampleFifo;

View File

@ -113,6 +113,13 @@ bool DSDDemodGUI::handleMessage(const Message& message)
updateAbsoluteCenterFrequency();
return true;
}
else if (DSDDemod::MsgReportAvailableAMBEFeatures::match(message))
{
DSDDemod::MsgReportAvailableAMBEFeatures& report = (DSDDemod::MsgReportAvailableAMBEFeatures&) message;
m_availableAMBEFeatures = report.getFeatures();
updateAMBEFeaturesList();
return true;
}
else
{
return false;
@ -263,6 +270,19 @@ void DSDDemodGUI::on_symbolPLLLock_toggled(bool checked)
applySettings();
}
void DSDDemodGUI::on_ambeSupport_clicked(bool checked)
{
m_settings.m_connectAMBE = checked;
m_settings.m_ambeFeatureIndex = m_availableAMBEFeatures[ui->ambeFeatures->currentIndex()].m_featureIndex;
applySettings();
}
void DSDDemodGUI::on_ambeFeatures_currentIndexChanged(int index)
{
m_settings.m_ambeFeatureIndex = m_availableAMBEFeatures[index].m_featureIndex;
applySettings();
}
void DSDDemodGUI::onWidgetRolled(QWidget* widget, bool rollDown)
{
(void) widget;
@ -490,6 +510,17 @@ void DSDDemodGUI::displaySettings()
ui->traceDecayText->setText(QString("%1").arg(m_settings.m_traceDecay));
m_scopeVisXY->setDecay(m_settings.m_traceDecay);
ui->ambeSupport->setChecked(m_settings.m_connectAMBE);
for (int i = 0; i < ui->ambeFeatures->count(); i++)
{
if (ui->ambeFeatures->itemData(i).toInt() == m_settings.m_ambeFeatureIndex)
{
ui->ambeFeatures->setCurrentIndex(i);
break;
}
}
updateIndexLabel();
getRollupContents()->restoreState(m_rollupState);
@ -497,6 +528,32 @@ void DSDDemodGUI::displaySettings()
blockApplySettings(false);
}
void DSDDemodGUI::updateAMBEFeaturesList()
{
ui->ambeFeatures->blockSignals(true);
ui->ambeSupport->blockSignals(true);
ui->ambeFeatures->clear();
bool unsetAMBE = true;
for (int i = 0; i < m_availableAMBEFeatures.count(); i++)
{
ui->ambeFeatures->addItem(tr("F:%1").arg(m_availableAMBEFeatures[i].m_featureIndex), m_availableAMBEFeatures[i].m_featureIndex);
if (m_settings.m_ambeFeatureIndex == m_availableAMBEFeatures[i].m_featureIndex)
{
unsetAMBE = false;
ui->ambeFeatures->setCurrentIndex(i);
}
}
if (unsetAMBE) {
ui->ambeSupport->setChecked(false);
}
ui->ambeSupport->blockSignals(false);
ui->ambeFeatures->blockSignals(false);
}
void DSDDemodGUI::applySettings(bool force)
{
if (m_doApplySettings)
@ -658,6 +715,8 @@ void DSDDemodGUI::makeUIConnections()
QObject::connect(ui->audioMute, &QToolButton::toggled, this, &DSDDemodGUI::on_audioMute_toggled);
QObject::connect(ui->symbolPLLLock, &QToolButton::toggled, this, &DSDDemodGUI::on_symbolPLLLock_toggled);
QObject::connect(ui->viewStatusLog, &QPushButton::clicked, this, &DSDDemodGUI::on_viewStatusLog_clicked);
QObject::connect(ui->ambeSupport, &QCheckBox::clicked, this, &DSDDemodGUI::on_ambeSupport_clicked);
QObject::connect(ui->ambeFeatures, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &DSDDemodGUI::on_ambeFeatures_currentIndexChanged);
}
void DSDDemodGUI::updateAbsoluteCenterFrequency()

View File

@ -90,6 +90,7 @@ private:
qint64 m_deviceCenterFrequency;
int m_basebandSampleRate;
bool m_doApplySettings;
QList<DSDDemodSettings::AvailableAMBEFeature> m_availableAMBEFeatures;
ScopeVisXY* m_scopeVisXY;
@ -117,6 +118,7 @@ private:
void blockApplySettings(bool block);
void applySettings(bool force = false);
void displaySettings();
void updateAMBEFeaturesList();
void updateMyPosition();
bool handleMessage(const Message& message);
void makeUIConnections();
@ -145,6 +147,8 @@ private slots:
void on_highPassFilter_toggled(bool checked);
void on_audioMute_toggled(bool checked);
void on_symbolPLLLock_toggled(bool checked);
void on_ambeSupport_clicked(bool checked);
void on_ambeFeatures_currentIndexChanged(int index);
void onWidgetRolled(QWidget* widget, bool rollDown);
void onMenuDialogCalled(const QPoint& p);
void on_viewStatusLog_clicked();

View File

@ -1231,6 +1231,29 @@
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
<widget class="QCheckBox" name="ambeSupport">
<property name="geometry">
<rect>
<x>10</x>
<y>170</y>
<width>71</width>
<height>23</height>
</rect>
</property>
<property name="text">
<string>AMBE</string>
</property>
</widget>
<widget class="QComboBox" name="ambeFeatures">
<property name="geometry">
<rect>
<x>80</x>
<y>170</y>
<width>50</width>
<height>20</height>
</rect>
</property>
</widget>
</widget>
</item>
</layout>

View File

@ -30,7 +30,7 @@
const PluginDescriptor DSDDemodPlugin::m_pluginDescriptor = {
DSDDemod::m_channelId,
QStringLiteral("DSD Demodulator"),
QStringLiteral("7.0.0"),
QStringLiteral("7.2.0"),
QStringLiteral("(c) Edouard Griffiths, F4EXB"),
QStringLiteral("https://github.com/f4exb/sdrangel"),
true,

View File

@ -61,6 +61,8 @@ void DSDDemodSettings::resetToDefaults()
m_reverseAPIChannelIndex = 0;
m_workspaceIndex = 0;
m_hidden = false;
m_ambeFeatureIndex = -1;
m_connectAMBE = false;
}
QByteArray DSDDemodSettings::serialize() const
@ -107,6 +109,8 @@ QByteArray DSDDemodSettings::serialize() const
s.writeS32(32, m_workspaceIndex);
s.writeBlob(33, m_geometryBytes);
s.writeBool(34, m_hidden);
s.writeS32(35, m_ambeFeatureIndex);
s.writeBool(36, m_connectAMBE);
return s.final();
}
@ -190,6 +194,8 @@ bool DSDDemodSettings::deserialize(const QByteArray& data)
d.readS32(32, &m_workspaceIndex, 0);
d.readBlob(33, &m_geometryBytes);
d.readBool(34, &m_hidden, false);
d.readS32(35, &m_ambeFeatureIndex, -1);
d.readBool(36, &m_connectAMBE, false);
return true;
}

View File

@ -21,9 +21,20 @@
#include <QByteArray>
class Serializable;
class Feature;
struct DSDDemodSettings
{
struct AvailableAMBEFeature
{
int m_featureIndex;
Feature *m_feature;
AvailableAMBEFeature() = default;
AvailableAMBEFeature(const AvailableAMBEFeature&) = default;
AvailableAMBEFeature& operator=(const AvailableAMBEFeature&) = default;
};
qint64 m_inputFrequencyOffset;
Real m_rfBandwidth;
Real m_fmDeviation;
@ -55,6 +66,8 @@ struct DSDDemodSettings
int m_workspaceIndex;
QByteArray m_geometryBytes;
bool m_hidden;
int m_ambeFeatureIndex;
bool m_connectAMBE;
Serializable *m_channelMarker;
Serializable *m_rollupState;

View File

@ -34,6 +34,8 @@
#include "dsp/dspengine.h"
#include "dsp/basebandsamplesink.h"
#include "dsp/datafifo.h"
#include "dsp/dspcommands.h"
#include "feature/feature.h"
#include "audio/audiooutputdevice.h"
#include "util/db.h"
#include "util/messagequeue.h"
@ -44,6 +46,7 @@
DSDDemodSink::DSDDemodSink() :
m_channelSampleRate(48000),
m_channelFrequencyOffset(0),
m_ambeFeature(nullptr),
m_audioSampleRate(48000),
m_interpolatorDistance(0.0f),
m_interpolatorDistanceRemain(0.0f),
@ -89,7 +92,7 @@ void DSDDemodSink::feed(const SampleVector::const_iterator& begin, const SampleV
m_scopeSampleBuffer.clear();
m_dsdDecoder.enableMbelib(!DSPEngine::instance()->hasDVSerialSupport()); // disable mbelib if DV serial support is present and activated else enable it
m_dsdDecoder.enableMbelib(!m_ambeFeature); // disable mbelib if DV serial support is present and activated else enable it
for (SampleVector::const_iterator it = begin; it != end; ++it)
{
@ -229,20 +232,24 @@ void DSDDemodSink::feed(const SampleVector::const_iterator& begin, const SampleV
m_scopeSampleBuffer.push_back(s);
}
if (DSPEngine::instance()->hasDVSerialSupport())
// if (DSPEngine::instance()->hasDVSerialSupport())
if (m_ambeFeature)
{
if ((m_settings.m_slot1On) && m_dsdDecoder.mbeDVReady1())
{
if (!m_settings.m_audioMute)
{
DSPEngine::instance()->pushMbeFrame(
m_dsdDecoder.getMbeDVFrame1(),
m_dsdDecoder.getMbeRateIndex(),
m_settings.m_volume * 10.0,
m_settings.m_tdmaStereo ? 1 : 3, // left or both channels
m_settings.m_highPassFilter,
m_audioSampleRate/8000, // upsample from native 8k
&m_audioFifo1);
DSPPushMbeFrame *msg = new DSPPushMbeFrame(
m_dsdDecoder.getMbeDVFrame1(),
m_dsdDecoder.getMbeRateIndex(),
m_settings.m_volume * 10.0,
m_settings.m_tdmaStereo ? 1 : 3, // left or both channels
m_settings.m_highPassFilter,
m_audioSampleRate/8000, // upsample from native 8k
&m_audioFifo1
);
m_ambeFeature->handleMessage(*msg);
delete msg;
}
m_dsdDecoder.resetMbeDV1();
@ -252,14 +259,17 @@ void DSDDemodSink::feed(const SampleVector::const_iterator& begin, const SampleV
{
if (!m_settings.m_audioMute)
{
DSPEngine::instance()->pushMbeFrame(
m_dsdDecoder.getMbeDVFrame2(),
m_dsdDecoder.getMbeRateIndex(),
m_settings.m_volume * 10.0,
m_settings.m_tdmaStereo ? 2 : 3, // right or both channels
m_settings.m_highPassFilter,
m_audioSampleRate/8000, // upsample from native 8k
&m_audioFifo2);
DSPPushMbeFrame *msg = new DSPPushMbeFrame(
m_dsdDecoder.getMbeDVFrame2(),
m_dsdDecoder.getMbeRateIndex(),
m_settings.m_volume * 10.0,
m_settings.m_tdmaStereo ? 2 : 3, // right or both channels
m_settings.m_highPassFilter,
m_audioSampleRate/8000, // upsample from native 8k
&m_audioFifo2
);
m_ambeFeature->handleMessage(*msg);
delete msg;
}
m_dsdDecoder.resetMbeDV2();
@ -270,7 +280,7 @@ void DSDDemodSink::feed(const SampleVector::const_iterator& begin, const SampleV
}
}
if (!DSPEngine::instance()->hasDVSerialSupport())
if (!m_ambeFeature)
{
if (m_settings.m_slot1On)
{

View File

@ -36,6 +36,7 @@
class BasebandSampleSink;
class ChannelAPI;
class Feature;
class DSDDemodSink : public ChannelSampleSink {
public:
@ -83,6 +84,7 @@ public:
}
const char *updateAndGetStatusText();
void setAmbeFeature(Feature *feature) { m_ambeFeature = feature; }
private:
struct MagSqLevelsStore
@ -114,6 +116,7 @@ private:
int m_channelFrequencyOffset;
DSDDemodSettings m_settings;
ChannelAPI *m_channel;
Feature *m_ambeFeature;
int m_audioSampleRate;
QVector<qint16> m_demodBuffer;
int m_demodBufferFill;

View File

@ -18,26 +18,9 @@ To enable this plugin at compile time you will need to have DSDcc installed in y
<h2>DV serial device support</h2>
You can use a serial device connected to your system that implements and exposes the packet interface of the AMBE3000 chip. This can be for example a ThumbDV USB dongle. You may also connect to an AMBE server instance over the network.
You can use a serial device connected to your system that implements and exposes the packet interface of the AMBE3000 chip. This can be for example a ThumbDV USB dongle. You may also connect to an AMBE server instance over the network. This is supported via the [AMBE feature](../../feature/ambe/readme.md).
DV serial devices are supported using the [SerialDV](https://github.com/f4exb/serialDV) library that is a mandatory requirement. Therefore you have to compile and install it in your system. Please refer to this project Readme.md to compile and install SerialDV. f you install it in a custom location say `/opt/install/serialdv` you will need to add this define to the cmake command: `-DSERIALDV_DIR=/opt/install/serialdv`
To effectively use serial DV devices for AMBE decoding you will have to add at least one device to the list of AMBE devices in use using the `AMBE devices control` dialog opened with the `AMBE` option in the `Preferences` menu. The list of devices is saved in the program preferences so that they are persistent across program stop/start. However if the device name or server address changes in between the corresponding reference will be lost.
Although such serial devices work with a serial interface at 400 kb in practice maybe for other reasons they are capable of handling only one conversation at a time. The software will allocate the device dynamically to a conversation with an inactivity timeout of 1 second so that conversations do not get interrupted constantly making the audio output too choppy. In practice you will have to have as many devices connected to your system as the number of conversations you would like to be handled in parallel.
Note also that hardware serial devices are not supported in Windows because of trouble with COM port support (contributors welcome!).
If no AMBE devices or servers are activated with the `AMBE devices control` AMBE decoding will take place with Mbelib. Possible copyright issues apart (see next) the audio quality with the DVSI AMBE chip is much better.
---
&#9888; With kernel 4.4.52 and maybe other 4.4 versions the default for FTDI devices (that is in the ftdi_sio kernel module) is not to set it as low latency. This results in the ThumbDV dongle not working anymore because its response is too slow to sustain the normal AMBE packets flow. The solution is to force low latency by changing the variable for your device (ex: /dev/ttyUSB0) as follows:
`echo 1 | sudo tee /sys/bus/usb-serial/devices/ttyUSB0/latency_timer` or `sudo setserial /dev/ttyUSB0 low_latency`
Newer kernels do not seem to have this issue.
---
If no AMBE features are active or the AMBE support is not engaged (B.19) AMBE decoding will take place with Mbelib. Possible copyright issues apart (see next) the audio quality with the DVSI AMBE chip is much better.
<h2>Mbelib support</h2>
@ -590,3 +573,11 @@ This is the one side deviation in kHz (&#177;) leading to maximum (100%) deviati
<h4>B.18: Gain after discriminator</h4>
This is the gain applied to the output of the discriminator before the decoder. Normally this would be set at unit gain 1.0 while the FM deviation is adjusted. However this can be used to extend the range of FM adjustment.
<h4>B.19: Activate AMBE hardware feature</h3>
Connects to an [AMBE Feature](../../feature/ambe/readme.md) to process AMBE frames in hardware
<h4>B.20: AMBE feature index for hardware decoding</h4>
Select the AMBE feature index used to process AMBE frames in hardware. If no AMBE feature is present then the list is empty. The list is automatically updated when an AMBE feature is added or removed.

View File

@ -42,7 +42,7 @@ Pressing this button downloads the OpenAIP.net Navaid database, which contains t
<h3>5: Draw Radials Adjusted for Magnetic Declination</h3>
When checked, radials on the map will drawn adjusted for magnetic declination. For example, if a VOR has a magnetic declination of 5 degrees, and the radial is calculated at 0 degrees, the radial will be drawn to magnetic North, i.e. -5 degress from true North. If not checked, the same radial would be drawn to true North (i.e 0 degrees), which may result in a less accurate position estimate.
When checked, radials on the map will drawn adjusted for magnetic declination. For example, if a VOR has a magnetic declination of 5 degrees, and the radial is calculated at 0 degrees, the radial will be drawn to magnetic North, i.e. -5 degrees from true North. If not checked, the same radial would be drawn to true North (i.e 0 degrees), which may result in a less accurate position estimate.
<h3>6: Morse ident threshold</h3>

View File

@ -35,3 +35,11 @@ if (Qt5Charts_FOUND)
add_subdirectory(radiosonde)
add_subdirectory(startracker)
endif()
if (ENABLE_LIMESUITE AND LIMESUITE_FOUND)
add_subdirectory(limerfe)
endif()
if (LIBSERIALDV_FOUND)
add_subdirectory(ambe)
endif()

View File

@ -0,0 +1,65 @@
project(ambe)
set(ambe_SOURCES
ambe.cpp
ambesettings.cpp
ambeplugin.cpp
ambeengine.cpp
ambeworker.cpp
ambewebapiadapter.cpp
)
set(ambe_HEADERS
ambe.h
ambesettings.h
ambeplugin.h
ambeengine.h
ambeworker.h
ambewebapiadapter.h
)
include_directories(
${CMAKE_SOURCE_DIR}/swagger/sdrangel/code/qt5/client
${LIBSERIALDV_INCLUDE_DIR}
)
if(NOT SERVER_MODE)
set(ambe_SOURCES
${ambe_SOURCES}
ambegui.cpp
ambegui.ui
)
set(ambe_HEADERS
${ambe_HEADERS}
ambegui.h
)
set(TARGET_NAME featureambe)
set(TARGET_LIB "Qt5::Widgets")
set(TARGET_LIB_GUI "sdrgui")
set(INSTALL_FOLDER ${INSTALL_PLUGINS_DIR})
else()
set(TARGET_NAME featureambesrv)
set(TARGET_LIB "")
set(TARGET_LIB_GUI "")
set(INSTALL_FOLDER ${INSTALL_PLUGINSSRV_DIR})
endif()
add_library(${TARGET_NAME} SHARED
${ambe_SOURCES}
)
target_link_libraries(${TARGET_NAME}
Qt5::Core
${TARGET_LIB}
sdrbase
${TARGET_LIB_GUI}
${LIBSERIALDV_LIBRARY}
)
install(TARGETS ${TARGET_NAME} DESTINATION ${INSTALL_FOLDER})
# Install debug symbols
if (WIN32)
install(FILES $<TARGET_PDB_FILE:${TARGET_NAME}> CONFIGURATIONS Debug RelWithDebInfo DESTINATION ${INSTALL_FOLDER} )
endif()

View File

@ -0,0 +1,430 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2022 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 //
// (at your option) any later version. //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 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 <QDebug>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QBuffer>
#include "SWGFeatureSettings.h"
#include "SWGFeatureReport.h"
#include "SWGFeatureActions.h"
#include "SWGDVSerialDevices.h"
#include "SWGDVSerialDevice.h"
#include "SWGAMBEDevices.h"
#include "settings/serializable.h"
#include "util/simpleserializer.h"
#include "dsp/dspcommands.h"
#include "ambe.h"
MESSAGE_CLASS_DEFINITION(AMBE::MsgConfigureAMBE, Message)
MESSAGE_CLASS_DEFINITION(AMBE::MsgReportDevices, Message)
const char* const AMBE::m_featureIdURI = "sdrangel.feature.ambe";
const char* const AMBE::m_featureId = "AMBE";
AMBE::AMBE(WebAPIAdapterInterface *webAPIAdapterInterface) :
Feature(m_featureIdURI, webAPIAdapterInterface)
{
setObjectName(m_featureId);
m_state = StIdle;
m_errorMessage = "AMBE error";
m_networkManager = new QNetworkAccessManager();
QObject::connect(
m_networkManager,
&QNetworkAccessManager::finished,
this,
&AMBE::networkManagerFinished
);
}
AMBE::~AMBE()
{
QObject::disconnect(
m_networkManager,
&QNetworkAccessManager::finished,
this,
&AMBE::networkManagerFinished
);
delete m_networkManager;
}
void AMBE::start()
{
qDebug("AMBE::start");
m_state = StRunning;
}
void AMBE::stop()
{
qDebug("AMBE::stop");
m_state = StIdle;
}
void AMBE::applySettings(const AMBESettings& settings, bool force)
{
(void) force;
m_settings = settings;
}
bool AMBE::handleMessage(const Message& cmd)
{
if (MsgConfigureAMBE::match(cmd))
{
MsgConfigureAMBE& cfg = (MsgConfigureAMBE&) cmd;
qDebug() << "AMBE::handleMessage: MsgConfigureAMBE";
applySettings(cfg.getSettings(), cfg.getForce());
return true;
}
else if (DSPPushMbeFrame::match(cmd))
{
DSPPushMbeFrame& cfg = (DSPPushMbeFrame&) cmd;
m_ambeEngine.pushMbeFrame(
cfg.getMbeFrame(),
cfg.getMbeRateIndex(),
cfg.getMbeVolumeIndex(),
cfg.getChannels(),
cfg.getUseHP(),
cfg.getUpsampling(),
cfg.getAudioFifo()
);
return true;
}
return false;
}
QByteArray AMBE::serialize() const
{
SimpleSerializer s(1);
s.writeBlob(1, m_settings.serialize());
return s.final();
}
bool AMBE::deserialize(const QByteArray& data)
{
SimpleDeserializer d(data);
if (!d.isValid())
{
m_settings.resetToDefaults();
return false;
}
if (d.getVersion() == 1)
{
QByteArray bytetmp;
d.readBlob(1, &bytetmp);
if (m_settings.deserialize(bytetmp))
{
MsgConfigureAMBE *msg = MsgConfigureAMBE::create(m_settings, true);
m_inputMessageQueue.push(msg);
return true;
}
else
{
m_settings.resetToDefaults();
MsgConfigureAMBE *msg = MsgConfigureAMBE::create(m_settings, true);
m_inputMessageQueue.push(msg);
return false;
}
}
else
{
return false;
}
}
void AMBE::networkManagerFinished(QNetworkReply *reply)
{
QNetworkReply::NetworkError replyError = reply->error();
if (replyError)
{
qWarning() << "AMBE::networkManagerFinished:"
<< " error(" << (int) replyError
<< "): " << replyError
<< ": " << reply->errorString();
}
else
{
QString answer = reply->readAll();
answer.chop(1); // remove last \n
qDebug("AMBE::networkManagerFinished: reply:\n%s", answer.toStdString().c_str());
}
reply->deleteLater();
}
int AMBE::webapiSettingsGet(
SWGSDRangel::SWGFeatureSettings& response,
QString& errorMessage)
{
(void) errorMessage;
response.setAmbeSettings(new SWGSDRangel::SWGAMBESettings());
response.getAmbeSettings()->init();
webapiFormatFeatureSettings(response, m_settings);
return 200;
}
int AMBE::webapiSettingsPutPatch(
bool force,
const QStringList& featureSettingsKeys,
SWGSDRangel::SWGFeatureSettings& response,
QString& errorMessage)
{
(void) errorMessage;
AMBESettings settings = m_settings;
webapiUpdateFeatureSettings(settings, featureSettingsKeys, response);
MsgConfigureAMBE *msg = MsgConfigureAMBE::create(settings, force);
m_inputMessageQueue.push(msg);
if (m_guiMessageQueue) // forward to GUI if any
{
MsgConfigureAMBE *msgToGUI = MsgConfigureAMBE::create(settings, force);
m_guiMessageQueue->push(msgToGUI);
}
webapiFormatFeatureSettings(response, settings);
return 200;
}
int AMBE::webapiReportGet(
SWGSDRangel::SWGFeatureReport& response,
QString& errorMessage)
{
(void) errorMessage;
response.setAmbeReport(new SWGSDRangel::SWGAMBEReport());
response.getAmbeReport()->init();
webapiFormatFeatureReport(response);
return 200;
}
void AMBE::webapiFormatFeatureSettings(
SWGSDRangel::SWGFeatureSettings& response,
const AMBESettings& settings)
{
if (response.getAmbeSettings()->getTitle()) {
*response.getAmbeSettings()->getTitle() = settings.m_title;
} else {
response.getAmbeSettings()->setTitle(new QString(settings.m_title));
}
response.getAmbeSettings()->setRgbColor(settings.m_rgbColor);
response.getAmbeSettings()->setUseReverseApi(settings.m_useReverseAPI ? 1 : 0);
if (response.getAmbeSettings()->getReverseApiAddress()) {
*response.getAmbeSettings()->getReverseApiAddress() = settings.m_reverseAPIAddress;
} else {
response.getAmbeSettings()->setReverseApiAddress(new QString(settings.m_reverseAPIAddress));
}
response.getAmbeSettings()->setReverseApiPort(settings.m_reverseAPIPort);
response.getAmbeSettings()->setReverseApiFeatureSetIndex(settings.m_reverseAPIFeatureSetIndex);
response.getAmbeSettings()->setReverseApiFeatureIndex(settings.m_reverseAPIFeatureIndex);
if (settings.m_rollupState)
{
if (response.getAmbeSettings()->getRollupState())
{
settings.m_rollupState->formatTo(response.getAmbeSettings()->getRollupState());
}
else
{
SWGSDRangel::SWGRollupState *swgRollupState = new SWGSDRangel::SWGRollupState();
settings.m_rollupState->formatTo(swgRollupState);
response.getAmbeSettings()->setRollupState(swgRollupState);
}
}
}
void AMBE::webapiUpdateFeatureSettings(
AMBESettings& settings,
const QStringList& featureSettingsKeys,
SWGSDRangel::SWGFeatureSettings& response)
{
if (featureSettingsKeys.contains("title")) {
settings.m_title = *response.getAmbeSettings()->getTitle();
}
if (featureSettingsKeys.contains("rgbColor")) {
settings.m_rgbColor = response.getAmbeSettings()->getRgbColor();
}
if (featureSettingsKeys.contains("useReverseAPI")) {
settings.m_useReverseAPI = response.getAmbeSettings()->getUseReverseApi() != 0;
}
if (featureSettingsKeys.contains("reverseAPIAddress")) {
settings.m_reverseAPIAddress = *response.getAmbeSettings()->getReverseApiAddress();
}
if (featureSettingsKeys.contains("reverseAPIPort")) {
settings.m_reverseAPIPort = response.getAmbeSettings()->getReverseApiPort();
}
if (featureSettingsKeys.contains("reverseAPIFeatureSetIndex")) {
settings.m_reverseAPIFeatureSetIndex = response.getAmbeSettings()->getReverseApiFeatureSetIndex();
}
if (featureSettingsKeys.contains("reverseAPIFeatureIndex")) {
settings.m_reverseAPIFeatureIndex = response.getAmbeSettings()->getReverseApiFeatureIndex();
}
if (settings.m_rollupState && featureSettingsKeys.contains("rollupState")) {
settings.m_rollupState->updateFrom(featureSettingsKeys, response.getAmbeSettings()->getRollupState());
}
}
void AMBE::webapiReverseSendSettings(QList<QString>& featureSettingsKeys, const AMBESettings& settings, bool force)
{
SWGSDRangel::SWGFeatureSettings *swgFeatureSettings = new SWGSDRangel::SWGFeatureSettings();
// swgFeatureSettings->setOriginatorFeatureIndex(getIndexInDeviceSet());
// swgFeatureSettings->setOriginatorFeatureSetIndex(getDeviceSetIndex());
swgFeatureSettings->setFeatureType(new QString("AMBE"));
swgFeatureSettings->setAmbeSettings(new SWGSDRangel::SWGAMBESettings());
SWGSDRangel::SWGAMBESettings *swgAMBESettings = swgFeatureSettings->getAmbeSettings();
// transfer data that has been modified. When force is on transfer all data except reverse API data
if (featureSettingsKeys.contains("title") || force) {
swgAMBESettings->setTitle(new QString(settings.m_title));
}
if (featureSettingsKeys.contains("rgbColor") || force) {
swgAMBESettings->setRgbColor(settings.m_rgbColor);
}
QString channelSettingsURL = QString("http://%1:%2/sdrangel/featureset/%3/feature/%4/settings")
.arg(settings.m_reverseAPIAddress)
.arg(settings.m_reverseAPIPort)
.arg(settings.m_reverseAPIFeatureSetIndex)
.arg(settings.m_reverseAPIFeatureIndex);
m_networkRequest.setUrl(QUrl(channelSettingsURL));
m_networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
QBuffer *buffer = new QBuffer();
buffer->open((QBuffer::ReadWrite));
buffer->write(swgFeatureSettings->asJson().toUtf8());
buffer->seek(0);
// Always use PATCH to avoid passing reverse API settings
QNetworkReply *reply = m_networkManager->sendCustomRequest(m_networkRequest, "PATCH", buffer);
buffer->setParent(reply);
delete swgFeatureSettings;
}
void AMBE::webapiFormatFeatureReport(SWGSDRangel::SWGFeatureReport& response)
{
// serial
SWGSDRangel::SWGDVSerialDevices *swgDVSerialDevices = response.getAmbeReport()->getSerial();
swgDVSerialDevices->init();
QList<QString> qDeviceNames;
getAMBEEngine()->scan(qDeviceNames);
swgDVSerialDevices->setNbDevices((int) qDeviceNames.size());
QList<SWGSDRangel::SWGDVSerialDevice*> *serialDeviceNamesList = swgDVSerialDevices->getDvSerialDevices();
for (const auto& deviceName : qDeviceNames)
{
serialDeviceNamesList->append(new SWGSDRangel::SWGDVSerialDevice);
serialDeviceNamesList->back()->init();
*serialDeviceNamesList->back()->getDeviceName() = deviceName;
}
// devices
response.getAmbeReport()->setDevices(new QList<SWGSDRangel::SWGAMBEDeviceReport*>);
QList<AMBEEngine::DeviceRef> deviceRefs;
getAMBEEngine()->getDeviceRefs(deviceRefs);
for (auto& deviceRef : deviceRefs)
{
response.getAmbeReport()->getDevices()->append(new SWGSDRangel::SWGAMBEDeviceReport);
response.getAmbeReport()->getDevices()->back()->setDevicePath(new QString(deviceRef.m_devicePath));
response.getAmbeReport()->getDevices()->back()->setSuccessCount(deviceRef.m_successCount);
response.getAmbeReport()->getDevices()->back()->setFailureCount(deviceRef.m_failureCount);
}
}
int AMBE::webapiActionsPost(
const QStringList& featureActionsKeys,
SWGSDRangel::SWGFeatureActions& query,
QString& errorMessage)
{
SWGSDRangel::SWGAMBEActions *swgAMBEActions = query.getAmbeActions();
if (swgAMBEActions)
{
bool unknownAction = true;
if (featureActionsKeys.contains("removeAll") && (swgAMBEActions->getRemoveAll() != 0))
{
unknownAction = false;
getAMBEEngine()->releaseAll();
if (getMessageQueueToGUI())
{
MsgReportDevices *msg = MsgReportDevices::create();
getAMBEEngine()->scan(msg->getAvailableDevices());
getAMBEEngine()->getDeviceRefs(msg->getUsedDevices());
getMessageQueueToGUI()->push(msg);
}
}
if (featureActionsKeys.contains("updateDevices"))
{
unknownAction = false;
bool updated = false;
SWGSDRangel::SWGAMBEDevices *swgAMBEDevices = swgAMBEActions->getUpdateDevices();
QList<SWGSDRangel::SWGAMBEDevice *> *ambeList = swgAMBEDevices->getAmbeDevices();
for (QList<SWGSDRangel::SWGAMBEDevice *>::const_iterator it = ambeList->begin(); it != ambeList->end(); ++it)
{
updated = true;
if ((*it)->getDelete() != 0) {
getAMBEEngine()->releaseController((*it)->getDeviceRef()->toStdString());
} else {
getAMBEEngine()->registerController((*it)->getDeviceRef()->toStdString());
}
}
if (updated && getMessageQueueToGUI())
{
MsgReportDevices *msg = MsgReportDevices::create();
getAMBEEngine()->scan(msg->getAvailableDevices());
getAMBEEngine()->getDeviceRefs(msg->getUsedDevices());
getMessageQueueToGUI()->push(msg);
}
}
if (unknownAction)
{
errorMessage = "Unknown action";
return 400;
}
else
{
return 202;
}
}
else
{
errorMessage = "Missing AMBEActions in query";
return 400;
}
}

142
plugins/feature/ambe/ambe.h Normal file
View File

@ -0,0 +1,142 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2022 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 //
// (at your option) any later version. //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License V3 for more details. //
// //
// You should have received a copy of the GNU General Public License //
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#ifndef INCLUDE_FEATURE_AMBE_H_
#define INCLUDE_FEATURE_AMBE_H_
#include <QNetworkRequest>
#include <QSet>
#include "feature/feature.h"
#include "util/message.h"
#include "ambeengine.h"
#include "ambesettings.h"
class WebAPIAdapterInterface;
class QNetworkAccessManager;
class QNetworkReply;
class AMBE : public Feature
{
Q_OBJECT
public:
class MsgConfigureAMBE : public Message {
MESSAGE_CLASS_DECLARATION
public:
const AMBESettings& getSettings() const { return m_settings; }
bool getForce() const { return m_force; }
static MsgConfigureAMBE* create(const AMBESettings& settings, bool force) {
return new MsgConfigureAMBE(settings, force);
}
private:
AMBESettings m_settings;
bool m_force;
MsgConfigureAMBE(const AMBESettings& settings, bool force) :
Message(),
m_settings(settings),
m_force(force)
{ }
};
class MsgReportDevices : public Message {
MESSAGE_CLASS_DECLARATION
public:
QList<QString>& getAvailableDevices() { return m_availableDevices; }
QList<AMBEEngine::DeviceRef>& getUsedDevices() { return m_usedDevices; }
static MsgReportDevices* create() {
return new MsgReportDevices();
}
private:
QList<QString> m_availableDevices;
QList<AMBEEngine::DeviceRef> m_usedDevices;
MsgReportDevices() :
Message()
{}
};
AMBE(WebAPIAdapterInterface *webAPIAdapterInterface);
virtual ~AMBE();
virtual void destroy() { delete this; }
virtual bool handleMessage(const Message& cmd);
virtual void getIdentifier(QString& id) const { id = objectName(); }
virtual QString getIdentifier() const { return objectName(); }
virtual void getTitle(QString& title) const { title = m_settings.m_title; }
virtual QByteArray serialize() const;
virtual bool deserialize(const QByteArray& data);
AMBEEngine *getAMBEEngine() { return &m_ambeEngine; }
virtual int webapiSettingsGet(
SWGSDRangel::SWGFeatureSettings& response,
QString& errorMessage);
virtual int webapiSettingsPutPatch(
bool force,
const QStringList& featureSettingsKeys,
SWGSDRangel::SWGFeatureSettings& response,
QString& errorMessage);
virtual int webapiReportGet(
SWGSDRangel::SWGFeatureReport& response,
QString& errorMessage);
virtual int webapiActionsPost(
const QStringList& featureActionsKeys,
SWGSDRangel::SWGFeatureActions& query,
QString& errorMessage);
static void webapiFormatFeatureSettings(
SWGSDRangel::SWGFeatureSettings& response,
const AMBESettings& settings);
static void webapiUpdateFeatureSettings(
AMBESettings& settings,
const QStringList& featureSettingsKeys,
SWGSDRangel::SWGFeatureSettings& response);
static const char* const m_featureIdURI;
static const char* const m_featureId;
private:
AMBESettings m_settings;
AMBEEngine m_ambeEngine;
QNetworkAccessManager *m_networkManager;
QNetworkRequest m_networkRequest;
void start();
void stop();
void applySettings(const AMBESettings& settings, bool force = false);
void webapiFormatFeatureReport(SWGSDRangel::SWGFeatureReport& response);
void webapiReverseSendSettings(QList<QString>& featureSettingsKeys, const AMBESettings& settings, bool force);
private slots:
void networkManagerFinished(QNetworkReply *reply);
};
#endif

View File

@ -43,6 +43,16 @@
#include "ambeworker.h"
#include "ambeengine.h"
uint32_t AMBEEngine::AMBEController::getSuccessCount() const
{
return worker ? worker->getSuccessCount() : 0;
}
uint32_t AMBEEngine::AMBEController::getFailureCount() const
{
return worker ? worker->getFailureCount() : 0;
}
AMBEEngine::AMBEEngine()
{}
@ -54,6 +64,7 @@ AMBEEngine::~AMBEEngine()
#if defined(_WIN32)
void AMBEEngine::getComList()
{
qDebug("AMBEEngine::getComList: Win");
m_comList.clear();
m_comList8250.clear();
char comCStr[16];
@ -67,21 +78,23 @@ void AMBEEngine::getComList()
}
// Do not activate serial support at all for windows
void AMBEEngine::scan(std::vector<QString>& ambeDevices)
void AMBEEngine::scan(QList<QString>& ambeDevices)
{
(void) ambeDevices;
}
#elif defined(__APPLE__)
void AMBEEngine::getComList()
{
qDebug("AMBEEngine::getComList: Apple");
}
void AMBEEngine::scan(std::vector<QString>& ambeDevices)
void AMBEEngine::scan(QList<QString>& ambeDevices)
{
(void) ambeDevices;
}
#else
void AMBEEngine::getComList()
{
qDebug("AMBEEngine::getComList: Linux");
int n;
struct dirent **namelist;
m_comList.clear();
@ -197,9 +210,10 @@ std::string AMBEEngine::get_driver(const std::string& tty)
return "";
}
void AMBEEngine::scan(std::vector<QString>& ambeDevices)
void AMBEEngine::scan(QList<QString>& ambeDevices)
{
getComList();
qDebug("AMBEEngine::scan");
AMBEEngine::getComList();
std::vector<std::string>::const_iterator it = m_comList.begin();
ambeDevices.clear();
@ -226,6 +240,7 @@ bool AMBEEngine::registerController(const std::string& deviceRef)
if (worker->open(deviceRef))
{
qDebug("AMBEEngine::registerController: device: %s", deviceRef.c_str());
m_controllers.push_back(AMBEController());
m_controllers.back().worker = worker;
m_controllers.back().thread = new QThread();
@ -242,6 +257,7 @@ bool AMBEEngine::registerController(const std::string& deviceRef)
return true;
}
qWarning("AMBEEngine::registerController: failed to register device: %s", deviceRef.c_str());
return false;
}
@ -285,13 +301,13 @@ void AMBEEngine::releaseAll()
m_controllers.clear();
}
void AMBEEngine::getDeviceRefs(std::vector<QString>& deviceNames)
void AMBEEngine::getDeviceRefs(QList<DeviceRef>& deviceRefs)
{
std::vector<AMBEController>::const_iterator it = m_controllers.begin();
while (it != m_controllers.end())
{
deviceNames.push_back(QString(it->device.c_str()));
deviceRefs.push_back(DeviceRef{QString(it->device.c_str()), it->getSuccessCount(), it->getFailureCount()});
++it;
}
}
@ -340,47 +356,3 @@ void AMBEEngine::pushMbeFrame(
}
}
}
QByteArray AMBEEngine::serialize() const
{
QStringList qDeviceList;
std::vector<AMBEController>::const_iterator it = m_controllers.begin();
while (it != m_controllers.end())
{
qDebug("AMBEEngine::serialize: %s", it->device.c_str());
qDeviceList << QString(it->device.c_str());
++it;
}
QByteArray data;
QDataStream *stream = new QDataStream(&data, QIODevice::WriteOnly);
(*stream) << qDeviceList;
delete stream;
return data;
}
bool AMBEEngine::deserialize(const QByteArray& data)
{
if (data.size() <= 0)
{
qDebug("AMBEEngine::deserialize: invalid or no data");
return false;
}
QStringList qDeviceList;
QDataStream *stream = new QDataStream(data);
(*stream) >> qDeviceList;
delete stream;
releaseAll();
for (int i = 0; i < qDeviceList.size(); ++i)
{
qDebug(" AMBEEngine::deserialize: %s", qDeviceList.at(i).toStdString().c_str());
registerController(qDeviceList.at(i).toStdString());
}
return true;
}

View File

@ -25,26 +25,32 @@
#include <QObject>
#include <QMutex>
#include <QString>
#include <QList>
#include <QByteArray>
#include "export.h"
class QThread;
class AMBEWorker;
class AudioFifo;
class SDRBASE_API AMBEEngine : public QObject
class AMBEEngine : public QObject
{
Q_OBJECT
public:
struct DeviceRef
{
QString m_devicePath; //!< device path or url
uint32_t m_successCount; //!< number of frames successfully decoded
uint32_t m_failureCount; //!< number of frames failing decoding
};
AMBEEngine();
~AMBEEngine();
void scan(std::vector<QString>& ambeDevices);
void scan(QList<QString>& ambeDevices);
void releaseAll();
int getNbDevices() const { return m_controllers.size(); } //!< number of devices used
void getDeviceRefs(std::vector<QString>& devicesRefs); //!< reference of the devices used (device path or url)
void getDeviceRefs(QList<DeviceRef>& devicesRefs); //!< reference of the devices used
bool registerController(const std::string& deviceRef); //!< create a new controller for the device in reference
void releaseController(const std::string& deviceRef); //!< release controller resources for the device in reference
@ -57,9 +63,6 @@ public:
int upsampling,
AudioFifo *audioFifo);
QByteArray serialize() const;
bool deserialize(const QByteArray& data);
private:
struct AMBEController
{
@ -71,6 +74,9 @@ private:
QThread *thread;
AMBEWorker *worker;
std::string device;
uint32_t getSuccessCount() const;
uint32_t getFailureCount() const;
};
#ifndef _WIN32

View File

@ -0,0 +1,377 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2022 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 //
// (at your option) any later version. //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 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 "feature/featureuiset.h"
#include "gui/basicfeaturesettingsdialog.h"
#include "gui/crightclickenabler.h"
#include "ui_ambegui.h"
#include "ambegui.h"
#include "ambe.h"
AMBEGUI* AMBEGUI::create(PluginAPI* pluginAPI, FeatureUISet *featureUISet, Feature *feature)
{
AMBEGUI* gui = new AMBEGUI(pluginAPI, featureUISet, feature);
return gui;
}
void AMBEGUI::destroy()
{
delete this;
}
AMBEGUI::AMBEGUI(PluginAPI* pluginAPI, FeatureUISet *featureUISet, Feature *feature, QWidget* parent) :
FeatureGUI(parent),
ui(new Ui::AMBEGUI),
m_pluginAPI(pluginAPI),
m_featureUISet(featureUISet),
m_doApplySettings(true)
{
m_feature = feature;
setAttribute(Qt::WA_DeleteOnClose, true);
m_helpURL = "plugins/feature/ambe/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_ambe = reinterpret_cast<AMBE*>(feature);
m_ambe->setMessageQueueToGUI(&m_inputMessageQueue);
m_settings.setRollupState(&m_rollupState);
connect(this, SIGNAL(customContextMenuRequested(const QPoint &)), this, SLOT(onMenuDialogCalled(const QPoint &)));
connect(getInputMessageQueue(), SIGNAL(messageEnqueued()), this, SLOT(handleInputMessages()));
populateSerialList();
refreshInUseList();
displaySettings();
makeUIConnections();
}
AMBEGUI::~AMBEGUI()
{
delete ui;
}
void AMBEGUI::resetToDefaults()
{
m_settings.resetToDefaults();
displaySettings();
applySettings(true);
}
QByteArray AMBEGUI::serialize() const
{
return m_settings.serialize();
}
bool AMBEGUI::deserialize(const QByteArray& data)
{
if (m_settings.deserialize(data))
{
m_feature->setWorkspaceIndex(m_settings.m_workspaceIndex);
displaySettings();
refreshInUseList();
return true;
}
else
{
resetToDefaults();
return false;
}
}
void AMBEGUI::setWorkspaceIndex(int index)
{
m_settings.m_workspaceIndex = index;
m_feature->setWorkspaceIndex(index);
}
void AMBEGUI::resizeEvent(QResizeEvent* size)
{
int maxWidth = getRollupContents()->maximumWidth();
int minHeight = getRollupContents()->minimumHeight() + getAdditionalHeight();
resize(width() < maxWidth ? width() : maxWidth, minHeight);
size->accept();
}
void AMBEGUI::onWidgetRolled(QWidget* widget, bool rollDown)
{
(void) widget;
(void) rollDown;
getRollupContents()->saveState(m_rollupState);
applySettings();
}
void AMBEGUI::onMenuDialogCalled(const QPoint &p)
{
if (m_contextMenuType == ContextMenuChannelSettings)
{
BasicFeatureSettingsDialog dialog(this);
dialog.setTitle(m_settings.m_title);
dialog.setUseReverseAPI(m_settings.m_useReverseAPI);
dialog.setReverseAPIAddress(m_settings.m_reverseAPIAddress);
dialog.setReverseAPIPort(m_settings.m_reverseAPIPort);
dialog.setReverseAPIFeatureSetIndex(m_settings.m_reverseAPIFeatureSetIndex);
dialog.setReverseAPIFeatureIndex(m_settings.m_reverseAPIFeatureIndex);
dialog.setDefaultTitle(m_displayedName);
dialog.move(p);
dialog.exec();
m_settings.m_title = dialog.getTitle();
m_settings.m_useReverseAPI = dialog.useReverseAPI();
m_settings.m_reverseAPIAddress = dialog.getReverseAPIAddress();
m_settings.m_reverseAPIPort = dialog.getReverseAPIPort();
m_settings.m_reverseAPIFeatureSetIndex = dialog.getReverseAPIFeatureSetIndex();
m_settings.m_reverseAPIFeatureIndex = dialog.getReverseAPIFeatureIndex();
setTitle(m_settings.m_title);
setTitleColor(m_settings.m_rgbColor);
applySettings();
}
resetContextMenuType();
}
void AMBEGUI::displaySettings()
{
setTitleColor(m_settings.m_rgbColor);
setWindowTitle(m_settings.m_title);
setTitle(m_settings.m_title);
}
void AMBEGUI::applySettings(bool force)
{
if (m_doApplySettings)
{
AMBE::MsgConfigureAMBE* message = AMBE::MsgConfigureAMBE::create( m_settings, force);
m_ambe->getInputMessageQueue()->push(message);
}
}
bool AMBEGUI::handleMessage(const Message& message)
{
if (AMBE::MsgConfigureAMBE::match(message))
{
qDebug("AMBEGUI::handleMessage: AMBE::MsgConfigureAMBE");
const AMBE::MsgConfigureAMBE& cfg = (AMBE::MsgConfigureAMBE&) message;
m_settings = cfg.getSettings();
displaySettings();
return true;
}
else if (AMBE::MsgReportDevices::match(message))
{
qDebug("AMBEGUI::handleMessage: AMBE::MsgReportDevices");
AMBE::MsgReportDevices& cfg = (AMBE::MsgReportDevices&) message;
ui->ambeSerialDevices->clear();
ui->statusText->setText("Updated all devices lists");
for (const auto& ambeDevice : cfg.getAvailableDevices()) {
ui->ambeSerialDevices->addItem(ambeDevice);
}
ui->ambeDeviceRefs->clear();
for (const auto& inUseDevice : cfg.getUsedDevices()) {
ui->ambeDeviceRefs->addItem(
tr("%1 - %2|%3")
.arg(inUseDevice.m_devicePath)
.arg(inUseDevice.m_successCount)
.arg(inUseDevice.m_failureCount)
);
}
return true;
}
return false;
}
void AMBEGUI::handleInputMessages()
{
Message* message;
while ((message = getInputMessageQueue()->pop()))
{
if (handleMessage(*message)) {
delete message;
}
}
}
void AMBEGUI::populateSerialList()
{
QList<QString> ambeSerialDevices;
m_ambe->getAMBEEngine()->scan(ambeSerialDevices);
ui->ambeSerialDevices->clear();
for (const auto& ambeDevice : ambeSerialDevices) {
ui->ambeSerialDevices->addItem(ambeDevice);
}
}
void AMBEGUI::refreshInUseList()
{
QList<AMBEEngine::DeviceRef> inUseDevices;
m_ambe->getAMBEEngine()->getDeviceRefs(inUseDevices);
ui->ambeDeviceRefs->clear();
for (const auto& inUseDevice : inUseDevices)
{
qDebug("AMBEGUI::refreshInUseList: %s", qPrintable(inUseDevice.m_devicePath));
ui->ambeDeviceRefs->addItem(
tr("%1 - %2|%3")
.arg(inUseDevice.m_devicePath)
.arg(inUseDevice.m_successCount)
.arg(inUseDevice.m_failureCount)
);
}
}
void AMBEGUI::on_importSerial_clicked()
{
QListWidgetItem *serialItem = ui->ambeSerialDevices->currentItem();
if (!serialItem)
{
ui->statusText->setText("No selection");
return;
}
QString serialName = serialItem->text();
QList<QListWidgetItem*> foundItems = ui->ambeDeviceRefs->findItems(serialName, Qt::MatchFixedString|Qt::MatchCaseSensitive);
if (foundItems.size() == 0)
{
if (m_ambe->getAMBEEngine()->registerController(serialName.toStdString()))
{
ui->ambeDeviceRefs->addItem(tr("%1 - 0|0").arg(serialName));
ui->statusText->setText(tr("%1 added").arg(serialName));
}
else
{
ui->statusText->setText(tr("Cannot open %1").arg(serialName));
}
}
else
{
ui->statusText->setText("Device already in use");
}
}
void AMBEGUI::on_importAllSerial_clicked()
{
int count = 0;
for (int i = 0; i < ui->ambeSerialDevices->count(); i++)
{
const QListWidgetItem *serialItem = ui->ambeSerialDevices->item(i);
QString serialName = serialItem->text();
QList<QListWidgetItem*> foundItems = ui->ambeDeviceRefs->findItems(serialName, Qt::MatchFixedString|Qt::MatchCaseSensitive);
if (foundItems.size() == 0)
{
if (m_ambe->getAMBEEngine()->registerController(serialName.toStdString()))
{
ui->ambeDeviceRefs->addItem(serialName);
count++;
}
}
}
ui->statusText->setText(tr("%1 devices added").arg(count));
}
void AMBEGUI::on_removeAmbeDevice_clicked()
{
QListWidgetItem *deviceItem = ui->ambeDeviceRefs->currentItem();
if (!deviceItem)
{
ui->statusText->setText("No selection");
return;
}
QString deviceName = deviceItem->text().split(" ").at(0);
m_ambe->getAMBEEngine()->releaseController(deviceName.toStdString());
ui->statusText->setText(tr("%1 removed").arg(deviceName));
refreshInUseList();
}
void AMBEGUI::on_refreshAmbeList_clicked()
{
refreshInUseList();
ui->statusText->setText("In use refreshed");
}
void AMBEGUI::on_refreshSerial_clicked()
{
populateSerialList();
ui->statusText->setText("Serial refreshed");
}
void AMBEGUI::on_clearAmbeList_clicked()
{
if (ui->ambeDeviceRefs->count() == 0)
{
ui->statusText->setText("No active items");
return;
}
m_ambe->getAMBEEngine()->releaseAll();
ui->ambeDeviceRefs->clear();
ui->statusText->setText("All items released");
}
void AMBEGUI::on_importAddress_clicked()
{
QString addressAndPort = ui->ambeAddressText->text();
QList<QListWidgetItem*> foundItems = ui->ambeDeviceRefs->findItems(addressAndPort, Qt::MatchFixedString|Qt::MatchCaseSensitive);
if (foundItems.size() == 0)
{
if (m_ambe->getAMBEEngine()->registerController(addressAndPort.toStdString()))
{
ui->ambeDeviceRefs->addItem(addressAndPort);
ui->statusText->setText(tr("%1 added").arg(addressAndPort));
}
else
{
ui->statusText->setText(tr("Cannot open %1").arg(addressAndPort));
}
}
else
{
ui->statusText->setText("Address already in use");
}
}
void AMBEGUI::makeUIConnections()
{
QObject::connect(ui->importSerial, &QPushButton::clicked, this, &AMBEGUI::on_importSerial_clicked);
QObject::connect(ui->importAllSerial, &QPushButton::clicked, this, &AMBEGUI::on_importAllSerial_clicked);
QObject::connect(ui->removeAmbeDevice, &QPushButton::clicked, this, &AMBEGUI::on_removeAmbeDevice_clicked);
QObject::connect(ui->refreshAmbeList, &QPushButton::clicked, this, &AMBEGUI::on_refreshAmbeList_clicked);
QObject::connect(ui->refreshSerial, &QPushButton::clicked, this, &AMBEGUI::on_refreshSerial_clicked);
QObject::connect(ui->clearAmbeList, &QPushButton::clicked, this, &AMBEGUI::on_clearAmbeList_clicked);
QObject::connect(ui->importAddress, &QPushButton::clicked, this, &AMBEGUI::on_importAddress_clicked);
}

View File

@ -0,0 +1,93 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2022 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 //
// (at your option) any later version. //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License V3 for more details. //
// //
// You should have received a copy of the GNU General Public License //
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#ifndef INCLUDE_FEATURE_AMBEGUI_H_
#define INCLUDE_FEATURE_AMBEGUI_H_
#include "feature/featuregui.h"
#include "util/messagequeue.h"
#include "util/movingaverage.h"
#include "settings/rollupstate.h"
#include "ambesettings.h"
class PluginAPI;
class FeatureUISet;
class Feature;
class AMBE;
class DSPDeviceSourceEngine;
class DSPDeviceSinkEngine;
namespace Ui {
class AMBEGUI;
}
class AMBEGUI : public FeatureGUI
{
Q_OBJECT
public:
static AMBEGUI* create(PluginAPI* pluginAPI, FeatureUISet *featureUISet, Feature *feature);
virtual void destroy();
void resetToDefaults();
QByteArray serialize() const;
bool deserialize(const QByteArray& data);
virtual MessageQueue *getInputMessageQueue() { return &m_inputMessageQueue; }
virtual void setWorkspaceIndex(int 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; }
protected:
void resizeEvent(QResizeEvent* size);
private:
Ui::AMBEGUI* ui;
AMBE *m_ambe;
PluginAPI* m_pluginAPI;
FeatureUISet* m_featureUISet;
AMBESettings m_settings;
RollupState m_rollupState;
bool m_doApplySettings;
MessageQueue m_inputMessageQueue;
explicit AMBEGUI(PluginAPI* pluginAPI, FeatureUISet *featureUISet, Feature *feature, QWidget* parent = nullptr);
virtual ~AMBEGUI();
void populateSerialList();
void refreshInUseList();
void blockApplySettings(bool block) { m_doApplySettings = !block; }
void applySettings(bool force = false);
void displaySettings();
bool handleMessage(const Message& message);
void makeUIConnections();
private slots:
void onMenuDialogCalled(const QPoint &p);
void onWidgetRolled(QWidget* widget, bool rollDown);
void handleInputMessages();
void on_importSerial_clicked();
void on_importAllSerial_clicked();
void on_removeAmbeDevice_clicked();
void on_refreshAmbeList_clicked();
void on_refreshSerial_clicked();
void on_clearAmbeList_clicked();
void on_importAddress_clicked();
};
#endif

View File

@ -0,0 +1,299 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>AMBEGUI</class>
<widget class="RollupContents" name="AMBEGUI">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>360</width>
<height>452</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>360</width>
<height>452</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>560</width>
<height>452</height>
</size>
</property>
<property name="font">
<font>
<family>Liberation Sans</family>
<pointsize>9</pointsize>
</font>
</property>
<property name="windowTitle">
<string>AMBE Decoder Controller</string>
</property>
<widget class="QWidget" name="settingsContainer" native="true">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>358</width>
<height>450</height>
</rect>
</property>
<property name="windowTitle">
<string>Settings</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="spacing">
<number>3</number>
</property>
<property name="leftMargin">
<number>2</number>
</property>
<property name="topMargin">
<number>2</number>
</property>
<property name="rightMargin">
<number>2</number>
</property>
<property name="bottomMargin">
<number>2</number>
</property>
<item>
<layout class="QHBoxLayout" name="ipTextLayout">
<item>
<widget class="QLabel" name="ambeServerLabel">
<property name="text">
<string>AMBE server IP and port or direct input</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="ipLayout">
<item>
<widget class="QLineEdit" name="ambeAddressText">
<property name="toolTip">
<string>AMBE server address as ip:port or direct input</string>
</property>
<property name="inputMask">
<string/>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="inUseLayout">
<item>
<widget class="QLabel" name="ambeSerialLabel">
<property name="text">
<string>In use</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="importAddress">
<property name="toolTip">
<string>Use server</string>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="../../../sdrgui/resources/res.qrc">
<normaloff>:/arrow_down.png</normaloff>:/arrow_down.png</iconset>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="removeAmbeDevice">
<property name="toolTip">
<string>Remove selected device or server</string>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="../../../sdrgui/resources/res.qrc">
<normaloff>:/bin.png</normaloff>:/bin.png</iconset>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="clearAmbeList">
<property name="toolTip">
<string>Remove all devices</string>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="../../../sdrgui/resources/res.qrc">
<normaloff>:/sweep.png</normaloff>:/sweep.png</iconset>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="refreshAmbeList">
<property name="toolTip">
<string>Refresh list of devices and servers in use</string>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="../../../sdrgui/resources/res.qrc">
<normaloff>:/recycle.png</normaloff>:/recycle.png</iconset>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="localDeviceLayout">
<item>
<widget class="QListWidget" name="ambeDeviceRefs">
<property name="maximumSize">
<size>
<width>16777215</width>
<height>140</height>
</size>
</property>
<property name="toolTip">
<string>List of devices/servers in use</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="serialLayout">
<item>
<widget class="QLabel" name="ambeSerialLabel_2">
<property name="text">
<string>Serial devices</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="importSerial">
<property name="toolTip">
<string>Use serial device</string>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="../../../sdrgui/resources/res.qrc">
<normaloff>:/arrow_up.png</normaloff>:/arrow_up.png</iconset>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="importAllSerial">
<property name="toolTip">
<string>Use all serial devices</string>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="../../../sdrgui/resources/res.qrc">
<normaloff>:/double_arrow_up.png</normaloff>:/double_arrow_up.png</iconset>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="refreshSerial">
<property name="toolTip">
<string>Refresh AMBE serial devices list</string>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="../../../sdrgui/resources/res.qrc">
<normaloff>:/recycle.png</normaloff>:/recycle.png</iconset>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="serialLayout_2">
<item>
<widget class="QListWidget" name="ambeSerialDevices">
<property name="maximumSize">
<size>
<width>16777215</width>
<height>140</height>
</size>
</property>
<property name="toolTip">
<string>List of AMBE serial devices in the system</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="statusLayout">
<item>
<widget class="QLabel" name="statusText">
<property name="text">
<string>...</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</widget>
<customwidgets>
<customwidget>
<class>RollupContents</class>
<extends>QWidget</extends>
<header>gui/rollupcontents.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources>
<include location="../../../sdrgui/resources/res.qrc"/>
</resources>
<connections/>
</ui>

View File

@ -0,0 +1,80 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2022 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 //
// (at your option) any later version. //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 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 <QtPlugin>
#include "plugin/pluginapi.h"
#ifndef SERVER_MODE
#include "ambegui.h"
#endif
#include "ambe.h"
#include "ambeplugin.h"
#include "ambewebapiadapter.h"
const PluginDescriptor AMBEPlugin::m_pluginDescriptor = {
AMBE::m_featureId,
QStringLiteral("AMBE Controller"),
QStringLiteral("7.2.1"),
QStringLiteral("(c) Edouard Griffiths, F4EXB"),
QStringLiteral("https://github.com/f4exb/sdrangel"),
true,
QStringLiteral("https://github.com/f4exb/sdrangel")
};
AMBEPlugin::AMBEPlugin(QObject* parent) :
QObject(parent),
m_pluginAPI(nullptr)
{
}
const PluginDescriptor& AMBEPlugin::getPluginDescriptor() const
{
return m_pluginDescriptor;
}
void AMBEPlugin::initPlugin(PluginAPI* pluginAPI)
{
m_pluginAPI = pluginAPI;
// register Simple PTT feature
m_pluginAPI->registerFeature(AMBE::m_featureIdURI, AMBE::m_featureId, this);
}
#ifdef SERVER_MODE
FeatureGUI* AMBEPlugin::createFeatureGUI(FeatureUISet *featureUISet, Feature *feature) const
{
(void) featureUISet;
(void) feature;
return nullptr;
}
#else
FeatureGUI* AMBEPlugin::createFeatureGUI(FeatureUISet *featureUISet, Feature *feature) const
{
return AMBEGUI::create(m_pluginAPI, featureUISet, feature);
}
#endif
Feature* AMBEPlugin::createFeature(WebAPIAdapterInterface* webAPIAdapterInterface) const
{
return new AMBE(webAPIAdapterInterface);
}
FeatureWebAPIAdapter* AMBEPlugin::createFeatureWebAPIAdapter() const
{
return new AMBEWebAPIAdapter();
}

View File

@ -1,6 +1,5 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2019 F4EXB //
// written by Edouard Griffiths //
// Copyright (C) 2022 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 //
@ -16,41 +15,34 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#ifndef SDRGUI_GUI_AMBEDEVICESDIALOG_H_
#define SDRGUI_GUI_AMBEDEVICESDIALOG_H_
#ifndef INCLUDE_FEATURE_AMBEPLUGIN_H
#define INCLUDE_FEATURE_AMBEPLUGIN_H
#include <QDialog>
#include <QObject>
#include "plugin/plugininterface.h"
#include "export.h"
#include "ambe/ambeengine.h"
class FeatureGUI;
class WebAPIAdapterInterface;
class QListWidgetItem;
namespace Ui {
class AMBEDevicesDialog;
}
class SDRGUI_API AMBEDevicesDialog : public QDialog {
Q_OBJECT
class AMBEPlugin : public QObject, PluginInterface {
Q_OBJECT
Q_INTERFACES(PluginInterface)
Q_PLUGIN_METADATA(IID "sdrangel.feature.ambe")
public:
explicit AMBEDevicesDialog(AMBEEngine* ambeEngine, QWidget* parent = nullptr);
~AMBEDevicesDialog();
explicit AMBEPlugin(QObject* parent = nullptr);
const PluginDescriptor& getPluginDescriptor() const;
void initPlugin(PluginAPI* pluginAPI);
virtual FeatureGUI* createFeatureGUI(FeatureUISet *featureUISet, Feature *feature) const;
virtual Feature* createFeature(WebAPIAdapterInterface *webAPIAdapterInterface) const;
virtual FeatureWebAPIAdapter* createFeatureWebAPIAdapter() const;
private:
void populateSerialList();
void refreshInUseList();
static const PluginDescriptor m_pluginDescriptor;
Ui::AMBEDevicesDialog* ui;
AMBEEngine* m_ambeEngine;
private slots:
void on_importSerial_clicked();
void on_importAllSerial_clicked();
void on_removeAmbeDevice_clicked();
void on_refreshAmbeList_clicked();
void on_clearAmbeList_clicked();
void on_importAddress_clicked();
PluginAPI* m_pluginAPI;
};
#endif // SDRGUI_GUI_AMBEDEVICESDIALOG_H_
#endif // INCLUDE_FEATURE_AMBEPLUGIN_H

View File

@ -0,0 +1,114 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2022 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 //
// (at your option) any later version. //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 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 "util/simpleserializer.h"
#include "settings/serializable.h"
#include "ambesettings.h"
AMBESettings::AMBESettings() :
m_rollupState(nullptr)
{
resetToDefaults();
}
void AMBESettings::resetToDefaults()
{
m_title = "AMBE Controller";
m_rgbColor = QColor(255, 0, 0).rgb();
m_useReverseAPI = false;
m_reverseAPIAddress = "127.0.0.1";
m_reverseAPIPort = 8888;
m_reverseAPIFeatureSetIndex = 0;
m_reverseAPIFeatureIndex = 0;
m_workspaceIndex = 0;
}
QByteArray AMBESettings::serialize() const
{
SimpleSerializer s(1);
s.writeString(1, m_title);
s.writeU32(2, m_rgbColor);
s.writeBool(7, m_useReverseAPI);
s.writeString(8, m_reverseAPIAddress);
s.writeU32(9, m_reverseAPIPort);
s.writeU32(10, m_reverseAPIFeatureSetIndex);
s.writeU32(11, m_reverseAPIFeatureIndex);
if (m_rollupState) {
s.writeBlob(12, m_rollupState->serialize());
}
s.writeS32(18, m_workspaceIndex);
s.writeBlob(19, m_geometryBytes);
return s.final();
}
bool AMBESettings::deserialize(const QByteArray& data)
{
SimpleDeserializer d(data);
if(!d.isValid())
{
resetToDefaults();
return false;
}
if(d.getVersion() == 1)
{
QByteArray bytetmp;
uint32_t utmp;
QString strtmp;
d.readString(1, &m_title, "Simple PTT");
d.readU32(2, &m_rgbColor, QColor(255, 0, 0).rgb());
d.readBool(7, &m_useReverseAPI, false);
d.readString(8, &m_reverseAPIAddress, "127.0.0.1");
d.readU32(9, &utmp, 0);
if ((utmp > 1023) && (utmp < 65535)) {
m_reverseAPIPort = utmp;
} else {
m_reverseAPIPort = 8888;
}
d.readU32(10, &utmp, 0);
m_reverseAPIFeatureSetIndex = utmp > 99 ? 99 : utmp;
d.readU32(11, &utmp, 0);
m_reverseAPIFeatureIndex = utmp > 99 ? 99 : utmp;
if (m_rollupState)
{
d.readBlob(12, &bytetmp);
m_rollupState->deserialize(bytetmp);
}
d.readS32(18, &m_workspaceIndex, 0);
d.readBlob(19, &m_geometryBytes);
return true;
}
else
{
resetToDefaults();
return false;
}
}

View File

@ -0,0 +1,46 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2022 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 //
// (at your option) any later version. //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License V3 for more details. //
// //
// You should have received a copy of the GNU General Public License //
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#ifndef INCLUDE_FEATURE_AMBESETTINGS_H_
#define INCLUDE_FEATURE_AMBESETTINGS_H_
#include <QByteArray>
#include <QString>
class Serializable;
struct AMBESettings
{
QString m_title;
quint32 m_rgbColor;
bool m_useReverseAPI;
QString m_reverseAPIAddress;
uint16_t m_reverseAPIPort;
uint16_t m_reverseAPIFeatureSetIndex;
uint16_t m_reverseAPIFeatureIndex;
Serializable *m_rollupState;
int m_workspaceIndex;
QByteArray m_geometryBytes;
AMBESettings();
void resetToDefaults();
QByteArray serialize() const;
bool deserialize(const QByteArray& data);
void setRollupState(Serializable *rollupState) { m_rollupState = rollupState; }
};
#endif // INCLUDE_FEATURE_AMBESETTINGS_H_

View File

@ -0,0 +1,51 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2022 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 //
// (at your option) any later version. //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 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 "SWGFeatureSettings.h"
#include "ambe.h"
#include "ambewebapiadapter.h"
AMBEWebAPIAdapter::AMBEWebAPIAdapter()
{}
AMBEWebAPIAdapter::~AMBEWebAPIAdapter()
{}
int AMBEWebAPIAdapter::webapiSettingsGet(
SWGSDRangel::SWGFeatureSettings& response,
QString& errorMessage)
{
(void) errorMessage;
response.setAmbeSettings(new SWGSDRangel::SWGAMBESettings());
response.getAmbeSettings()->init();
AMBE::webapiFormatFeatureSettings(response, m_settings);
return 200;
}
int AMBEWebAPIAdapter::webapiSettingsPutPatch(
bool force,
const QStringList& featureSettingsKeys,
SWGSDRangel::SWGFeatureSettings& response,
QString& errorMessage)
{
(void) force; // no action
(void) errorMessage;
AMBE::webapiUpdateFeatureSettings(m_settings, featureSettingsKeys, response);
return 200;
}

View File

@ -0,0 +1,49 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2022 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 //
// (at your option) any later version. //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License V3 for more details. //
// //
// You should have received a copy of the GNU General Public License //
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#ifndef INCLUDE_AMBE_WEBAPIADAPTER_H
#define INCLUDE_AMBE_WEBAPIADAPTER_H
#include "feature/featurewebapiadapter.h"
#include "ambesettings.h"
/**
* Standalone API adapter only for the settings
*/
class AMBEWebAPIAdapter : public FeatureWebAPIAdapter {
public:
AMBEWebAPIAdapter();
virtual ~AMBEWebAPIAdapter();
virtual QByteArray serialize() const { return m_settings.serialize(); }
virtual bool deserialize(const QByteArray& data) { return m_settings.deserialize(data); }
virtual int webapiSettingsGet(
SWGSDRangel::SWGFeatureSettings& response,
QString& errorMessage);
virtual int webapiSettingsPutPatch(
bool force,
const QStringList& featureSettingsKeys,
SWGSDRangel::SWGFeatureSettings& response,
QString& errorMessage);
private:
AMBESettings m_settings;
};
#endif // INCLUDE_AIS_WEBAPIADAPTER_H

View File

@ -33,7 +33,9 @@ AMBEWorker::AMBEWorker() :
m_upsamplerLastValue(0.0f),
m_phase(0),
m_upsampling(1),
m_volume(1.0f)
m_volume(1.0f),
m_successCount(0),
m_failureCount(0)
{
m_audioBuffer.resize(48000);
m_audioBufferFill = 0;
@ -119,10 +121,13 @@ void AMBEWorker::handleInputMessages()
m_audioBufferFill = 0;
}
m_successCount++;
}
else
{
qDebug("AMBEWorker::handleInputMessages: MsgMbeDecode: decode failed");
m_failureCount++;
}
}

View File

@ -34,7 +34,7 @@
class AudioFifo;
class SDRBASE_API AMBEWorker : public QObject {
class AMBEWorker : public QObject {
Q_OBJECT
public:
class MsgTest : public Message
@ -115,6 +115,8 @@ public:
void stop();
bool isAvailable();
bool hasFifo(AudioFifo *audioFifo);
uint32_t getSuccessCount() const { return m_successCount; }
uint32_t getFailureCount() const { return m_failureCount; }
void postTest()
{
@ -151,6 +153,8 @@ private:
float m_volume;
float m_upsamplingFactors[7];
AudioCompressor m_compressor;
uint32_t m_successCount;
uint32_t m_failureCount;
};
#endif // SDRBASE_AMBE_AMBEWORKER_H_

View File

@ -0,0 +1,73 @@
<h1>AMBE controller</h1>
<h2>Introduction</h2>
Control AMBE3000 serial a.k.a. DV serial devices or AMBE server addresses to use for AMBE digital voice processing.
DV serial devices are supported using the [SerialDV](https://github.com/f4exb/serialDV) library that is a mandatory requirement for this feature to be compiled. Therefore you have to compile and install SerialDV in your system. Please refer to this project Readme.md to compile and install SerialDV. f you install it in a custom location say `/opt/install/serialdv` you will need to add this define to the cmake command: `-DSERIALDV_DIR=/opt/install/serialdv`
To effectively use serial DV devices for AMBE decoding you will have to add at least one device to the list of AMBE devices (6) in use.
Although such serial devices work with a serial interface at 400 kb in practice maybe for other reasons they are capable of handling only one conversation at a time. The software will allocate the device dynamically to a conversation with an inactivity timeout of 1 second so that conversations do not get interrupted constantly making the audio output too choppy. In practice you will have to have as many devices listed in (6) as the number of conversations you would like to be handled in parallel.
---
&#9888; With kernel 4.4.52 and maybe other 4.4 versions the default for FTDI devices (that is in the ftdi_sio kernel module) is not to set it as low latency. This results in the ThumbDV dongle not working anymore because its response is too slow to sustain the normal AMBE packets flow. The solution is to force low latency by changing the variable for your device (ex: /dev/ttyUSB0) as follows:
`echo 1 | sudo tee /sys/bus/usb-serial/devices/ttyUSB0/latency_timer` or `sudo setserial /dev/ttyUSB0 low_latency`
Newer kernels do not seem to have this issue.
---
<h2>Interface</h2>
![AMBE controller GUI](../../../doc/img/AMBE_plugin.png)
<h3>1: AMBE server address and port or direct input</h3>
Use this freeflow text input box to specify either the address and port of an AMBE server in the form: &lt;IPv4 address>:&lt;port> or any directly attached physical device address.
<h3>2: Import above address or device</h3>
Import the address or device specified in (1) into the list of used devices. The system will try to open the device or contact the server and will add it to the list only if successful.
<h3>3: Remove in use device or address</h3>
When a device or address is selected in the in use list (6) push this button to remove it from the list. The corresponding resources will be released.
<h3>4: Refresh in use list</h3>
Checks the list of devices or addresses currently in use and update the in use list (6).
<h3>5: Empty in use list</h3>
Removes all devices or addresses in use. The in use list (6) is cleared consequently. This removes all AMBE devices related resources attached to the current instance of the SDRangel program. Therefore consecutive AMBE frames decoding will be handled by the mbelib library if available or no audio will be output.
<h3>6: In use list</h3>
List of devices or addresses currently in use for AMBE frames decoding by this feature.
Format is the device path or URL followed by a dash then the number of frames successfully decoded then a vertical bar then the number of frames that failed decoding. i.e:
`<Device path> - <successful count>|<failed count>`
<h3>7: Import serial device</h3>
Imports a serial device scanned in the list of available AMBE 3000 serial devices (10) in the in use list. If this device is already in the in use list then nothing happens and this is reported in the status text (11)
<h3>8: Import all serial devices</h3>
Imports all serial devices scanned in the list of available AMBE 3000 serial devices (9) in the in use list. If any device is already in the in use list then it is not added twice.
<h3>9: Refresh list of AMBE serial devices</h3>
Scans available AMBE 3000 serial devices and updates the list.
<h3>10: List of AMBE 3000 serial devices</h3>
List of AMBE 3000 connected to the system. Use button (9) to update the list.
<h3>11: Status text</h3>
A brief text reports the result of the current action.

View File

@ -0,0 +1,63 @@
project(limerfe)
set(limerfe_SOURCES
limerfe.cpp
limerfesettings.cpp
limerfeusbcalib.cpp
limerfeplugin.cpp
limerfewebapiadapter.cpp
)
set(limerfe_HEADERS
limerfe.h
limerfesettings.h
limerfeusbcalib.h
limerfeplugin.h
limerfewebapiadapter.h
)
include_directories(
${CMAKE_SOURCE_DIR}/swagger/sdrangel/code/qt5/client
${LIMESUITE_INCLUDE_DIR}
)
if(NOT SERVER_MODE)
set(limerfe_SOURCES
${limerfe_SOURCES}
limerfegui.cpp
limerfegui.ui
)
set(limerfe_HEADERS
${limerfe_HEADERS}
limerfegui.h
)
set(TARGET_NAME featurelimerfe)
set(TARGET_LIB "Qt5::Widgets")
set(TARGET_LIB_GUI "sdrgui")
set(INSTALL_FOLDER ${INSTALL_PLUGINS_DIR})
else()
set(TARGET_NAME featurelimerfesrv)
set(TARGET_LIB "")
set(TARGET_LIB_GUI "")
set(INSTALL_FOLDER ${INSTALL_PLUGINSSRV_DIR})
endif()
add_library(${TARGET_NAME} SHARED
${limerfe_SOURCES}
)
target_link_libraries(${TARGET_NAME}
Qt5::Core
${TARGET_LIB}
sdrbase
${TARGET_LIB_GUI}
${LIMESUITE_LIBRARY}
)
install(TARGETS ${TARGET_NAME} DESTINATION ${INSTALL_FOLDER})
# Install debug symbols
if (WIN32)
install(FILES $<TARGET_PDB_FILE:${TARGET_NAME}> CONFIGURATIONS Debug RelWithDebInfo DESTINATION ${INSTALL_FOLDER} )
endif()

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,185 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2022 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 //
// (at your option) any later version. //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License V3 for more details. //
// //
// You should have received a copy of the GNU General Public License //
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#ifndef INCLUDE_FEATURE_LIMERFE_H_
#define INCLUDE_FEATURE_LIMERFE_H_
#include <QNetworkRequest>
#include <string>
#include <map>
#include "lime/limeRFE.h"
#include "feature/feature.h"
#include "util/message.h"
#include "limerfesettings.h"
class QNetworkReply;
class QNetworkAccessManager;
class LimeRFE : public Feature
{
Q_OBJECT
public:
class MsgConfigureLimeRFE : public Message {
MESSAGE_CLASS_DECLARATION
public:
const LimeRFESettings& getSettings() const { return m_settings; }
bool getForce() const { return m_force; }
static MsgConfigureLimeRFE* create(const LimeRFESettings& settings, bool force) {
return new MsgConfigureLimeRFE(settings, force);
}
private:
LimeRFESettings m_settings;
bool m_force;
MsgConfigureLimeRFE(const LimeRFESettings& settings, bool force) :
Message(),
m_settings(settings),
m_force(force)
{ }
};
class MsgReportSetRx : public Message {
MESSAGE_CLASS_DECLARATION
public:
bool isOn() const { return m_on; }
static MsgReportSetRx* create(bool on) {
return new MsgReportSetRx(on);
}
private:
bool m_on;
MsgReportSetRx(bool on) :
Message(),
m_on(on)
{ }
};
class MsgReportSetTx : public Message {
MESSAGE_CLASS_DECLARATION
public:
bool isOn() const { return m_on; }
static MsgReportSetTx* create(bool on) {
return new MsgReportSetTx(on);
}
private:
bool m_on;
MsgReportSetTx(bool on) :
Message(),
m_on(on)
{ }
};
LimeRFE(WebAPIAdapterInterface *webAPIAdapterInterface);
virtual ~LimeRFE();
virtual void destroy() { delete this; }
virtual bool handleMessage(const Message& cmd);
virtual void getIdentifier(QString& id) const { id = objectName(); }
virtual QString getIdentifier() const { return objectName(); }
virtual void getTitle(QString& title) const { title = m_settings.m_title; }
virtual QByteArray serialize() const;
virtual bool deserialize(const QByteArray& data);
virtual int webapiSettingsGet(
SWGSDRangel::SWGFeatureSettings& response,
QString& errorMessage);
virtual int webapiSettingsPutPatch(
bool force,
const QStringList& featureSettingsKeys,
SWGSDRangel::SWGFeatureSettings& response,
QString& errorMessage);
virtual int webapiReportGet(
SWGSDRangel::SWGFeatureReport& response,
QString& errorMessage);
virtual int webapiActionsPost(
const QStringList& featureActionsKeys,
SWGSDRangel::SWGFeatureActions& query,
QString& errorMessage);
static void webapiFormatFeatureSettings(
SWGSDRangel::SWGFeatureSettings& response,
const LimeRFESettings& settings);
static void webapiUpdateFeatureSettings(
LimeRFESettings& settings,
const QStringList& featureSettingsKeys,
SWGSDRangel::SWGFeatureSettings& response);
int openDevice(const std::string& serialDeviceName);
void closeDevice();
const QStringList& getComPorts() { return m_comPorts; }
int configure();
int getState();
static std::string getError(int errorCode);
int setRx(bool rxOn);
int setTx(bool txOn);
bool getRx() const { return m_rxOn; };
bool getTx() const { return m_txOn; };
bool turnDevice(int deviceSetIndex, bool on);
int getFwdPower(int& powerDB);
int getRefPower(int& powerDB);
void settingsToState(const LimeRFESettings& settings);
void stateToSettings(LimeRFESettings& settings);
static const char* const m_featureIdURI;
static const char* const m_featureId;
private:
LimeRFESettings m_settings;
bool m_rxOn;
bool m_txOn;
QNetworkAccessManager *m_networkManager;
QNetworkRequest m_networkRequest;
WebAPIAdapterInterface *m_webAPIAdapterInterface;
rfe_dev_t *m_rfeDevice;
rfe_boardState m_rfeBoardState;
static const std::map<int, std::string> m_errorCodesMap;
QStringList m_comPorts;
void start();
void stop();
void listComPorts();
void applySettings(const LimeRFESettings& settings, bool force = false);
int webapiFormatFeatureReport(SWGSDRangel::SWGFeatureReport& response, QString& errorMessage);
private slots:
void networkManagerFinished(QNetworkReply *reply);
};
#endif

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,5 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2020 F4EXB //
// written by Edouard Griffiths //
// Copyright (C) 2022 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 //
@ -16,36 +15,77 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#ifndef SDRGUI_LIMERFEGUI_LIMERFEUSBDIALOG_H_
#define SDRGUI_LIMERFEGUI_LIMERFEUSBDIALOG_H_
#ifndef INCLUDE_FEATURE_LIMERFEGUI_H_
#define INCLUDE_FEATURE_LIMERFEGUI_H_
#include <vector>
#include <QDialog>
#include <QTimer>
#include "feature/featuregui.h"
#include "util/messagequeue.h"
#include "util/movingaverage.h"
#include "limerfe/limerfecontroller.h"
#include "limerfe/limerfeusbcalib.h"
#include "export.h"
#include "settings/rollupstate.h"
#include "limerfesettings.h"
class PluginAPI;
class FeatureUISet;
class Feature;
class LimeRFE;
class DSPDeviceSourceEngine;
class DSPDeviceSinkEngine;
class MainWindow;
namespace Ui {
class LimeRFEUSBDialog;
class LimeRFEGUI;
}
class SDRGUI_API LimeRFEUSBDialog : public QDialog {
class LimeRFEGUI : public FeatureGUI
{
Q_OBJECT
public:
explicit LimeRFEUSBDialog(LimeRFEUSBCalib& limeRFEUSBCalib, MainWindow* mainWindow);
~LimeRFEUSBDialog();
static LimeRFEGUI* create(PluginAPI* pluginAPI, FeatureUISet *featureUISet, Feature *feature);
virtual void destroy();
void resetToDefaults();
QByteArray serialize() const;
bool deserialize(const QByteArray& data);
virtual MessageQueue *getInputMessageQueue() { return &m_inputMessageQueue; }
virtual void setWorkspaceIndex(int 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; }
protected:
void resizeEvent(QResizeEvent* size);
private:
void displaySettings();
Ui::LimeRFEGUI* ui;
PluginAPI* m_pluginAPI;
FeatureUISet* m_featureUISet;
LimeRFESettings m_settings;
RollupState m_rollupState;
bool m_rxOn;
bool m_txOn;
bool m_doApplySettings;
bool m_rxTxToggle;
QTimer m_timer;
double m_currentPowerCorrection;
bool m_avgPower;
MovingAverageUtil<double, double, 10> m_powerMovingAverage;
bool m_deviceSetSync;
std::vector<DSPDeviceSourceEngine*> m_sourceEngines;
std::vector<int> m_rxDeviceSetIndex;
std::vector<DSPDeviceSinkEngine*> m_sinkEngines;
std::vector<int> m_txDeviceSetIndex;
LimeRFE* m_limeRFE;
MessageQueue m_inputMessageQueue;
explicit LimeRFEGUI(PluginAPI* pluginAPI, FeatureUISet *featureUISet, Feature *feature, QWidget* parent = nullptr);
virtual ~LimeRFEGUI();
void blockApplySettings(bool block) { m_doApplySettings = !block; }
void applySettings(bool force = false);
void displaySettings();
void displayMode();
void displayPower();
void refreshPower();
@ -60,26 +100,13 @@ private:
void stopStartTx(bool start);
void syncRxTx();
void highlightApplyButton(bool highlight);
Ui::LimeRFEUSBDialog* ui;
MainWindow *m_mainWindow;
LimeRFEController m_controller;
LimeRFEController::LimeRFESettings m_settings;
LimeRFEUSBCalib& m_limeRFEUSBCalib;
bool m_rxTxToggle;
QTimer m_timer;
double m_currentPowerCorrection;
bool m_avgPower;
MovingAverageUtil<double, double, 10> m_powerMovingAverage;
bool m_deviceSetSync;
int m_rxDeviceSetSequence;
int m_txDeviceSetSequence;
std::vector<DSPDeviceSourceEngine*> m_sourceEngines;
std::vector<int> m_rxDeviceSetIndex;
std::vector<DSPDeviceSinkEngine*> m_sinkEngines;
std::vector<int> m_txDeviceSetIndex;
bool handleMessage(const Message& message);
void makeUIConnections();
private slots:
void onMenuDialogCalled(const QPoint &p);
void onWidgetRolled(QWidget* widget, bool rollDown);
void handleInputMessages();
void on_openDevice_clicked();
void on_closeDevice_clicked();
void on_deviceToGUI_clicked();
@ -107,4 +134,4 @@ private slots:
void tick();
};
#endif // SDRGUI_LIMERFEGUI_LIMERFEUSBDIALOG_H_
#endif

View File

@ -0,0 +1,980 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>LimeRFEGUI</class>
<widget class="RollupContents" name="LimeRFEGUI">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>392</width>
<height>667</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>390</width>
<height>667</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>560</width>
<height>667</height>
</size>
</property>
<property name="font">
<font>
<family>Liberation Sans</family>
<pointsize>9</pointsize>
</font>
</property>
<property name="windowTitle">
<string>LimeRFE USB controller</string>
</property>
<widget class="QWidget" name="settingsContainer" native="true">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>391</width>
<height>372</height>
</rect>
</property>
<property name="windowTitle">
<string>Settings</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="spacing">
<number>3</number>
</property>
<property name="leftMargin">
<number>2</number>
</property>
<property name="topMargin">
<number>2</number>
</property>
<property name="rightMargin">
<number>2</number>
</property>
<property name="bottomMargin">
<number>2</number>
</property>
<item>
<layout class="QHBoxLayout" name="deviceLayout1">
<item>
<widget class="QLabel" name="deviceLabel">
<property name="text">
<string>Dev</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="device">
<property name="minimumSize">
<size>
<width>220</width>
<height>0</height>
</size>
</property>
<property name="toolTip">
<string>Device</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="openDevice">
<property name="maximumSize">
<size>
<width>60</width>
<height>16777215</height>
</size>
</property>
<property name="toolTip">
<string>Open device</string>
</property>
<property name="text">
<string>Open</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="closeDevice">
<property name="maximumSize">
<size>
<width>60</width>
<height>16777215</height>
</size>
</property>
<property name="toolTip">
<string>Close Device</string>
</property>
<property name="text">
<string>Close</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="deviceLayout2">
<item>
<widget class="QPushButton" name="deviceToGUI">
<property name="toolTip">
<string>Transfer data to GUI</string>
</property>
<property name="text">
<string>to GUI</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="apply">
<property name="toolTip">
<string>Apply changes</string>
</property>
<property name="text">
<string>Apply</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_7">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<widget class="Line" name="line">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="rxTitleLayout">
<item>
<widget class="QLabel" name="rxChannelLabel">
<property name="text">
<string>Rx channel</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="rxLayout1">
<item>
<widget class="QComboBox" name="rxChannelGroup">
<property name="minimumSize">
<size>
<width>120</width>
<height>0</height>
</size>
</property>
<property name="toolTip">
<string>Rx channel group</string>
</property>
<item>
<property name="text">
<string>Wideband</string>
</property>
</item>
<item>
<property name="text">
<string>HAM</string>
</property>
</item>
<item>
<property name="text">
<string>Cellular</string>
</property>
</item>
</widget>
</item>
<item>
<widget class="QComboBox" name="rxChannel">
<property name="minimumSize">
<size>
<width>200</width>
<height>0</height>
</size>
</property>
<property name="toolTip">
<string>Rx channel range</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="rxLayout2">
<item>
<widget class="QLabel" name="rxPortLabel_2">
<property name="text">
<string>Rx port</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="rxPort">
<property name="maximumSize">
<size>
<width>99</width>
<height>16777215</height>
</size>
</property>
<property name="toolTip">
<string>Rx port</string>
</property>
<item>
<property name="text">
<string>Tx/Rx (J3)</string>
</property>
</item>
<item>
<property name="text">
<string>Tx/Rx HF (J5)</string>
</property>
</item>
</widget>
</item>
<item>
<widget class="QLabel" name="attenuationLabel">
<property name="text">
<string>Att</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="attenuation">
<property name="toolTip">
<string>Rx attenuation</string>
</property>
<item>
<property name="text">
<string>0</string>
</property>
</item>
<item>
<property name="text">
<string>2</string>
</property>
</item>
<item>
<property name="text">
<string>4</string>
</property>
</item>
<item>
<property name="text">
<string>6</string>
</property>
</item>
<item>
<property name="text">
<string>8</string>
</property>
</item>
<item>
<property name="text">
<string>10</string>
</property>
</item>
<item>
<property name="text">
<string>12</string>
</property>
</item>
<item>
<property name="text">
<string>14</string>
</property>
</item>
</widget>
</item>
<item>
<widget class="QLabel" name="attenuationUnits">
<property name="text">
<string>dB</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="amFmNotchFilter">
<property name="toolTip">
<string>AM/FM notch filter</string>
</property>
<property name="text">
<string>Notch</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="Line" name="line_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="txTitleLayout">
<item>
<widget class="QLabel" name="txChannelLabel">
<property name="text">
<string>Tx channel</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="txFollowsRx">
<property name="toolTip">
<string>Channel same as Rx</string>
</property>
<property name="text">
<string>Same as Rx</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_6">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="txLayout1">
<item>
<widget class="QComboBox" name="txChannelGroup">
<property name="minimumSize">
<size>
<width>120</width>
<height>0</height>
</size>
</property>
<property name="toolTip">
<string>Rx channel group</string>
</property>
<item>
<property name="text">
<string>Wideband</string>
</property>
</item>
<item>
<property name="text">
<string>HAM</string>
</property>
</item>
<item>
<property name="text">
<string>Cellular</string>
</property>
</item>
</widget>
</item>
<item>
<widget class="QComboBox" name="txChannel">
<property name="minimumSize">
<size>
<width>200</width>
<height>0</height>
</size>
</property>
<property name="toolTip">
<string>Rx channel range</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="txLayout2">
<item>
<widget class="QLabel" name="txPortLabel">
<property name="minimumSize">
<size>
<width>47</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>Tx port</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="txPort">
<property name="toolTip">
<string>Tx port</string>
</property>
<item>
<property name="text">
<string>Tx/Rx (J3)</string>
</property>
</item>
<item>
<property name="text">
<string>Tx (J4)</string>
</property>
</item>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
</layout>
</widget>
<widget class="QWidget" name="powerContainer" native="true">
<property name="geometry">
<rect>
<x>0</x>
<y>373</y>
<width>391</width>
<height>121</height>
</rect>
</property>
<property name="windowTitle">
<string>Power</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3">
<property name="spacing">
<number>3</number>
</property>
<property name="leftMargin">
<number>2</number>
</property>
<property name="topMargin">
<number>2</number>
</property>
<property name="rightMargin">
<number>2</number>
</property>
<property name="bottomMargin">
<number>2</number>
</property>
<item>
<layout class="QHBoxLayout" name="powerSetLayout">
<item>
<widget class="QCheckBox" name="powerEnable">
<property name="toolTip">
<string>Enable power measurements</string>
</property>
<property name="text">
<string>Pwr</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="powerRefresh">
<property name="toolTip">
<string>Refresh power</string>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="../../../sdrgui/resources/res.qrc">
<normaloff>:/recycle.png</normaloff>:/recycle.png</iconset>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="powerSource">
<property name="toolTip">
<string>Power measurement source (EXTernal, CELlular)</string>
</property>
<item>
<property name="text">
<string>EXT</string>
</property>
</item>
<item>
<property name="text">
<string>CEL</string>
</property>
</item>
</widget>
</item>
<item>
<widget class="ButtonSwitch" name="powerAutoRefresh">
<property name="toolTip">
<string>Auto refresh power</string>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="../../../sdrgui/resources/res.qrc">
<normaloff>:/play.png</normaloff>:/play.png</iconset>
</property>
<property name="checkable">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="powerCorrLabel">
<property name="text">
<string>Corr</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="powerCorrValue">
<property name="maximumSize">
<size>
<width>60</width>
<height>16777215</height>
</size>
</property>
<property name="focusPolicy">
<enum>Qt::ClickFocus</enum>
</property>
<property name="toolTip">
<string>Power correction in dBm</string>
</property>
<property name="text">
<string>-00.0</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="powerReadingsLayout">
<property name="rightMargin">
<number>10</number>
</property>
<item>
<widget class="QLabel" name="powerFwdLabel">
<property name="text">
<string>Fwd</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="powerFwdText">
<property name="toolTip">
<string>Relative forward power in dB</string>
</property>
<property name="text">
<string>00.0</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item>
<widget class="Line" name="line_4">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="powerRefLabel">
<property name="text">
<string>Ref</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="powerRefText">
<property name="toolTip">
<string>Relative reflected power in dB</string>
</property>
<property name="text">
<string>00.0</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item>
<widget class="Line" name="line_5">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="returnLossLabel">
<property name="text">
<string>RL</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="returnLossText">
<property name="toolTip">
<string>Return loss in dB</string>
</property>
<property name="text">
<string>00.0</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="powerUnits">
<property name="text">
<string>dB</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item>
<widget class="Line" name="line_6">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="swrLabel">
<property name="text">
<string>VSWR</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="swrText">
<property name="toolTip">
<string>Voltage Standing Wave Ratio</string>
</property>
<property name="text">
<string>1.000</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="absPowerLayout">
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>Abs power</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="powerAbsDbText">
<property name="toolTip">
<string>Corrected forward power in dBm</string>
</property>
<property name="text">
<string>-00.0 dBm</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="powerAbsWText">
<property name="toolTip">
<string>Corrected forward power in Watts</string>
</property>
<property name="text">
<string>0.000 W</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="powerAbsAvg">
<property name="toolTip">
<string>Corrected power averaging</string>
</property>
<property name="text">
<string>Avg</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_4">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
</layout>
</widget>
<widget class="QWidget" name="controlContainer" native="true">
<property name="geometry">
<rect>
<x>0</x>
<y>495</y>
<width>391</width>
<height>171</height>
</rect>
</property>
<property name="windowTitle">
<string>Control</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<property name="spacing">
<number>3</number>
</property>
<property name="leftMargin">
<number>2</number>
</property>
<property name="topMargin">
<number>2</number>
</property>
<property name="rightMargin">
<number>2</number>
</property>
<property name="bottomMargin">
<number>2</number>
</property>
<item>
<layout class="QHBoxLayout" name="modeLayout">
<item>
<widget class="QLabel" name="modeLabel">
<property name="text">
<string>Mode</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="modeText">
<property name="minimumSize">
<size>
<width>110</width>
<height>0</height>
</size>
</property>
<property name="toolTip">
<string>Rx/Tx state</string>
</property>
<property name="text">
<string>None</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="deviceSetSync">
<property name="toolTip">
<string>DeviceSet synchronization</string>
</property>
<property name="text">
<string>Rx/Tx Sync</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_5">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="rtxLayout">
<item>
<widget class="QToolButton" name="modeRx">
<property name="toolTip">
<string>Switch Rx</string>
</property>
<property name="text">
<string>RX</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="modeTx">
<property name="toolTip">
<string>Switch Tx</string>
</property>
<property name="text">
<string>TX</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="rxTxToggle">
<property name="toolTip">
<string>Rx/Tx toggle</string>
</property>
<property name="text">
<string>Toggle</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="deviceSetRxLabel">
<property name="text">
<string>Rx</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="deviceSetRx">
<property name="toolTip">
<string>Index of Rx DeviceSet </string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="deviceSetTxLabel">
<property name="text">
<string>Tx</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="deviceSetTx">
<property name="toolTip">
<string>Index of Tx DeviceSet </string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="deviceSetRefresh">
<property name="toolTip">
<string>Refresh DeviceSet indexes</string>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="../../../sdrgui/resources/res.qrc">
<normaloff>:/recycle.png</normaloff>:/recycle.png</iconset>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="statusLayout">
<item>
<widget class="QTextBrowser" name="statusText">
<property name="toolTip">
<string>Messages</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</widget>
<customwidgets>
<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>
</customwidgets>
<resources>
<include location="../../../sdrgui/resources/res.qrc"/>
</resources>
<connections/>
</ui>

View File

@ -0,0 +1,80 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2022 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 //
// (at your option) any later version. //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 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 <QtPlugin>
#include "plugin/pluginapi.h"
#ifndef SERVER_MODE
#include "limerfegui.h"
#endif
#include "limerfe.h"
#include "limerfeplugin.h"
#include "limerfewebapiadapter.h"
const PluginDescriptor LimeRFEPlugin::m_pluginDescriptor = {
LimeRFE::m_featureId,
QStringLiteral("LimeRFE USB Controller"),
QStringLiteral("7.1.0"),
QStringLiteral("(c) Edouard Griffiths, F4EXB"),
QStringLiteral("https://github.com/f4exb/sdrangel"),
true,
QStringLiteral("https://github.com/f4exb/sdrangel")
};
LimeRFEPlugin::LimeRFEPlugin(QObject* parent) :
QObject(parent),
m_pluginAPI(nullptr)
{
}
const PluginDescriptor& LimeRFEPlugin::getPluginDescriptor() const
{
return m_pluginDescriptor;
}
void LimeRFEPlugin::initPlugin(PluginAPI* pluginAPI)
{
m_pluginAPI = pluginAPI;
// register Simple PTT feature
m_pluginAPI->registerFeature(LimeRFE::m_featureIdURI, LimeRFE::m_featureId, this);
}
#ifdef SERVER_MODE
FeatureGUI* LimeRFEPlugin::createFeatureGUI(FeatureUISet *featureUISet, Feature *feature) const
{
(void) featureUISet;
(void) feature;
return nullptr;
}
#else
FeatureGUI* LimeRFEPlugin::createFeatureGUI(FeatureUISet *featureUISet, Feature *feature) const
{
return LimeRFEGUI::create(m_pluginAPI, featureUISet, feature);
}
#endif
Feature* LimeRFEPlugin::createFeature(WebAPIAdapterInterface* webAPIAdapterInterface) const
{
return new LimeRFE(webAPIAdapterInterface);
}
FeatureWebAPIAdapter* LimeRFEPlugin::createFeatureWebAPIAdapter() const
{
return new LimeRFEWebAPIAdapter();
}

View File

@ -0,0 +1,48 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2022 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 //
// (at your option) any later version. //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License V3 for more details. //
// //
// You should have received a copy of the GNU General Public License //
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#ifndef INCLUDE_FEATURE_LIMERFEPLUGIN_H
#define INCLUDE_FEATURE_LIMERFEPLUGIN_H
#include <QObject>
#include "plugin/plugininterface.h"
class FeatureGUI;
class WebAPIAdapterInterface;
class LimeRFEPlugin : public QObject, PluginInterface {
Q_OBJECT
Q_INTERFACES(PluginInterface)
Q_PLUGIN_METADATA(IID "sdrangel.feature.limerfe")
public:
explicit LimeRFEPlugin(QObject* parent = nullptr);
const PluginDescriptor& getPluginDescriptor() const;
void initPlugin(PluginAPI* pluginAPI);
virtual FeatureGUI* createFeatureGUI(FeatureUISet *featureUISet, Feature *feature) const;
virtual Feature* createFeature(WebAPIAdapterInterface *webAPIAdapterInterface) const;
virtual FeatureWebAPIAdapter* createFeatureWebAPIAdapter() const;
private:
static const PluginDescriptor m_pluginDescriptor;
PluginAPI* m_pluginAPI;
};
#endif // INCLUDE_FEATURE_SIMPLEPTTPLUGIN_H

View File

@ -0,0 +1,182 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2022 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 //
// (at your option) any later version. //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 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 "util/simpleserializer.h"
#include "settings/serializable.h"
#include "limerfesettings.h"
LimeRFESettings::LimeRFESettings() :
m_rollupState(nullptr)
{
resetToDefaults();
}
void LimeRFESettings::resetToDefaults()
{
m_devicePath = "";
m_title = "Lime RFE";
m_rgbColor = QColor(50, 205, 50).rgb();
m_rxChannels = ChannelsWideband;
m_rxWidebandChannel = WidebandLow;
m_rxHAMChannel = HAM_144_146MHz;
m_rxCellularChannel = CellularBand38;
m_rxPort = RxPortJ3;
m_amfmNotch = false;
m_attenuationFactor = 0;
m_txChannels = ChannelsWideband;
m_txWidebandChannel = WidebandLow;
m_txHAMChannel = HAM_144_146MHz;
m_txCellularChannel = CellularBand38;
m_txPort = TxPortJ3;
m_swrEnable = false;
m_swrSource = SWRExternal;
m_txRxDriven = false;
m_useReverseAPI = false;
m_reverseAPIAddress = "127.0.0.1";
m_reverseAPIPort = 8888;
m_reverseAPIFeatureSetIndex = 0;
m_reverseAPIFeatureIndex = 0;
m_workspaceIndex = 0;
}
QByteArray LimeRFESettings::serialize() const
{
SimpleSerializer s(1);
s.writeS32(1, (int) m_rxChannels);
s.writeS32(2, (int) m_rxWidebandChannel);
s.writeS32(3, (int) m_rxHAMChannel);
s.writeS32(4, (int) m_rxCellularChannel);
s.writeS32(5, (int) m_rxPort);
s.writeBool(6, m_amfmNotch);
s.writeU32(7, m_attenuationFactor);
s.writeS32(10, (int) m_txChannels);
s.writeS32(11, (int) m_txWidebandChannel);
s.writeS32(12, (int) m_txHAMChannel);
s.writeS32(13, (int) m_txCellularChannel);
s.writeS32(14, (int) m_txPort);
s.writeBool(15, m_swrEnable);
s.writeS32(16, (int) m_swrSource);
s.writeBool(20, m_txRxDriven);
s.writeString(30, m_title);
s.writeU32(31, m_rgbColor);
s.writeBool(32, m_useReverseAPI);
s.writeString(33, m_reverseAPIAddress);
s.writeU32(34, m_reverseAPIPort);
s.writeU32(35, m_reverseAPIFeatureSetIndex);
s.writeU32(36, m_reverseAPIFeatureIndex);
if (m_rollupState) {
s.writeBlob(37, m_rollupState->serialize());
}
s.writeS32(38, m_workspaceIndex);
s.writeBlob(39, m_geometryBytes);
s.writeString(40, m_devicePath);
s.writeBlob(41, m_calib.serialize());
return s.final();
}
bool LimeRFESettings::deserialize(const QByteArray& data)
{
SimpleDeserializer d(data);
if(!d.isValid())
{
resetToDefaults();
return false;
}
if(d.getVersion() == 1)
{
QByteArray bytetmp;
uint32_t utmp;
int tmp;
d.readS32(1, &tmp, (int) ChannelsWideband);
m_rxChannels = (ChannelGroups) tmp;
d.readS32(2, &tmp, (int) WidebandLow);
m_rxWidebandChannel = (WidebandChannel) tmp;
d.readS32(3, &tmp, (int) HAM_144_146MHz);
m_rxHAMChannel = (HAMChannel) tmp;
d.readS32(4, &tmp, (int) CellularBand38);
m_rxCellularChannel = (CellularChannel) tmp;
d.readS32(5, &tmp, (int) RxPortJ3);
m_rxPort = (RxPort) tmp;
d.readBool(6, &m_amfmNotch, false);
d.readU32(7, &m_attenuationFactor, 0);
d.readS32(10, &tmp, (int) ChannelsWideband);
m_txChannels = (ChannelGroups) tmp;
d.readS32(11, &tmp, (int) WidebandLow);
m_txWidebandChannel = (WidebandChannel) tmp;
d.readS32(12, &tmp, (int) HAM_144_146MHz);
m_txHAMChannel = (HAMChannel) tmp;
d.readS32(13, &tmp, (int) CellularBand38);
m_txCellularChannel = (CellularChannel) tmp;
d.readS32(14, &tmp, (int) TxPortJ3);
m_txPort = (TxPort) tmp;
d.readBool(15, &m_swrEnable, false);
d.readS32(16, &tmp, (int) SWRExternal);
m_swrSource = (SWRSource) tmp;
d.readBool(20, &m_txRxDriven, false);
d.readString(30, &m_title, "Lime RFE");
d.readU32(31, &m_rgbColor, QColor(50, 205, 50).rgb());
d.readBool(32, &m_useReverseAPI, false);
d.readString(33, &m_reverseAPIAddress, "127.0.0.1");
d.readU32(34, &utmp, 0);
if ((utmp > 1023) && (utmp < 65535)) {
m_reverseAPIPort = utmp;
} else {
m_reverseAPIPort = 8888;
}
d.readU32(35, &utmp, 0);
m_reverseAPIFeatureSetIndex = utmp > 99 ? 99 : utmp;
d.readU32(36, &utmp, 0);
m_reverseAPIFeatureIndex = utmp > 99 ? 99 : utmp;
if (m_rollupState)
{
d.readBlob(37, &bytetmp);
m_rollupState->deserialize(bytetmp);
}
d.readS32(38, &m_workspaceIndex, 0);
d.readBlob(39, &m_geometryBytes);
d.readString(40, &m_devicePath, "");
d.readBlob(41, &bytetmp);
m_calib.deserialize(bytetmp);
return true;
}
else
{
resetToDefaults();
return false;
}
}

View File

@ -1,5 +1,5 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2020 Edouard Griffiths, F4EXB //
// Copyright (C) 2022 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 //
@ -15,17 +15,18 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#ifndef SDRBASE_LIMERFE_LIMERFECONTROLLER_H_
#define SDRBASE_LIMERFE_LIMERFECONTROLLER_H_
#ifndef INCLUDE_FEATURE_LIMERFESETTINGS_H_
#define INCLUDE_FEATURE_LIMERFESETTINGS_H_
#include <string>
#include <map>
#include "lime/limeRFE.h"
#include "export.h"
#include <QByteArray>
#include <QString>
class SDRBASE_API LimeRFEController
#include "limerfeusbcalib.h"
class Serializable;
struct LimeRFESettings
{
public:
enum ChannelGroups
{
ChannelsWideband,
@ -80,51 +81,43 @@ public:
SWRCellular
};
struct SDRBASE_API LimeRFESettings
{
LimeRFESettings();
// Rx
LimeRFEController::ChannelGroups m_rxChannels;
LimeRFEController::WidebandChannel m_rxWidebandChannel;
LimeRFEController::HAMChannel m_rxHAMChannel;
LimeRFEController::CellularChannel m_rxCellularChannel;
LimeRFEController::RxPort m_rxPort;
unsigned int m_attenuationFactor; //!< Attenuation is 2 times this factor in dB (0..7 => 0..14dB)
bool m_amfmNotch;
// Tx
LimeRFEController::ChannelGroups m_txChannels;
LimeRFEController::WidebandChannel m_txWidebandChannel;
LimeRFEController::HAMChannel m_txHAMChannel;
LimeRFEController::CellularChannel m_txCellularChannel;
LimeRFEController::TxPort m_txPort;
bool m_swrEnable;
LimeRFEController::SWRSource m_swrSource;
// Rx/Tx
bool m_txRxDriven; //!< Tx settings set according to Rx settings
bool m_rxOn;
bool m_txOn;
};
// Rx
ChannelGroups m_rxChannels;
WidebandChannel m_rxWidebandChannel;
HAMChannel m_rxHAMChannel;
CellularChannel m_rxCellularChannel;
RxPort m_rxPort;
unsigned int m_attenuationFactor; //!< Attenuation is 2 times this factor in dB (0..7 => 0..14dB)
bool m_amfmNotch;
// Tx
ChannelGroups m_txChannels;
WidebandChannel m_txWidebandChannel;
HAMChannel m_txHAMChannel;
CellularChannel m_txCellularChannel;
TxPort m_txPort;
bool m_swrEnable;
SWRSource m_swrSource;
// Rx/Tx
bool m_txRxDriven; //!< Tx settings set according to Rx settings
// Common
QString m_devicePath;
QString m_title;
quint32 m_rgbColor;
bool m_useReverseAPI;
QString m_reverseAPIAddress;
uint16_t m_reverseAPIPort;
uint16_t m_reverseAPIFeatureSetIndex;
uint16_t m_reverseAPIFeatureIndex;
Serializable *m_rollupState;
int m_workspaceIndex;
QByteArray m_geometryBytes;
LimeRFEUSBCalib m_calib;
LimeRFEController();
~LimeRFEController();
int openDevice(const std::string& serialDeviceName);
void closeDevice();
int configure();
int getState();
static std::string getError(int errorCode);
int setRx(LimeRFESettings& settings, bool rxOn);
int setTx(LimeRFESettings& settings, bool txOn);
int getFwdPower(int& powerDB);
int getRefPower(int& powerDB);
void settingsToState(const LimeRFESettings& settings);
void stateToSettings(LimeRFESettings& settings);
private:
rfe_dev_t *m_rfeDevice;
rfe_boardState m_rfeBoardState;
static const std::map<int, std::string> m_errorCodesMap;
LimeRFESettings();
void resetToDefaults();
QByteArray serialize() const;
bool deserialize(const QByteArray& data);
void setRollupState(Serializable *rollupState) { m_rollupState = rollupState; }
};
#endif // SDRBASE_LIMERFE_LIMERFECONTROLLER_H_
#endif

View File

@ -19,11 +19,10 @@
#define SDRBASE_LIMERFE_LIMERFEUSBCALIB_H_
#include <QMap>
#include "export.h"
class QByteArray;
class SDRBASE_API LimeRFEUSBCalib
class LimeRFEUSBCalib
{
public:
QByteArray serialize() const;

View File

@ -0,0 +1,51 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2022 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 //
// (at your option) any later version. //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 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 "SWGFeatureSettings.h"
#include "limerfe.h"
#include "limerfewebapiadapter.h"
LimeRFEWebAPIAdapter::LimeRFEWebAPIAdapter()
{}
LimeRFEWebAPIAdapter::~LimeRFEWebAPIAdapter()
{}
int LimeRFEWebAPIAdapter::webapiSettingsGet(
SWGSDRangel::SWGFeatureSettings& response,
QString& errorMessage)
{
(void) errorMessage;
response.setDemodAnalyzerSettings(new SWGSDRangel::SWGDemodAnalyzerSettings());
response.getDemodAnalyzerSettings()->init();
LimeRFE::webapiFormatFeatureSettings(response, m_settings);
return 200;
}
int LimeRFEWebAPIAdapter::webapiSettingsPutPatch(
bool force,
const QStringList& featureSettingsKeys,
SWGSDRangel::SWGFeatureSettings& response,
QString& errorMessage)
{
(void) force; // no action
(void) errorMessage;
LimeRFE::webapiUpdateFeatureSettings(m_settings, featureSettingsKeys, response);
return 200;
}

View File

@ -0,0 +1,49 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2022 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 //
// (at your option) any later version. //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License V3 for more details. //
// //
// You should have received a copy of the GNU General Public License //
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#ifndef INCLUDE_LIMERFE_WEBAPIADAPTER_H
#define INCLUDE_LIMERFE_WEBAPIADAPTER_H
#include "feature/featurewebapiadapter.h"
#include "limerfesettings.h"
/**
* Standalone API adapter only for the settings
*/
class LimeRFEWebAPIAdapter : public FeatureWebAPIAdapter {
public:
LimeRFEWebAPIAdapter();
virtual ~LimeRFEWebAPIAdapter();
virtual QByteArray serialize() const { return m_settings.serialize(); }
virtual bool deserialize(const QByteArray& data) { return m_settings.deserialize(data); }
virtual int webapiSettingsGet(
SWGSDRangel::SWGFeatureSettings& response,
QString& errorMessage);
virtual int webapiSettingsPutPatch(
bool force,
const QStringList& featureSettingsKeys,
SWGSDRangel::SWGFeatureSettings& response,
QString& errorMessage);
private:
LimeRFESettings m_settings;
};
#endif // INCLUDE_DEMODANALYZER_WEBAPIADAPTER_H

View File

@ -1,36 +1,46 @@
<h1>LimeRFE USB control</h1>
<h1>LimeRFE USB controller</h1>
The LimeRFE or Lime RF Front End is a power amplifier and LNA board designed to augment the capabilities of the LimeSDR in order to build an operational radio solution. The usage is not limited to LimeSDR any Rx or Tx device can be connected to it. The LimeRFE can be controlled directly via its USB port independently of a LimeSDR device. This interface allows exactly that from the SDRangel GUI.
<h2>Introduction</h2>
To open the LimeRFE USB dialog open the Preferences sub-menu from the top bar and click on the `LimeRFE` item. This item is available only when the code is compiled with the `LimeRFE` branch of LimeSuite.
This plugin supports the [LimeRFE](https://github.com/myriadrf/LimeRFE) board. This board hosts a hardware power amplifier (PA) module with appropriate filtering and support circuitry to augment primarily but not only the LimeSDR, LimeSDR Mini, and LimeNET Micro platforms, providing a complete solution that addresses real life applications ranging from HAM radio to standards-compliant cellular network implementations.
The dialog is non-modal so that it can be left open and keep the control on LimeRFE while other functions can be used.
As mentioned above it can be connected to a wide variety of SDR receivers and transmitters and this feature supports the synchronization with any receiver or trasmiiter device sets.
Whenever a change requires the LimeRFE configuration to be changed to become effective the "Apply" button (6) becomes green to suggest it should be activated.
This plugin depends on [LimeSuite](https://github.com/myriadrf/LimeSuite) that should be available in your system in order to be compiled.
&#9888; Disclaimer: please use this interface and the LimeRFE sensibly by making sure you are licensed to operate it on the selected frequencies. If you are a licensed amateur radio you should make sure you operate on the bands allocated in your region as some bands are exclusive to a specific region or country.
<h2>Interface</h2>
![LimeRFE USB dialog](../doc/img/LimeRFEUSB_dialog.png)
![LimeRFE controller GUI](../../../doc/img/LimeRFE_plugin.png)
<h2>1. USB serial devices list</h2>
When starting you need first to open the LimeRFE device with button (2). You havr to select the appropriate serial device from (1). Note that all serial USB based devices are listed. You need to identify which one corresponds to the LimeRFE board you want to target.
Once opened successfully (check status message in 6) you will apply the settings using the Apply button (5). Whenever the settings are changed this button lits in green showing that you may press it to update the board. Conversely the "to GUI" button (4) reads the settings from the board and updates the GUI.
<h3>1. USB serial devices list</h3>
This combo lists all USB serial devices list available in the system regardless if they are LimeRFE or other devices. You must specify the device corresponding to a LimeRFE device to be able to open it successfully with (2)
<h2>2. Open device</h2>
<h3>2. Open device</h3>
Click on this button to open the serial device selected by (1). You need to open the device successfully prior to any operation. The open status is displayed in the status window (5).
<h2>3. Close device</h2>
<h3>3. Close device</h3>
If you have more than one LimeRFE connected to your system you have to close one before opening another by using this button.
<h2>4. Pull device configuration to GUI</h2>
<h3>4. Pull device configuration to GUI</h3>
Use this button to retrieve the LimeRFE device current configuration and populate the GUI with its data.
<h3>5. Apply changes</h3>
Use this button to apply configuration changes. You must press this button to make any of your changes active. Whenever a change requires the LimeRFE configuration to be changed to become effective this button becomes green to suggest it should be activated.
<h3>6. Status window</h3
<h2>A. Rx channel control</h2>
![LimeRFE USB Rx dialog](../doc/img/LimeRFEUSB_dialog_rx.png)
![LimeRFE Rx section](../../../doc/img/LimeRFE_plugin_rx.png)
<h3>A.1. Rx channel group</h3>
@ -85,7 +95,7 @@ Toggle AM/FM broadcast bands notch filter.
<h2>B. Tx channel control</h2>
![LimeRFE USB Tx dialog](../doc/img/LimeRFEUSB_dialog_tx.png)
![LimeRFE Tx section](../../../doc/img/LimeRFE_plugin_tx.png)
<h3>B.1 Copy Rx band settings</h3>
@ -106,9 +116,12 @@ Select which port to connect the Rx to:
- **Tx/Rx (J3)**: this is the J3 port combining Rx and Tx. When cellular bands are selected this is connected to a duplexer internally
- **Tx (J4)**: Tx connected port only. Can be used to split Rx and Tx to drive a higher power P.A. for example
This is where status messages are displayed.
<h2>C. Power and SWR</h2>
![LimeRFE USB power dialog](../doc/img/LimeRFEUSB_dialog_power.png)
![LimeRFE power section](../../../doc/img/LimeRFE_plugin_power.png)
<h3>C.1 Activate power measurement</h3>
@ -118,52 +131,46 @@ Check this box to enable power measurements.
Use this button to refresh the power measurements.
<h3>C.3 Forward power (relative)</h3>
This is the relative forward direction power in dB.
<h3>C.4 Reflected power (relative)</h3>
This is the relative reverse direction power in dB.
<h3>C.5 Return loss</h3>
This is the return loss in dB and is exactly (C.3) minus (C.4).
<h3>C.6 Voltage Standing Wave Ratio</h3>
This is the VSWR computed from the return loss in (C.5)
<h3>C.7 Power measurement source</h3>
<h3>C.3 Power measurement source</h3>
Use this combo to select the power measurement source:
- **EXT**: External: select this when a dual directional coupler is connected to `Ref` (J17) and `Fwd` (J18) ports
- **CEL**: Cellular: select this to use the internal coupler when cellular bands are engaged
<h3>C.8 Monitor power continuously</h3>
<h3>C.4 Monitor power continuously</h3>
Use this switch to activate the continuous monitoring. A measurement will be taken every 500ms.
<h3>C.9 Power correction</h3>
<h3>C.5 Power correction</h3>
Use a power meter and apply this correction to obtain the real delivered power in dBm. There is one correction factor by band. The values are saved in the persistent settings.
<h3>C.10 Corrected power</h3>
<h3>C.6 Coupler relative power measurements</h3>
This is the corrected power in dBm and is exactly (C.3) plus (C.9).
- **Fwd**: This is the relative forward direction power in dB.
- **Ref**: This is the relative reverse direction power in dB.
- **RL**: This is the return loss in dB and is exactly Fwd minus Ref
<h3>C.11 Corrected power in Watts</h3>
<h3>C.7 Voltage Standing Wave Ratio</h3>
This is the VSWR computed from the return loss RL in (C.6)
<h3>C.8 Corrected power in dBm</h3>
This is the corrected power in dBm and is exactly Fwd in (C.6) plus correction in (C.8).
<h3>C.9 Corrected power in Watts</h3>
This is the corrected power in Watts.
<h3>C.12 Corrected power averaging</h3>
<h3>C.10 Corrected power averaging</h3>
Use this switch to activate the averaging of corrected power. This is a moving average over 10 measurements thus over a 5s period.
<h2>D. Rx/Tx mode selection</h2>
<h2>D. Control</h2>
![LimeRFE USB mode dialog](../doc/img/LimeRFEUSB_dialog_mode.png)
![LimeRFE control section](../../../doc/img/LimeRFE_plugin_control.png)
<h3>D.1 Rx mode</h3>
@ -192,15 +199,3 @@ Select the Tx device set index with which you want to synchronize the Tx switch
<h3>D.7 Refresh device sets indexes</h3>
When the configuration of device sets changes you can use this button to refresh the device set indexes in (D.5) and (D.6).
<h2>5. Status window</h2>
This is where status messages are displayed.
<h2>6. Apply changes</h2>
Use this button to apply configuration changes. You must press this button to make any of your changes active. Whenever a change requires the LimeRFE configuration to be changed to become effective this button becomes green to suggest it should be activated.
<h2>7. Close dialog</h2>
This dismisses the dialog.

View File

@ -27,7 +27,7 @@ Pressing this button downloads the OpenAIP.net Navaid database, which contains t
<h3>3: Draw Radials Adjusted for Magnetic Declination</h3>
When checked, radials on the map will drawn adjusted for magnetic declination. For example, if a VOR has a magnetic declination of 5 degrees, and the radial is calculated at 0 degrees, the radial will be drawn to magnetic North, i.e. -5 degress from true North. If not checked, the same radial would be drawn to true North (i.e 0 degrees), which may result in a less accurate position estimate.
When checked, radials on the map will drawn adjusted for magnetic declination. For example, if a VOR has a magnetic declination of 5 degrees, and the radial is calculated at 0 degrees, the radial will be drawn to magnetic North, i.e. -5 degrees from true North. If not checked, the same radial would be drawn to true North (i.e 0 degrees), which may result in a less accurate position estimate.
<h3>4: Round robin turn time</h3>

View File

@ -104,7 +104,7 @@ With SR as the sample rate before decimation Fc is calculated as:
For Rx streams the I/Q stream from the BladeRF ADC is downsampled by a power of two before being sent to the passband.
For Tx strams the baseband stream is interpolated by this value before being sent to the BladeRF device.
For Tx streams the baseband stream is interpolated by this value before being sent to the BladeRF device.
Possible values are increasing powers of two: 1 (no decimation or interpolation), 2, 4, 8, 16, 32, 64.

View File

@ -161,7 +161,7 @@ Use this button to adjust the global gain of the LNA, TIA and PGA. LimeSuite sof
<h4>8.3: LNA manual gain</h4>
Use this button to adjust the gain of tha LNA when manual gain mode is set (8.1). Gain can be set between 1 and 30 dB in 1 dB steps. However the hardware has 3 dB steps for the lower gain values so increasing or decreasing by one step does not always produce a change. The value in dB appears at the right of the button.
Use this button to adjust the gain of the LNA when manual gain mode is set (8.1). Gain can be set between 1 and 30 dB in 1 dB steps. However the hardware has 3 dB steps for the lower gain values so increasing or decreasing by one step does not always produce a change. The value in dB appears at the right of the button.
<h4>8.4: TIA manual gain</h4>
@ -169,7 +169,7 @@ Use this combo to select the TIA gain in dB when manual gain mode is set (8.1).
<h4>8.5: PGA manual gain</h4>
Use this button to adjust the gain of tha PGA when manual gain mode is set (8.1). Gain can be set between 0 and 32 dB in 1 dB steps. The value in dB appears at the right of the button.
Use this button to adjust the gain of the PGA when manual gain mode is set (8.1). Gain can be set between 0 and 32 dB in 1 dB steps. The value in dB appears at the right of the button.
<h3>9: Antenna select</h3>

View File

@ -179,7 +179,7 @@ Use this button to adjust the global gain of the LNA, TIA and PGA. LimeSuite sof
<h4>8.3: LNA manual gain</h4>
Use this button to adjust the gain of tha LNA when manual gain mode is set (9.1). Gain can be set between 1 and 30 dB in 1 dB steps. However the hardware has 3 dB steps for the lower gain values so increasing or decreasing by one step does not always produce a change. The value in dB appears at the right of the button.
Use this button to adjust the gain of the LNA when manual gain mode is set (9.1). Gain can be set between 1 and 30 dB in 1 dB steps. However the hardware has 3 dB steps for the lower gain values so increasing or decreasing by one step does not always produce a change. The value in dB appears at the right of the button.
<h4>8.4: TIA manual gain</h4>
@ -187,7 +187,7 @@ Use this combo to select the TIA gain in dB when manual gain mode is set (9.1).
<h4>8.5: PGA manual gain</h4>
Use this button to adjust the gain of tha PGA when manual gain mode is set (9.1). Gain can be set between 0 and 32 dB in 1 dB steps. The value in dB appears at the right of the button.
Use this button to adjust the gain of the PGA when manual gain mode is set (9.1). Gain can be set between 0 and 32 dB in 1 dB steps. The value in dB appears at the right of the button.
<h3>9: Antenna select</h3>

View File

@ -31,19 +31,6 @@ else(FFTW3F_FOUND)
add_definitions(-DUSE_KISSFFT)
endif(FFTW3F_FOUND)
if (LIMESUITE_FOUND)
set(sdrbase_SOURCES
${sdrbase_SOURCES}
limerfe/limerfecontroller.cpp
)
set(sdrbase_HEADERS
${sdrbase_HEADERS}
limerfe/limerfecontroller.h
)
include_directories(${LIMESUITE_INCLUDE_DIR})
set(sdrbase_LIMERFE_LIB ${LIMESUITE_LIBRARY})
endif (LIMESUITE_FOUND)
if (LIBSIGMF_FOUND AND CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
set(sdrbase_SOURCES
${sdrbase_SOURCES}
@ -65,8 +52,6 @@ set(sdrbase_SERIALDV_LIB ${LIBSERIALDV_LIBRARY})
set(sdrbase_SOURCES
${sdrbase_SOURCES}
ambe/ambeengine.cpp
ambe/ambeworker.cpp
audio/audiocompressor.cpp
audio/audiocompressorsnd.cpp
@ -165,8 +150,6 @@ set(sdrbase_SOURCES
feature/featureutils.cpp
feature/featurewebapiutils.cpp
limerfe/limerfeusbcalib.cpp
pipes/datafifostore.cpp
pipes/datapipes.cpp
pipes/datapipesgcworker.cpp
@ -242,8 +225,6 @@ set(sdrbase_SOURCES
set(sdrbase_HEADERS
${sdrbase_HEADERS}
ambe/ambeengine.h
ambe/ambeworker.h
audio/audiocompressor.h
audio/audiocompressorsnd.h
@ -373,8 +354,6 @@ set(sdrbase_HEADERS
feature/featureutils.h
feature/featurewebapiutils.h
limerfe/limerfeusbcalib.h
pipes/datafifostore.h
pipes/datapipes.h
pipes/datapipesgcworker.h

View File

@ -44,3 +44,4 @@ MESSAGE_CLASS_DEFINITION(DSPSignalNotification, Message)
MESSAGE_CLASS_DEFINITION(DSPMIMOSignalNotification, Message)
MESSAGE_CLASS_DEFINITION(DSPConfigureChannelizer, Message)
MESSAGE_CLASS_DEFINITION(DSPConfigureAudio, Message)
MESSAGE_CLASS_DEFINITION(DSPPushMbeFrame, Message)

View File

@ -345,4 +345,45 @@ private:
AudioType m_autioType;
};
class SDRBASE_API DSPPushMbeFrame : public Message {
MESSAGE_CLASS_DECLARATION
public:
DSPPushMbeFrame(
const unsigned char *mbeFrame,
int mbeRateIndex,
int mbeVolumeIndex,
unsigned char channels,
bool useHP,
int upsampling,
AudioFifo *audioFifo
) :
Message(),
m_mbeFrame(mbeFrame),
m_mbeRateIndex(mbeRateIndex),
m_mbeVolumeIndex(mbeVolumeIndex),
m_channels(channels),
m_useHP(useHP),
m_upsampling(upsampling),
m_audioFifo(audioFifo)
{ }
const unsigned char * getMbeFrame() const { return m_mbeFrame; }
int getMbeRateIndex() const { return m_mbeRateIndex; }
int getMbeVolumeIndex() const { return m_mbeVolumeIndex; }
unsigned char getChannels() const { return m_channels; }
bool getUseHP() const { return m_useHP; }
int getUpsampling() const { return m_upsampling; }
AudioFifo *getAudioFifo() const { return m_audioFifo; }
private:
const unsigned char *m_mbeFrame;
int m_mbeRateIndex;
int m_mbeVolumeIndex;
unsigned char m_channels;
bool m_useHP;
int m_upsampling;
AudioFifo *m_audioFifo;
};
#endif // INCLUDE_DSPCOMMANDS_H

View File

@ -168,37 +168,6 @@ void DSPEngine::removeDeviceEngineAt(int deviceIndex)
m_deviceEngineReferences.removeAt(deviceIndex);
}
bool DSPEngine::hasDVSerialSupport()
{
return m_ambeEngine.getNbDevices() > 0;
}
void DSPEngine::setDVSerialSupport(bool support)
{ (void) support; }
void DSPEngine::getDVSerialNames(std::vector<std::string>& deviceNames)
{
std::vector<QString> qDeviceRefs;
m_ambeEngine.getDeviceRefs(qDeviceRefs);
deviceNames.clear();
for (std::vector<QString>::const_iterator it = qDeviceRefs.begin(); it != qDeviceRefs.end(); ++it) {
deviceNames.push_back(it->toStdString());
}
}
void DSPEngine::pushMbeFrame(
const unsigned char *mbeFrame,
int mbeRateIndex,
int mbeVolumeIndex,
unsigned char channels,
bool useHP,
int upsampling,
AudioFifo *audioFifo)
{
m_ambeEngine.pushMbeFrame(mbeFrame, mbeRateIndex, mbeVolumeIndex, channels, useHP, upsampling, audioFifo);
}
void DSPEngine::createFFTFactory(const QString& fftWisdomFileName)
{
m_fftFactory = new FFTFactory(fftWisdomFileName);

View File

@ -26,7 +26,6 @@
#include "audio/audiodevicemanager.h"
#include "audio/audiooutputdevice.h"
#include "export.h"
#include "ambe/ambeengine.h"
class DSPDeviceSourceEngine;
class DSPDeviceSinkEngine;
@ -55,7 +54,6 @@ public:
void removeDeviceEngineAt(int deviceIndex);
AudioDeviceManager *getAudioDeviceManager() { return &m_audioDeviceManager; }
AMBEEngine *getAMBEEngine() { return &m_ambeEngine; }
uint32_t getDeviceSourceEnginesNumber() const { return m_deviceSourceEngines.size(); }
DSPDeviceSourceEngine *getDeviceSourceEngineByIndex(unsigned int deviceIndex) { return m_deviceSourceEngines[deviceIndex]; }
@ -66,20 +64,6 @@ public:
uint32_t getDeviceMIMOEnginesNumber() const { return m_deviceMIMOEngines.size(); }
DSPDeviceMIMOEngine *getDeviceMIMOEngineByIndex(unsigned int deviceIndex) { return m_deviceMIMOEngines[deviceIndex]; }
// Serial DV methods:
bool hasDVSerialSupport();
void setDVSerialSupport(bool support);
void getDVSerialNames(std::vector<std::string>& deviceNames);
void pushMbeFrame(
const unsigned char *mbeFrame,
int mbeRateIndex,
int mbeVolumeIndex,
unsigned char channels,
bool useHP,
int upsampling,
AudioFifo *audioFifo);
const QTimer& getMasterTimer() const { return m_masterTimer; }
void setMIMOSupport(bool mimoSupport) { m_mimoSupport = mimoSupport; }
bool getMIMOSupport() const { return m_mimoSupport; }
@ -109,7 +93,6 @@ private:
QTimer m_masterTimer;
bool m_dvSerialSupport;
bool m_mimoSupport;
AMBEEngine m_ambeEngine;
FFTFactory *m_fftFactory;
};

View File

@ -1,567 +0,0 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2020 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 //
// (at your option) any later version. //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 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 <QDebug>
#include "limerfecontroller.h"
const std::map<int, std::string> LimeRFEController::m_errorCodesMap = {
{ 0, "OK"},
{-4, "Error synchronizing communication"},
{-3, "Non-configurable GPIO pin specified. Only pins 4 and 5 are configurable."},
{-2, "Problem with .ini configuration file"},
{-1, "Communication error"},
{ 1, "Wrong TX connector - not possible to route TX of the selecrted channel to the specified port"},
{ 2, "Wrong RX connector - not possible to route RX of the selecrted channel to the specified port"},
{ 3, "Mode TXRX not allowed - when the same port is selected for RX and TX, it is not allowed to use mode RX & TX"},
{ 4, "Wrong mode for cellular channel - Cellular FDD bands (1, 2, 3, and 7) are only allowed mode RX & TX, while TDD band 38 is allowed only RX or TX mode"},
{ 5, "Cellular channels must be the same both for RX and TX"},
{ 6, "Requested channel code is wrong"}
};
LimeRFEController::LimeRFESettings::LimeRFESettings()
{
m_rxChannels = ChannelsWideband;
m_rxWidebandChannel = WidebandLow;
m_rxHAMChannel = HAM_144_146MHz;
m_rxCellularChannel = CellularBand38;
m_rxPort = RxPortJ3;
m_amfmNotch = false;
m_attenuationFactor = 0;
m_txChannels = ChannelsWideband;
m_txWidebandChannel = WidebandLow;
m_txHAMChannel = HAM_144_146MHz;
m_txCellularChannel = CellularBand38;
m_txPort = TxPortJ3;
m_swrEnable = false;
m_swrSource = SWRExternal;
m_txRxDriven = false;
m_rxOn = false;
m_txOn = false;
}
LimeRFEController::LimeRFEController() :
m_rfeDevice(nullptr)
{}
LimeRFEController::~LimeRFEController()
{
closeDevice();
}
int LimeRFEController::openDevice(const std::string& serialDeviceName)
{
closeDevice();
rfe_dev_t *rfeDevice = RFE_Open(serialDeviceName.c_str(), nullptr);
if (rfeDevice != (void *) -1) {
m_rfeDevice = rfeDevice;
return 0;
}
else
{
return -1;
}
}
void LimeRFEController::closeDevice()
{
if (m_rfeDevice)
{
RFE_Close(m_rfeDevice);
m_rfeDevice = nullptr;
}
}
int LimeRFEController::configure()
{
if (!m_rfeDevice) {
return -1;
}
qDebug() << "LimeRFEController::configure: "
<< "attValue: " << (int) m_rfeBoardState.attValue
<< "channelIDRX: " << (int) m_rfeBoardState.channelIDRX
<< "channelIDTX: " << (int) m_rfeBoardState.channelIDTX
<< "mode: " << (int) m_rfeBoardState.mode
<< "notchOnOff: " << (int) m_rfeBoardState.notchOnOff
<< "selPortRX: " << (int) m_rfeBoardState.selPortRX
<< "selPortTX: " << (int) m_rfeBoardState.selPortTX
<< "enableSWR: " << (int) m_rfeBoardState.enableSWR
<< "sourceSWR: " << (int) m_rfeBoardState.sourceSWR;
int rc = RFE_ConfigureState(m_rfeDevice, m_rfeBoardState);
if (rc != 0) {
qInfo("LimeRFEController::configure: %s", getError(rc).c_str());
} else {
qDebug() << "LimeRFEController::configure: done";
}
return rc;
}
int LimeRFEController::getState()
{
if (!m_rfeDevice) {
return -1;
}
int rc = RFE_GetState(m_rfeDevice, &m_rfeBoardState);
qDebug() << "LimeRFEController::getState: "
<< "attValue: " << (int) m_rfeBoardState.attValue
<< "channelIDRX: " << (int) m_rfeBoardState.channelIDRX
<< "channelIDTX: " << (int) m_rfeBoardState.channelIDTX
<< "mode: " << (int) m_rfeBoardState.mode
<< "notchOnOff: " << (int) m_rfeBoardState.notchOnOff
<< "selPortRX: " << (int) m_rfeBoardState.selPortRX
<< "selPortTX: " << (int) m_rfeBoardState.selPortTX
<< "enableSWR: " << (int) m_rfeBoardState.enableSWR
<< "sourceSWR: " << (int) m_rfeBoardState.sourceSWR;
if (rc != 0) {
qInfo("LimeRFEController::getState: %s", getError(rc).c_str());
}
return rc;
}
std::string LimeRFEController::getError(int errorCode)
{
std::map<int, std::string>::const_iterator it = m_errorCodesMap.find(errorCode);
if (it == m_errorCodesMap.end()) {
return "Unknown error";
} else {
return it->second;
}
}
int LimeRFEController::setRx(LimeRFESettings& settings, bool rxOn)
{
if (!m_rfeDevice) {
return -1;
}
int mode = rxOn && settings.m_txOn ?
RFE_MODE_TXRX : rxOn ?
RFE_MODE_RX : settings.m_txOn ?
RFE_MODE_TX : RFE_MODE_NONE;
int rc = RFE_Mode(m_rfeDevice, mode);
if (rc == 0) {
settings.m_rxOn = rxOn;
}
return rc;
}
int LimeRFEController::setTx(LimeRFESettings& settings, bool txOn)
{
if (!m_rfeDevice) {
return -1;
}
int mode = txOn && settings.m_rxOn ?
RFE_MODE_TXRX : txOn ?
RFE_MODE_TX : settings.m_rxOn ?
RFE_MODE_RX : RFE_MODE_NONE;
int rc = RFE_Mode(m_rfeDevice, mode);
if (rc == 0) {
settings.m_txOn = txOn;
}
return rc;
}
int LimeRFEController::getFwdPower(int& powerDB)
{
if (!m_rfeDevice) {
return -1;
}
int power;
int rc = RFE_ReadADC(m_rfeDevice, RFE_ADC1, &power);
if (rc == 0) {
powerDB = power;
}
return rc;
}
int LimeRFEController::getRefPower(int& powerDB)
{
if (!m_rfeDevice) {
return -1;
}
int power;
int rc = RFE_ReadADC(m_rfeDevice, RFE_ADC2, &power);
if (rc == 0) {
powerDB = power;
}
return rc;
}
void LimeRFEController::settingsToState(const LimeRFESettings& settings)
{
if (settings.m_rxChannels == ChannelsCellular)
{
if (settings.m_rxCellularChannel == CellularBand1)
{
m_rfeBoardState.channelIDRX = RFE_CID_CELL_BAND01;
m_rfeBoardState.mode = RFE_MODE_TXRX;
}
else if (settings.m_rxCellularChannel == CellularBand2)
{
m_rfeBoardState.channelIDRX = RFE_CID_CELL_BAND02;
m_rfeBoardState.mode = RFE_MODE_TXRX;
}
else if (settings.m_rxCellularChannel == CellularBand3)
{
m_rfeBoardState.channelIDRX = RFE_CID_CELL_BAND03;
m_rfeBoardState.mode = RFE_MODE_TXRX;
}
else if (settings.m_rxCellularChannel == CellularBand38)
{
m_rfeBoardState.channelIDRX = RFE_CID_CELL_BAND38;
}
else if (settings.m_rxCellularChannel == CellularBand7)
{
m_rfeBoardState.channelIDRX = RFE_CID_CELL_BAND07;
m_rfeBoardState.mode = RFE_MODE_TXRX;
}
m_rfeBoardState.selPortRX = RFE_PORT_1;
m_rfeBoardState.selPortTX = RFE_PORT_1;
m_rfeBoardState.channelIDTX = m_rfeBoardState.channelIDRX;
}
else
{
m_rfeBoardState.mode = settings.m_rxOn && settings.m_txOn ?
RFE_MODE_TXRX : settings.m_rxOn ?
RFE_MODE_RX : settings.m_txOn ?
RFE_MODE_TX : RFE_MODE_NONE;
if (settings.m_rxChannels == ChannelsWideband)
{
if (settings.m_rxWidebandChannel == WidebandLow) {
m_rfeBoardState.channelIDRX = RFE_CID_WB_1000;
} else if (settings.m_rxWidebandChannel == WidebandHigh) {
m_rfeBoardState.channelIDRX = RFE_CID_WB_4000;
}
}
else if (settings.m_rxChannels == ChannelsHAM)
{
if (settings.m_rxHAMChannel == HAM_30M) {
m_rfeBoardState.channelIDRX = RFE_CID_HAM_0030;
} else if (settings.m_rxHAMChannel == HAM_50_70MHz) {
m_rfeBoardState.channelIDRX = RFE_CID_HAM_0070;
} else if (settings.m_rxHAMChannel == HAM_144_146MHz) {
m_rfeBoardState.channelIDRX = RFE_CID_HAM_0145;
} else if (settings.m_rxHAMChannel == HAM_220_225MHz) {
m_rfeBoardState.channelIDRX = RFE_CID_HAM_0220;
} else if (settings.m_rxHAMChannel == HAM_430_440MHz) {
m_rfeBoardState.channelIDRX = RFE_CID_HAM_0435;
} else if (settings.m_rxHAMChannel == HAM_902_928MHz) {
m_rfeBoardState.channelIDRX = RFE_CID_HAM_0920;
} else if (settings.m_rxHAMChannel == HAM_1240_1325MHz) {
m_rfeBoardState.channelIDRX = RFE_CID_HAM_1280;
} else if (settings.m_rxHAMChannel == HAM_2300_2450MHz) {
m_rfeBoardState.channelIDRX = RFE_CID_HAM_2400;
} else if (settings.m_rxHAMChannel == HAM_3300_3500MHz) {
m_rfeBoardState.channelIDRX = RFE_CID_HAM_3500;
}
}
if (settings.m_rxPort == RxPortJ3) {
m_rfeBoardState.selPortRX = RFE_PORT_1;
} else if (settings.m_rxPort == RxPortJ5) {
m_rfeBoardState.selPortRX = RFE_PORT_3;
}
if (settings.m_txRxDriven)
{
m_rfeBoardState.channelIDTX = m_rfeBoardState.channelIDRX;
}
else
{
if (settings.m_txChannels == ChannelsWideband)
{
if (settings.m_txWidebandChannel == WidebandLow) {
m_rfeBoardState.channelIDTX = RFE_CID_WB_1000;
} else if (settings.m_txWidebandChannel == WidebandHigh) {
m_rfeBoardState.channelIDTX = RFE_CID_WB_4000;
}
}
else if (settings.m_txChannels == ChannelsHAM)
{
if (settings.m_txHAMChannel == HAM_30M) {
m_rfeBoardState.channelIDTX = RFE_CID_HAM_0030;
} else if (settings.m_txHAMChannel == HAM_50_70MHz) {
m_rfeBoardState.channelIDTX = RFE_CID_HAM_0070;
} else if (settings.m_txHAMChannel == HAM_144_146MHz) {
m_rfeBoardState.channelIDTX = RFE_CID_HAM_0145;
} else if (settings.m_txHAMChannel == HAM_220_225MHz) {
m_rfeBoardState.channelIDTX = RFE_CID_HAM_0220;
} else if (settings.m_txHAMChannel == HAM_430_440MHz) {
m_rfeBoardState.channelIDTX = RFE_CID_HAM_0435;
} else if (settings.m_txHAMChannel == HAM_902_928MHz) {
m_rfeBoardState.channelIDTX = RFE_CID_HAM_0920;
} else if (settings.m_txHAMChannel == HAM_1240_1325MHz) {
m_rfeBoardState.channelIDTX = RFE_CID_HAM_1280;
} else if (settings.m_txHAMChannel == HAM_2300_2450MHz) {
m_rfeBoardState.channelIDTX = RFE_CID_HAM_2400;
} else if (settings.m_txHAMChannel == HAM_3300_3500MHz) {
m_rfeBoardState.channelIDTX = RFE_CID_HAM_3500;
}
}
}
if (settings.m_txPort == TxPortJ3) {
m_rfeBoardState.selPortTX = RFE_PORT_1;
} else if (settings.m_txPort == TxPortJ4) {
m_rfeBoardState.selPortTX = RFE_PORT_2;
} else if (settings.m_txPort == TxPortJ5) {
m_rfeBoardState.selPortTX = RFE_PORT_3;
}
}
m_rfeBoardState.attValue = settings.m_attenuationFactor > 7 ? 7 : settings.m_attenuationFactor;
m_rfeBoardState.notchOnOff = settings.m_amfmNotch;
m_rfeBoardState.enableSWR = settings.m_swrEnable ? RFE_SWR_ENABLE : RFE_SWR_DISABLE;
if (settings.m_swrSource == SWRExternal) {
m_rfeBoardState.sourceSWR = RFE_SWR_SRC_EXT;
} else if (settings.m_swrSource == SWRCellular) {
m_rfeBoardState.sourceSWR = RFE_SWR_SRC_CELL;
}
}
void LimeRFEController::stateToSettings(LimeRFESettings& settings)
{
if (m_rfeBoardState.channelIDRX == RFE_CID_CELL_BAND01)
{
settings.m_rxChannels = ChannelsCellular;
settings.m_rxCellularChannel = CellularBand1;
}
else if (m_rfeBoardState.channelIDRX == RFE_CID_CELL_BAND02)
{
settings.m_rxChannels = ChannelsCellular;
settings.m_rxCellularChannel = CellularBand2;
}
else if (m_rfeBoardState.channelIDRX == RFE_CID_CELL_BAND03)
{
settings.m_rxChannels = ChannelsCellular;
settings.m_rxCellularChannel = CellularBand3;
}
else if (m_rfeBoardState.channelIDRX == RFE_CID_CELL_BAND07)
{
settings.m_rxChannels = ChannelsCellular;
settings.m_rxCellularChannel = CellularBand7;
}
else if (m_rfeBoardState.channelIDRX == RFE_CID_CELL_BAND38)
{
settings.m_rxChannels = ChannelsCellular;
settings.m_rxCellularChannel = CellularBand38;
}
else if (m_rfeBoardState.channelIDRX == RFE_CID_WB_1000)
{
settings.m_rxChannels = ChannelsWideband;
settings.m_rxWidebandChannel = WidebandLow;
}
else if (m_rfeBoardState.channelIDRX == RFE_CID_WB_4000)
{
settings.m_rxChannels = ChannelsWideband;
settings.m_rxWidebandChannel = WidebandHigh;
}
else if (m_rfeBoardState.channelIDRX == RFE_CID_HAM_0030)
{
settings.m_rxChannels = ChannelsHAM;
settings.m_rxHAMChannel = HAM_30M;
}
else if (m_rfeBoardState.channelIDRX == RFE_CID_HAM_0070)
{
settings.m_rxChannels = ChannelsHAM;
settings.m_rxHAMChannel = HAM_50_70MHz;
}
else if (m_rfeBoardState.channelIDRX == RFE_CID_HAM_0145)
{
settings.m_rxChannels = ChannelsHAM;
settings.m_rxHAMChannel = HAM_144_146MHz;
}
else if (m_rfeBoardState.channelIDRX == RFE_CID_HAM_0220)
{
settings.m_rxChannels = ChannelsHAM;
settings.m_rxHAMChannel = HAM_220_225MHz;
}
else if (m_rfeBoardState.channelIDRX == RFE_CID_HAM_0435)
{
settings.m_rxChannels = ChannelsHAM;
settings.m_rxHAMChannel = HAM_430_440MHz;
}
else if (m_rfeBoardState.channelIDRX == RFE_CID_HAM_0920)
{
settings.m_rxChannels = ChannelsHAM;
settings.m_rxHAMChannel = HAM_902_928MHz;
}
else if (m_rfeBoardState.channelIDRX == RFE_CID_HAM_1280)
{
settings.m_rxChannels = ChannelsHAM;
settings.m_rxHAMChannel = HAM_1240_1325MHz;
}
else if (m_rfeBoardState.channelIDRX == RFE_CID_HAM_2400)
{
settings.m_rxChannels = ChannelsHAM;
settings.m_rxHAMChannel = HAM_2300_2450MHz;
}
else if (m_rfeBoardState.channelIDRX == RFE_CID_HAM_3500)
{
settings.m_rxChannels = ChannelsHAM;
settings.m_rxHAMChannel = HAM_3300_3500MHz;
}
if (m_rfeBoardState.selPortRX == RFE_PORT_1) {
settings.m_rxPort = RxPortJ3;
} else if (m_rfeBoardState.selPortRX == RFE_PORT_3) {
settings.m_rxPort = RxPortJ5;
}
if (m_rfeBoardState.channelIDTX == RFE_CID_CELL_BAND01)
{
settings.m_txChannels = ChannelsCellular;
settings.m_txCellularChannel = CellularBand1;
}
else if (m_rfeBoardState.channelIDTX == RFE_CID_CELL_BAND02)
{
settings.m_txChannels = ChannelsCellular;
settings.m_txCellularChannel = CellularBand2;
}
else if (m_rfeBoardState.channelIDTX == RFE_CID_CELL_BAND03)
{
settings.m_txChannels = ChannelsCellular;
settings.m_txCellularChannel = CellularBand3;
}
else if (m_rfeBoardState.channelIDTX == RFE_CID_CELL_BAND07)
{
settings.m_txChannels = ChannelsCellular;
settings.m_txCellularChannel = CellularBand7;
}
else if (m_rfeBoardState.channelIDTX == RFE_CID_CELL_BAND38)
{
settings.m_txChannels = ChannelsCellular;
settings.m_txCellularChannel = CellularBand38;
}
else if (m_rfeBoardState.channelIDTX == RFE_CID_WB_1000)
{
settings.m_txChannels = ChannelsWideband;
settings.m_txWidebandChannel = WidebandLow;
}
else if (m_rfeBoardState.channelIDTX == RFE_CID_WB_4000)
{
settings.m_txChannels = ChannelsWideband;
settings.m_txWidebandChannel = WidebandHigh;
}
else if (m_rfeBoardState.channelIDTX == RFE_CID_HAM_0030)
{
settings.m_txChannels = ChannelsHAM;
settings.m_txHAMChannel = HAM_30M;
}
else if (m_rfeBoardState.channelIDTX == RFE_CID_HAM_0070)
{
settings.m_txChannels = ChannelsHAM;
settings.m_txHAMChannel = HAM_50_70MHz;
}
else if (m_rfeBoardState.channelIDTX == RFE_CID_HAM_0145)
{
settings.m_txChannels = ChannelsHAM;
settings.m_txHAMChannel = HAM_144_146MHz;
}
else if (m_rfeBoardState.channelIDTX == RFE_CID_HAM_0220)
{
settings.m_txChannels = ChannelsHAM;
settings.m_txHAMChannel = HAM_220_225MHz;
}
else if (m_rfeBoardState.channelIDTX == RFE_CID_HAM_0435)
{
settings.m_txChannels = ChannelsHAM;
settings.m_txHAMChannel = HAM_430_440MHz;
}
else if (m_rfeBoardState.channelIDTX == RFE_CID_HAM_0920)
{
settings.m_txChannels = ChannelsHAM;
settings.m_txHAMChannel = HAM_902_928MHz;
}
else if (m_rfeBoardState.channelIDTX == RFE_CID_HAM_1280)
{
settings.m_txChannels = ChannelsHAM;
settings.m_txHAMChannel = HAM_1240_1325MHz;
}
else if (m_rfeBoardState.channelIDTX == RFE_CID_HAM_2400)
{
settings.m_txChannels = ChannelsHAM;
settings.m_txHAMChannel = HAM_2300_2450MHz;
}
else if (m_rfeBoardState.channelIDTX == RFE_CID_HAM_3500)
{
settings.m_txChannels = ChannelsHAM;
settings.m_txHAMChannel = HAM_3300_3500MHz;
}
if (m_rfeBoardState.selPortTX == RFE_PORT_1) {
settings.m_txPort = TxPortJ3;
} else if (m_rfeBoardState.selPortTX == RFE_PORT_2) {
settings.m_txPort = TxPortJ4;
} else if (m_rfeBoardState.selPortTX == RFE_PORT_3) {
settings.m_txPort = TxPortJ5;
}
settings.m_attenuationFactor = m_rfeBoardState.attValue;
settings.m_amfmNotch = m_rfeBoardState.notchOnOff == RFE_NOTCH_ON;
if (m_rfeBoardState.mode == RFE_MODE_RX)
{
settings.m_rxOn = true;
settings.m_txOn = false;
}
else if (m_rfeBoardState.mode == RFE_MODE_TX)
{
settings.m_rxOn = false;
settings.m_txOn = true;
}
else if (m_rfeBoardState.mode == RFE_MODE_NONE)
{
settings.m_rxOn = false;
settings.m_txOn = false;
}
else if (m_rfeBoardState.mode == RFE_MODE_TXRX)
{
settings.m_rxOn = true;
settings.m_txOn = true;
}
settings.m_swrEnable = m_rfeBoardState.enableSWR == RFE_SWR_ENABLE;
settings.m_swrSource = m_rfeBoardState.sourceSWR == RFE_SWR_SRC_CELL ? SWRCellular : SWRExternal;
}

View File

@ -9,6 +9,7 @@
<file>webapi/doc/swagger/include/AIS.yaml</file>
<file>webapi/doc/swagger/include/AISDemod.yaml</file>
<file>webapi/doc/swagger/include/AISMod.yaml</file>
<file>webapi/doc/swagger/include/AMBE.yaml</file>
<file>webapi/doc/swagger/include/AMDemod.yaml</file>
<file>webapi/doc/swagger/include/AMMod.yaml</file>
<file>webapi/doc/swagger/include/AntennaTools.yaml</file>

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,103 @@
AMBESettings:
description: AMBE
properties:
title:
type: string
rgbColor:
type: integer
useReverseAPI:
description: Synchronize with reverse API (1 for yes, 0 for no)
type: integer
reverseAPIAddress:
type: string
reverseAPIPort:
type: integer
reverseAPIFeatureSetIndex:
type: integer
reverseAPIFeatureIndex:
type: integer
rollupState:
$ref: "/doc/swagger/include/RollupState.yaml#/RollupState"
AMBEReport:
description: AMBE
properties:
serial:
description: List of AMBE serial devices in the system
$ref: "/doc/swagger/include/AMBE.yaml#/definitions/DVSerialDevices"
devices:
description: List of AMBE devices or servers in use
type: array
items:
$ref: "/doc/swagger/include/AMBE.yaml#/definitions/AMBEDeviceReport"
AMBEActions:
description: AMBE
properties:
updateDevices:
description: Add or remove AMBE devices (serial or address) int the list to be used for AMBE frames processing
$ref: "/doc/swagger/include/AMBE.yaml#/definitions/AMBEDevices"
removeAll:
type: integer
description: Set to a non zero value to remove all AMBE devices from the list of used AMBE devices
definitions:
DVSerialDevices:
description: "List of DV serial devices available in the system"
required:
- nbDevices
properties:
nbDevices:
description: "Number of DV serial devices"
type: integer
dvSerialDevices:
description: "Device names of DV serial devices"
type: array
items:
$ref: "#/definitions/DVSerialDevice"
DVSerialDevice:
description: "DV serial device details"
properties:
deviceName:
description: "Name of the serial device in the system"
type: string
AMBEDevices:
description: "List of AMBE devices (serial or server address)"
required:
- nbDevices
properties:
nbDevices:
description: "Number of DV serial devices"
type: integer
ambeDevices:
description: "List of AMBE devices"
type: array
items:
$ref: "#/definitions/AMBEDevice"
AMBEDevice:
description: "AMBE devices active in the system"
properties:
deviceRef:
description: "Serial device name or server address"
type: string
delete:
description: "1 if device is to be removed from active list"
type: integer
AMBEDeviceReport:
description: "Report of AMBE device in use"
properties:
devicePath:
type: string
description: AMBE device full path or AMBE server URL
successCount:
type: integer
description: number of frames decoded successfully
failureCount:
type: integer
description: number of frames that failed to decode

View File

@ -72,7 +72,15 @@ DSDDemodSettings:
$ref: "/doc/swagger/include/ChannelMarker.yaml#/ChannelMarker"
rollupState:
$ref: "/doc/swagger/include/RollupState.yaml#/RollupState"
ambeFeatureIndex:
type: integer
description: index of AMBE controller feature to be used for AMBE frames decoding
connectAMBE:
type: integer
description: >
Decode frames with AMBE feature
* 0 - Do not decode frames with AMBE feature
* 1 - Decode frames with AMBE feature
DSDDemodReport:
description: DSDDemod
properties:

View File

@ -15,8 +15,12 @@ FeatureActions:
type: integer
AFCActions:
$ref: "/doc/swagger/include/AFC.yaml#/AFCActions"
AMBEActions:
$ref: "/doc/swagger/include/AMBE.yaml#/AMBEActions"
GS232ControllerActions:
$ref: "/doc/swagger/include/GS232Controller.yaml#/GS232ControllerActions"
LimeRFEActions:
$ref: "/doc/swagger/include/LimeRFE.yaml#/LimeRFEActions"
MapActions:
$ref: "/doc/swagger/include/Map.yaml#/MapActions"
PERTesterActions:

View File

@ -9,8 +9,12 @@ FeatureReport:
type: string
AFCReport:
$ref: "/doc/swagger/include/AFC.yaml#/AFCReport"
AMBEReport:
$ref: "/doc/swagger/include/AMBE.yaml#/AMBEReport"
GS232ControllerReport:
$ref: "/doc/swagger/include/GS232Controller.yaml#/GS232ControllerReport"
LimeRFEReport:
$ref: "/doc/swagger/include/LimeRFE.yaml#/LimeRFEReport"
MapReport:
$ref: "/doc/swagger/include/Map.yaml#/MapReport"
PERTesterReport:

View File

@ -17,6 +17,8 @@ FeatureSettings:
$ref: "/doc/swagger/include/AFC.yaml#/AFCSettings"
AISSettings:
$ref: "/doc/swagger/include/AIS.yaml#/AISSettings"
AMBESettings:
$ref: "/doc/swagger/include/AMBE.yaml#/AMBESettings"
AntennaToolsSettings:
$ref: "/doc/swagger/include/AntennaTools.yaml#/AntennaToolsSettings"
APRSSettings:
@ -27,6 +29,8 @@ FeatureSettings:
$ref: "/doc/swagger/include/JogdialController.yaml#/JogdialControllerSettings"
GS232ControllerSettings:
$ref: "/doc/swagger/include/GS232Controller.yaml#/GS232ControllerSettings"
LimeRFESettings:
$ref: "/doc/swagger/include/LimeRFE.yaml#/LimeRFESettings"
MapSettings:
$ref: "/doc/swagger/include/Map.yaml#/MapSettings"
PERTesterSettings:

View File

@ -1,6 +1,10 @@
LimeRFESettings:
description: LimeRFE
properties:
title:
type: string
rgbColor:
type: integer
devicePath:
description: Path to the device serial interface (ex /dev/ttyUSB2)
type: string
@ -102,19 +106,69 @@ LimeRFESettings:
SWR measurement source (LimeRFEController::SWRSource)
* 0 - External
* 1 - Cellular
txRxDriven:
description: Boolean 1 if Tx is copy of Rx else 0
type: integer
useReverseAPI:
description: Synchronize with reverse API (1 for yes, 0 for no)
type: integer
reverseAPIAddress:
type: string
reverseAPIPort:
type: integer
reverseAPIFeatureSetIndex:
type: integer
reverseAPIFeatureIndex:
type: integer
rollupState:
$ref: "/doc/swagger/include/RollupState.yaml#/RollupState"
LimeRFEReport:
description: LimeRFE
properties:
rxOn:
description: Boolean 1 if Rx is active else 0
type: integer
txOn:
description: Boolean 1 if Tx is active else 0
type: integer
LimeRFEPower:
description: report of forward and reflected power measurements
properties:
forward:
forwardPower:
description: relative forward power in centi-Bels
type: integer
reflected:
reflectedPower:
description: relative reflected power in centi-Bels
type: integer
type: integer
LimeRFEActions:
description: LimeRFE
properties:
selectChannel:
type: integer
description: >
Select channel
* 0 - Rx
* 1 - Tx
deviceSetIndex:
type: integer
dexcription: Index of device set to synchronize switch with
switchChannel:
type: integer
description: >
Switch on or off
* 0 - Off
* 1 - On
getState:
type: integer
description: Set to non zero value to get the board state
fromToSettings:
type: integer
description: >
Move from/to settings to/from device
* 0 - From device to settings. The toGUI button in GUI mode
* 1 - From settings to device. The Apply button in GUI mode
openCloseDevice:
type: integer
description: >
Open or close device
* 0 - Close device
* 1 - Open device

View File

@ -454,222 +454,6 @@ paths:
"501":
$ref: "#/responses/Response_501"
/sdrangel/ambe/serial:
x-swagger-router-controller: instance
get:
description: get a list of available DV serial devices
operationId: instanceAMBESerialGet
tags:
- Instance
responses:
"200":
description: On success return list of device paths possibly empty
schema:
$ref: "#/definitions/DVSerialDevices"
"500":
$ref: "#/responses/Response_500"
"501":
$ref: "#/responses/Response_501"
/sdrangel/ambe/devices:
x-swagger-router-controller: instance
get:
description: get the list of AMBE devices (serial or address) used for AMBE frames decoding in digital voice modes
operationId: InstanceAMBEDevicesGet
tags:
- Instance
responses:
"200":
description: On success return list of devices possibly empty
schema:
$ref: "#/definitions/AMBEDevices"
"500":
$ref: "#/responses/Response_500"
"501":
$ref: "#/responses/Response_501"
put:
description: Replace the list of active devices
operationId: InstanceAMBEDevicesPut
tags:
- Instance
consumes:
- application/json
parameters:
- name: body
in: body
description: List of AMBE devices (serial or address)
required: true
schema:
$ref: "#/definitions/AMBEDevices"
responses:
"200":
description: On success return list of devices
schema:
$ref: "#/definitions/AMBEDevices"
"500":
$ref: "#/responses/Response_500"
"501":
$ref: "#/responses/Response_501"
delete:
description: Emtpy the active devices thus effectively closing down AMBE devices support
operationId: InstanceAMBEDevicesDelete
tags:
- Instance
responses:
"200":
description: Success.
schema:
$ref: "#/definitions/SuccessResponse"
"500":
$ref: "#/responses/Response_500"
"501":
$ref: "#/responses/Response_501"
patch:
description: Add and/or delete devices to/from the active list
operationId: InstanceAMBEDevicesPatch
tags:
- Instance
consumes:
- application/json
parameters:
- name: body
in: body
description: List of AMBE devices (serial or address)
required: true
schema:
$ref: "#/definitions/AMBEDevices"
responses:
"200":
description: On success return list of devices
schema:
$ref: "#/definitions/AMBEDevices"
"500":
$ref: "#/responses/Response_500"
"501":
$ref: "#/responses/Response_501"
/sdrangel/limerfe/serial:
x-swagger-router-controller: instance
get:
description: get a list of available serial interfaces to LimeRFE device
operationId: instanceLimeRFESerialGet
tags:
- Instance
responses:
"200":
description: On success return list of device paths possibly empty
schema:
$ref: "#/definitions/LimeRFEDevices"
"500":
$ref: "#/responses/Response_500"
"501":
$ref: "#/responses/Response_501"
/sdrangel/limerfe/config:
x-swagger-router-controller: instance
get:
description: get LimeRFE configuration
operationId: instanceLimeRFEConfigGet
tags:
- Instance
parameters:
- name: serial
in: query
description: device serial path
required: true
type: string
responses:
"200":
description: On success return configuration information for the given device in input
schema:
$ref: "/doc/swagger/include/LimeRFE.yaml#/LimeRFESettings"
"500":
$ref: "#/responses/Response_500"
"501":
$ref: "#/responses/Response_501"
put:
description: replace LimeRFE configuration
operationId: instanceLimeRFEConfigPut
tags:
- Instance
consumes:
- application/json
parameters:
- name: body
in: body
description: Give device serial path in devicePath field. To switch Rx and/or Tx on or off use the run API.
required: true
schema:
$ref: "/doc/swagger/include/LimeRFE.yaml#/LimeRFESettings"
responses:
"200":
description: Success
schema:
$ref: "#/definitions/SuccessResponse"
"400":
description: Error
schema:
$ref: "#/definitions/ErrorResponse"
"500":
$ref: "#/responses/Response_500"
"501":
$ref: "#/responses/Response_501"
/sdrangel/limerfe/run:
x-swagger-router-controller: instance
put:
description: set Rx and Tx on or off
operationId: instanceLimeRFERunPut
tags:
- Instance
parameters:
- name: body
in: body
description: Give device serial path in devicePath field and run status in rxOn and txOn
required: true
schema:
$ref: "/doc/swagger/include/LimeRFE.yaml#/LimeRFESettings"
responses:
"200":
description: Success
schema:
$ref: "#/definitions/SuccessResponse"
"400":
description: Error
schema:
$ref: "#/definitions/ErrorResponse"
"500":
$ref: "#/responses/Response_500"
"501":
$ref: "#/responses/Response_501"
/sdrangel/limerfe/power:
x-swagger-router-controller: instance
get:
description: get forward and reflected relative powers in centi-Bels
operationId: instanceLimeRFEPowerGet
tags:
- Instance
parameters:
- name: serial
in: query
description: device serial path
required: true
type: string
responses:
"200":
description: On success return forward and reflected powers in centi-Bels
schema:
$ref: "/doc/swagger/include/LimeRFE.yaml#/LimeRFEPower"
"400":
description: Error
schema:
$ref: "#/definitions/ErrorResponse"
"500":
$ref: "#/responses/Response_500"
"501":
$ref: "#/responses/Response_501"
/sdrangel/presets:
x-swagger-router-controller: instance
get:
@ -3433,51 +3217,6 @@ definitions:
type: number
format: float
DVSerialDevices:
description: "List of DV serial devices available in the system"
required:
- nbDevices
properties:
nbDevices:
description: "Number of DV serial devices"
type: integer
dvSerialDevices:
description: "Device names of DV serial devices"
type: array
items:
$ref: "#/definitions/DVSerialDevice"
DVSerialDevice:
description: "DV serial device details"
properties:
deviceName:
description: "Name of the serial device in the system"
type: string
AMBEDevices:
description: "List of AMBE devices (serial or server address)"
required:
- nbDevices
properties:
nbDevices:
description: "Number of DV serial devices"
type: integer
ambeDevices:
description: "List of AMBE devices"
type: array
items:
$ref: "#/definitions/AMBEDevice"
AMBEDevice:
description: "AMBE devices active in the system"
properties:
deviceRef:
description: "Serial device name or server address"
type: string
delete:
description: "1 if device is to be removed from active list"
type: integer
LimeRFEDevices:
description: "List of LimeRFE devices (serial or server address)"
required:

View File

@ -7,11 +7,9 @@
#include "settings/mainsettings.h"
#include "commands/command.h"
#include "audio/audiodevicemanager.h"
#include "ambe/ambeengine.h"
MainSettings::MainSettings() :
m_audioDeviceManager(nullptr),
m_ambeEngine(nullptr)
m_audioDeviceManager(nullptr)
{
resetToDefaults();
qInfo("MainSettings::MainSettings: settings file: format: %d location: %s", getFileFormat(), qPrintable(getFileLocation()));
@ -60,10 +58,6 @@ void MainSettings::load()
m_audioDeviceManager->deserialize(qUncompress(QByteArray::fromBase64(s.value("audio").toByteArray())));
}
if (m_ambeEngine) {
m_ambeEngine->deserialize(qUncompress(QByteArray::fromBase64(s.value("ambe").toByteArray())));
}
QStringList groups = s.childGroups();
for (int i = 0; i < groups.size(); ++i)
@ -135,7 +129,6 @@ void MainSettings::load()
}
m_hardwareDeviceUserArgs.deserialize(qUncompress(QByteArray::fromBase64(s.value("hwDeviceUserArgs").toByteArray())));
m_limeRFEUSBCalib.deserialize(qUncompress(QByteArray::fromBase64(s.value("limeRFEUSBCalib").toByteArray())));
}
void MainSettings::save() const
@ -149,10 +142,6 @@ void MainSettings::save() const
s.setValue("audio", qCompress(m_audioDeviceManager->serialize()).toBase64());
}
if (m_ambeEngine) {
s.setValue("ambe", qCompress(m_ambeEngine->serialize()).toBase64());
}
QStringList groups = s.childGroups();
for(int i = 0; i < groups.size(); ++i)
@ -196,7 +185,6 @@ void MainSettings::save() const
}
s.setValue("hwDeviceUserArgs", qCompress(m_hardwareDeviceUserArgs.serialize()).toBase64());
s.setValue("limeRFEUSBCalib", qCompress(m_limeRFEUSBCalib.serialize()).toBase64());
}
void MainSettings::initialize()

View File

@ -4,7 +4,6 @@
#include <QObject>
#include <QString>
#include "device/deviceuserargs.h"
#include "limerfe/limerfeusbcalib.h"
#include "preferences.h"
#include "preset.h"
#include "featuresetpreset.h"
@ -14,7 +13,6 @@
class Command;
class AudioDeviceManager;
class AMBEEngine;
class SDRBASE_API MainSettings : public QObject {
@ -182,10 +180,8 @@ public:
}
DeviceUserArgs& getDeviceUserArgs() { return m_hardwareDeviceUserArgs; }
LimeRFEUSBCalib& getLimeRFEUSBCalib() { return m_limeRFEUSBCalib; }
const AudioDeviceManager *getAudioDeviceManager() const { return m_audioDeviceManager; }
void setAudioDeviceManager(AudioDeviceManager *audioDeviceManager) { m_audioDeviceManager = audioDeviceManager; }
void setAMBEEngine(AMBEEngine *ambeEngine) { m_ambeEngine = ambeEngine; }
signals:
void preferenceChanged(int);
@ -205,8 +201,6 @@ protected:
typedef QList<Configuration*> Configurations;
Configurations m_configurations;
DeviceUserArgs m_hardwareDeviceUserArgs;
LimeRFEUSBCalib m_limeRFEUSBCalib;
AMBEEngine *m_ambeEngine;
};
#endif // INCLUDE_SETTINGS_H

View File

@ -51,9 +51,6 @@
#include "SWGDeviceListItem.h"
#include "SWGAudioDevices.h"
#include "SWGLocationInformation.h"
#include "SWGDVSerialDevices.h"
#include "SWGDVSerialDevice.h"
#include "SWGAMBEDevices.h"
#include "SWGPresets.h"
#include "SWGPresetGroup.h"
#include "SWGPresetItem.h"
@ -79,7 +76,6 @@
#include "SWGDeviceState.h"
#include "SWGLimeRFEDevices.h"
#include "SWGLimeRFESettings.h"
#include "SWGLimeRFEPower.h"
#include "SWGFeaturePresets.h"
#include "SWGFeaturePresetGroup.h"
#include "SWGFeaturePresetItem.h"
@ -88,10 +84,6 @@
#include "SWGFeatureReport.h"
#include "SWGFeatureActions.h"
#ifdef HAS_LIMERFEUSB
#include "limerfe/limerfecontroller.h"
#endif
#include "webapiadapter.h"
WebAPIAdapter::WebAPIAdapter()
@ -758,391 +750,6 @@ int WebAPIAdapter::instanceLocationPut(
return 200;
}
int WebAPIAdapter::instanceDVSerialGet(
SWGSDRangel::SWGDVSerialDevices& response,
SWGSDRangel::SWGErrorResponse& error)
{
(void) error;
DSPEngine *dspEngine = DSPEngine::instance();
response.init();
std::vector<std::string> deviceNames;
dspEngine->getDVSerialNames(deviceNames);
response.setNbDevices((int) deviceNames.size());
QList<SWGSDRangel::SWGDVSerialDevice*> *deviceNamesList = response.getDvSerialDevices();
std::vector<std::string>::iterator it = deviceNames.begin();
while (it != deviceNames.end())
{
deviceNamesList->append(new SWGSDRangel::SWGDVSerialDevice);
deviceNamesList->back()->init();
*deviceNamesList->back()->getDeviceName() = QString::fromStdString(*it);
++it;
}
return 200;
}
int WebAPIAdapter::instanceDVSerialPatch(
bool dvserial,
SWGSDRangel::SWGDVSerialDevices& response,
SWGSDRangel::SWGErrorResponse& error)
{
(void) error;
DSPEngine *dspEngine = DSPEngine::instance();
dspEngine->setDVSerialSupport(dvserial);
MainCore::MsgDVSerial *msg = MainCore::MsgDVSerial::create(dvserial);
m_mainCore->m_mainMessageQueue->push(msg);
response.init();
if (dvserial)
{
std::vector<std::string> deviceNames;
dspEngine->getDVSerialNames(deviceNames);
response.setNbDevices((int) deviceNames.size());
QList<SWGSDRangel::SWGDVSerialDevice*> *deviceNamesList = response.getDvSerialDevices();
std::vector<std::string>::iterator it = deviceNames.begin();
while (it != deviceNames.end())
{
deviceNamesList->append(new SWGSDRangel::SWGDVSerialDevice);
deviceNamesList->back()->init();
*deviceNamesList->back()->getDeviceName() = QString::fromStdString(*it);
++it;
}
}
else
{
response.setNbDevices(0);
}
return 200;
}
int WebAPIAdapter::instanceAMBESerialGet(
SWGSDRangel::SWGDVSerialDevices& response,
SWGSDRangel::SWGErrorResponse& error)
{
(void) error;
DSPEngine *dspEngine = DSPEngine::instance();
response.init();
std::vector<std::string> deviceNames;
std::vector<QString> qDeviceNames;
dspEngine->getAMBEEngine()->scan(qDeviceNames);
for (std::vector<QString>::const_iterator it = qDeviceNames.begin(); it != qDeviceNames.end(); ++it) {
deviceNames.push_back(it->toStdString());
}
response.setNbDevices((int) deviceNames.size());
QList<SWGSDRangel::SWGDVSerialDevice*> *deviceNamesList = response.getDvSerialDevices();
std::vector<std::string>::iterator it = deviceNames.begin();
while (it != deviceNames.end())
{
deviceNamesList->append(new SWGSDRangel::SWGDVSerialDevice);
deviceNamesList->back()->init();
*deviceNamesList->back()->getDeviceName() = QString::fromStdString(*it);
++it;
}
return 200;
}
int WebAPIAdapter::instanceAMBEDevicesGet(
SWGSDRangel::SWGAMBEDevices& response,
SWGSDRangel::SWGErrorResponse& error)
{
(void) error;
DSPEngine *dspEngine = DSPEngine::instance();
response.init();
std::vector<std::string> deviceNames;
dspEngine->getDVSerialNames(deviceNames);
response.setNbDevices((int) deviceNames.size());
QList<SWGSDRangel::SWGAMBEDevice*> *deviceNamesList = response.getAmbeDevices();
std::vector<std::string>::iterator it = deviceNames.begin();
while (it != deviceNames.end())
{
deviceNamesList->append(new SWGSDRangel::SWGAMBEDevice);
deviceNamesList->back()->init();
*deviceNamesList->back()->getDeviceRef() = QString::fromStdString(*it);
deviceNamesList->back()->setDelete(0);
++it;
}
return 200;
}
int WebAPIAdapter::instanceAMBEDevicesDelete(
SWGSDRangel::SWGSuccessResponse& response,
SWGSDRangel::SWGErrorResponse& error)
{
(void) error;
DSPEngine *dspEngine = DSPEngine::instance();
dspEngine->getAMBEEngine()->releaseAll();
response.init();
*response.getMessage() = QString("All AMBE devices released");
return 200;
}
int WebAPIAdapter::instanceAMBEDevicesPut(
SWGSDRangel::SWGAMBEDevices& query,
SWGSDRangel::SWGAMBEDevices& response,
SWGSDRangel::SWGErrorResponse& error)
{
DSPEngine *dspEngine = DSPEngine::instance();
dspEngine->getAMBEEngine()->releaseAll();
QList<SWGSDRangel::SWGAMBEDevice *> *ambeList = query.getAmbeDevices();
for (QList<SWGSDRangel::SWGAMBEDevice *>::const_iterator it = ambeList->begin(); it != ambeList->end(); ++it) {
dspEngine->getAMBEEngine()->registerController((*it)->getDeviceRef()->toStdString());
}
instanceAMBEDevicesGet(response, error);
return 200;
}
int WebAPIAdapter::instanceAMBEDevicesPatch(
SWGSDRangel::SWGAMBEDevices& query,
SWGSDRangel::SWGAMBEDevices& response,
SWGSDRangel::SWGErrorResponse& error)
{
DSPEngine *dspEngine = DSPEngine::instance();
QList<SWGSDRangel::SWGAMBEDevice *> *ambeList = query.getAmbeDevices();
for (QList<SWGSDRangel::SWGAMBEDevice *>::const_iterator it = ambeList->begin(); it != ambeList->end(); ++it)
{
if ((*it)->getDelete()) {
dspEngine->getAMBEEngine()->releaseController((*it)->getDeviceRef()->toStdString());
} else {
dspEngine->getAMBEEngine()->registerController((*it)->getDeviceRef()->toStdString());
}
}
instanceAMBEDevicesGet(response, error);
return 200;
}
#ifdef HAS_LIMERFEUSB
int WebAPIAdapter::instanceLimeRFESerialGet(
SWGSDRangel::SWGLimeRFEDevices& response,
SWGSDRangel::SWGErrorResponse& error)
{
(void) error;
response.init();
std::vector<std::string> comPorts;
SerialUtil::getComPorts(comPorts, "ttyUSB[0-9]+"); // regex is for Linux only
response.setNbDevices((int) comPorts.size());
QList<SWGSDRangel::SWGLimeRFEDevice*> *deviceNamesList = response.getLimeRfeDevices();
std::vector<std::string>::iterator it = comPorts.begin();
while (it != comPorts.end())
{
deviceNamesList->append(new SWGSDRangel::SWGLimeRFEDevice);
deviceNamesList->back()->init();
*deviceNamesList->back()->getDeviceRef() = QString::fromStdString(*it);
++it;
}
return 200;
}
int WebAPIAdapter::instanceLimeRFEConfigGet(
const QString& serial,
SWGSDRangel::SWGLimeRFESettings& response,
SWGSDRangel::SWGErrorResponse& error)
{
LimeRFEController controller;
int rc = controller.openDevice(serial.toStdString());
if (rc != 0)
{
error.init();
*error.getMessage() = QString("Error opening LimeRFE device %1: %2")
.arg(serial).arg(controller.getError(rc).c_str());
return 400;
}
rc = controller.getState();
if (rc != 0)
{
error.init();
*error.getMessage() = QString("Error getting config from LimeRFE device %1: %2")
.arg(serial).arg(controller.getError(rc).c_str());
return 500;
}
controller.closeDevice();
LimeRFEController::LimeRFESettings settings;
controller.stateToSettings(settings);
response.init();
response.setDevicePath(new QString(serial));
response.setRxChannels((int) settings.m_rxChannels);
response.setRxWidebandChannel((int) settings.m_rxWidebandChannel);
response.setRxHamChannel((int) settings.m_rxHAMChannel);
response.setRxCellularChannel((int) settings.m_rxCellularChannel);
response.setRxPort((int) settings.m_rxPort);
response.setRxOn(settings.m_rxOn ? 1 : 0);
response.setAmfmNotch(settings.m_amfmNotch ? 1 : 0);
response.setAttenuationFactor(settings.m_attenuationFactor);
response.setTxChannels((int) settings.m_txChannels);
response.setTxWidebandChannel((int) settings.m_txWidebandChannel);
response.setTxHamChannel((int) settings.m_txHAMChannel);
response.setTxCellularChannel((int) settings.m_txCellularChannel);
response.setTxPort((int) settings.m_txPort);
response.setTxOn(settings.m_txOn ? 1 : 0);
response.setSwrEnable(settings.m_swrEnable ? 1 : 0);
response.setSwrSource((int) settings.m_swrSource);
return 200;
}
int WebAPIAdapter::instanceLimeRFEConfigPut(
SWGSDRangel::SWGLimeRFESettings& query,
SWGSDRangel::SWGSuccessResponse& response,
SWGSDRangel::SWGErrorResponse& error)
{
LimeRFEController controller;
int rc = controller.openDevice(query.getDevicePath()->toStdString());
if (rc != 0)
{
error.init();
*error.getMessage() = QString("Error opening LimeRFE device %1: %2")
.arg(*query.getDevicePath()).arg(controller.getError(rc).c_str());
return 400;
}
LimeRFEController::LimeRFESettings settings;
settings.m_rxChannels = (LimeRFEController::ChannelGroups) query.getRxChannels();
settings.m_rxWidebandChannel = (LimeRFEController::WidebandChannel) query.getRxWidebandChannel();
settings.m_rxHAMChannel = (LimeRFEController::HAMChannel) query.getRxHamChannel();
settings.m_rxCellularChannel = (LimeRFEController::CellularChannel) query.getRxCellularChannel();
settings.m_rxPort = (LimeRFEController::RxPort) query.getRxPort();
settings.m_rxOn = query.getRxOn() != 0;
settings.m_amfmNotch = query.getAmfmNotch() != 0;
settings.m_attenuationFactor = query.getAttenuationFactor();
settings.m_txChannels = (LimeRFEController::ChannelGroups) query.getTxChannels();
settings.m_txWidebandChannel = (LimeRFEController::WidebandChannel) query.getTxWidebandChannel();
settings.m_txHAMChannel = (LimeRFEController::HAMChannel) query.getTxHamChannel();
settings.m_txCellularChannel = (LimeRFEController::CellularChannel) query.getTxCellularChannel();
settings.m_txPort = (LimeRFEController::TxPort) query.getTxPort();
settings.m_txOn = query.getTxOn() != 0;
settings.m_swrEnable = query.getSwrEnable() != 0;
settings.m_swrSource = (LimeRFEController::SWRSource) query.getSwrSource();
controller.settingsToState(settings);
rc = controller.configure();
if (rc != 0)
{
error.init();
*error.getMessage() = QString("Error configuring LimeRFE device %1: %2")
.arg(*query.getDevicePath()).arg(controller.getError(rc).c_str());
return 500;
}
response.init();
*response.getMessage() = QString("LimeRFE device at %1 configuration updated successfully").arg(*query.getDevicePath());
return 200;
}
int WebAPIAdapter::instanceLimeRFERunPut(
SWGSDRangel::SWGLimeRFESettings& query,
SWGSDRangel::SWGSuccessResponse& response,
SWGSDRangel::SWGErrorResponse& error)
{
LimeRFEController controller;
int rc = controller.openDevice(query.getDevicePath()->toStdString());
if (rc != 0)
{
error.init();
*error.getMessage() = QString("Error opening LimeRFE device %1: %2")
.arg(*query.getDevicePath()).arg(controller.getError(rc).c_str());
return 400;
}
LimeRFEController::LimeRFESettings settings;
settings.m_rxOn = query.getRxOn() != 0;
settings.m_txOn = query.getTxOn() != 0;
rc = controller.setRx(settings, settings.m_rxOn);
if (rc != 0)
{
error.init();
*error.getMessage() = QString("Error setting Rx/Tx LimeRFE device %1: %2")
.arg(*query.getDevicePath()).arg(controller.getError(rc).c_str());
return 400;
}
response.init();
*response.getMessage() = QString("LimeRFE device at %1 mode updated successfully").arg(*query.getDevicePath());
return 200;
}
int WebAPIAdapter::instanceLimeRFEPowerGet(
const QString& serial,
SWGSDRangel::SWGLimeRFEPower& response,
SWGSDRangel::SWGErrorResponse& error)
{
LimeRFEController controller;
int rc = controller.openDevice(serial.toStdString());
if (rc != 0)
{
error.init();
*error.getMessage() = QString("Error opening LimeRFE device %1: %2")
.arg(serial).arg(controller.getError(rc).c_str());
return 400;
}
int fwdPower;
rc = controller.getFwdPower(fwdPower);
if (rc != 0)
{
error.init();
*error.getMessage() = QString("Error getting forward power from LimeRFE device %1: %2")
.arg(serial).arg(controller.getError(rc).c_str());
return 500;
}
int refPower;
rc = controller.getRefPower(refPower);
if (rc != 0)
{
error.init();
*error.getMessage() = QString("Error getting reflected power from LimeRFE device %1: %2")
.arg(serial).arg(controller.getError(rc).c_str());
return 500;
}
controller.closeDevice();
response.init();
response.setForward(fwdPower);
response.setReflected(refPower);
return 200;
}
#endif
int WebAPIAdapter::instancePresetsGet(
SWGSDRangel::SWGPresets& response,
SWGSDRangel::SWGErrorResponse& error)

View File

@ -115,63 +115,6 @@ public:
SWGSDRangel::SWGLocationInformation& response,
SWGSDRangel::SWGErrorResponse& error);
virtual int instanceDVSerialGet(
SWGSDRangel::SWGDVSerialDevices& response,
SWGSDRangel::SWGErrorResponse& error);
virtual int instanceDVSerialPatch(
bool dvserial,
SWGSDRangel::SWGDVSerialDevices& response,
SWGSDRangel::SWGErrorResponse& error);
virtual int instanceAMBESerialGet(
SWGSDRangel::SWGDVSerialDevices& response,
SWGSDRangel::SWGErrorResponse& error);
virtual int instanceAMBEDevicesGet(
SWGSDRangel::SWGAMBEDevices& response,
SWGSDRangel::SWGErrorResponse& error);
virtual int instanceAMBEDevicesPut(
SWGSDRangel::SWGAMBEDevices& query,
SWGSDRangel::SWGAMBEDevices& response,
SWGSDRangel::SWGErrorResponse& error);
virtual int instanceAMBEDevicesPatch(
SWGSDRangel::SWGAMBEDevices& query,
SWGSDRangel::SWGAMBEDevices& response,
SWGSDRangel::SWGErrorResponse& error);
virtual int instanceAMBEDevicesDelete(
SWGSDRangel::SWGSuccessResponse& response,
SWGSDRangel::SWGErrorResponse& error);
#ifdef HAS_LIMERFEUSB
virtual int instanceLimeRFESerialGet(
SWGSDRangel::SWGLimeRFEDevices& response,
SWGSDRangel::SWGErrorResponse& error);
virtual int instanceLimeRFEConfigGet(
const QString& serial,
SWGSDRangel::SWGLimeRFESettings& response,
SWGSDRangel::SWGErrorResponse& error);
virtual int instanceLimeRFEConfigPut(
SWGSDRangel::SWGLimeRFESettings& query,
SWGSDRangel::SWGSuccessResponse& response,
SWGSDRangel::SWGErrorResponse& error);
virtual int instanceLimeRFERunPut(
SWGSDRangel::SWGLimeRFESettings& query,
SWGSDRangel::SWGSuccessResponse& response,
SWGSDRangel::SWGErrorResponse& error);
virtual int instanceLimeRFEPowerGet(
const QString& serial,
SWGSDRangel::SWGLimeRFEPower& response,
SWGSDRangel::SWGErrorResponse& error);
#endif
virtual int instancePresetsGet(
SWGSDRangel::SWGPresets& response,
SWGSDRangel::SWGErrorResponse& error);

View File

@ -31,12 +31,6 @@ QString WebAPIAdapterInterface::instanceAudioOutputParametersURL = "/sdrangel/au
QString WebAPIAdapterInterface::instanceAudioInputCleanupURL = "/sdrangel/audio/input/cleanup";
QString WebAPIAdapterInterface::instanceAudioOutputCleanupURL = "/sdrangel/audio/output/cleanup";
QString WebAPIAdapterInterface::instanceLocationURL = "/sdrangel/location";
QString WebAPIAdapterInterface::instanceAMBESerialURL = "/sdrangel/ambe/serial";
QString WebAPIAdapterInterface::instanceAMBEDevicesURL = "/sdrangel/ambe/devices";
QString WebAPIAdapterInterface::instanceLimeRFESerialURL = "/sdrangel/limerfe/serial";
QString WebAPIAdapterInterface::instanceLimeRFEConfigURL = "/sdrangel/limerfe/config";
QString WebAPIAdapterInterface::instanceLimeRFERunURL = "/sdrangel/limerfe/run";
QString WebAPIAdapterInterface::instanceLimeRFEPowerURL = "/sdrangel/limerfe/power";
QString WebAPIAdapterInterface::instancePresetsURL = "/sdrangel/presets";
QString WebAPIAdapterInterface::instancePresetURL = "/sdrangel/preset";
QString WebAPIAdapterInterface::instancePresetFileURL = "/sdrangel/preset/file";

View File

@ -41,8 +41,6 @@ namespace SWGSDRangel
class SWGAudioInputDevice;
class SWGAudioOutputDevice;
class SWGLocationInformation;
class SWGDVSerialDevices;
class SWGAMBEDevices;
class SWGLimeRFEDevices;
class SWGLimeRFESettings;
class SWGLimeRFEPower;
@ -401,80 +399,6 @@ public:
return 501;
}
/**
* Handler of /sdrangel/ambe/serial (GET) swagger/sdrangel/code/html2/index.html#api-Default-instanceChannels
* returns the Http status code (default 501: not implemented)
*/
virtual int instanceAMBESerialGet(
SWGSDRangel::SWGDVSerialDevices& response,
SWGSDRangel::SWGErrorResponse& error)
{
(void) response;
error.init();
*error.getMessage() = QString("Function not implemented");
return 501;
}
/**
* Handler of /sdrangel/ambe/devices (GET) swagger/sdrangel/code/html2/index.html#api-Default-instanceChannels
* returns the Http status code (default 501: not implemented)
*/
virtual int instanceAMBEDevicesGet(
SWGSDRangel::SWGAMBEDevices& response,
SWGSDRangel::SWGErrorResponse& error)
{
(void) response;
error.init();
*error.getMessage() = QString("Function not implemented");
return 501;
}
/**
* Handler of /sdrangel/ambe/devices (PUT) swagger/sdrangel/code/html2/index.html#api-Default-instanceChannels
* returns the Http status code (default 501: not implemented)
*/
virtual int instanceAMBEDevicesPut(
SWGSDRangel::SWGAMBEDevices& query,
SWGSDRangel::SWGAMBEDevices& response,
SWGSDRangel::SWGErrorResponse& error)
{
(void) query;
(void) response;
error.init();
*error.getMessage() = QString("Function not implemented");
return 501;
}
/**
* Handler of /sdrangel/ambe/devices (PATCH) swagger/sdrangel/code/html2/index.html#api-Default-instanceChannels
* returns the Http status code (default 501: not implemented)
*/
virtual int instanceAMBEDevicesPatch(
SWGSDRangel::SWGAMBEDevices& query,
SWGSDRangel::SWGAMBEDevices& response,
SWGSDRangel::SWGErrorResponse& error)
{
(void) query;
(void) response;
error.init();
*error.getMessage() = QString("Function not implemented");
return 501;
}
/**
* Handler of /sdrangel/ambe/devices (DELETE) swagger/sdrangel/code/html2/index.html#api-Default-instanceChannels
* returns the Http status code (default 501: not implemented)
*/
virtual int instanceAMBEDevicesDelete(
SWGSDRangel::SWGSuccessResponse& response,
SWGSDRangel::SWGErrorResponse& error)
{
(void) response;
error.init();
*error.getMessage() = QString("Function not implemented");
return 501;
}
/**
* Handler of /sdrangel/limerfe/serial (GET) swagger/sdrangel/code/html2/index.html#api-Default-instanceChannels
* returns the Http status code (default 501: not implemented)
@ -537,22 +461,6 @@ public:
return 501;
}
/**
* Handler of /sdrangel/limerfe/power (GET) swagger/sdrangel/code/html2/index.html#api-Default-instanceChannels
* returns the Http status code (default 501: not implemented)
*/
virtual int instanceLimeRFEPowerGet(
const QString& serial,
SWGSDRangel::SWGLimeRFEPower& response,
SWGSDRangel::SWGErrorResponse& error)
{
(void) serial;
(void) response;
error.init();
*error.getMessage() = QString("Function not implemented");
return 501;
}
/**
* Handler of /sdrangel/presets (GET) swagger/sdrangel/code/html2/index.html#api-Default-instanceChannels
* returns the Http status code (default 501: not implemented)
@ -1786,12 +1694,6 @@ public:
static QString instanceAudioInputCleanupURL;
static QString instanceAudioOutputCleanupURL;
static QString instanceLocationURL;
static QString instanceAMBESerialURL;
static QString instanceAMBEDevicesURL;
static QString instanceLimeRFESerialURL;
static QString instanceLimeRFEConfigURL;
static QString instanceLimeRFERunURL;
static QString instanceLimeRFEPowerURL;
static QString instancePresetsURL;
static QString instancePresetURL;
static QString instancePresetFileURL;

View File

@ -33,11 +33,9 @@
#include "SWGInstanceFeaturesResponse.h"
#include "SWGAudioDevices.h"
#include "SWGLocationInformation.h"
#include "SWGDVSerialDevices.h"
#include "SWGAMBEDevices.h"
#include "SWGLimeRFEDevices.h"
#include "SWGLimeRFESettings.h"
#include "SWGLimeRFEPower.h"
#include "SWGPresets.h"
#include "SWGPresetTransfer.h"
#include "SWGPresetIdentifier.h"
@ -139,18 +137,6 @@ void WebAPIRequestMapper::service(qtwebapp::HttpRequest& request, qtwebapp::Http
instanceAudioOutputCleanupService(request, response);
} else if (path == WebAPIAdapterInterface::instanceLocationURL) {
instanceLocationService(request, response);
} else if (path == WebAPIAdapterInterface::instanceAMBESerialURL) {
instanceAMBESerialService(request, response);
} else if (path == WebAPIAdapterInterface::instanceAMBEDevicesURL) {
instanceAMBEDevicesService(request, response);
} else if (path == WebAPIAdapterInterface::instanceLimeRFESerialURL) {
instanceLimeRFESerialService(request, response);
} else if (path == WebAPIAdapterInterface::instanceLimeRFEConfigURL) {
instanceLimeRFEConfigService(request, response);
} else if (path == WebAPIAdapterInterface::instanceLimeRFERunURL) {
instanceLimeRFERunService(request, response);
} else if (path == WebAPIAdapterInterface::instanceLimeRFEPowerURL) {
instanceLimeRFEPowerService(request, response);
} else if (path == WebAPIAdapterInterface::instancePresetsURL) {
instancePresetsService(request, response);
} else if (path == WebAPIAdapterInterface::instancePresetURL) {
@ -808,315 +794,6 @@ void WebAPIRequestMapper::instanceLocationService(qtwebapp::HttpRequest& request
}
}
void WebAPIRequestMapper::instanceAMBESerialService(qtwebapp::HttpRequest& request, qtwebapp::HttpResponse& response)
{
SWGSDRangel::SWGErrorResponse errorResponse;
response.setHeader("Content-Type", "application/json");
response.setHeader("Access-Control-Allow-Origin", "*");
if (request.getMethod() == "GET")
{
SWGSDRangel::SWGDVSerialDevices normalResponse;
int status = m_adapter->instanceAMBESerialGet(normalResponse, errorResponse);
response.setStatus(status);
if (status/100 == 2) {
response.write(normalResponse.asJson().toUtf8());
} else {
response.write(errorResponse.asJson().toUtf8());
}
}
else
{
response.setStatus(405,"Invalid HTTP method");
errorResponse.init();
*errorResponse.getMessage() = "Invalid HTTP method";
response.write(errorResponse.asJson().toUtf8());
}
}
void WebAPIRequestMapper::instanceAMBEDevicesService(qtwebapp::HttpRequest& request, qtwebapp::HttpResponse& response)
{
SWGSDRangel::SWGErrorResponse errorResponse;
response.setHeader("Content-Type", "application/json");
response.setHeader("Access-Control-Allow-Origin", "*");
if (request.getMethod() == "GET")
{
SWGSDRangel::SWGAMBEDevices normalResponse;
int status = m_adapter->instanceAMBEDevicesGet(normalResponse, errorResponse);
response.setStatus(status);
if (status/100 == 2) {
response.write(normalResponse.asJson().toUtf8());
} else {
response.write(errorResponse.asJson().toUtf8());
}
}
else if ((request.getMethod() == "PATCH") || (request.getMethod() == "PUT"))
{
SWGSDRangel::SWGAMBEDevices query;
SWGSDRangel::SWGAMBEDevices normalResponse;
QString jsonStr = request.getBody();
QJsonObject jsonObject;
if (parseJsonBody(jsonStr, jsonObject, response))
{
if (validateAMBEDevices(query, jsonObject))
{
int status;
if (request.getMethod() == "PATCH") {
status = m_adapter->instanceAMBEDevicesPatch(query, normalResponse, errorResponse);
} else {
status = m_adapter->instanceAMBEDevicesPut(query, normalResponse, errorResponse);
}
response.setStatus(status);
if (status/100 == 2) {
response.write(normalResponse.asJson().toUtf8());
} else {
response.write(errorResponse.asJson().toUtf8());
}
}
else
{
response.setStatus(400,"Invalid JSON request");
errorResponse.init();
*errorResponse.getMessage() = "Invalid JSON request";
response.write(errorResponse.asJson().toUtf8());
}
}
else
{
response.setStatus(400,"Invalid JSON format");
errorResponse.init();
*errorResponse.getMessage() = "Invalid JSON format";
response.write(errorResponse.asJson().toUtf8());
}
}
else if (request.getMethod() == "DELETE")
{
SWGSDRangel::SWGSuccessResponse normalResponse;
int status = m_adapter->instanceAMBEDevicesDelete(normalResponse, errorResponse);
response.setStatus(status);
if (status/100 == 2) {
response.write(normalResponse.asJson().toUtf8());
} else {
response.write(errorResponse.asJson().toUtf8());
}
}
else
{
response.setStatus(405,"Invalid HTTP method");
errorResponse.init();
*errorResponse.getMessage() = "Invalid HTTP method";
response.write(errorResponse.asJson().toUtf8());
}
}
void WebAPIRequestMapper::instanceLimeRFESerialService(qtwebapp::HttpRequest& request, qtwebapp::HttpResponse& response)
{
SWGSDRangel::SWGErrorResponse errorResponse;
response.setHeader("Content-Type", "application/json");
response.setHeader("Access-Control-Allow-Origin", "*");
if (request.getMethod() == "GET")
{
SWGSDRangel::SWGLimeRFEDevices normalResponse;
int status = m_adapter->instanceLimeRFESerialGet(normalResponse, errorResponse);
response.setStatus(status);
if (status/100 == 2) {
response.write(normalResponse.asJson().toUtf8());
} else {
response.write(errorResponse.asJson().toUtf8());
}
}
else
{
response.setStatus(405,"Invalid HTTP method");
errorResponse.init();
*errorResponse.getMessage() = "Invalid HTTP method";
response.write(errorResponse.asJson().toUtf8());
}
}
void WebAPIRequestMapper::instanceLimeRFEConfigService(qtwebapp::HttpRequest& request, qtwebapp::HttpResponse& response)
{
SWGSDRangel::SWGErrorResponse errorResponse;
response.setHeader("Content-Type", "application/json");
response.setHeader("Access-Control-Allow-Origin", "*");
if (request.getMethod() == "GET")
{
QByteArray serialStr = request.getParameter("serial");
SWGSDRangel::SWGLimeRFESettings normalResponse;
int status = m_adapter->instanceLimeRFEConfigGet(serialStr, normalResponse, errorResponse);
response.setStatus(status);
if (status/100 == 2) {
response.write(normalResponse.asJson().toUtf8());
} else {
response.write(errorResponse.asJson().toUtf8());
}
}
else if (request.getMethod() == "PUT")
{
SWGSDRangel::SWGLimeRFESettings query;
SWGSDRangel::SWGSuccessResponse normalResponse;
QString jsonStr = request.getBody();
QJsonObject jsonObject;
if (parseJsonBody(jsonStr, jsonObject, response))
{
QStringList limeRFESettingsKeys;
if (validateLimeRFEConfig(query, jsonObject, limeRFESettingsKeys))
{
if (limeRFESettingsKeys.contains("devicePath"))
{
int status = m_adapter->instanceLimeRFEConfigPut(query, normalResponse, errorResponse);
response.setStatus(status);
if (status/100 == 2) {
response.write(normalResponse.asJson().toUtf8());
} else {
response.write(errorResponse.asJson().toUtf8());
}
}
else
{
response.setStatus(400,"LimeRFE device path expected in JSON body");
errorResponse.init();
*errorResponse.getMessage() = "Invalid request";
response.write(errorResponse.asJson().toUtf8());
}
}
else
{
response.setStatus(400,"Invalid JSON format");
errorResponse.init();
*errorResponse.getMessage() = "Invalid JSON format";
response.write(errorResponse.asJson().toUtf8());
}
}
else
{
response.setStatus(400,"Invalid JSON format");
errorResponse.init();
*errorResponse.getMessage() = "Invalid JSON format";
response.write(errorResponse.asJson().toUtf8());
}
}
else
{
response.setStatus(405,"Invalid HTTP method");
errorResponse.init();
*errorResponse.getMessage() = "Invalid HTTP method";
response.write(errorResponse.asJson().toUtf8());
}
}
void WebAPIRequestMapper::instanceLimeRFERunService(qtwebapp::HttpRequest& request, qtwebapp::HttpResponse& response)
{
SWGSDRangel::SWGErrorResponse errorResponse;
response.setHeader("Content-Type", "application/json");
response.setHeader("Access-Control-Allow-Origin", "*");
if (request.getMethod() == "PUT")
{
SWGSDRangel::SWGLimeRFESettings query;
QString jsonStr = request.getBody();
QJsonObject jsonObject;
if (parseJsonBody(jsonStr, jsonObject, response))
{
QStringList limeRFESettingsKeys;
if (validateLimeRFEConfig(query, jsonObject, limeRFESettingsKeys))
{
if (limeRFESettingsKeys.contains("devicePath"))
{
SWGSDRangel::SWGSuccessResponse normalResponse;
int status = m_adapter->instanceLimeRFERunPut(query, normalResponse, errorResponse);
response.setStatus(status);
if (status/100 == 2) {
response.write(normalResponse.asJson().toUtf8());
} else {
response.write(errorResponse.asJson().toUtf8());
}
}
else
{
response.setStatus(400,"LimeRFE device path expected in JSON body");
errorResponse.init();
*errorResponse.getMessage() = "Invalid JSON format";
response.write(errorResponse.asJson().toUtf8());
}
}
else
{
response.setStatus(400,"Invalid JSON format");
errorResponse.init();
*errorResponse.getMessage() = "Invalid JSON format";
response.write(errorResponse.asJson().toUtf8());
}
}
else
{
response.setStatus(400,"Invalid JSON format");
errorResponse.init();
*errorResponse.getMessage() = "Invalid JSON format";
response.write(errorResponse.asJson().toUtf8());
}
}
else
{
response.setStatus(405,"Invalid HTTP method");
errorResponse.init();
*errorResponse.getMessage() = "Invalid HTTP method";
response.write(errorResponse.asJson().toUtf8());
}
}
void WebAPIRequestMapper::instanceLimeRFEPowerService(qtwebapp::HttpRequest& request, qtwebapp::HttpResponse& response)
{
SWGSDRangel::SWGErrorResponse errorResponse;
response.setHeader("Content-Type", "application/json");
response.setHeader("Access-Control-Allow-Origin", "*");
if (request.getMethod() == "GET")
{
QByteArray serialStr = request.getParameter("serial");
SWGSDRangel::SWGLimeRFEPower normalResponse;
int status = m_adapter->instanceLimeRFEPowerGet(serialStr, normalResponse, errorResponse);
response.setStatus(status);
if (status/100 == 2) {
response.write(normalResponse.asJson().toUtf8());
} else {
response.write(errorResponse.asJson().toUtf8());
}
}
else
{
response.setStatus(405,"Invalid HTTP method");
errorResponse.init();
*errorResponse.getMessage() = "Invalid HTTP method";
response.write(errorResponse.asJson().toUtf8());
}
}
void WebAPIRequestMapper::instancePresetsService(qtwebapp::HttpRequest& request, qtwebapp::HttpResponse& response)
{
SWGSDRangel::SWGErrorResponse errorResponse;
@ -4263,138 +3940,6 @@ bool WebAPIRequestMapper::validateAudioOutputDevice(
return true;
}
bool WebAPIRequestMapper::validateAMBEDevices(SWGSDRangel::SWGAMBEDevices& ambeDevices, QJsonObject& jsonObject)
{
if (jsonObject.contains("nbDevices"))
{
int nbDevices = jsonObject["nbDevices"].toInt();
if (jsonObject.contains("ambeDevices"))
{
QJsonArray ambeDevicesJson = jsonObject["ambeDevices"].toArray();
if (nbDevices != ambeDevicesJson.size()) {
return false;
}
ambeDevices.init();
ambeDevices.setNbDevices(nbDevices);
QList<SWGSDRangel::SWGAMBEDevice *> *ambeList = ambeDevices.getAmbeDevices();
for (int i = 0; i < nbDevices; i++)
{
QJsonObject ambeDeviceJson = ambeDevicesJson.at(i).toObject();
if (ambeDeviceJson.contains("deviceRef") && ambeDeviceJson.contains("delete"))
{
ambeList->push_back(new SWGSDRangel::SWGAMBEDevice());
ambeList->back()->init();
ambeList->back()->setDeviceRef(new QString(ambeDeviceJson["deviceRef"].toString()));
ambeList->back()->setDelete(ambeDeviceJson["delete"].toInt());
}
else
{
return false;
}
}
return true;
}
}
return false;
}
bool WebAPIRequestMapper::validateLimeRFEConfig(SWGSDRangel::SWGLimeRFESettings& limeRFESettings, QJsonObject& jsonObject, QStringList& limeRFESettingsKeys)
{
if (jsonObject.contains("devicePath"))
{
limeRFESettings.setDevicePath(new QString(jsonObject["devicePath"].toString()));
limeRFESettingsKeys.append("devicePath");
}
if (jsonObject.contains("rxChannels"))
{
limeRFESettings.setRxChannels(jsonObject["rxChannels"].toInt());
limeRFESettingsKeys.append("rxChannels");
}
if (jsonObject.contains("rxWidebandChannel"))
{
limeRFESettings.setRxWidebandChannel(jsonObject["rxWidebandChannel"].toInt());
limeRFESettingsKeys.append("rxWidebandChannel");
}
if (jsonObject.contains("rxHAMChannel"))
{
limeRFESettings.setRxHamChannel(jsonObject["rxHAMChannel"].toInt());
limeRFESettingsKeys.append("rxHAMChannel");
}
if (jsonObject.contains("rxCellularChannel"))
{
limeRFESettings.setRxCellularChannel(jsonObject["rxCellularChannel"].toInt());
limeRFESettingsKeys.append("rxCellularChannel");
}
if (jsonObject.contains("rxPort"))
{
limeRFESettings.setRxPort(jsonObject["rxPort"].toInt());
limeRFESettingsKeys.append("rxPort");
}
if (jsonObject.contains("attenuationFactor"))
{
limeRFESettings.setAttenuationFactor(jsonObject["attenuationFactor"].toInt());
limeRFESettingsKeys.append("attenuationFactor");
}
if (jsonObject.contains("amfmNotch"))
{
limeRFESettings.setAmfmNotch(jsonObject["amfmNotch"].toInt());
limeRFESettingsKeys.append("amfmNotch");
}
if (jsonObject.contains("txChannels"))
{
limeRFESettings.setTxChannels(jsonObject["txChannels"].toInt());
limeRFESettingsKeys.append("txChannels");
}
if (jsonObject.contains("txWidebandChannel"))
{
limeRFESettings.setTxWidebandChannel(jsonObject["txWidebandChannel"].toInt());
limeRFESettingsKeys.append("txWidebandChannel");
}
if (jsonObject.contains("txHAMChannel"))
{
limeRFESettings.setTxHamChannel(jsonObject["txHAMChannel"].toInt());
limeRFESettingsKeys.append("txHAMChannel");
}
if (jsonObject.contains("txCellularChannel"))
{
limeRFESettings.setTxCellularChannel(jsonObject["txCellularChannel"].toInt());
limeRFESettingsKeys.append("txCellularChannel");
}
if (jsonObject.contains("txPort"))
{
limeRFESettings.setTxPort(jsonObject["txPort"].toInt());
limeRFESettingsKeys.append("txPort");
}
if (jsonObject.contains("rxOn"))
{
limeRFESettings.setRxOn(jsonObject["rxOn"].toInt());
limeRFESettingsKeys.append("rxOn");
}
if (jsonObject.contains("txOn"))
{
limeRFESettings.setTxOn(jsonObject["txOn"].toInt());
limeRFESettingsKeys.append("txOn");
}
if (jsonObject.contains("swrEnable"))
{
limeRFESettings.setSwrEnable(jsonObject["swrEnable"].toInt());
limeRFESettingsKeys.append("swrEnable");
}
if (jsonObject.contains("swrSource"))
{
limeRFESettings.setSwrSource(jsonObject["swrSource"].toInt());
limeRFESettingsKeys.append("swrSource");
}
return true;
}
bool WebAPIRequestMapper::validateSpectrumSettings(SWGSDRangel::SWGGLSpectrum& spectrumSettings, QJsonObject& jsonObject, QStringList& spectrumSettingsKeys)
{
extractKeys(jsonObject, spectrumSettingsKeys);
@ -5597,11 +5142,21 @@ bool WebAPIRequestMapper::getFeatureActions(
featureActions->setAfcActions(new SWGSDRangel::SWGAFCActions());
featureActions->getAfcActions()->fromJsonObject(actionsJsonObject);
}
else if (featureActionsKey == "AMBEActions")
{
featureActions->setAmbeActions(new SWGSDRangel::SWGAMBEActions());
featureActions->getAmbeActions()->fromJsonObject(actionsJsonObject);
}
else if (featureActionsKey == "GS232ControllerActions")
{
featureActions->setGs232ControllerActions(new SWGSDRangel::SWGGS232ControllerActions());
featureActions->getGs232ControllerActions()->fromJsonObject(actionsJsonObject);
}
else if (featureActionsKey == "LimeRFEActions")
{
featureActions->setLimeRfeActions(new SWGSDRangel::SWGLimeRFEActions());
featureActions->getLimeRfeActions()->fromJsonObject(actionsJsonObject);
}
else if (featureActionsKey == "MapActions")
{
featureActions->setMapActions(new SWGSDRangel::SWGMapActions());

View File

@ -66,13 +66,6 @@ private:
void instanceAudioInputCleanupService(qtwebapp::HttpRequest& request, qtwebapp::HttpResponse& response);
void instanceAudioOutputCleanupService(qtwebapp::HttpRequest& request, qtwebapp::HttpResponse& response);
void instanceLocationService(qtwebapp::HttpRequest& request, qtwebapp::HttpResponse& response);
void instanceDVSerialService(qtwebapp::HttpRequest& request, qtwebapp::HttpResponse& response);
void instanceAMBESerialService(qtwebapp::HttpRequest& request, qtwebapp::HttpResponse& response);
void instanceAMBEDevicesService(qtwebapp::HttpRequest& request, qtwebapp::HttpResponse& response);
void instanceLimeRFESerialService(qtwebapp::HttpRequest& request, qtwebapp::HttpResponse& response);
void instanceLimeRFEConfigService(qtwebapp::HttpRequest& request, qtwebapp::HttpResponse& response);
void instanceLimeRFERunService(qtwebapp::HttpRequest& request, qtwebapp::HttpResponse& response);
void instanceLimeRFEPowerService(qtwebapp::HttpRequest& request, qtwebapp::HttpResponse& response);
void instancePresetsService(qtwebapp::HttpRequest& request, qtwebapp::HttpResponse& response);
void instancePresetService(qtwebapp::HttpRequest& request, qtwebapp::HttpResponse& response);
void instancePresetFileService(qtwebapp::HttpRequest& request, qtwebapp::HttpResponse& response);
@ -130,8 +123,6 @@ private:
bool validateFeatureActions(SWGSDRangel::SWGFeatureActions& featureActions, QJsonObject& jsonObject, QStringList& featureActionsKeys);
bool validateAudioInputDevice(SWGSDRangel::SWGAudioInputDevice& audioInputDevice, QJsonObject& jsonObject, QStringList& audioInputDeviceKeys);
bool validateAudioOutputDevice(SWGSDRangel::SWGAudioOutputDevice& audioOutputDevice, QJsonObject& jsonObject, QStringList& audioOutputDeviceKeys);
bool validateAMBEDevices(SWGSDRangel::SWGAMBEDevices& ambeDevices, QJsonObject& jsonObject);
bool validateLimeRFEConfig(SWGSDRangel::SWGLimeRFESettings& limeRFESettings, QJsonObject& jsonObject, QStringList& limeRFESettingsKeys);
bool validateConfig(SWGSDRangel::SWGInstanceConfigResponse& config, QJsonObject& jsonObject, WebAPIAdapterInterface::ConfigKeys& configKeys);
bool validateWorkspaceInfo(SWGSDRangel::SWGWorkspaceInfo& workspaceInfo, QJsonObject& jsonObject);
bool validateConfigurationIdentifier(SWGSDRangel::SWGConfigurationIdentifier& configurationIdentifier);

View File

@ -270,11 +270,13 @@ const QMap<QString, QString> WebAPIUtils::m_mimoDeviceHwIdToActionsKey = {
const QMap<QString, QString> WebAPIUtils::m_featureTypeToSettingsKey = {
{"AFC", "AFCSettings"},
{"AIS", "AISSettings"},
{"AMBE", "AMBESettings"},
{"AntennaTools", "AntennaToolsSettings"},
{"APRS", "APRSSettings"},
{"DemodAnalyzer", "DemodAnalyzerSettings"},
{"JogdialController", "JogdialControllerSettings"},
{"GS232Controller", "GS232ControllerSettings"}, // a.k.a Rotator Controller
{"LimeRFE", "LimeRFESettings"},
{"Map", "MapSettings"},
{"PERTester", "PERTesterSettings"},
{"Radiosonde", "RadiosondeSettings"},
@ -287,7 +289,9 @@ const QMap<QString, QString> WebAPIUtils::m_featureTypeToSettingsKey = {
const QMap<QString, QString> WebAPIUtils::m_featureTypeToActionsKey = {
{"AFC", "AFCActions"},
{"AMBE", "AMBEActions"},
{"GS232Controller", "GS232ControllerActions"},
{"LimeRFE", "LimeRFEActions"},
{"Map", "MapActions"},
{"PERTester", "PERTesterActions"},
{"RigCtlServer", "RigCtlServerActions"},
@ -300,11 +304,13 @@ const QMap<QString, QString> WebAPIUtils::m_featureTypeToActionsKey = {
const QMap<QString, QString> WebAPIUtils::m_featureURIToSettingsKey = {
{"sdrangel.feature.afc", "AFCSettings"},
{"sdrangel.feature.ais", "AISSSettings"},
{"sdrangel.feature.ambe", "AMBESSettings"},
{"sdrangel.feature.antennatools", "AntennaToolsSettings"},
{"sdrangel.feature.aprs", "APRSSettings"},
{"sdrangel.feature.demodanalyzer", "DemodAnalyzerSettings"},
{"sdrangel.feature.jogdialcontroller", "JogdialControllerSettings"},
{"sdrangel.feature.gs232controller", "GS232ControllerSettings"},
{"sdrangel.feature.limerfe", "LimeRFESettings"},
{"sdrangel.feature.map", "MapSettings"},
{"sdrangel.feature.pertester", "PERTesterSettings"},
{"sdrangel.feature.radiosonde", "RadiosondeSettings"},

View File

@ -20,8 +20,6 @@
#include <QDebug>
#include <QElapsedTimer>
#include "ambe/ambeengine.h"
#include "mainbench.h"
MainBench *MainBench::m_instance = 0;
@ -62,8 +60,6 @@ void MainBench::run()
testDecimateFI();
} else if (m_parser.getTestType() == ParserBench::TestDecimatorsFF) {
testDecimateFF();
} else if (m_parser.getTestType() == ParserBench::TestAMBE) {
testAMBE();
} else if (m_parser.getTestType() == ParserBench::TestGolay2312) {
testGolay2312();
} else {
@ -197,19 +193,6 @@ void MainBench::testDecimateFF()
delete[] buf;
}
void MainBench::testAMBE()
{
qDebug() << "MainBench::testAMBE";
AMBEEngine ambeEngine;
std::vector<QString> ambeDevices;
ambeEngine.scan(ambeDevices);
for (std::vector<QString>::const_iterator it = ambeDevices.begin(); it != ambeDevices.end(); ++it) {
qDebug("MainBench::testAMBE: detected AMBE device %s", qPrintable(*it));
}
}
void MainBench::decimateII(const qint16* buf, int len)
{
SampleVector::iterator it = m_convertBuffer.begin();

View File

@ -53,7 +53,6 @@ private:
void testDecimateIF();
void testDecimateFI();
void testDecimateFF();
void testAMBE();
void testGolay2312();
void decimateII(const qint16 *buf, int len);
void decimateInfII(const qint16 *buf, int len);

View File

@ -125,8 +125,6 @@ ParserBench::TestType ParserBench::getTestType() const
return TestDecimatorsInfII;
} else if (m_testStr == "decimatesupii") {
return TestDecimatorsSupII;
} else if (m_testStr == "ambe") {
return TestAMBE;
} else if (m_testStr == "golay2312") {
return TestGolay2312;
} else {

View File

@ -35,7 +35,6 @@ public:
TestDecimatorsFF,
TestDecimatorsInfII,
TestDecimatorsSupII,
TestAMBE,
TestGolay2312
} TestType;

Some files were not shown because too many files have changed in this diff Show More