1
0
mirror of https://github.com/f4exb/sdrangel.git synced 2024-11-10 10:33:29 -05:00

Beam steering CW channel

This commit is contained in:
f4exb 2020-11-10 21:49:43 +01:00
parent 17a9d387c3
commit f1544852b9
31 changed files with 2968 additions and 2 deletions

View File

@ -1,5 +1,7 @@
project(channelmimo)
add_subdirectory(beamsteeringcwmod)
if (NOT SERVER_MODE)
add_subdirectory(interferometer)
endif()

View File

@ -0,0 +1,60 @@
project(beamsteeringcwmod)
set(beamsteeringcwmod_SOURCES
beamsteeringcwmod.cpp
beamsteeringcwmodsettings.cpp
beamsteeringcwmodbaseband.cpp
beamsteeringcwmodstreamsource.cpp
beamsteeringcwmodplugin.cpp
beamsteeringcwmodwebapiadapter.cpp
)
set(beamsteeringcwmod_HEADERS
beamsteeringcwmod.h
beamsteeringcwmodsettings.h
beamsteeringcwmodbaseband.h
beamsteeringcwmodstreamsource.h
beamsteeringcwmodplugin.h
beamsteeringcwmodwebapiadapter.h
)
include_directories(
${CMAKE_SOURCE_DIR}/swagger/sdrangel/code/qt5/client
${Boost_INCLUDE_DIR}
)
if (NOT SERVER_MODE)
set(beamsteeringcwmod_SOURCES
${beamsteeringcwmod_SOURCES}
beamsteeringcwmodgui.cpp
beamsteeringcwmodgui.ui
)
set(beamsteeringcwmod_HEADERS
${beamsteeringcwmod_HEADERS}
beamsteeringcwmodgui.h
)
set(TARGET_NAME beamsteeringcwmod)
set(TARGET_LIB "Qt5::Widgets")
set(TARGET_LIB_GUI "sdrgui")
set(INSTALL_FOLDER ${INSTALL_PLUGINS_DIR})
else()
set(TARGET_NAME beamsteeringcwmodsrv)
set(TARGET_LIB "")
set(TARGET_LIB_GUI "")
set(INSTALL_FOLDER ${INSTALL_PLUGINSSRV_DIR})
endif()
add_library(${TARGET_NAME} SHARED
${beamsteeringcwmod_SOURCES}
)
target_link_libraries(${TARGET_NAME}
Qt5::Core
${TARGET_LIB}
sdrbase
${TARGET_LIB_GUI}
swagger
)
install(TARGETS ${TARGET_NAME} DESTINATION ${INSTALL_FOLDER})

View File

@ -0,0 +1,457 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2019 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 <QThread>
#include <QDebug>
#include <QBuffer>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include "SWGChannelSettings.h"
#include "device/deviceapi.h"
#include "dsp/hbfilterchainconverter.h"
#include "dsp/dspcommands.h"
#include "feature/feature.h"
#include "maincore.h"
#include "beamsteeringcwmodbaseband.h"
#include "beamsteeringcwmod.h"
MESSAGE_CLASS_DEFINITION(BeamSteeringCWMod::MsgConfigureBeamSteeringCWMod, Message)
MESSAGE_CLASS_DEFINITION(BeamSteeringCWMod::MsgBasebandNotification, Message)
const QString BeamSteeringCWMod::m_channelIdURI = "sdrangel.channel.beamsteeringcwmod";
const QString BeamSteeringCWMod::m_channelId = "BeamSteeringCWMod";
BeamSteeringCWMod::BeamSteeringCWMod(DeviceAPI *deviceAPI) :
ChannelAPI(m_channelIdURI, ChannelAPI::StreamMIMO),
m_deviceAPI(deviceAPI),
m_guiMessageQueue(nullptr),
m_frequencyOffset(0),
m_basebandSampleRate(48000)
{
setObjectName(m_channelId);
m_thread = new QThread(this);
m_basebandSource = new BeamSteeringCWModBaseband();
m_basebandSource->moveToThread(m_thread);
m_deviceAPI->addMIMOChannel(this);
m_deviceAPI->addMIMOChannelAPI(this);
connect(&m_inputMessageQueue, SIGNAL(messageEnqueued()), this, SLOT(handleInputMessages()));
m_networkManager = new QNetworkAccessManager();
connect(m_networkManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(networkManagerFinished(QNetworkReply*)));
}
BeamSteeringCWMod::~BeamSteeringCWMod()
{
disconnect(m_networkManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(networkManagerFinished(QNetworkReply*)));
delete m_networkManager;
m_deviceAPI->removeChannelSinkAPI(this);
m_deviceAPI->removeMIMOChannel(this);
delete m_basebandSource;
delete m_thread;
}
void BeamSteeringCWMod::startSources()
{
qDebug("BeamSteeringCWMod::startSources");
m_basebandSource->reset();
m_thread->start();
BeamSteeringCWModBaseband::MsgSignalNotification *sig = BeamSteeringCWModBaseband::MsgSignalNotification::create(
m_basebandSampleRate);
m_basebandSource->getInputMessageQueue()->push(sig);
BeamSteeringCWModBaseband::MsgConfigureBeamSteeringCWModBaseband *msg = BeamSteeringCWModBaseband::MsgConfigureBeamSteeringCWModBaseband::create(
m_settings, true);
m_basebandSource->getInputMessageQueue()->push(msg);
}
void BeamSteeringCWMod::stopSources()
{
qDebug("BeamSteeringCWMod::stopSources");
m_thread->exit();
m_thread->wait();
}
void BeamSteeringCWMod::pull(SampleVector::iterator& begin, unsigned int nbSamples, unsigned int sourceIndex)
{
m_basebandSource->pull(begin, nbSamples, sourceIndex);
}
void BeamSteeringCWMod::feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end, unsigned int sinkIndex)
{
(void) begin;
(void) end;
(void) sinkIndex;
}
void BeamSteeringCWMod::applySettings(const BeamSteeringCWModSettings& settings, bool force)
{
qDebug() << "BeamSteeringCWMod::applySettings: "
<< "m_steerDegrees: " << settings.m_steerDegrees
<< "m_channelOutput: " << settings.m_channelOutput
<< "m_filterChainHash: " << settings.m_filterChainHash
<< "m_log2Interp: " << settings.m_log2Interp
<< "m_filterChainHash: " << settings.m_filterChainHash
<< "m_useReverseAPI: " << settings.m_useReverseAPI
<< "m_reverseAPIAddress: " << settings.m_reverseAPIAddress
<< "m_reverseAPIPort: " << settings.m_reverseAPIPort
<< "m_reverseAPIDeviceIndex: " << settings.m_reverseAPIDeviceIndex
<< "m_reverseAPIChannelIndex: " << settings.m_reverseAPIChannelIndex
<< "m_title: " << settings.m_title;
QList<QString> reverseAPIKeys;
if ((m_settings.m_steerDegrees != settings.m_steerDegrees) || force) {
reverseAPIKeys.append("steerDegrees");
}
if ((m_settings.m_channelOutput != settings.m_channelOutput) || force) {
reverseAPIKeys.append("channelOutput");
}
if ((m_settings.m_filterChainHash != settings.m_filterChainHash) || force) {
reverseAPIKeys.append("filterChainHash");
}
if ((m_settings.m_log2Interp != settings.m_log2Interp) || force) {
reverseAPIKeys.append("log2Interp");
}
if ((m_settings.m_filterChainHash != settings.m_filterChainHash) || force) {
reverseAPIKeys.append("filterChainHash");
}
BeamSteeringCWModBaseband::MsgConfigureBeamSteeringCWModBaseband *msg = BeamSteeringCWModBaseband::MsgConfigureBeamSteeringCWModBaseband::create(settings, force);
m_basebandSource->getInputMessageQueue()->push(msg);
if (m_featuresSettingsFeedback.size() > 0) {
featuresSendSettings(reverseAPIKeys, settings, force);
}
m_settings = settings;
}
void BeamSteeringCWMod::handleInputMessages()
{
Message* message;
while ((message = m_inputMessageQueue.pop()) != 0)
{
if (handleMessage(*message))
{
delete message;
}
}
}
bool BeamSteeringCWMod::handleMessage(const Message& cmd)
{
if (MsgConfigureBeamSteeringCWMod::match(cmd))
{
MsgConfigureBeamSteeringCWMod& cfg = (MsgConfigureBeamSteeringCWMod&) cmd;
qDebug() << "BeamSteeringCWMod::handleMessage: MsgConfigureBeamSteeringCWMod";
applySettings(cfg.getSettings(), cfg.getForce());
return true;
}
else if (DSPMIMOSignalNotification::match(cmd))
{
DSPMIMOSignalNotification& notif = (DSPMIMOSignalNotification&) cmd;
qDebug() << "BeamSteeringCWMod::handleMessage: DSPMIMOSignalNotification:"
<< " basebandSampleRate: " << notif.getSampleRate()
<< " centerFrequency: " << notif.getCenterFrequency()
<< " sourceElseSink: " << notif.getSourceOrSink()
<< " streamIndex: " << notif.getIndex();
if (!notif.getSourceOrSink()) // deals with sink messages only
{
m_basebandSampleRate = notif.getSampleRate();
calculateFrequencyOffset(); // This is when device sample rate changes
// Notify source of input sample rate change
BeamSteeringCWModBaseband::MsgSignalNotification *sig = BeamSteeringCWModBaseband::MsgSignalNotification::create(
m_basebandSampleRate);
qDebug() << "BeamSteeringCWMod::handleMessage: DSPMIMOSignalNotification: push to source";
m_basebandSource->getInputMessageQueue()->push(sig);
if (m_guiMessageQueue)
{
qDebug() << "BeamSteeringCWMod::handleMessage: DSPMIMOSignalNotification: push to GUI";
MsgBasebandNotification *msg = MsgBasebandNotification::create(
notif.getSampleRate(), notif.getCenterFrequency());
m_guiMessageQueue->push(msg);
}
}
return true;
}
else
{
return false;
}
}
QByteArray BeamSteeringCWMod::serialize() const
{
return m_settings.serialize();
}
bool BeamSteeringCWMod::deserialize(const QByteArray& data)
{
(void) data;
if (m_settings.deserialize(data))
{
MsgConfigureBeamSteeringCWMod *msg = MsgConfigureBeamSteeringCWMod::create(m_settings, true);
m_inputMessageQueue.push(msg);
return true;
}
else
{
m_settings.resetToDefaults();
MsgConfigureBeamSteeringCWMod *msg = MsgConfigureBeamSteeringCWMod::create(m_settings, true);
m_inputMessageQueue.push(msg);
return false;
}
}
void BeamSteeringCWMod::validateFilterChainHash(BeamSteeringCWModSettings& settings)
{
unsigned int s = 1;
for (unsigned int i = 0; i < settings.m_log2Interp; i++) {
s *= 3;
}
settings.m_filterChainHash = settings.m_filterChainHash >= s ? s-1 : settings.m_filterChainHash;
}
void BeamSteeringCWMod::calculateFrequencyOffset()
{
double shiftFactor = HBFilterChainConverter::getShiftFactor(m_settings.m_log2Interp, m_settings.m_filterChainHash);
m_frequencyOffset = m_basebandSampleRate * shiftFactor;
}
int BeamSteeringCWMod::webapiSettingsGet(
SWGSDRangel::SWGChannelSettings& response,
QString& errorMessage)
{
(void) errorMessage;
response.setBeamSteeringCwModSettings(new SWGSDRangel::SWGBeamSteeringCWModSettings());
response.getBeamSteeringCwModSettings()->init();
webapiFormatChannelSettings(response, m_settings);
return 200;
}
int BeamSteeringCWMod::webapiSettingsPutPatch(
bool force,
const QStringList& channelSettingsKeys,
SWGSDRangel::SWGChannelSettings& response,
QString& errorMessage)
{
(void) errorMessage;
BeamSteeringCWModSettings settings = m_settings;
webapiUpdateChannelSettings(settings, channelSettingsKeys, response);
MsgConfigureBeamSteeringCWMod *msg = MsgConfigureBeamSteeringCWMod::create(settings, force);
m_inputMessageQueue.push(msg);
if (getMessageQueueToGUI()) // forward to GUI if any
{
MsgConfigureBeamSteeringCWMod *msgToGUI = MsgConfigureBeamSteeringCWMod::create(settings, force);
getMessageQueueToGUI()->push(msgToGUI);
}
webapiFormatChannelSettings(response, settings);
return 200;
}
void BeamSteeringCWMod::webapiUpdateChannelSettings(
BeamSteeringCWModSettings& settings,
const QStringList& channelSettingsKeys,
SWGSDRangel::SWGChannelSettings& response)
{
if (channelSettingsKeys.contains("steerDegrees")) {
settings.m_rgbColor = response.getBeamSteeringCwModSettings()->getSteerDegrees();
}
if (channelSettingsKeys.contains("rgbColor")) {
settings.m_rgbColor = response.getBeamSteeringCwModSettings()->getRgbColor();
}
if (channelSettingsKeys.contains("title")) {
settings.m_title = *response.getBeamSteeringCwModSettings()->getTitle();
}
if (channelSettingsKeys.contains("log2Interp")) {
settings.m_log2Interp = response.getBeamSteeringCwModSettings()->getLog2Interp();
}
if (channelSettingsKeys.contains("filterChainHash"))
{
settings.m_filterChainHash = response.getBeamSteeringCwModSettings()->getFilterChainHash();
validateFilterChainHash(settings);
}
if (channelSettingsKeys.contains("useReverseAPI")) {
settings.m_useReverseAPI = response.getBeamSteeringCwModSettings()->getUseReverseApi() != 0;
}
if (channelSettingsKeys.contains("reverseAPIAddress")) {
settings.m_reverseAPIAddress = *response.getBeamSteeringCwModSettings()->getReverseApiAddress();
}
if (channelSettingsKeys.contains("reverseAPIPort")) {
settings.m_reverseAPIPort = response.getBeamSteeringCwModSettings()->getReverseApiPort();
}
if (channelSettingsKeys.contains("reverseAPIDeviceIndex")) {
settings.m_reverseAPIDeviceIndex = response.getBeamSteeringCwModSettings()->getReverseApiDeviceIndex();
}
if (channelSettingsKeys.contains("reverseAPIChannelIndex")) {
settings.m_reverseAPIChannelIndex = response.getBeamSteeringCwModSettings()->getReverseApiChannelIndex();
}
}
void BeamSteeringCWMod::webapiFormatChannelSettings(SWGSDRangel::SWGChannelSettings& response, const BeamSteeringCWModSettings& settings)
{
response.getBeamSteeringCwModSettings()->setSteerDegrees(settings.m_steerDegrees);
response.getBeamSteeringCwModSettings()->setRgbColor(settings.m_rgbColor);
if (response.getBeamSteeringCwModSettings()->getTitle()) {
*response.getBeamSteeringCwModSettings()->getTitle() = settings.m_title;
} else {
response.getBeamSteeringCwModSettings()->setTitle(new QString(settings.m_title));
}
response.getBeamSteeringCwModSettings()->setLog2Interp(settings.m_log2Interp);
response.getBeamSteeringCwModSettings()->setFilterChainHash(settings.m_filterChainHash);
response.getBeamSteeringCwModSettings()->setUseReverseApi(settings.m_useReverseAPI ? 1 : 0);
if (response.getBeamSteeringCwModSettings()->getReverseApiAddress()) {
*response.getBeamSteeringCwModSettings()->getReverseApiAddress() = settings.m_reverseAPIAddress;
} else {
response.getBeamSteeringCwModSettings()->setReverseApiAddress(new QString(settings.m_reverseAPIAddress));
}
response.getBeamSteeringCwModSettings()->setReverseApiPort(settings.m_reverseAPIPort);
response.getBeamSteeringCwModSettings()->setReverseApiDeviceIndex(settings.m_reverseAPIDeviceIndex);
response.getBeamSteeringCwModSettings()->setReverseApiChannelIndex(settings.m_reverseAPIChannelIndex);
}
void BeamSteeringCWMod::webapiReverseSendSettings(QList<QString>& channelSettingsKeys, const BeamSteeringCWModSettings& settings, bool force)
{
SWGSDRangel::SWGChannelSettings *swgChannelSettings = new SWGSDRangel::SWGChannelSettings();
webapiFormatChannelSettings(channelSettingsKeys, swgChannelSettings, settings, force);
QString channelSettingsURL = QString("http://%1:%2/sdrangel/deviceset/%3/channel/%4/settings")
.arg(settings.m_reverseAPIAddress)
.arg(settings.m_reverseAPIPort)
.arg(settings.m_reverseAPIDeviceIndex)
.arg(settings.m_reverseAPIChannelIndex);
m_networkRequest.setUrl(QUrl(channelSettingsURL));
m_networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
QBuffer *buffer = new QBuffer();
buffer->open((QBuffer::ReadWrite));
buffer->write(swgChannelSettings->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 swgChannelSettings;
}
void BeamSteeringCWMod::featuresSendSettings(QList<QString>& channelSettingsKeys, const BeamSteeringCWModSettings& settings, bool force)
{
QList<Feature*>::iterator it = m_featuresSettingsFeedback.begin();
MainCore *mainCore = MainCore::instance();
for (; it != m_featuresSettingsFeedback.end(); ++it)
{
if (mainCore->existsFeature(*it))
{
SWGSDRangel::SWGChannelSettings *swgChannelSettings = new SWGSDRangel::SWGChannelSettings();
webapiFormatChannelSettings(channelSettingsKeys, swgChannelSettings, settings, force);
Feature::MsgChannelSettings *msg = Feature::MsgChannelSettings::create(
this,
channelSettingsKeys,
swgChannelSettings,
force
);
(*it)->getInputMessageQueue()->push(msg);
}
else
{
m_featuresSettingsFeedback.removeOne(*it);
}
}
}
void BeamSteeringCWMod::webapiFormatChannelSettings(
QList<QString>& channelSettingsKeys,
SWGSDRangel::SWGChannelSettings *swgChannelSettings,
const BeamSteeringCWModSettings& settings,
bool force
)
{
swgChannelSettings->setDirection(2); // MIMO sink
swgChannelSettings->setOriginatorChannelIndex(getIndexInDeviceSet());
swgChannelSettings->setOriginatorDeviceSetIndex(getDeviceSetIndex());
swgChannelSettings->setChannelType(new QString("BeamSteeringCWSource"));
swgChannelSettings->setBeamSteeringCwModSettings(new SWGSDRangel::SWGBeamSteeringCWModSettings());
SWGSDRangel::SWGBeamSteeringCWModSettings *swgBeamSteeringCWSettings = swgChannelSettings->getBeamSteeringCwModSettings();
// transfer data that has been modified. When force is on transfer all data except reverse API data
if (channelSettingsKeys.contains("steerDegrees") || force) {
swgBeamSteeringCWSettings->setSteerDegrees(settings.m_steerDegrees);
}
if (channelSettingsKeys.contains("rgbColor") || force) {
swgBeamSteeringCWSettings->setRgbColor(settings.m_rgbColor);
}
if (channelSettingsKeys.contains("title") || force) {
swgBeamSteeringCWSettings->setTitle(new QString(settings.m_title));
}
if (channelSettingsKeys.contains("log2Decim") || force) {
swgBeamSteeringCWSettings->setLog2Interp(settings.m_log2Interp);
}
if (channelSettingsKeys.contains("filterChainHash") || force) {
swgBeamSteeringCWSettings->setFilterChainHash(settings.m_filterChainHash);
}
}
void BeamSteeringCWMod::networkManagerFinished(QNetworkReply *reply)
{
QNetworkReply::NetworkError replyError = reply->error();
if (replyError)
{
qWarning() << "BeamSteeringCWMod::networkManagerFinished:"
<< " error(" << (int) replyError
<< "): " << replyError
<< ": " << reply->errorString();
}
else
{
QString answer = reply->readAll();
answer.chop(1); // remove last \n
qDebug("BeamSteeringCWMod::networkManagerFinished: reply:\n%s", answer.toStdString().c_str());
}
reply->deleteLater();
}

View File

@ -0,0 +1,180 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2019 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_BEAMSTEERINGCWMOD_H
#define INCLUDE_BEAMSTEERINGCWMOD_H
#include <vector>
#include <QNetworkRequest>
#include "dsp/mimochannel.h"
#include "channel/channelapi.h"
#include "util/messagequeue.h"
#include "util/message.h"
#include "beamsteeringcwmodsettings.h"
class QThread;
class DeviceAPI;
class BeamSteeringCWModBaseband;
class QNetworkReply;
class QNetworkAccessManager;
class BasebandSampleSink;
class BeamSteeringCWMod: public MIMOChannel, public ChannelAPI
{
Q_OBJECT
public:
class MsgConfigureBeamSteeringCWMod : public Message {
MESSAGE_CLASS_DECLARATION
public:
const BeamSteeringCWModSettings& getSettings() const { return m_settings; }
bool getForce() const { return m_force; }
static MsgConfigureBeamSteeringCWMod* create(const BeamSteeringCWModSettings& settings, bool force)
{
return new MsgConfigureBeamSteeringCWMod(settings, force);
}
private:
BeamSteeringCWModSettings m_settings;
bool m_force;
MsgConfigureBeamSteeringCWMod(const BeamSteeringCWModSettings& settings, bool force) :
Message(),
m_settings(settings),
m_force(force)
{ }
};
class MsgBasebandNotification : public Message {
MESSAGE_CLASS_DECLARATION
public:
static MsgBasebandNotification* create(int sampleRate, qint64 centerFrequency) {
return new MsgBasebandNotification(sampleRate, centerFrequency);
}
int getSampleRate() const { return m_sampleRate; }
qint64 getCenterFrequency() const { return m_centerFrequency; }
private:
MsgBasebandNotification(int sampleRate, qint64 centerFrequency) :
Message(),
m_sampleRate(sampleRate),
m_centerFrequency(centerFrequency)
{ }
int m_sampleRate;
qint64 m_centerFrequency;
};
BeamSteeringCWMod(DeviceAPI *deviceAPI);
virtual ~BeamSteeringCWMod();
virtual void destroy() { delete this; }
virtual void startSinks() {}
virtual void stopSinks() {}
virtual void startSources(); //!< thread start()
virtual void stopSources(); //!< thread exit() and wait()
virtual void feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end, unsigned int sinkIndex);
virtual void pull(SampleVector::iterator& begin, unsigned int nbSamples, unsigned int sourceIndex);
virtual bool handleMessage(const Message& cmd); //!< Processing of a message. Returns true if message has actually been processed
virtual void getIdentifier(QString& id) { id = m_channelId; }
virtual const QString& getURI() const { return m_channelIdURI; }
virtual void getTitle(QString& title) { title = "BeamSteeringCWMod"; }
virtual qint64 getCenterFrequency() const { return m_frequencyOffset; }
uint32_t getBasebandSampleRate() const { return m_basebandSampleRate; }
virtual QByteArray serialize() const;
virtual bool deserialize(const QByteArray& data);
virtual int getNbSinkStreams() const { return 0; }
virtual int getNbSourceStreams() const { return 2; }
virtual qint64 getStreamCenterFrequency(int streamIndex, bool sinkElseSource) const
{
(void) streamIndex;
(void) sinkElseSource;
return m_frequencyOffset;
}
MessageQueue *getInputMessageQueue() { return &m_inputMessageQueue; } //!< Get the queue for asynchronous inbound communication
virtual void setMessageQueueToGUI(MessageQueue *queue) { m_guiMessageQueue = queue; }
MessageQueue *getMessageQueueToGUI() { return m_guiMessageQueue; }
virtual int webapiSettingsGet(
SWGSDRangel::SWGChannelSettings& response,
QString& errorMessage);
virtual int webapiSettingsPutPatch(
bool force,
const QStringList& channelSettingsKeys,
SWGSDRangel::SWGChannelSettings& response,
QString& errorMessage);
static void webapiFormatChannelSettings(
SWGSDRangel::SWGChannelSettings& response,
const BeamSteeringCWModSettings& settings);
static void webapiUpdateChannelSettings(
BeamSteeringCWModSettings& settings,
const QStringList& channelSettingsKeys,
SWGSDRangel::SWGChannelSettings& response);
static const QString m_channelIdURI;
static const QString m_channelId;
static const int m_fftSize;
private:
DeviceAPI *m_deviceAPI;
QThread *m_thread;
BeamSteeringCWModBaseband* m_basebandSource;
BasebandSampleSink* m_spectrumSink;
BasebandSampleSink* m_scopeSink;
BeamSteeringCWModSettings m_settings;
MessageQueue m_inputMessageQueue; //!< Queue for asynchronous inbound communication
MessageQueue *m_guiMessageQueue; //!< Input message queue to the GUI
QNetworkAccessManager *m_networkManager;
QNetworkRequest m_networkRequest;
int64_t m_frequencyOffset;
uint32_t m_basebandSampleRate;
int m_count0, m_count1;
void applySettings(const BeamSteeringCWModSettings& settings, bool force = false);
static void validateFilterChainHash(BeamSteeringCWModSettings& settings);
void calculateFrequencyOffset();
void webapiReverseSendSettings(QList<QString>& channelSettingsKeys, const BeamSteeringCWModSettings& settings, bool force);
void featuresSendSettings(QList<QString>& channelSettingsKeys, const BeamSteeringCWModSettings& settings, bool force);
void webapiFormatChannelSettings(
QList<QString>& channelSettingsKeys,
SWGSDRangel::SWGChannelSettings *swgChannelSettings,
const BeamSteeringCWModSettings& settings,
bool force
);
private slots:
void handleInputMessages();
void networkManagerFinished(QNetworkReply *reply);
};
#endif // INCLUDE_BEAMSTEERINGCWSOURCE_H

View File

@ -0,0 +1,247 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2019 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 <QMutexLocker>
#include <QDebug>
#include "dsp/upchannelizer.h"
#include "dsp/dspcommands.h"
#include "beamsteeringcwmodbaseband.h"
MESSAGE_CLASS_DEFINITION(BeamSteeringCWModBaseband::MsgConfigureBeamSteeringCWModBaseband, Message)
MESSAGE_CLASS_DEFINITION(BeamSteeringCWModBaseband::MsgSignalNotification, Message)
BeamSteeringCWModBaseband::BeamSteeringCWModBaseband() :
m_mutex(QMutex::Recursive)
{
m_sampleMOFifo.init(2, SampleMOFifo::getSizePolicy(48000));
m_vbegin.resize(2);
for (int i = 0; i < 2; i++)
{
m_streamSources[i].setStreamIndex(i);
m_channelizers[i] = new UpChannelizer(&m_streamSources[i]);
m_sizes[i] = 0;
}
QObject::connect(
&m_sampleMOFifo,
&SampleMOFifo::dataReadSync,
this,
&BeamSteeringCWModBaseband::handleData,
Qt::QueuedConnection
);
connect(&m_inputMessageQueue, SIGNAL(messageEnqueued()), this, SLOT(handleInputMessages()));
m_lastStream = 0;
}
BeamSteeringCWModBaseband::~BeamSteeringCWModBaseband()
{
for (int i = 0; i < 2; i++) {
delete m_channelizers[i];
}
}
void BeamSteeringCWModBaseband::reset()
{
QMutexLocker mutexLocker(&m_mutex);
m_sampleMOFifo.reset();
for (int i = 0; i < 2; i++)
{
m_streamSources[i].reset();
m_sizes[i] = 0;
}
}
void BeamSteeringCWModBaseband::pull(SampleVector::iterator& begin, unsigned int nbSamples, unsigned int streamIndex)
{
if (streamIndex > 1) {
return;
}
if (streamIndex == m_lastStream) {
qWarning("BeamSteeringCWModBaseband::pull: twice same stream in a row: %u", streamIndex);
}
m_lastStream = streamIndex;
m_vbegin[streamIndex] = begin;
m_sizes[streamIndex] = nbSamples;
if (streamIndex == 1)
{
unsigned int part1Begin, part1End, part2Begin, part2End, size;
if (m_sizes[0] != m_sizes[1])
{
qWarning("BeamSteeringCWModBaseband::pull: unequal sizes: [0]: %d [1]: %d", m_sizes[0], m_sizes[1]);
size = std::min(m_sizes[0], m_sizes[1]);
}
else
{
size = m_sizes[0];
}
std::vector<SampleVector>& data = m_sampleMOFifo.getData();
m_sampleMOFifo.readSync(size, part1Begin, part1End, part2Begin, part2End);
if (part1Begin != part1End)
{
std::copy(data[0].begin() + part1Begin, data[0].begin() + part1End, m_vbegin[0]);
std::copy(data[1].begin() + part1Begin, data[1].begin() + part1End, m_vbegin[1]);
}
if (part2Begin != part2End)
{
std::copy(data[0].begin() + part2Begin, data[0].begin() + part2End, m_vbegin[0]);
std::copy(data[1].begin() + part2Begin, data[1].begin() + part2End, m_vbegin[1]);
}
}
}
void BeamSteeringCWModBaseband::handleData()
{
QMutexLocker mutexLocker(&m_mutex);
std::vector<SampleVector>& data = m_sampleMOFifo.getData();
unsigned int ipart1begin;
unsigned int ipart1end;
unsigned int ipart2begin;
unsigned int ipart2end;
unsigned int remainder = m_sampleMOFifo.remainderSync();
while ((remainder > 0) && (m_inputMessageQueue.size() == 0))
{
m_sampleMOFifo.writeSync(remainder, ipart1begin, ipart1end, ipart2begin, ipart2end);
if (ipart1begin != ipart1end) { // first part of FIFO data
processFifo(data, ipart1begin, ipart1end);
}
if (ipart2begin != ipart2end) { // second part of FIFO data (used when block wraps around)
processFifo(data, ipart2begin, ipart2end);
}
remainder = m_sampleMOFifo.remainderSync();
}
}
void BeamSteeringCWModBaseband::processFifo(std::vector<SampleVector>& data, unsigned int ibegin, unsigned int iend)
{
for (unsigned int stream = 0; stream < 2; stream++) {
m_channelizers[stream]->pull(data[stream].begin() + ibegin, iend - ibegin);
}
}
void BeamSteeringCWModBaseband::handleInputMessages()
{
Message* message;
while ((message = m_inputMessageQueue.pop()) != nullptr)
{
if (handleMessage(*message)) {
delete message;
}
}
}
bool BeamSteeringCWModBaseband::handleMessage(const Message& cmd)
{
if (MsgConfigureBeamSteeringCWModBaseband::match(cmd))
{
QMutexLocker mutexLocker(&m_mutex);
MsgConfigureBeamSteeringCWModBaseband& cfg = (MsgConfigureBeamSteeringCWModBaseband&) cmd;
qDebug() << "BeamSteeringCWModBaseband::handleMessage: MsgConfigureBeamSteeringCWModBaseband";
applySettings(cfg.getSettings(), cfg.getForce());
return true;
}
else if (MsgSignalNotification::match(cmd))
{
QMutexLocker mutexLocker(&m_mutex);
MsgSignalNotification& cfg = (MsgSignalNotification&) cmd;
int basebandSampleRate = cfg.getBasebandSampleRate();
qDebug() << "BeamSteeringCWModBaseband::handleMessage: MsgSignalNotification:"
<< " basebandSampleRate: " << basebandSampleRate;
m_sampleMOFifo.resize(SampleMOFifo::getSizePolicy(basebandSampleRate));
for (int i = 0; i < 2; i++)
{
m_channelizers[i]->setBasebandSampleRate(basebandSampleRate, true);
m_streamSources[i].reset();
}
return true;
}
else
{
qDebug("BeamSteeringCWModBaseband::handleMessage: unhandled: %s", cmd.getIdentifier());
return false;
}
}
void BeamSteeringCWModBaseband::applySettings(const BeamSteeringCWModSettings& settings, bool force)
{
if ((m_settings.m_filterChainHash != settings.m_filterChainHash) || (m_settings.m_log2Interp != settings.m_log2Interp) || force)
{
for (int i = 0; i < 2; i++)
{
m_channelizers[i]->setInterpolation(settings.m_log2Interp, settings.m_filterChainHash);
m_streamSources[i].reset();
}
}
if ((m_settings.m_steerDegrees != settings.m_steerDegrees) || force)
{
float steeringAngle = settings.m_steerDegrees / 180.0f;
steeringAngle = steeringAngle < -M_PI ? -M_PI : steeringAngle > M_PI ? M_PI : steeringAngle;
m_streamSources[1].setPhase(M_PI*cos(steeringAngle));
}
if ((m_settings.m_channelOutput != settings.m_channelOutput) || force)
{
if (settings.m_channelOutput == 0)
{
m_streamSources[0].muteChannel(false);
m_streamSources[1].muteChannel(false);
}
else if (settings.m_channelOutput == 1)
{
m_streamSources[0].muteChannel(false);
m_streamSources[1].muteChannel(true);
}
else if (settings.m_channelOutput == 2)
{
m_streamSources[0].muteChannel(true);
m_streamSources[1].muteChannel(false);
}
else
{
m_streamSources[0].muteChannel(false);
m_streamSources[1].muteChannel(false);
}
}
m_settings = settings;
}

View File

@ -0,0 +1,105 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2019 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_BEAMSTEERINGCWMODBASEBAND_H
#define INCLUDE_BEAMSTEERINGCWMODBASEBAND_H
#include <QObject>
#include <QMutex>
#include "dsp/samplemofifo.h"
#include "util/message.h"
#include "util/messagequeue.h"
#include "beamsteeringcwmodstreamsource.h"
#include "beamsteeringcwmodsettings.h"
class UpChannelizer;
class BeamSteeringCWModBaseband : public QObject
{
Q_OBJECT
public:
class MsgConfigureBeamSteeringCWModBaseband : public Message {
MESSAGE_CLASS_DECLARATION
public:
const BeamSteeringCWModSettings& getSettings() const { return m_settings; }
bool getForce() const { return m_force; }
static MsgConfigureBeamSteeringCWModBaseband* create(const BeamSteeringCWModSettings& settings, bool force)
{
return new MsgConfigureBeamSteeringCWModBaseband(settings, force);
}
private:
BeamSteeringCWModSettings m_settings;
bool m_force;
MsgConfigureBeamSteeringCWModBaseband(const BeamSteeringCWModSettings& settings, bool force) :
Message(),
m_settings(settings),
m_force(force)
{ }
};
class MsgSignalNotification : public Message {
MESSAGE_CLASS_DECLARATION
public:
int getBasebandSampleRate() const { return m_basebandSampleRate; }
static MsgSignalNotification* create(int basebandSampleRate) {
return new MsgSignalNotification(basebandSampleRate);
}
private:
int m_basebandSampleRate;
MsgSignalNotification(int basebandSampleRate) :
Message(),
m_basebandSampleRate(basebandSampleRate)
{ }
};
BeamSteeringCWModBaseband();
~BeamSteeringCWModBaseband();
void reset();
MessageQueue *getInputMessageQueue() { return &m_inputMessageQueue; } //!< Get the queue for asynchronous inbound communication
void pull(SampleVector::iterator& begin, unsigned int nbSamples, unsigned int streamIndex);
private:
void processFifo(std::vector<SampleVector>& data, unsigned int ibegin, unsigned int iend);
bool handleMessage(const Message& cmd);
void applySettings(const BeamSteeringCWModSettings& settings, bool force = false);
BeamSteeringCWModSettings m_settings;
SampleMOFifo m_sampleMOFifo;
std::vector<SampleVector::iterator> m_vbegin;
int m_sizes[2];
UpChannelizer *m_channelizers[2];
BeamSteeringCWModStreamSource m_streamSources[2];
MessageQueue m_inputMessageQueue; //!< Queue for asynchronous inbound communication
QMutex m_mutex;
unsigned int m_lastStream;
private slots:
void handleInputMessages();
void handleData(); //!< Handle data when samples have to be processed
};
#endif // INCLUDE_BEAMSTEERINGCWMODBASEBAND_H

View File

@ -0,0 +1,299 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2019 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 <QLocale>
#include "device/deviceuiset.h"
#include "gui/basicchannelsettingsdialog.h"
#include "dsp/hbfilterchainconverter.h"
#include "maincore.h"
#include "beamsteeringcwmodgui.h"
#include "beamsteeringcwmod.h"
#include "ui_beamsteeringcwmodgui.h"
BeamSteeringCWModGUI* BeamSteeringCWModGUI::create(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, MIMOChannel *mimoChannel)
{
BeamSteeringCWModGUI* gui = new BeamSteeringCWModGUI(pluginAPI, deviceUISet, mimoChannel);
return gui;
}
void BeamSteeringCWModGUI::destroy()
{
delete this;
}
void BeamSteeringCWModGUI::resetToDefaults()
{
m_settings.resetToDefaults();
displaySettings();
applySettings(true);
}
QByteArray BeamSteeringCWModGUI::serialize() const
{
return m_settings.serialize();
}
bool BeamSteeringCWModGUI::deserialize(const QByteArray& data)
{
if(m_settings.deserialize(data)) {
displaySettings();
applySettings(true);
return true;
} else {
resetToDefaults();
return false;
}
}
bool BeamSteeringCWModGUI::handleMessage(const Message& message)
{
if (BeamSteeringCWMod::MsgBasebandNotification::match(message))
{
BeamSteeringCWMod::MsgBasebandNotification& notif = (BeamSteeringCWMod::MsgBasebandNotification&) message;
m_basebandSampleRate = notif.getSampleRate();
m_centerFrequency = notif.getCenterFrequency();
displayRateAndShift();
return true;
}
else if (BeamSteeringCWMod::MsgConfigureBeamSteeringCWMod::match(message))
{
const BeamSteeringCWMod::MsgConfigureBeamSteeringCWMod& cfg = (BeamSteeringCWMod::MsgConfigureBeamSteeringCWMod&) message;
m_settings = cfg.getSettings();
blockApplySettings(true);
displaySettings();
blockApplySettings(false);
return true;
}
else
{
return false;
}
}
BeamSteeringCWModGUI::BeamSteeringCWModGUI(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, MIMOChannel *mimoChannel, QWidget* parent) :
ChannelGUI(parent),
ui(new Ui::BeamSteeringCWModGUI),
m_pluginAPI(pluginAPI),
m_deviceUISet(deviceUISet),
m_basebandSampleRate(48000),
m_centerFrequency(435000000),
m_tickCount(0)
{
ui->setupUi(this);
setAttribute(Qt::WA_DeleteOnClose, true);
setStreamIndicator("M");
connect(this, SIGNAL(widgetRolled(QWidget*,bool)), this, SLOT(onWidgetRolled(QWidget*,bool)));
connect(this, SIGNAL(customContextMenuRequested(const QPoint &)), this, SLOT(onMenuDialogCalled(const QPoint &)));
m_bsCWSource = (BeamSteeringCWMod*) mimoChannel;
m_bsCWSource->setMessageQueueToGUI(getInputMessageQueue());
m_basebandSampleRate = m_bsCWSource->getBasebandSampleRate();
connect(&MainCore::instance()->getMasterTimer(), SIGNAL(timeout()), this, SLOT(tick()));
m_channelMarker.blockSignals(true);
m_channelMarker.addStreamIndex(1);
m_channelMarker.setColor(m_settings.m_rgbColor);
m_channelMarker.setCenterFrequency(0);
m_channelMarker.setTitle("Beam Steering CW Source");
m_channelMarker.setSourceOrSinkStream(false);
m_channelMarker.blockSignals(false);
m_channelMarker.setVisible(true); // activate signal on the last setting only
m_settings.setChannelMarker(&m_channelMarker);
m_deviceUISet->addChannelMarker(&m_channelMarker);
m_deviceUISet->addRollupWidget(this);
connect(getInputMessageQueue(), SIGNAL(messageEnqueued()), this, SLOT(handleSourceMessages()));
displaySettings();
displayRateAndShift();
applySettings(true);
}
BeamSteeringCWModGUI::~BeamSteeringCWModGUI()
{
delete ui;
}
void BeamSteeringCWModGUI::blockApplySettings(bool block)
{
m_doApplySettings = !block;
}
void BeamSteeringCWModGUI::applySettings(bool force)
{
if (m_doApplySettings)
{
setTitleColor(m_channelMarker.getColor());
BeamSteeringCWMod::MsgConfigureBeamSteeringCWMod* message = BeamSteeringCWMod::MsgConfigureBeamSteeringCWMod::create(m_settings, force);
m_bsCWSource->getInputMessageQueue()->push(message);
}
}
void BeamSteeringCWModGUI::displaySettings()
{
m_channelMarker.blockSignals(true);
m_channelMarker.setCenterFrequency(0);
m_channelMarker.setTitle(m_settings.m_title);
m_channelMarker.setBandwidth(m_basebandSampleRate);
m_channelMarker.setMovable(false); // do not let user move the center arbitrarily
m_channelMarker.blockSignals(false);
m_channelMarker.setColor(m_settings.m_rgbColor); // activate signal on the last setting only
setTitleColor(m_settings.m_rgbColor);
setWindowTitle(m_channelMarker.getTitle());
blockApplySettings(true);
ui->interpolationFactor->setCurrentIndex(m_settings.m_log2Interp);
applyInterpolation();
ui->steeringDegreesText->setText(tr("%1").arg(m_settings.m_steerDegrees));
blockApplySettings(false);
}
void BeamSteeringCWModGUI::displayRateAndShift()
{
int shift = m_shiftFrequencyFactor * m_basebandSampleRate;
double channelSampleRate = ((double) m_basebandSampleRate) / (1<<m_settings.m_log2Interp);
QLocale loc;
ui->offsetFrequencyText->setText(tr("%1 Hz").arg(loc.toString(shift)));
ui->channelRateText->setText(tr("%1k").arg(QString::number(channelSampleRate / 1000.0, 'g', 5)));
m_channelMarker.setCenterFrequency(shift);
m_channelMarker.setBandwidth(channelSampleRate);
}
void BeamSteeringCWModGUI::leaveEvent(QEvent*)
{
m_channelMarker.setHighlighted(false);
}
void BeamSteeringCWModGUI::enterEvent(QEvent*)
{
m_channelMarker.setHighlighted(true);
}
void BeamSteeringCWModGUI::handleSourceMessages()
{
Message* message;
while ((message = getInputMessageQueue()->pop()) != 0)
{
if (handleMessage(*message))
{
delete message;
}
}
}
void BeamSteeringCWModGUI::onWidgetRolled(QWidget* widget, bool rollDown)
{
(void) widget;
(void) rollDown;
}
void BeamSteeringCWModGUI::onMenuDialogCalled(const QPoint &p)
{
if (m_contextMenuType == ContextMenuChannelSettings)
{
BasicChannelSettingsDialog dialog(&m_channelMarker, this);
dialog.setUseReverseAPI(m_settings.m_useReverseAPI);
dialog.setReverseAPIAddress(m_settings.m_reverseAPIAddress);
dialog.setReverseAPIPort(m_settings.m_reverseAPIPort);
dialog.setReverseAPIDeviceIndex(m_settings.m_reverseAPIDeviceIndex);
dialog.setReverseAPIChannelIndex(m_settings.m_reverseAPIChannelIndex);
dialog.move(p);
dialog.exec();
m_settings.m_rgbColor = m_channelMarker.getColor().rgb();
m_settings.m_title = m_channelMarker.getTitle();
m_settings.m_useReverseAPI = dialog.useReverseAPI();
m_settings.m_reverseAPIAddress = dialog.getReverseAPIAddress();
m_settings.m_reverseAPIPort = dialog.getReverseAPIPort();
m_settings.m_reverseAPIDeviceIndex = dialog.getReverseAPIDeviceIndex();
m_settings.m_reverseAPIChannelIndex = dialog.getReverseAPIChannelIndex();
setWindowTitle(m_settings.m_title);
setTitleColor(m_settings.m_rgbColor);
applySettings();
}
resetContextMenuType();
}
void BeamSteeringCWModGUI::on_channelOutput_currentIndexChanged(int index)
{
m_settings.m_channelOutput = index;
applySettings();
}
void BeamSteeringCWModGUI::on_interpolationFactor_currentIndexChanged(int index)
{
m_settings.m_log2Interp = index;
applyInterpolation();
}
void BeamSteeringCWModGUI::on_position_valueChanged(int value)
{
m_settings.m_filterChainHash = value;
applyPosition();
}
void BeamSteeringCWModGUI::on_steeringDegrees_valueChanged(int value)
{
m_settings.m_steerDegrees = value;
ui->steeringDegreesText->setText(tr("%1").arg(m_settings.m_steerDegrees));
applySettings();
}
void BeamSteeringCWModGUI::applyInterpolation()
{
uint32_t maxHash = 1;
for (uint32_t i = 0; i < m_settings.m_log2Interp; i++) {
maxHash *= 3;
}
ui->position->setMaximum(maxHash-1);
ui->position->setValue(m_settings.m_filterChainHash);
m_settings.m_filterChainHash = ui->position->value();
applyPosition();
}
void BeamSteeringCWModGUI::applyPosition()
{
ui->filterChainIndex->setText(tr("%1").arg(m_settings.m_filterChainHash));
QString s;
m_shiftFrequencyFactor = HBFilterChainConverter::convertToString(m_settings.m_log2Interp, m_settings.m_filterChainHash, s);
ui->filterChainText->setText(s);
displayRateAndShift();
applySettings();
}
void BeamSteeringCWModGUI::tick()
{
if (++m_tickCount == 20) { // once per second
m_tickCount = 0;
}
}

View File

@ -0,0 +1,95 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2019 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_BEAMSTEERINGCWMODGUI_H_
#define INCLUDE_BEAMSTEERINGCWMODGUI_H_
#include <stdint.h>
#include <QObject>
#include "dsp/channelmarker.h"
#include "channel/channelgui.h"
#include "util/messagequeue.h"
#include "beamsteeringcwmodsettings.h"
class PluginAPI;
class DeviceUISet;
class BeamSteeringCWMod;
class MIMOChannel;
namespace Ui {
class BeamSteeringCWModGUI;
}
class BeamSteeringCWModGUI : public ChannelGUI {
Q_OBJECT
public:
static BeamSteeringCWModGUI* create(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, MIMOChannel *mimoChannel);
virtual void destroy();
virtual void resetToDefaults();
QByteArray serialize() const;
bool deserialize(const QByteArray& data);
virtual MessageQueue *getInputMessageQueue() { return &m_inputMessageQueue; }
private:
Ui::BeamSteeringCWModGUI* ui;
PluginAPI* m_pluginAPI;
DeviceUISet* m_deviceUISet;
ChannelMarker m_channelMarker;
BeamSteeringCWModSettings m_settings;
int m_basebandSampleRate;
qint64 m_centerFrequency;
double m_shiftFrequencyFactor; //!< Channel frequency shift factor
bool m_doApplySettings;
BeamSteeringCWMod* m_bsCWSource;
MessageQueue m_inputMessageQueue;
uint32_t m_tickCount;
explicit BeamSteeringCWModGUI(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, MIMOChannel *mimoChannel, QWidget* parent = nullptr);
virtual ~BeamSteeringCWModGUI();
void blockApplySettings(bool block);
void applySettings(bool force = false);
void displaySettings();
void displayRateAndShift();
bool handleMessage(const Message& message);
void leaveEvent(QEvent*);
void enterEvent(QEvent*);
void applyInterpolation();
void applyPosition();
private slots:
void handleSourceMessages();
void on_channelOutput_currentIndexChanged(int index);
void on_interpolationFactor_currentIndexChanged(int index);
void on_position_valueChanged(int value);
void on_steeringDegrees_valueChanged(int value);
void onWidgetRolled(QWidget* widget, bool rollDown);
void onMenuDialogCalled(const QPoint& p);
void tick();
};
#endif /* INCLUDE_BEAMSTEERINGCWSOURCEGUI_H_ */

View File

@ -0,0 +1,342 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>BeamSteeringCWModGUI</class>
<widget class="RollupWidget" name="BeamSteeringCWModGUI">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>320</width>
<height>102</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>320</width>
<height>100</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>320</width>
<height>16777215</height>
</size>
</property>
<property name="font">
<font>
<family>Liberation Sans</family>
<pointsize>9</pointsize>
</font>
</property>
<property name="windowTitle">
<string>Beam steering CW source</string>
</property>
<property name="statusTip">
<string>Beam steering CW source</string>
</property>
<widget class="QWidget" name="settingsContainer" native="true">
<property name="geometry">
<rect>
<x>10</x>
<y>10</y>
<width>301</width>
<height>91</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="QVBoxLayout" name="decimationLayer">
<property name="spacing">
<number>3</number>
</property>
<item>
<layout class="QHBoxLayout" name="decimationStageLayer">
<item>
<widget class="QComboBox" name="channelOutput">
<property name="toolTip">
<string>Channel output</string>
</property>
<item>
<property name="text">
<string>A,B</string>
</property>
</item>
<item>
<property name="text">
<string>A</string>
</property>
</item>
<item>
<property name="text">
<string>B</string>
</property>
</item>
</widget>
</item>
<item>
<widget class="QLabel" name="interpolationLabel">
<property name="text">
<string>Int</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="interpolationFactor">
<property name="maximumSize">
<size>
<width>55</width>
<height>16777215</height>
</size>
</property>
<property name="toolTip">
<string>Decimation factor</string>
</property>
<item>
<property name="text">
<string>1</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>8</string>
</property>
</item>
<item>
<property name="text">
<string>16</string>
</property>
</item>
<item>
<property name="text">
<string>32</string>
</property>
</item>
<item>
<property name="text">
<string>64</string>
</property>
</item>
</widget>
</item>
<item>
<widget class="QLabel" name="channelRateText">
<property name="minimumSize">
<size>
<width>50</width>
<height>0</height>
</size>
</property>
<property name="toolTip">
<string>Effective channel rate (kS/s)</string>
</property>
<property name="text">
<string>0000k</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="filterChainText">
<property name="minimumSize">
<size>
<width>50</width>
<height>0</height>
</size>
</property>
<property name="toolTip">
<string>Filter chain stages left to right (L: low, C: center, H: high) </string>
</property>
<property name="text">
<string>LLLLLL</string>
</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>
<item>
<widget class="QLabel" name="offsetFrequencyText">
<property name="minimumSize">
<size>
<width>85</width>
<height>0</height>
</size>
</property>
<property name="toolTip">
<string>Offset frequency with thousands separator (Hz)</string>
</property>
<property name="text">
<string>-9,999,999 Hz</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="decimationShiftLayer">
<property name="rightMargin">
<number>10</number>
</property>
<item>
<widget class="QLabel" name="positionLabel">
<property name="text">
<string>Pos</string>
</property>
</widget>
</item>
<item>
<widget class="QSlider" name="position">
<property name="toolTip">
<string>Center frequency position</string>
</property>
<property name="maximum">
<number>2</number>
</property>
<property name="pageStep">
<number>1</number>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="filterChainIndex">
<property name="minimumSize">
<size>
<width>24</width>
<height>0</height>
</size>
</property>
<property name="toolTip">
<string>Filter chain hash code</string>
</property>
<property name="text">
<string>000</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="steeringDegreesLabel">
<property name="text">
<string>Steer</string>
</property>
</widget>
</item>
<item>
<widget class="QSlider" name="steeringDegrees">
<property name="toolTip">
<string>Steering angle vs antennas axis</string>
</property>
<property name="minimum">
<number>0</number>
</property>
<property name="maximum">
<number>180</number>
</property>
<property name="pageStep">
<number>1</number>
</property>
<property name="value">
<number>90</number>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="steeringDegreesText">
<property name="minimumSize">
<size>
<width>25</width>
<height>0</height>
</size>
</property>
<property name="toolTip">
<string>Steering angle vs antennas axis in degrees</string>
</property>
<property name="text">
<string>180</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</item>
</layout>
</widget>
</widget>
<customwidgets>
<customwidget>
<class>RollupWidget</class>
<extends>QWidget</extends>
<header>gui/rollupwidget.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources>
<include location="../../../sdrgui/resources/res.qrc"/>
</resources>
<connections/>
</ui>

View File

@ -0,0 +1,91 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2019 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 "beamsteeringcwmodgui.h"
#endif
#include "beamsteeringcwmod.h"
#include "beamsteeringcwmodwebapiadapter.h"
#include "beamsteeringcwmodplugin.h"
const PluginDescriptor BeamSteeringCWModPlugin::m_pluginDescriptor = {
QString(BeamSteeringCWMod::m_channelId),
QString("BeamSteeringCWMod"),
QString("5.13.0"),
QString("(c) Edouard Griffiths, F4EXB"),
QString("https://github.com/f4exb/sdrangel"),
true,
QString("https://github.com/f4exb/sdrangel")
};
BeamSteeringCWModPlugin::BeamSteeringCWModPlugin(QObject* parent) :
QObject(parent),
m_pluginAPI(nullptr)
{
}
const PluginDescriptor& BeamSteeringCWModPlugin::getPluginDescriptor() const
{
return m_pluginDescriptor;
}
void BeamSteeringCWModPlugin::initPlugin(PluginAPI* pluginAPI)
{
m_pluginAPI = pluginAPI;
// register channel MIMO
m_pluginAPI->registerMIMOChannel(BeamSteeringCWMod::m_channelIdURI, BeamSteeringCWMod::m_channelId, this);
}
void BeamSteeringCWModPlugin::createMIMOChannel(DeviceAPI *deviceAPI, MIMOChannel **bs, ChannelAPI **cs) const
{
if (bs || cs)
{
BeamSteeringCWMod *instance = new BeamSteeringCWMod(deviceAPI);
if (bs) {
*bs = instance;
}
if (cs) {
*cs = instance;
}
}
}
#ifdef SERVER_MODE
ChannelGUI* BeamSteeringCWModPlugin::createMIMOChannelGUI(
DeviceUISet *deviceUISet,
MIMOChannel *mimoChannel) const
{
return nullptr;
}
#else
ChannelGUI* BeamSteeringCWModPlugin::createMIMOChannelGUI(DeviceUISet *deviceUISet, MIMOChannel *mimoChannel) const
{
return BeamSteeringCWModGUI::create(m_pluginAPI, deviceUISet, mimoChannel);
}
#endif
ChannelWebAPIAdapter* BeamSteeringCWModPlugin::createChannelWebAPIAdapter() const
{
return new BeamSteeringCWModWebAPIAdapter();
}

View File

@ -0,0 +1,49 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2019 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_BEAMSTEERINGCWMODPLUGIN_H_
#define INCLUDE_BEAMSTEERINGCWMODPLUGIN_H_
#include <QObject>
#include "plugin/plugininterface.h"
class DeviceUISet;
class MIMOChannel;
class BeamSteeringCWModPlugin : public QObject, PluginInterface {
Q_OBJECT
Q_INTERFACES(PluginInterface)
Q_PLUGIN_METADATA(IID "sdrangel.channelmimo.beamsteeringcwmod")
public:
explicit BeamSteeringCWModPlugin(QObject* parent = nullptr);
const PluginDescriptor& getPluginDescriptor() const;
void initPlugin(PluginAPI* pluginAPI);
virtual void createMIMOChannel(DeviceAPI *deviceAPI, MIMOChannel **bs, ChannelAPI **cs) const;
virtual ChannelGUI* createMIMOChannelGUI(DeviceUISet *deviceUISet, MIMOChannel *mimoChannel) const;
virtual ChannelWebAPIAdapter* createChannelWebAPIAdapter() const;
private:
static const PluginDescriptor m_pluginDescriptor;
PluginAPI* m_pluginAPI;
};
#endif /* INCLUDE_BEAMSTEERINGCWMODPLUGIN_H_ */

View File

@ -0,0 +1,117 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2019 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 "beamsteeringcwmodsettings.h"
#include <QColor>
#include "util/simpleserializer.h"
#include "settings/serializable.h"
BeamSteeringCWModSettings::BeamSteeringCWModSettings()
{
resetToDefaults();
}
void BeamSteeringCWModSettings::resetToDefaults()
{
m_steerDegrees = 90;
m_rgbColor = QColor(140, 4, 4).rgb();
m_title = "Beam Steering CW Modulator";
m_log2Interp = 0;
m_filterChainHash = 0;
m_channelOutput = 0;
m_channelMarker = nullptr;
m_useReverseAPI = false;
m_reverseAPIAddress = "127.0.0.1";
m_reverseAPIPort = 8888;
m_reverseAPIDeviceIndex = 0;
m_reverseAPIChannelIndex = 0;
}
QByteArray BeamSteeringCWModSettings::serialize() const
{
SimpleSerializer s(1);
s.writeS32(1, m_steerDegrees);
s.writeU32(5, m_rgbColor);
s.writeString(6, m_title);
s.writeBool(7, m_useReverseAPI);
s.writeString(8, m_reverseAPIAddress);
s.writeU32(9, m_reverseAPIPort);
s.writeU32(10, m_reverseAPIDeviceIndex);
s.writeU32(11, m_reverseAPIChannelIndex);
s.writeU32(12, m_log2Interp);
s.writeU32(13, m_filterChainHash);
s.writeS32(14, m_channelOutput);
return s.final();
}
bool BeamSteeringCWModSettings::deserialize(const QByteArray& data)
{
SimpleDeserializer d(data);
if(!d.isValid())
{
resetToDefaults();
return false;
}
if(d.getVersion() == 1)
{
uint32_t tmp;
int stmp;
QString strtmp;
d.readS32(1, &stmp, 90);
m_steerDegrees = stmp < 0 ? -0 : stmp > 180 ? 180 : stmp;
d.readU32(5, &m_rgbColor, QColor(0, 255, 255).rgb());
d.readString(6, &m_title, "Local sink");
d.readBool(7, &m_useReverseAPI, false);
d.readString(8, &m_reverseAPIAddress, "127.0.0.1");
d.readU32(9, &tmp, 0);
if ((tmp > 1023) && (tmp < 65535)) {
m_reverseAPIPort = tmp;
} else {
m_reverseAPIPort = 8888;
}
d.readU32(10, &tmp, 0);
m_reverseAPIDeviceIndex = tmp > 99 ? 99 : tmp;
d.readU32(11, &tmp, 0);
m_reverseAPIChannelIndex = tmp > 99 ? 99 : tmp;
d.readU32(12, &tmp, 0);
m_log2Interp = tmp > 6 ? 6 : tmp;
d.readU32(13, &m_filterChainHash, 0);
d.readS32(14, &stmp, 0);
m_channelOutput = tmp < 0 ? 0 : tmp > 2 ? 2 : tmp;
return true;
}
else
{
resetToDefaults();
return false;
}
}

View File

@ -0,0 +1,49 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2019 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_BEAMSTEERINGCWMODSETTINGS_H_
#define INCLUDE_BEAMSTEERINGCWMODSETTINGS_H_
#include <QByteArray>
#include <QString>
class Serializable;
struct BeamSteeringCWModSettings
{
int m_steerDegrees;
quint32 m_rgbColor;
QString m_title;
uint32_t m_log2Interp;
uint32_t m_filterChainHash;
int m_channelOutput; //!< 0: 1&2, 1: 1, 2: 2
bool m_useReverseAPI;
QString m_reverseAPIAddress;
uint16_t m_reverseAPIPort;
uint16_t m_reverseAPIDeviceIndex;
uint16_t m_reverseAPIChannelIndex;
Serializable *m_channelMarker;
BeamSteeringCWModSettings();
void resetToDefaults();
void setChannelMarker(Serializable *channelMarker) { m_channelMarker = channelMarker; }
QByteArray serialize() const;
bool deserialize(const QByteArray& data);
};
#endif /* INCLUDE_BEAMSTEERINGCWMODSETTINGS_H_ */

View File

@ -0,0 +1,67 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2019 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 <cmath>
#include "dsp/dsptypes.h"
#include "beamsteeringcwmodstreamsource.h"
BeamSteeringCWModStreamSource::BeamSteeringCWModStreamSource() :
m_amp(SDR_TX_SCALEF/sqrt(2.0f)),
m_phase(0)
{
m_real = m_amp;
m_imag = 0.0f;
}
BeamSteeringCWModStreamSource::~BeamSteeringCWModStreamSource()
{}
void BeamSteeringCWModStreamSource::muteChannel(bool mute)
{
if (mute)
{
m_real = 0;
m_imag = 0;
}
else
{
setPhase(m_phase);
}
}
void BeamSteeringCWModStreamSource::setPhase(float phase)
{
float normPhase = phase < -M_PI ? -M_PI : phase > M_PI ? M_PI : phase;
m_real = m_amp * cos(normPhase);
m_imag = m_amp * sin(normPhase);
m_phase = phase;
}
void BeamSteeringCWModStreamSource::pull(SampleVector::iterator begin, unsigned int nbSamples)
{
std::fill(begin, begin + nbSamples, Sample{m_real, m_imag});
}
void BeamSteeringCWModStreamSource::pullOne(Sample& sample)
{
sample.setReal(m_real);
sample.setImag(m_imag);
}
void BeamSteeringCWModStreamSource::reset()
{}

View File

@ -0,0 +1,47 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2019 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_BEAMSTEERINGCWMODSTREAMSOURCE_H
#define INCLUDE_BEAMSTEERINGCWMODSTREAMSOURCE_H
#include "dsp/channelsamplesource.h"
class BeamSteeringCWModStreamSource : public ChannelSampleSource
{
public:
BeamSteeringCWModStreamSource();
virtual ~BeamSteeringCWModStreamSource();
virtual void pull(SampleVector::iterator begin, unsigned int nbSamples);
virtual void pullOne(Sample& sample);
virtual void prefetch(unsigned int nbSamples) {} // prefetching of samples is not implemented
void reset();
void setPhase(float phase);
unsigned int getStreamIndex() const { return m_streamIndex; }
void setStreamIndex(unsigned int streamIndex) { m_streamIndex = streamIndex; }
void muteChannel(bool mute);
private:
unsigned int m_streamIndex;
float m_amp;
float m_phase;
FixReal m_real;
FixReal m_imag;
};
#endif // INCLUDE_BEAMSTEERINGCWMODSTREAMSOURCE_H

View File

@ -0,0 +1,50 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2019 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 "SWGChannelSettings.h"
#include "beamsteeringcwmod.h"
#include "beamsteeringcwmodwebapiadapter.h"
BeamSteeringCWModWebAPIAdapter::BeamSteeringCWModWebAPIAdapter()
{}
BeamSteeringCWModWebAPIAdapter::~BeamSteeringCWModWebAPIAdapter()
{}
int BeamSteeringCWModWebAPIAdapter::webapiSettingsGet(
SWGSDRangel::SWGChannelSettings& response,
QString& errorMessage)
{
(void) errorMessage;
response.setBeamSteeringCwModSettings(new SWGSDRangel::SWGBeamSteeringCWModSettings());
response.getBeamSteeringCwModSettings()->init();
BeamSteeringCWMod::webapiFormatChannelSettings(response, m_settings);
return 200;
}
int BeamSteeringCWModWebAPIAdapter::webapiSettingsPutPatch(
bool force,
const QStringList& channelSettingsKeys,
SWGSDRangel::SWGChannelSettings& response,
QString& errorMessage)
{
(void) errorMessage;
BeamSteeringCWMod::webapiUpdateChannelSettings(m_settings, channelSettingsKeys, response);
return 200;
}

View File

@ -0,0 +1,49 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2019 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_BEAMSTEERINGCWMO_WEBAPIADAPTER_H
#define INCLUDE_BEAMSTEERINGCWMO_WEBAPIADAPTER_H
#include "channel/channelwebapiadapter.h"
#include "beamsteeringcwmodsettings.h"
/**
* Standalone API adapter only for the settings
*/
class BeamSteeringCWModWebAPIAdapter : public ChannelWebAPIAdapter {
public:
BeamSteeringCWModWebAPIAdapter();
virtual ~BeamSteeringCWModWebAPIAdapter();
virtual QByteArray serialize() const { return m_settings.serialize(); }
virtual bool deserialize(const QByteArray& data) { return m_settings.deserialize(data); }
virtual int webapiSettingsGet(
SWGSDRangel::SWGChannelSettings& response,
QString& errorMessage);
virtual int webapiSettingsPutPatch(
bool force,
const QStringList& channelSettingsKeys,
SWGSDRangel::SWGChannelSettings& response,
QString& errorMessage);
private:
BeamSteeringCWModSettings m_settings;
};
#endif // INCLUDE_BEAMSTEERINGCWMO_WEBAPIADAPTER_H

View File

@ -0,0 +1,56 @@
<h1>Beam Steering Continuous Wave plugin</h1>
<h2>Introduction</h2>
This is a v5 only plugin.
This MIMO transmission only (MO) plugin can be used to drive a 2 channel MO device in order to produce a continuous wave signal (CW) with a control of hte phase between the two streams. When the MO device is connected to a two antenna system the resulting beam can be steered in direction using the phase difference. Control is made directly in angle units.
; This was designed more as a proof of concept of multiple output plugin rather than something really useful.
<h2>Interface</h2>
![Beam steering CW plugin GUI](../../../doc/img/BeamsteeringCWMod_plugin.png)
<h3>1: Channel output</h3>
The two channels A and B are connected to device output streams 0 and 1 respectively. The device must expose these channels.
Use this combo box to select channel output:
- **A,B**: output A and B channels
- **A**: output A channel only
- **B**: output B channel only
<h3>2: Interpolation factor</h2>
The channel sample rate is interpolated by a power of two to feed the channels at baseband sample rate.
<h3>3: Channel sample rate</h2>
This is the channel sample rate in kilo or mega samples per second indicated by the `k` or `M` letter.
<h3>4: Half-band filter chain sequence display</h3>
This string represents the sequence of half-band filters used in the interpolation from channel to device baseband. Each character represents a filter type:
- **L**: lower half-band
- **H**: higher half-band
- **C**: centered
<h3>5: Center frequency shift</h3>
This is the shift of the channel center frequency from the device center frequency. Its value is driven by the baseband sample rate, the interpolation factor (2) and the filter chain sequence (4).
<h3>6: Half-band filter chain sequence adjust</h3>
The slider moves the channel center frequency roughly from the lower to the higher frequency in the device baseband. The number on the right represents the filter sequence as the decimal value of a base 3 number. Each base 3 digit represents the filter type and its sequence from MSB to LSB in the filter chain:
- **0**: lower half-band
- **1**: centered
- **2**: higher half-band
<h3>7: Steering angle</h3>
This slider controls the beam steering angle &theta; in degrees when the configuration of antennas is made like this:
![Beam steering CW plugin GUI](../../../doc/img/beamsteeringcw_angle.png)

View File

@ -10,6 +10,7 @@
<file>webapi/doc/swagger/include/AMMod.yaml</file>
<file>webapi/doc/swagger/include/ATVDemod.yaml</file>
<file>webapi/doc/swagger/include/ATVMod.yaml</file>
<file>webapi/doc/swagger/include/BeamSteeringCWMod.yaml</file>
<file>webapi/doc/swagger/include/BFMDemod.yaml</file>
<file>webapi/doc/swagger/include/BladeRF1.yaml</file>
<file>webapi/doc/swagger/include/BladeRF2.yaml</file>

View File

@ -1771,6 +1771,42 @@ margin-bottom: 20px;
}
},
"description" : "A bandwidth expressed in Hertz (Hz)"
};
defs.BeamSteeringCWModSettings = {
"properties" : {
"steerDegrees" : {
"type" : "integer"
},
"rgbColor" : {
"type" : "integer"
},
"title" : {
"type" : "string"
},
"log2Interp" : {
"type" : "integer"
},
"filterChainHash" : {
"type" : "integer"
},
"useReverseAPI" : {
"type" : "integer",
"description" : "Synchronize with reverse API (1 for yes, 0 for no)"
},
"reverseAPIAddress" : {
"type" : "string"
},
"reverseAPIPort" : {
"type" : "integer"
},
"reverseAPIDeviceIndex" : {
"type" : "integer"
},
"reverseAPIChannelIndex" : {
"type" : "integer"
}
},
"description" : "BeamSteeringCWMod"
};
defs.BladeRF1InputSettings = {
"properties" : {
@ -2548,6 +2584,9 @@ margin-bottom: 20px;
"ATVModSettings" : {
"$ref" : "#/definitions/ATVModSettings"
},
"BeamSteeringCWModSettings" : {
"$ref" : "#/definitions/BeamSteeringCWModSettings"
},
"BFMDemodSettings" : {
"$ref" : "#/definitions/BFMDemodSettings"
},
@ -41110,7 +41149,7 @@ except ApiException as e:
</div>
<div id="generator">
<div class="content">
Generated 2020-11-10T19:50:40.958+01:00
Generated 2020-11-10T21:31:22.328+01:00
</div>
</div>
</div>

View File

@ -0,0 +1,24 @@
BeamSteeringCWModSettings:
description: BeamSteeringCWMod
properties:
steerDegrees:
type: integer
rgbColor:
type: integer
title:
type: string
log2Interp:
type: integer
filterChainHash:
type: integer
useReverseAPI:
description: Synchronize with reverse API (1 for yes, 0 for no)
type: integer
reverseAPIAddress:
type: string
reverseAPIPort:
type: integer
reverseAPIDeviceIndex:
type: integer
reverseAPIChannelIndex:
type: integer

View File

@ -27,6 +27,8 @@ ChannelSettings:
$ref: "/doc/swagger/include/ATVDemod.yaml#/ATVDemodSettings"
ATVModSettings:
$ref: "/doc/swagger/include/ATVMod.yaml#/ATVModSettings"
BeamSteeringCWModSettings:
$ref: "/doc/swagger/include/BeamSteeringCWMod.yaml#/BeamSteeringCWModSettings"
BFMDemodSettings:
$ref: "/doc/swagger/include/BFMDemod.yaml#/BFMDemodSettings"
ChannelAnalyzerSettings:

View File

@ -3550,6 +3550,11 @@ bool WebAPIRequestMapper::getChannelSettings(
channelSettings->setAtvModSettings(new SWGSDRangel::SWGATVModSettings());
channelSettings->getAtvModSettings()->fromJsonObject(settingsJsonObject);
}
else if (channelSettingsKey == "BeamSteeringCWModSettings")
{
channelSettings->setBeamSteeringCwModSettings(new SWGSDRangel::SWGBeamSteeringCWModSettings());
channelSettings->getBeamSteeringCwModSettings()->fromJsonObject(settingsJsonObject);
}
else if (channelSettingsKey == "BFMDemodSettings")
{
channelSettings->setBfmDemodSettings(new SWGSDRangel::SWGBFMDemodSettings());

View File

@ -0,0 +1,24 @@
BeamSteeringCWModSettings:
description: BeamSteeringCWMod
properties:
steerDegrees:
type: integer
rgbColor:
type: integer
title:
type: string
log2Interp:
type: integer
filterChainHash:
type: integer
useReverseAPI:
description: Synchronize with reverse API (1 for yes, 0 for no)
type: integer
reverseAPIAddress:
type: string
reverseAPIPort:
type: integer
reverseAPIDeviceIndex:
type: integer
reverseAPIChannelIndex:
type: integer

View File

@ -27,6 +27,8 @@ ChannelSettings:
$ref: "http://swgserver:8081/api/swagger/include/ATVDemod.yaml#/ATVDemodSettings"
ATVModSettings:
$ref: "http://swgserver:8081/api/swagger/include/ATVMod.yaml#/ATVModSettings"
BeamSteeringCWModSettings:
$ref: "http://swgserver:8081/api/swagger/include/BeamSteeringCWMod.yaml#/BeamSteeringCWModSettings"
BFMDemodSettings:
$ref: "http://swgserver:8081/api/swagger/include/BFMDemod.yaml#/BFMDemodSettings"
ChannelAnalyzerSettings:

View File

@ -1771,6 +1771,42 @@ margin-bottom: 20px;
}
},
"description" : "A bandwidth expressed in Hertz (Hz)"
};
defs.BeamSteeringCWModSettings = {
"properties" : {
"steerDegrees" : {
"type" : "integer"
},
"rgbColor" : {
"type" : "integer"
},
"title" : {
"type" : "string"
},
"log2Interp" : {
"type" : "integer"
},
"filterChainHash" : {
"type" : "integer"
},
"useReverseAPI" : {
"type" : "integer",
"description" : "Synchronize with reverse API (1 for yes, 0 for no)"
},
"reverseAPIAddress" : {
"type" : "string"
},
"reverseAPIPort" : {
"type" : "integer"
},
"reverseAPIDeviceIndex" : {
"type" : "integer"
},
"reverseAPIChannelIndex" : {
"type" : "integer"
}
},
"description" : "BeamSteeringCWMod"
};
defs.BladeRF1InputSettings = {
"properties" : {
@ -2548,6 +2584,9 @@ margin-bottom: 20px;
"ATVModSettings" : {
"$ref" : "#/definitions/ATVModSettings"
},
"BeamSteeringCWModSettings" : {
"$ref" : "#/definitions/BeamSteeringCWModSettings"
},
"BFMDemodSettings" : {
"$ref" : "#/definitions/BFMDemodSettings"
},
@ -41110,7 +41149,7 @@ except ApiException as e:
</div>
<div id="generator">
<div class="content">
Generated 2020-11-10T19:50:40.958+01:00
Generated 2020-11-10T21:31:22.328+01:00
</div>
</div>
</div>

View File

@ -0,0 +1,319 @@
/**
* SDRangel
* This is the web REST/JSON API of SDRangel SDR software. SDRangel is an Open Source Qt5/OpenGL 3.0+ (4.3+ in Windows) GUI and server Software Defined Radio and signal analyzer in software. It supports Airspy, BladeRF, HackRF, LimeSDR, PlutoSDR, RTL-SDR, SDRplay RSP1, USRP and FunCube --- Limitations and specifcities: * In SDRangel GUI the first Rx device set cannot be deleted. Conversely the server starts with no device sets and its number of device sets can be reduced to zero by as many calls as necessary to /sdrangel/deviceset with DELETE method. * Preset import and export from/to file is a server only feature. * Device set focus is a GUI only feature. * The following channels are not implemented (status 501 is returned): ATV and DATV demodulators, Channel Analyzer NG, LoRa demodulator * The device settings and report structures contains only the sub-structure corresponding to the device type. The DeviceSettings and DeviceReport structures documented here shows all of them but only one will be or should be present at a time * The channel settings and report structures contains only the sub-structure corresponding to the channel type. The ChannelSettings and ChannelReport structures documented here shows all of them but only one will be or should be present at a time ---
*
* OpenAPI spec version: 4.15.0
* Contact: f4exb06@gmail.com
*
* NOTE: This class is auto generated by the swagger code generator program.
* https://github.com/swagger-api/swagger-codegen.git
* Do not edit the class manually.
*/
#include "SWGBeamSteeringCWModSettings.h"
#include "SWGHelpers.h"
#include <QJsonDocument>
#include <QJsonArray>
#include <QObject>
#include <QDebug>
namespace SWGSDRangel {
SWGBeamSteeringCWModSettings::SWGBeamSteeringCWModSettings(QString* json) {
init();
this->fromJson(*json);
}
SWGBeamSteeringCWModSettings::SWGBeamSteeringCWModSettings() {
steer_degrees = 0;
m_steer_degrees_isSet = false;
rgb_color = 0;
m_rgb_color_isSet = false;
title = nullptr;
m_title_isSet = false;
log2_interp = 0;
m_log2_interp_isSet = false;
filter_chain_hash = 0;
m_filter_chain_hash_isSet = false;
use_reverse_api = 0;
m_use_reverse_api_isSet = false;
reverse_api_address = nullptr;
m_reverse_api_address_isSet = false;
reverse_api_port = 0;
m_reverse_api_port_isSet = false;
reverse_api_device_index = 0;
m_reverse_api_device_index_isSet = false;
reverse_api_channel_index = 0;
m_reverse_api_channel_index_isSet = false;
}
SWGBeamSteeringCWModSettings::~SWGBeamSteeringCWModSettings() {
this->cleanup();
}
void
SWGBeamSteeringCWModSettings::init() {
steer_degrees = 0;
m_steer_degrees_isSet = false;
rgb_color = 0;
m_rgb_color_isSet = false;
title = new QString("");
m_title_isSet = false;
log2_interp = 0;
m_log2_interp_isSet = false;
filter_chain_hash = 0;
m_filter_chain_hash_isSet = false;
use_reverse_api = 0;
m_use_reverse_api_isSet = false;
reverse_api_address = new QString("");
m_reverse_api_address_isSet = false;
reverse_api_port = 0;
m_reverse_api_port_isSet = false;
reverse_api_device_index = 0;
m_reverse_api_device_index_isSet = false;
reverse_api_channel_index = 0;
m_reverse_api_channel_index_isSet = false;
}
void
SWGBeamSteeringCWModSettings::cleanup() {
if(title != nullptr) {
delete title;
}
if(reverse_api_address != nullptr) {
delete reverse_api_address;
}
}
SWGBeamSteeringCWModSettings*
SWGBeamSteeringCWModSettings::fromJson(QString &json) {
QByteArray array (json.toStdString().c_str());
QJsonDocument doc = QJsonDocument::fromJson(array);
QJsonObject jsonObject = doc.object();
this->fromJsonObject(jsonObject);
return this;
}
void
SWGBeamSteeringCWModSettings::fromJsonObject(QJsonObject &pJson) {
::SWGSDRangel::setValue(&steer_degrees, pJson["steerDegrees"], "qint32", "");
::SWGSDRangel::setValue(&rgb_color, pJson["rgbColor"], "qint32", "");
::SWGSDRangel::setValue(&title, pJson["title"], "QString", "QString");
::SWGSDRangel::setValue(&log2_interp, pJson["log2Interp"], "qint32", "");
::SWGSDRangel::setValue(&filter_chain_hash, pJson["filterChainHash"], "qint32", "");
::SWGSDRangel::setValue(&use_reverse_api, pJson["useReverseAPI"], "qint32", "");
::SWGSDRangel::setValue(&reverse_api_address, pJson["reverseAPIAddress"], "QString", "QString");
::SWGSDRangel::setValue(&reverse_api_port, pJson["reverseAPIPort"], "qint32", "");
::SWGSDRangel::setValue(&reverse_api_device_index, pJson["reverseAPIDeviceIndex"], "qint32", "");
::SWGSDRangel::setValue(&reverse_api_channel_index, pJson["reverseAPIChannelIndex"], "qint32", "");
}
QString
SWGBeamSteeringCWModSettings::asJson ()
{
QJsonObject* obj = this->asJsonObject();
QJsonDocument doc(*obj);
QByteArray bytes = doc.toJson();
delete obj;
return QString(bytes);
}
QJsonObject*
SWGBeamSteeringCWModSettings::asJsonObject() {
QJsonObject* obj = new QJsonObject();
if(m_steer_degrees_isSet){
obj->insert("steerDegrees", QJsonValue(steer_degrees));
}
if(m_rgb_color_isSet){
obj->insert("rgbColor", QJsonValue(rgb_color));
}
if(title != nullptr && *title != QString("")){
toJsonValue(QString("title"), title, obj, QString("QString"));
}
if(m_log2_interp_isSet){
obj->insert("log2Interp", QJsonValue(log2_interp));
}
if(m_filter_chain_hash_isSet){
obj->insert("filterChainHash", QJsonValue(filter_chain_hash));
}
if(m_use_reverse_api_isSet){
obj->insert("useReverseAPI", QJsonValue(use_reverse_api));
}
if(reverse_api_address != nullptr && *reverse_api_address != QString("")){
toJsonValue(QString("reverseAPIAddress"), reverse_api_address, obj, QString("QString"));
}
if(m_reverse_api_port_isSet){
obj->insert("reverseAPIPort", QJsonValue(reverse_api_port));
}
if(m_reverse_api_device_index_isSet){
obj->insert("reverseAPIDeviceIndex", QJsonValue(reverse_api_device_index));
}
if(m_reverse_api_channel_index_isSet){
obj->insert("reverseAPIChannelIndex", QJsonValue(reverse_api_channel_index));
}
return obj;
}
qint32
SWGBeamSteeringCWModSettings::getSteerDegrees() {
return steer_degrees;
}
void
SWGBeamSteeringCWModSettings::setSteerDegrees(qint32 steer_degrees) {
this->steer_degrees = steer_degrees;
this->m_steer_degrees_isSet = true;
}
qint32
SWGBeamSteeringCWModSettings::getRgbColor() {
return rgb_color;
}
void
SWGBeamSteeringCWModSettings::setRgbColor(qint32 rgb_color) {
this->rgb_color = rgb_color;
this->m_rgb_color_isSet = true;
}
QString*
SWGBeamSteeringCWModSettings::getTitle() {
return title;
}
void
SWGBeamSteeringCWModSettings::setTitle(QString* title) {
this->title = title;
this->m_title_isSet = true;
}
qint32
SWGBeamSteeringCWModSettings::getLog2Interp() {
return log2_interp;
}
void
SWGBeamSteeringCWModSettings::setLog2Interp(qint32 log2_interp) {
this->log2_interp = log2_interp;
this->m_log2_interp_isSet = true;
}
qint32
SWGBeamSteeringCWModSettings::getFilterChainHash() {
return filter_chain_hash;
}
void
SWGBeamSteeringCWModSettings::setFilterChainHash(qint32 filter_chain_hash) {
this->filter_chain_hash = filter_chain_hash;
this->m_filter_chain_hash_isSet = true;
}
qint32
SWGBeamSteeringCWModSettings::getUseReverseApi() {
return use_reverse_api;
}
void
SWGBeamSteeringCWModSettings::setUseReverseApi(qint32 use_reverse_api) {
this->use_reverse_api = use_reverse_api;
this->m_use_reverse_api_isSet = true;
}
QString*
SWGBeamSteeringCWModSettings::getReverseApiAddress() {
return reverse_api_address;
}
void
SWGBeamSteeringCWModSettings::setReverseApiAddress(QString* reverse_api_address) {
this->reverse_api_address = reverse_api_address;
this->m_reverse_api_address_isSet = true;
}
qint32
SWGBeamSteeringCWModSettings::getReverseApiPort() {
return reverse_api_port;
}
void
SWGBeamSteeringCWModSettings::setReverseApiPort(qint32 reverse_api_port) {
this->reverse_api_port = reverse_api_port;
this->m_reverse_api_port_isSet = true;
}
qint32
SWGBeamSteeringCWModSettings::getReverseApiDeviceIndex() {
return reverse_api_device_index;
}
void
SWGBeamSteeringCWModSettings::setReverseApiDeviceIndex(qint32 reverse_api_device_index) {
this->reverse_api_device_index = reverse_api_device_index;
this->m_reverse_api_device_index_isSet = true;
}
qint32
SWGBeamSteeringCWModSettings::getReverseApiChannelIndex() {
return reverse_api_channel_index;
}
void
SWGBeamSteeringCWModSettings::setReverseApiChannelIndex(qint32 reverse_api_channel_index) {
this->reverse_api_channel_index = reverse_api_channel_index;
this->m_reverse_api_channel_index_isSet = true;
}
bool
SWGBeamSteeringCWModSettings::isSet(){
bool isObjectUpdated = false;
do{
if(m_steer_degrees_isSet){
isObjectUpdated = true; break;
}
if(m_rgb_color_isSet){
isObjectUpdated = true; break;
}
if(title && *title != QString("")){
isObjectUpdated = true; break;
}
if(m_log2_interp_isSet){
isObjectUpdated = true; break;
}
if(m_filter_chain_hash_isSet){
isObjectUpdated = true; break;
}
if(m_use_reverse_api_isSet){
isObjectUpdated = true; break;
}
if(reverse_api_address && *reverse_api_address != QString("")){
isObjectUpdated = true; break;
}
if(m_reverse_api_port_isSet){
isObjectUpdated = true; break;
}
if(m_reverse_api_device_index_isSet){
isObjectUpdated = true; break;
}
if(m_reverse_api_channel_index_isSet){
isObjectUpdated = true; break;
}
}while(false);
return isObjectUpdated;
}
}

View File

@ -0,0 +1,113 @@
/**
* SDRangel
* This is the web REST/JSON API of SDRangel SDR software. SDRangel is an Open Source Qt5/OpenGL 3.0+ (4.3+ in Windows) GUI and server Software Defined Radio and signal analyzer in software. It supports Airspy, BladeRF, HackRF, LimeSDR, PlutoSDR, RTL-SDR, SDRplay RSP1, USRP and FunCube --- Limitations and specifcities: * In SDRangel GUI the first Rx device set cannot be deleted. Conversely the server starts with no device sets and its number of device sets can be reduced to zero by as many calls as necessary to /sdrangel/deviceset with DELETE method. * Preset import and export from/to file is a server only feature. * Device set focus is a GUI only feature. * The following channels are not implemented (status 501 is returned): ATV and DATV demodulators, Channel Analyzer NG, LoRa demodulator * The device settings and report structures contains only the sub-structure corresponding to the device type. The DeviceSettings and DeviceReport structures documented here shows all of them but only one will be or should be present at a time * The channel settings and report structures contains only the sub-structure corresponding to the channel type. The ChannelSettings and ChannelReport structures documented here shows all of them but only one will be or should be present at a time ---
*
* OpenAPI spec version: 4.15.0
* Contact: f4exb06@gmail.com
*
* NOTE: This class is auto generated by the swagger code generator program.
* https://github.com/swagger-api/swagger-codegen.git
* Do not edit the class manually.
*/
/*
* SWGBeamSteeringCWModSettings.h
*
* BeamSteeringCWMod
*/
#ifndef SWGBeamSteeringCWModSettings_H_
#define SWGBeamSteeringCWModSettings_H_
#include <QJsonObject>
#include <QString>
#include "SWGObject.h"
#include "export.h"
namespace SWGSDRangel {
class SWG_API SWGBeamSteeringCWModSettings: public SWGObject {
public:
SWGBeamSteeringCWModSettings();
SWGBeamSteeringCWModSettings(QString* json);
virtual ~SWGBeamSteeringCWModSettings();
void init();
void cleanup();
virtual QString asJson () override;
virtual QJsonObject* asJsonObject() override;
virtual void fromJsonObject(QJsonObject &json) override;
virtual SWGBeamSteeringCWModSettings* fromJson(QString &jsonString) override;
qint32 getSteerDegrees();
void setSteerDegrees(qint32 steer_degrees);
qint32 getRgbColor();
void setRgbColor(qint32 rgb_color);
QString* getTitle();
void setTitle(QString* title);
qint32 getLog2Interp();
void setLog2Interp(qint32 log2_interp);
qint32 getFilterChainHash();
void setFilterChainHash(qint32 filter_chain_hash);
qint32 getUseReverseApi();
void setUseReverseApi(qint32 use_reverse_api);
QString* getReverseApiAddress();
void setReverseApiAddress(QString* reverse_api_address);
qint32 getReverseApiPort();
void setReverseApiPort(qint32 reverse_api_port);
qint32 getReverseApiDeviceIndex();
void setReverseApiDeviceIndex(qint32 reverse_api_device_index);
qint32 getReverseApiChannelIndex();
void setReverseApiChannelIndex(qint32 reverse_api_channel_index);
virtual bool isSet() override;
private:
qint32 steer_degrees;
bool m_steer_degrees_isSet;
qint32 rgb_color;
bool m_rgb_color_isSet;
QString* title;
bool m_title_isSet;
qint32 log2_interp;
bool m_log2_interp_isSet;
qint32 filter_chain_hash;
bool m_filter_chain_hash_isSet;
qint32 use_reverse_api;
bool m_use_reverse_api_isSet;
QString* reverse_api_address;
bool m_reverse_api_address_isSet;
qint32 reverse_api_port;
bool m_reverse_api_port_isSet;
qint32 reverse_api_device_index;
bool m_reverse_api_device_index_isSet;
qint32 reverse_api_channel_index;
bool m_reverse_api_channel_index_isSet;
};
}
#endif /* SWGBeamSteeringCWModSettings_H_ */

View File

@ -46,6 +46,8 @@ SWGChannelSettings::SWGChannelSettings() {
m_atv_demod_settings_isSet = false;
atv_mod_settings = nullptr;
m_atv_mod_settings_isSet = false;
beam_steering_cw_mod_settings = nullptr;
m_beam_steering_cw_mod_settings_isSet = false;
bfm_demod_settings = nullptr;
m_bfm_demod_settings_isSet = false;
channel_analyzer_settings = nullptr;
@ -126,6 +128,8 @@ SWGChannelSettings::init() {
m_atv_demod_settings_isSet = false;
atv_mod_settings = new SWGATVModSettings();
m_atv_mod_settings_isSet = false;
beam_steering_cw_mod_settings = new SWGBeamSteeringCWModSettings();
m_beam_steering_cw_mod_settings_isSet = false;
bfm_demod_settings = new SWGBFMDemodSettings();
m_bfm_demod_settings_isSet = false;
channel_analyzer_settings = new SWGChannelAnalyzerSettings();
@ -205,6 +209,9 @@ SWGChannelSettings::cleanup() {
if(atv_mod_settings != nullptr) {
delete atv_mod_settings;
}
if(beam_steering_cw_mod_settings != nullptr) {
delete beam_steering_cw_mod_settings;
}
if(bfm_demod_settings != nullptr) {
delete bfm_demod_settings;
}
@ -317,6 +324,8 @@ SWGChannelSettings::fromJsonObject(QJsonObject &pJson) {
::SWGSDRangel::setValue(&atv_mod_settings, pJson["ATVModSettings"], "SWGATVModSettings", "SWGATVModSettings");
::SWGSDRangel::setValue(&beam_steering_cw_mod_settings, pJson["BeamSteeringCWModSettings"], "SWGBeamSteeringCWModSettings", "SWGBeamSteeringCWModSettings");
::SWGSDRangel::setValue(&bfm_demod_settings, pJson["BFMDemodSettings"], "SWGBFMDemodSettings", "SWGBFMDemodSettings");
::SWGSDRangel::setValue(&channel_analyzer_settings, pJson["ChannelAnalyzerSettings"], "SWGChannelAnalyzerSettings", "SWGChannelAnalyzerSettings");
@ -414,6 +423,9 @@ SWGChannelSettings::asJsonObject() {
if((atv_mod_settings != nullptr) && (atv_mod_settings->isSet())){
toJsonValue(QString("ATVModSettings"), atv_mod_settings, obj, QString("SWGATVModSettings"));
}
if((beam_steering_cw_mod_settings != nullptr) && (beam_steering_cw_mod_settings->isSet())){
toJsonValue(QString("BeamSteeringCWModSettings"), beam_steering_cw_mod_settings, obj, QString("SWGBeamSteeringCWModSettings"));
}
if((bfm_demod_settings != nullptr) && (bfm_demod_settings->isSet())){
toJsonValue(QString("BFMDemodSettings"), bfm_demod_settings, obj, QString("SWGBFMDemodSettings"));
}
@ -589,6 +601,16 @@ SWGChannelSettings::setAtvModSettings(SWGATVModSettings* atv_mod_settings) {
this->m_atv_mod_settings_isSet = true;
}
SWGBeamSteeringCWModSettings*
SWGChannelSettings::getBeamSteeringCwModSettings() {
return beam_steering_cw_mod_settings;
}
void
SWGChannelSettings::setBeamSteeringCwModSettings(SWGBeamSteeringCWModSettings* beam_steering_cw_mod_settings) {
this->beam_steering_cw_mod_settings = beam_steering_cw_mod_settings;
this->m_beam_steering_cw_mod_settings_isSet = true;
}
SWGBFMDemodSettings*
SWGChannelSettings::getBfmDemodSettings() {
return bfm_demod_settings;
@ -891,6 +913,9 @@ SWGChannelSettings::isSet(){
if(atv_mod_settings && atv_mod_settings->isSet()){
isObjectUpdated = true; break;
}
if(beam_steering_cw_mod_settings && beam_steering_cw_mod_settings->isSet()){
isObjectUpdated = true; break;
}
if(bfm_demod_settings && bfm_demod_settings->isSet()){
isObjectUpdated = true; break;
}

View File

@ -28,6 +28,7 @@
#include "SWGATVDemodSettings.h"
#include "SWGATVModSettings.h"
#include "SWGBFMDemodSettings.h"
#include "SWGBeamSteeringCWModSettings.h"
#include "SWGChannelAnalyzerSettings.h"
#include "SWGChirpChatDemodSettings.h"
#include "SWGChirpChatModSettings.h"
@ -101,6 +102,9 @@ public:
SWGATVModSettings* getAtvModSettings();
void setAtvModSettings(SWGATVModSettings* atv_mod_settings);
SWGBeamSteeringCWModSettings* getBeamSteeringCwModSettings();
void setBeamSteeringCwModSettings(SWGBeamSteeringCWModSettings* beam_steering_cw_mod_settings);
SWGBFMDemodSettings* getBfmDemodSettings();
void setBfmDemodSettings(SWGBFMDemodSettings* bfm_demod_settings);
@ -213,6 +217,9 @@ private:
SWGATVModSettings* atv_mod_settings;
bool m_atv_mod_settings_isSet;
SWGBeamSteeringCWModSettings* beam_steering_cw_mod_settings;
bool m_beam_steering_cw_mod_settings_isSet;
SWGBFMDemodSettings* bfm_demod_settings;
bool m_bfm_demod_settings_isSet;

View File

@ -41,6 +41,7 @@
#include "SWGBFMDemodReport.h"
#include "SWGBFMDemodSettings.h"
#include "SWGBandwidth.h"
#include "SWGBeamSteeringCWModSettings.h"
#include "SWGBladeRF1InputSettings.h"
#include "SWGBladeRF1OutputSettings.h"
#include "SWGBladeRF2InputReport.h"
@ -307,6 +308,9 @@ namespace SWGSDRangel {
if(QString("SWGBandwidth").compare(type) == 0) {
return new SWGBandwidth();
}
if(QString("SWGBeamSteeringCWModSettings").compare(type) == 0) {
return new SWGBeamSteeringCWModSettings();
}
if(QString("SWGBladeRF1InputSettings").compare(type) == 0) {
return new SWGBladeRF1InputSettings();
}