Add Radio Astronomy plugin

This commit is contained in:
Jon Beniston 2021-10-12 11:31:14 +01:00
parent 05fce637bc
commit fbef25884e
83 changed files with 19095 additions and 112 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 86 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 65 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 75 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 82 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 115 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 141 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 148 KiB

View File

@ -20,6 +20,7 @@ add_subdirectory(demodpacket)
add_subdirectory(demodais)
add_subdirectory(demodpager)
add_subdirectory(radioclock)
add_subdirectory(radioastronomy)
if(DAB_FOUND AND ZLIB_FOUND AND FAAD_FOUND)
add_subdirectory(demoddab)

View File

@ -0,0 +1,67 @@
project(radioastronomy)
set(radioastronomy_SOURCES
radioastronomy.cpp
radioastronomysettings.cpp
radioastronomybaseband.cpp
radioastronomysink.cpp
radioastronomyplugin.cpp
radioastronomywebapiadapter.cpp
radioastronomyworker.cpp
)
set(radioastronomy_HEADERS
radioastronomy.h
radioastronomysettings.h
radioastronomybaseband.h
radioastronomysink.h
radioastronomyplugin.h
radioastronomywebapiadapter.h
radioastronomyworker.h
)
include_directories(
${CMAKE_SOURCE_DIR}/swagger/sdrangel/code/qt5/client
)
if(NOT SERVER_MODE)
set(radioastronomy_SOURCES
${radioastronomy_SOURCES}
radioastronomygui.cpp
radioastronomygui.ui
radioastronomycalibrationdialog.cpp
radioastronomycalibrationdialog.ui
radioastronomysensordialog.cpp
radioastronomysensordialog.ui
icons.qrc
)
set(radioastronomy_HEADERS
${radioastronomy_HEADERS}
radioastronomygui.h
radioastronomycalibrationdialog.h
radioastronomysensordialog.h
)
set(TARGET_NAME radioastronomy)
set(TARGET_LIB "Qt5::Widgets" Qt5::Charts)
set(TARGET_LIB_GUI "sdrgui")
set(INSTALL_FOLDER ${INSTALL_PLUGINS_DIR})
else()
set(TARGET_NAME radioastronomysrv)
set(TARGET_LIB "")
set(TARGET_LIB_GUI "")
set(INSTALL_FOLDER ${INSTALL_PLUGINSSRV_DIR})
endif()
add_library(${TARGET_NAME} SHARED
${radioastronomy_SOURCES}
)
target_link_libraries(${TARGET_NAME}
Qt5::Core
${TARGET_LIB}
sdrbase
${TARGET_LIB_GUI}
)
install(TARGETS ${TARGET_NAME} DESTINATION ${INSTALL_FOLDER})

View File

@ -0,0 +1,16 @@
<RCC>
<qresource prefix="/radioastronomy/">
<file>icons/hot.png</file>
<file>icons/cold.png</file>
<file>icons/temperature.png</file>
<file>icons/reverse.png</file>
<file>icons/gaussian.png</file>
<file>icons/peak.png</file>
<file>icons/marker.png</file>
<file>icons/refline.png</file>
<file>icons/legend.png</file>
<file>icons/lab.png</file>
<file>icons/galactictriangle.png</file>
<file>icons/noise.png</file>
</qresource>
</RCC>

Binary file not shown.

After

Width:  |  Height:  |  Size: 521 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 485 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 539 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 513 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 324 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 265 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 286 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 456 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 443 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 187 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 333 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 391 B

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,437 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2015-2018 Edouard Griffiths, F4EXB. //
// Copyright (C) 2021 Jon Beniston, M7RCE //
// //
// 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_RADIOASTRONOMY_H
#define INCLUDE_RADIOASTRONOMY_H
#include <vector>
#include <QNetworkRequest>
#include <QUdpSocket>
#include <QThread>
#include <QDateTime>
#include <QTimer>
#include "dsp/basebandsamplesink.h"
#include "channel/channelapi.h"
#include "util/message.h"
#include "pipes/pipeendpoint.h"
#include "radioastronomybaseband.h"
#include "radioastronomysettings.h"
class QNetworkAccessManager;
class QNetworkReply;
class QThread;
class DeviceAPI;
class RadioAstronomyWorker;
class RadioAstronomy : public BasebandSampleSink, public ChannelAPI {
Q_OBJECT
public:
class MsgConfigureRadioAstronomy : public Message {
MESSAGE_CLASS_DECLARATION
public:
const RadioAstronomySettings& getSettings() const { return m_settings; }
bool getForce() const { return m_force; }
static MsgConfigureRadioAstronomy* create(const RadioAstronomySettings& settings, bool force)
{
return new MsgConfigureRadioAstronomy(settings, force);
}
private:
RadioAstronomySettings m_settings;
bool m_force;
MsgConfigureRadioAstronomy(const RadioAstronomySettings& settings, bool force) :
Message(),
m_settings(settings),
m_force(force)
{ }
};
class MsgSensorMeasurement : public Message {
MESSAGE_CLASS_DECLARATION
public:
int getSensor() const { return m_sensor; }
double getValue() const { return m_value; }
QDateTime getDateTime() const { return m_dateTime; }
static MsgSensorMeasurement* create(int sensor, double value)
{
return new MsgSensorMeasurement(sensor, value, QDateTime::currentDateTime());
}
private:
int m_sensor;
double m_value;
QDateTime m_dateTime;
MsgSensorMeasurement(int sensor, double value, QDateTime dateTime) :
Message(),
m_sensor(sensor),
m_value(value),
m_dateTime(dateTime)
{
}
};
class MsgFFTMeasurement : public Message {
MESSAGE_CLASS_DECLARATION
public:
Real *getFFT() const { return m_fft; }
int getSize() const { return m_size; }
QDateTime getDateTime() const { return m_dateTime; }
static MsgFFTMeasurement* create(const Real *fft, int size, QDateTime dateTime)
{
return new MsgFFTMeasurement(fft, size, dateTime);
}
private:
Real *m_fft;
int m_size;
QDateTime m_dateTime;
MsgFFTMeasurement(const Real *fft, int size, QDateTime dateTime) :
Message(),
m_size(size),
m_dateTime(dateTime)
{
// Take a copy of the data
m_fft = new Real[size];
std::copy(fft, fft + size, m_fft);
}
};
class MsgStartMeasurements : public Message {
MESSAGE_CLASS_DECLARATION
public:
static MsgStartMeasurements* create()
{
return new MsgStartMeasurements();
}
private:
MsgStartMeasurements() :
Message()
{
}
};
class MsgStopMeasurements : public Message {
MESSAGE_CLASS_DECLARATION
public:
static MsgStopMeasurements* create()
{
return new MsgStopMeasurements();
}
private:
MsgStopMeasurements() :
Message()
{
}
};
class MsgMeasurementProgress : public Message {
MESSAGE_CLASS_DECLARATION
public:
int getPercentComplete() const { return m_percentComplete; }
static MsgMeasurementProgress* create(int percentComplete)
{
return new MsgMeasurementProgress(percentComplete);
}
private:
int m_percentComplete;
MsgMeasurementProgress(int percentComplete) :
Message(),
m_percentComplete(percentComplete)
{
}
};
class MsgStartCal : public Message {
MESSAGE_CLASS_DECLARATION
public:
bool getHot() const { return m_hot; }
static MsgStartCal* create(bool hot)
{
return new MsgStartCal(hot);
}
private:
bool m_hot;
MsgStartCal(bool hot) :
Message(),
m_hot(hot)
{
}
};
class MsgCalComplete : public Message {
MESSAGE_CLASS_DECLARATION
public:
Real *getCal() const { return m_cal; }
int getSize() const { return m_size; }
bool getHot() const { return m_hot; }
QDateTime getDateTime() const { return m_dateTime; }
static MsgCalComplete* create(const Real *cal, int size, QDateTime dateTime, bool hot)
{
return new MsgCalComplete(cal, size, dateTime, hot);
}
private:
Real *m_cal;
int m_size;
QDateTime m_dateTime;
bool m_hot;
MsgCalComplete(const Real *cal, int size, QDateTime dateTime, bool hot) :
Message(),
m_size(size),
m_dateTime(dateTime),
m_hot(hot)
{
// Take a copy of the data
m_cal = new Real[size];
std::copy(cal, cal + size, m_cal);
}
};
class MsgStartSweep : public Message {
MESSAGE_CLASS_DECLARATION
public:
static MsgStartSweep* create()
{
return new MsgStartSweep();
}
private:
MsgStartSweep() :
Message()
{
}
};
class MsgStopSweep : public Message {
MESSAGE_CLASS_DECLARATION
public:
static MsgStopSweep* create()
{
return new MsgStopSweep();
}
private:
MsgStopSweep() :
Message()
{
}
};
class MsgSweepComplete : public Message {
MESSAGE_CLASS_DECLARATION
public:
static MsgSweepComplete* create()
{
return new MsgSweepComplete();
}
private:
MsgSweepComplete() :
Message()
{
}
};
class MsgSweepStatus : public Message {
MESSAGE_CLASS_DECLARATION
public:
QString getStatus() const { return m_status; }
static MsgSweepStatus* create(const QString& status)
{
return new MsgSweepStatus(status);
}
private:
QString m_status;
MsgSweepStatus(const QString& status) :
Message(),
m_status(status)
{
}
};
RadioAstronomy(DeviceAPI *deviceAPI);
virtual ~RadioAstronomy();
virtual void destroy() { delete this; }
using BasebandSampleSink::feed;
virtual void feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end, bool po);
virtual void start();
virtual void stop();
virtual bool handleMessage(const Message& cmd);
virtual void getIdentifier(QString& id) { id = objectName(); }
virtual const QString& getURI() const { return getName(); }
virtual void getTitle(QString& title) { title = m_settings.m_title; }
virtual qint64 getCenterFrequency() const { return 0; }
virtual QByteArray serialize() const;
virtual bool deserialize(const QByteArray& data);
virtual int getNbSinkStreams() const { return 1; }
virtual int getNbSourceStreams() const { return 0; }
virtual qint64 getStreamCenterFrequency(int streamIndex, bool sinkElseSource) const
{
(void) streamIndex;
(void) sinkElseSource;
return 0;
}
virtual int webapiSettingsGet(
SWGSDRangel::SWGChannelSettings& response,
QString& errorMessage) override;
virtual int webapiSettingsPutPatch(
bool force,
const QStringList& channelSettingsKeys,
SWGSDRangel::SWGChannelSettings& response,
QString& errorMessage) override;
virtual int webapiActionsPost(
const QStringList& channelActionsKeys,
SWGSDRangel::SWGChannelActions& query,
QString& errorMessage) override;
static void webapiFormatChannelSettings(
SWGSDRangel::SWGChannelSettings& response,
const RadioAstronomySettings& settings);
static void webapiUpdateChannelSettings(
RadioAstronomySettings& settings,
const QStringList& channelSettingsKeys,
SWGSDRangel::SWGChannelSettings& response);
double getMagSq() const { return m_basebandSink->getMagSq(); }
void getMagSqLevels(double& avg, double& peak, int& nbSamples) {
m_basebandSink->getMagSqLevels(avg, peak, nbSamples);
}
/* void setMessageQueueToGUI(MessageQueue* queue) override {
ChannelAPI::setMessageQueueToGUI(queue);
m_basebandSink->setMessageQueueToGUI(queue);
}*/
uint32_t getNumberOfDeviceStreams() const;
static const char * const m_channelIdURI;
static const char * const m_channelId;
private:
DeviceAPI *m_deviceAPI;
QThread m_thread;
QThread m_workerThread;
RadioAstronomyBaseband* m_basebandSink;
RadioAstronomyWorker *m_worker;
RadioAstronomySettings m_settings;
int m_basebandSampleRate; //!< stored from device message used when starting baseband sink
qint64 m_centerFrequency;
QList<AvailablePipeSource> m_availablePipes;
PipeEndPoint *m_selectedPipe;
QTimer m_updatePipesTimer;
QNetworkAccessManager *m_networkManager;
QNetworkRequest m_networkRequest;
int m_starTrackerFeatureSetIndex;
int m_starTrackerFeatureIndex;
int m_rotatorFeatureSetIndex;
int m_rotatorFeatureIndex;
void (*sweepState)();
float m_sweep1; // Current sweep position
float m_sweep2;
float m_sweep1Stop;
float m_sweep1Start;
bool m_sweeping;
bool m_sweepStop;
QTimer m_sweepTimer;
QMetaObject::Connection m_sweepTimerConnection;
void applySettings(const RadioAstronomySettings& settings, bool force = false);
void webapiReverseSendSettings(QList<QString>& channelSettingsKeys, const RadioAstronomySettings& settings, bool force);
void webapiFormatChannelSettings(
QList<QString>& channelSettingsKeys,
SWGSDRangel::SWGChannelSettings *swgChannelSettings,
const RadioAstronomySettings& settings,
bool force
);
void callOnStartTime(void (RadioAstronomy::*f)());
void sweepStart();
void startCal(bool hot);
void calComplete(MsgCalComplete* report);
private slots:
void networkManagerFinished(QNetworkReply *reply);
void updatePipes();
void handleChannelMessages();
void startMeasurement();
void sweepStartMeasurement();
void sweep1();
void sweep2();
void waitUntilOnTarget();
void sweepNext();
void sweepComplete();
};
#endif // INCLUDE_RADIOASTRONOMY_H

View File

@ -0,0 +1,197 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2019 Edouard Griffiths, F4EXB //
// Copyright (C) 2021 Jon Beniston, M7RCE //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation as version 3 of the License, or //
// (at your option) any later version. //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License V3 for more details. //
// //
// You should have received a copy of the GNU General Public License //
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#include <QDebug>
#include "dsp/dspengine.h"
#include "dsp/dspcommands.h"
#include "dsp/downchannelizer.h"
#include "radioastronomybaseband.h"
#include "radioastronomy.h"
MESSAGE_CLASS_DEFINITION(RadioAstronomyBaseband::MsgConfigureRadioAstronomyBaseband, Message)
RadioAstronomyBaseband::RadioAstronomyBaseband(RadioAstronomy *aisDemod) :
m_sink(aisDemod),
m_running(false),
m_mutex(QMutex::Recursive)
{
qDebug("RadioAstronomyBaseband::RadioAstronomyBaseband");
m_sampleFifo.setSize(SampleSinkFifo::getSizePolicy(48000));
m_channelizer = new DownChannelizer(&m_sink);
}
RadioAstronomyBaseband::~RadioAstronomyBaseband()
{
m_inputMessageQueue.clear();
delete m_channelizer;
}
void RadioAstronomyBaseband::reset()
{
QMutexLocker mutexLocker(&m_mutex);
m_inputMessageQueue.clear();
m_sampleFifo.reset();
}
void RadioAstronomyBaseband::startWork()
{
QMutexLocker mutexLocker(&m_mutex);
QObject::connect(
&m_sampleFifo,
&SampleSinkFifo::dataReady,
this,
&RadioAstronomyBaseband::handleData,
Qt::QueuedConnection
);
connect(&m_inputMessageQueue, SIGNAL(messageEnqueued()), this, SLOT(handleInputMessages()));
m_running = true;
}
void RadioAstronomyBaseband::stopWork()
{
QMutexLocker mutexLocker(&m_mutex);
disconnect(&m_inputMessageQueue, SIGNAL(messageEnqueued()), this, SLOT(handleInputMessages()));
QObject::disconnect(
&m_sampleFifo,
&SampleSinkFifo::dataReady,
this,
&RadioAstronomyBaseband::handleData
);
m_running = false;
}
void RadioAstronomyBaseband::setChannel(ChannelAPI *channel)
{
m_sink.setChannel(channel);
}
void RadioAstronomyBaseband::feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end)
{
m_sampleFifo.write(begin, end);
}
void RadioAstronomyBaseband::handleData()
{
QMutexLocker mutexLocker(&m_mutex);
while ((m_sampleFifo.fill() > 0) && (m_inputMessageQueue.size() == 0))
{
SampleVector::iterator part1begin;
SampleVector::iterator part1end;
SampleVector::iterator part2begin;
SampleVector::iterator part2end;
std::size_t count = m_sampleFifo.readBegin(m_sampleFifo.fill(), &part1begin, &part1end, &part2begin, &part2end);
// first part of FIFO data
if (part1begin != part1end) {
m_channelizer->feed(part1begin, part1end);
}
// second part of FIFO data (used when block wraps around)
if(part2begin != part2end) {
m_channelizer->feed(part2begin, part2end);
}
m_sampleFifo.readCommit((unsigned int) count);
}
}
void RadioAstronomyBaseband::handleInputMessages()
{
Message* message;
while ((message = m_inputMessageQueue.pop()) != nullptr)
{
if (handleMessage(*message)) {
delete message;
}
}
}
bool RadioAstronomyBaseband::handleMessage(const Message& cmd)
{
if (MsgConfigureRadioAstronomyBaseband::match(cmd))
{
QMutexLocker mutexLocker(&m_mutex);
MsgConfigureRadioAstronomyBaseband& cfg = (MsgConfigureRadioAstronomyBaseband&) cmd;
qDebug() << "RadioAstronomyBaseband::handleMessage: MsgConfigureRadioAstronomyBaseband";
applySettings(cfg.getSettings(), cfg.getForce());
return true;
}
else if (DSPSignalNotification::match(cmd))
{
QMutexLocker mutexLocker(&m_mutex);
DSPSignalNotification& notif = (DSPSignalNotification&) cmd;
qDebug() << "RadioAstronomyBaseband::handleMessage: DSPSignalNotification: basebandSampleRate: " << notif.getSampleRate();
setBasebandSampleRate(notif.getSampleRate());
m_sampleFifo.setSize(SampleSinkFifo::getSizePolicy(notif.getSampleRate()));
return true;
}
else if (RadioAstronomy::MsgStartMeasurements::match(cmd))
{
m_sink.startMeasurements();
return true;
}
else if (RadioAstronomy::MsgStopMeasurements::match(cmd))
{
m_sink.stopMeasurements();
return true;
}
else if (RadioAstronomy::MsgStartCal::match(cmd))
{
RadioAstronomy::MsgStartCal& cal = (RadioAstronomy::MsgStartCal&)cmd;
m_sink.startCal(cal.getHot());
return true;
}
else
{
return false;
}
}
void RadioAstronomyBaseband::applySettings(const RadioAstronomySettings& settings, bool force)
{
if ((settings.m_inputFrequencyOffset != m_settings.m_inputFrequencyOffset)
|| (settings.m_sampleRate != m_settings.m_sampleRate)
|| force)
{
m_channelizer->setChannelization(settings.m_sampleRate, settings.m_inputFrequencyOffset);
m_sink.applyChannelSettings(m_channelizer->getChannelSampleRate(), m_channelizer->getChannelFrequencyOffset());
}
m_sink.applySettings(settings, force);
m_settings = settings;
}
void RadioAstronomyBaseband::setBasebandSampleRate(int sampleRate)
{
m_channelizer->setBasebandSampleRate(sampleRate);
m_sink.applyChannelSettings(m_channelizer->getChannelSampleRate(), m_channelizer->getChannelFrequencyOffset());
}

View File

@ -0,0 +1,97 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2019 Edouard Griffiths, F4EXB //
// Copyright (C) 2021 Jon Beniston, M7RCE //
// //
// 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_RADIOASTRONOMYBASEBAND_H
#define INCLUDE_RADIOASTRONOMYBASEBAND_H
#include <QObject>
#include <QMutex>
#include "dsp/samplesinkfifo.h"
#include "dsp/scopevis.h"
#include "util/message.h"
#include "util/messagequeue.h"
#include "radioastronomysink.h"
class DownChannelizer;
class ChannelAPI;
class RadioAstronomy;
class RadioAstronomyBaseband : public QObject
{
Q_OBJECT
public:
class MsgConfigureRadioAstronomyBaseband : public Message {
MESSAGE_CLASS_DECLARATION
public:
const RadioAstronomySettings& getSettings() const { return m_settings; }
bool getForce() const { return m_force; }
static MsgConfigureRadioAstronomyBaseband* create(const RadioAstronomySettings& settings, bool force)
{
return new MsgConfigureRadioAstronomyBaseband(settings, force);
}
private:
RadioAstronomySettings m_settings;
bool m_force;
MsgConfigureRadioAstronomyBaseband(const RadioAstronomySettings& settings, bool force) :
Message(),
m_settings(settings),
m_force(force)
{ }
};
RadioAstronomyBaseband(RadioAstronomy *aisDemod);
~RadioAstronomyBaseband();
void reset();
void startWork();
void stopWork();
void feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end);
MessageQueue *getInputMessageQueue() { return &m_inputMessageQueue; } //!< Get the queue for asynchronous inbound communication
void getMagSqLevels(double& avg, double& peak, int& nbSamples) {
m_sink.getMagSqLevels(avg, peak, nbSamples);
}
void setMessageQueueToChannel(MessageQueue *messageQueue) { m_sink.setMessageQueueToChannel(messageQueue); }
void setBasebandSampleRate(int sampleRate);
void setChannel(ChannelAPI *channel);
double getMagSq() const { return m_sink.getMagSq(); }
bool isRunning() const { return m_running; }
private:
SampleSinkFifo m_sampleFifo;
DownChannelizer *m_channelizer;
RadioAstronomySink m_sink;
MessageQueue m_inputMessageQueue; //!< Queue for asynchronous inbound communication
RadioAstronomySettings m_settings;
bool m_running;
QMutex m_mutex;
bool handleMessage(const Message& cmd);
void calculateOffset(RadioAstronomySink *sink);
void applySettings(const RadioAstronomySettings& settings, bool force = false);
private slots:
void handleInputMessages();
void handleData(); //!< Handle data when samples have to be processed
};
#endif // INCLUDE_RADIOASTRONOMYBASEBAND_H

View File

@ -0,0 +1,48 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2021 Jon Beniston, M7RCE //
// //
// 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 "radioastronomycalibrationdialog.h"
RadioAstronomyCalibrationDialog::RadioAstronomyCalibrationDialog(RadioAstronomySettings *settings, QWidget* parent) :
QDialog(parent),
m_settings(settings),
ui(new Ui::RadioAstronomyCalibrationDialog)
{
ui->setupUi(this);
ui->gpioEnabled->setChecked(settings->m_gpioEnabled);
ui->gpioPin->setValue(settings->m_gpioPin);
ui->gpioSense->setCurrentIndex(settings->m_gpioSense);
ui->startCalCommand->setText(settings->m_startCalCommand);
ui->stopCalCommand->setText(settings->m_stopCalCommand);
ui->calCommandDelay->setValue(settings->m_calCommandDelay);
}
RadioAstronomyCalibrationDialog::~RadioAstronomyCalibrationDialog()
{
delete ui;
}
void RadioAstronomyCalibrationDialog::accept()
{
m_settings->m_gpioEnabled = ui->gpioEnabled->isChecked();
m_settings->m_gpioPin = ui->gpioPin->value();
m_settings->m_gpioSense = ui->gpioSense->currentIndex();
m_settings->m_startCalCommand = ui->stopCalCommand->text().trimmed();
m_settings->m_stopCalCommand = ui->stopCalCommand->text().trimmed();
m_settings->m_calCommandDelay = ui->calCommandDelay->value();
QDialog::accept();
}

View File

@ -0,0 +1,40 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2021 Jon Beniston, M7RCE //
// //
// 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_RADIOASTRONOMYCALIBRATIONDIALOG_H
#define INCLUDE_RADIOASTRONOMYCALIBRATIONDIALOG_H
#include "ui_radioastronomycalibrationdialog.h"
#include "radioastronomysettings.h"
class RadioAstronomyCalibrationDialog : public QDialog {
Q_OBJECT
public:
explicit RadioAstronomyCalibrationDialog(RadioAstronomySettings *settings, QWidget* parent = 0);
~RadioAstronomyCalibrationDialog();
RadioAstronomySettings *m_settings;
private slots:
void accept();
private:
Ui::RadioAstronomyCalibrationDialog* ui;
};
#endif // INCLUDE_RADIOASTRONOMYCALIBRATIONDIALOG_H

View File

@ -0,0 +1,247 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>RadioAstronomyCalibrationDialog</class>
<widget class="QDialog" name="RadioAstronomyCalibrationDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>514</width>
<height>345</height>
</rect>
</property>
<property name="font">
<font>
<family>Liberation Sans</family>
<pointsize>9</pointsize>
</font>
</property>
<property name="windowTitle">
<string>Calibration Settings</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QGroupBox" name="groupBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<widget class="QGroupBox" name="gpioGroup">
<property name="title">
<string>SDR Device GPIO</string>
</property>
<layout class="QFormLayout" name="formLayout_4">
<item row="1" column="0">
<widget class="QLabel" name="gpioEnabledLabel">
<property name="text">
<string>Enabled</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QCheckBox" name="gpioEnabled">
<property name="toolTip">
<string>Check to enable setting a GPIO pin in SDR to enable calibration</string>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="gpioPinLabel">
<property name="text">
<string>Pin</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QSpinBox" name="gpioPin">
<property name="toolTip">
<string>SDR GPIO pin to set to start/stop calibration</string>
</property>
<property name="maximum">
<number>3</number>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="gpioSenseLabel">
<property name="text">
<string>Sense</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QComboBox" name="gpioSense">
<property name="toolTip">
<string>Whether pin should be set to 1 or 0 to enable calibration</string>
</property>
<property name="currentIndex">
<number>1</number>
</property>
<item>
<property name="text">
<string>Calibrate=0</string>
</property>
</item>
<item>
<property name="text">
<string>Calibrate=1</string>
</property>
</item>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="commandGroup">
<property name="title">
<string>Commands</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="2" column="0">
<widget class="QLabel" name="stopCalCommandLabel">
<property name="text">
<string>Stop calibration</string>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QLineEdit" name="startCalCommand">
<property name="toolTip">
<string>Program/script to execute to start calibration</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="startCalCommandLabel">
<property name="text">
<string>Start calibration</string>
</property>
</widget>
</item>
<item row="2" column="2">
<widget class="QLineEdit" name="stopCalCommand">
<property name="toolTip">
<string>Program/script to execute to stop calibration</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="timingGroup">
<property name="title">
<string>Timing</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QLabel" name="calCommandDelayLabel">
<property name="text">
<string>Pre-calibration delay (seconds)</string>
</property>
</widget>
</item>
<item>
<widget class="QDoubleSpinBox" name="calCommandDelay">
<property name="toolTip">
<string>Delay in seconds after command/GPIO before calibration starts</string>
</property>
<property name="decimals">
<number>3</number>
</property>
<property name="minimum">
<double>0.000000000000000</double>
</property>
<property name="maximum">
<double>100.000000000000000</double>
</property>
<property name="value">
<double>0.000000000000000</double>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</widget>
<tabstops>
<tabstop>gpioEnabled</tabstop>
<tabstop>gpioPin</tabstop>
<tabstop>gpioSense</tabstop>
<tabstop>startCalCommand</tabstop>
<tabstop>stopCalCommand</tabstop>
<tabstop>calCommandDelay</tabstop>
</tabstops>
<resources>
<include location="../../../sdrgui/resources/res.qrc"/>
</resources>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>RadioAstronomyCalibrationDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>RadioAstronomyCalibrationDialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,672 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2016 Edouard Griffiths, F4EXB //
// Copyright (C) 2021 Jon Beniston, M7RCE //
// //
// 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_RADIOASTRONOMYGUI_H
#define INCLUDE_RADIOASTRONOMYGUI_H
#include <QTableWidgetItem>
#include <QPushButton>
#include <QToolButton>
#include <QHBoxLayout>
#include <QMenu>
#include <QtCharts>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QDebug>
#include "channel/channelgui.h"
#include "dsp/channelmarker.h"
#include "util/messagequeue.h"
#include "util/httpdownloadmanager.h"
#include "pipes/pipeendpoint.h"
#include "radioastronomysettings.h"
#include "radioastronomy.h"
class PluginAPI;
class DeviceUISet;
class BasebandSampleSink;
class RadioAstronomy;
class RadioAstronomyGUI;
namespace Ui {
class RadioAstronomyGUI;
}
class RadioAstronomyGUI;
using namespace QtCharts;
class RadioAstronomyGUI : public ChannelGUI {
Q_OBJECT
struct FFTMeasurement {
QDateTime m_dateTime;
qint64 m_centerFrequency;
int m_sampleRate;
int m_integration;
int m_rfBandwidth;
int m_fftSize;
Real* m_fftData;
Real* m_db; // dBFS
Real* m_snr; // SNR (noise is cold cal data)
Real* m_temp; // Temp in Kelvin base on hot/cold cal data
Real m_totalPower; // Total power based on sum of fftData (i.e unknown units)
Real m_totalPowerdBFS; // m_totalPower in dB
Real m_totalPowerdBm; // Total power in dBm
Real m_totalPowerWatts; // Total power in Watts
Real m_tSys; // Total temp in K
Real m_tSys0; // Total unwanted noise (E.g. Trx+Tgal..) in K
Real m_tSource; // Estimated source temp (tSys-tSys0) in K
Real m_flux; // Average spectral flux density of source in W m^-2 Hz^-1
Real m_sigmaT; // Temperature variation
Real m_sigmaS; // Flux variation
Real m_tempMin; // Minimum value in m_temp array
RadioAstronomySettings::SpectrumBaseline m_baseline;
float m_omegaA;
float m_omegaS;
bool m_coordsValid; //!< Whether follow variables are valid
float m_ra;
float m_dec;
float m_azimuth;
float m_elevation;
float m_l;
float m_b;
float m_vBCRS;
float m_vLSR;
float m_solarFlux;
float m_airTemp;
float m_skyTemp;
float m_sensor[RADIOASTRONOMY_SENSORS];
int m_sweepIndex;
FFTMeasurement() :
m_fftSize(0),
m_fftData(nullptr),
m_db(nullptr),
m_snr(nullptr),
m_temp(nullptr),
m_totalPower(0.0f),
m_totalPowerdBFS(0.0f),
m_totalPowerdBm(0.0f),
m_totalPowerWatts(0.0f),
m_tSys(0.0f),
m_tSys0(0.0f),
m_tSource(0.0f),
m_flux(0.0f),
m_sigmaT(0.0f),
m_sigmaS(0.0f),
m_tempMin(0.0f),
m_baseline(RadioAstronomySettings::SBL_TSYS0),
m_coordsValid(false),
m_airTemp(0.0),
m_skyTemp(0.0),
m_sweepIndex(0)
{
}
~FFTMeasurement()
{
delete[] m_fftData;
delete[] m_db;
delete[] m_snr;
delete[] m_temp;
}
};
struct LABData {
float m_l;
float m_b;
QList<Real> m_vlsr;
QList<Real> m_temp;
LABData() :
m_l(0.0f),
m_b(0.0f)
{
}
void read(QFile* file, float l, float b);
void toSeries(QLineSeries *series);
};
struct SensorMeasurement {
QDateTime m_dateTime;
double m_value;
SensorMeasurement(QDateTime dateTime, double value) :
m_dateTime(dateTime),
m_value(value)
{
}
};
class SensorMeasurements {
QLineSeries* m_series;
QValueAxis* m_yAxis;
double m_max;
double m_min;
QList<SensorMeasurement *> m_measurements;
public:
SensorMeasurements() :
m_series(nullptr),
m_yAxis(nullptr)
{
}
void init(const QString& name, bool visible);
void setName(const QString& name);
void clicked(bool checked);
void append(SensorMeasurement *measurement);
void addToSeries(SensorMeasurement *measurement);
void addAllToSeries();
void clear();
void addToChart(QChart* chart, QDateTimeAxis* xAxis);
void setPen(const QPen& pen);
QValueAxis* yAxis() const;
qreal lastValue();
};
public:
static RadioAstronomyGUI* create(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, BasebandSampleSink *rxChannel);
virtual void destroy();
void resetToDefaults();
QByteArray serialize() const;
bool deserialize(const QByteArray& data);
virtual MessageQueue *getInputMessageQueue() { return &m_inputMessageQueue; }
public slots:
void channelMarkerChangedByCursor();
void channelMarkerHighlightedByCursor();
private:
Ui::RadioAstronomyGUI* ui;
PluginAPI* m_pluginAPI;
DeviceUISet* m_deviceUISet;
ChannelMarker m_channelMarker;
RadioAstronomySettings m_settings;
bool m_doApplySettings;
QList<PipeEndPoint::AvailablePipeSource> m_availablePipes;
int m_basebandSampleRate;
quint64 m_centerFrequency;
RadioAstronomy* m_radioAstronomy;
uint32_t m_tickCount;
MessageQueue m_inputMessageQueue;
QMenu *powerTableMenu; // Column select context menu
QMenu *copyMenu;
QChart *m_powerChart;
QLineSeries *m_powerSeries;
QDateTimeAxis *m_powerXAxis;
bool m_powerXAxisSameDay;
QValueAxis *m_powerYAxis;
QScatterSeries *m_powerPeakSeries;
QScatterSeries *m_powerMarkerSeries;
QLineSeries *m_powerTsys0Series;
QLineSeries *m_powerGaussianSeries;
double m_powerMin; // For axis autoscale
double m_powerMax;
bool m_powerPeakValid;
qreal m_powerMinX; // For min peak
qreal m_powerMinY;
qreal m_powerMaxX; // For max peak
qreal m_powerMaxY;
QChart *m_2DChart;
QValueAxis *m_2DXAxis;
QValueAxis *m_2DYAxis;
float *m_2DMapIntensity;
float m_2DMapMax;
float m_2DMapMin;
QImage m_2DMap;
int m_sweepIndex;
SensorMeasurements m_airTemps;
SensorMeasurements m_sensors[RADIOASTRONOMY_SENSORS];
QChart *m_calChart;
QValueAxis *m_calXAxis;
QValueAxis *m_calYAxis;
QLineSeries *m_calHotSeries;
QLineSeries *m_calColdSeries;
FFTMeasurement* m_calHot;
FFTMeasurement* m_calCold;
double *m_calG;
QChart *m_fftChart;
QLineSeries *m_fftSeries;
QLineSeries *m_fftHlineSeries;
QScatterSeries *m_fftPeakSeries;
QScatterSeries *m_fftMarkerSeries;
QLineSeries *m_fftGaussianSeries;
QLineSeries *m_fftLABSeries;
QValueAxis *m_fftXAxis;
QValueAxis *m_fftYAxis;
QValueAxis *m_fftDopplerAxis;
QList<FFTMeasurement*> m_fftMeasurements;
// Markers
bool m_powerM1Valid;
bool m_powerM2Valid;
qreal m_powerM1X;
qreal m_powerM1Y;
qreal m_powerM2X;
qreal m_powerM2Y;
bool m_spectrumM1Valid;
bool m_spectrumM2Valid;
qreal m_spectrumM1X;
qreal m_spectrumM1Y;
qreal m_spectrumM2X;
qreal m_spectrumM2Y;
// Target received from Star Tracker
bool m_coordsValid;
float m_ra;
float m_dec;
float m_azimuth;
float m_elevation;
float m_l;
float m_b;
float m_vBCRS;
float m_vLSR;
float m_solarFlux;
float m_skyTemp;
float m_beamWidth;
float m_lLAB; // Galactic coords for current LAB data
float m_bLAB;
QString m_filenameLAB;
bool m_downloadingLAB;
QList<LABData *> m_dataLAB;
QNetworkAccessManager *m_networkManager;
QNetworkRequest m_networkRequest;
HttpDownloadManager m_dlm;
explicit RadioAstronomyGUI(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, BasebandSampleSink *rxChannel, QWidget* parent = 0);
virtual ~RadioAstronomyGUI();
void blockApplySettings(bool block);
void applySettings(bool force = false);
void displaySettings();
void displayStreamIndex();
void displaySpectrumLineFrequency();
void displayRunModeSettings();
void updatePipeList();
void updateRotatorList();
bool handleMessage(const Message& message);
double degreesToSteradian(double deg) const;
double hpbwToSteradians(double hpbw) const;
double calcOmegaA() const;
double calcOmegaS() const;
double beamFillingFactor() const;
void updateOmegaA();
void powerMeasurementReceived(FFTMeasurement *fft, bool skipCalcs);
void calCompletetReceived(const RadioAstronomy::MsgCalComplete& measurement);
void calcFFTPower(FFTMeasurement* fft);
void calcFFTTotalPower(FFTMeasurement* fft);
void calcFFTTemperatures(FFTMeasurement* fft);
void calcFFTTotalTemperature(FFTMeasurement* fft);
void calcFFTMinTemperature(FFTMeasurement* fft);
void addFFT(FFTMeasurement *fft, bool skipCalcs=false);
void fftMeasurementReceived(const RadioAstronomy::MsgFFTMeasurement& measurement);
void addToPowerSeries(FFTMeasurement *fft, bool skipCalcs=false);
void plotPowerGaussian();
void plotSpectrum();
void plotCalSpectrum();
void plotCalMeasurements();
void plotFFTMeasurement(int index);
void plotFFTMeasurement();
void plotTempGaussian(double startFreq, double freqStep, int steps);
void plotRefLine(FFTMeasurement *fft);
void plotLAB();
void plotLAB(float l, float b, float beamWidth);
LABData* parseLAB(QFile* file, float l, float b);
int fftSizeToIndex(int size);
double dopplerToVelocity(double centre, double f, FFTMeasurement *fft);
QHash<QString,int> csvHeadersToHash(QStringList cols);
QString csvData(QHash<QString,int> hash, QStringList cols, QString col);
bool hasNeededFFTData(QHash<QString,int> hash);
void saveFFT(QTextStream& out, const FFTMeasurement* fft);
FFTMeasurement* loadFFT(QHash<QString,int> hash, QStringList cols);
void clearData();
void clearCalData();
bool deleteRow(int row);
void deleteRowsComplete(bool deletedCurrent, int next);
void calcCalibrationScaleFactors();
void calibrate();
void recalibrate();
void calcGalacticBackgroundTemp();
void calcAtmosphericTemp();
void calcCalAvgDiff();
void calcCalTrx();
void calcCalTsp();
void calcAverages();
void calcFWHM();
void calcHPBWFromFWHM();
void calcFHWMFromHPBW();
void calcColumnDensity();
qreal calcSeriesFloor(QXYSeries *series, int percent=10);
void calcVrAndDistanceToPeak(double freq, FFTMeasurement *fft, int row);
int calcDistanceToPeak(double vr, float l, float b, double& r, double &d1, double &d2);
void calcDistances();
void clearLoSMarker(const QString& name);
void updateLoSMarker(const QString& name, float l, float b, float d);
bool losMarkerEnabled(const QString& name);
void showLoSMarker(const QString& name);
void showLoSMarker(int row);
void sensorMeasurementReceived(const RadioAstronomy::MsgSensorMeasurement& measurement);
void updateSpectrumMarkerTableVisibility();
void updatePowerMarkerTableVisibility();
void updatePowerChartWidgetsVisibility();
void updateSpectrumChartWidgetsVisibility();
void updateSpectrumSelect();
void updatePowerSelect();
void spectrumAutoscale();
void powerAutoscale();
void calcSpectrumMarkerDelta();
void calcPowerMarkerDelta();
void calcPowerPeakDelta();
QRgb intensityToColor(float intensity);
void set2DAxisTitles();
void update2DSettingsFromSweep();
void create2DImage();
void update2DImage(FFTMeasurement* fft, bool skipCalcs);
void recolour2DImage();
void power2DAutoscale();
void powerColourAutoscale();
void updatePowerColourScaleStep();
void updateSpectrumMinMax(qreal x, qreal y);
RadioAstronomyGUI::FFTMeasurement* currentFFT();
void spectrumUpdateXRange(FFTMeasurement* fft = nullptr);
void spectrumUpdateYRange(FFTMeasurement* fft = nullptr);
void updateDistanceColumns();
void updateBWLimits();
void updateIntegrationTime();
void updateTSys0();
double calcTSys0() const;
double calcTau() const;
double calcTau(const FFTMeasurement* fft) const;
double calcSigmaT(double tSys) const;
double calcSigmaS(double tSys) const;
double calcSigmaT(const FFTMeasurement* fft) const;
double calcSigmaS(const FFTMeasurement* fft) const;
double calcFlux(double Ta, const FFTMeasurement *fft) const;
double calcTSource(FFTMeasurement *fft) const;
void updatePowerColumns(int row, FFTMeasurement* fft);
void calcPowerChartTickCount(int width);
void calcSpectrumChartTickCount(QValueAxis *axis, int width);
int powerYUnitsToIndex(RadioAstronomySettings::PowerYUnits units);
void leaveEvent(QEvent*);
void enterEvent(QEvent*);
void resizePowerTable();
void resizePowerMarkerTable();
void resizeSpectrumMarkerTable();
QAction *createCheckableItem(QString& text, int idx, bool checked, const char *slot);
enum PowerTableCol {
POWER_COL_DATE,
POWER_COL_TIME,
POWER_COL_POWER,
POWER_COL_POWER_DB,
POWER_COL_POWER_DBM,
POWER_COL_TSYS,
POWER_COL_TSYS0,
POWER_COL_TSOURCE,
POWER_COL_TB,
POWER_COL_TSKY,
POWER_COL_FLUX,
POWER_COL_SIGMA_T,
POWER_COL_SIGMA_S,
POWER_COL_OMEGA_A,
POWER_COL_OMEGA_S,
POWER_COL_RA,
POWER_COL_DEC,
POWER_COL_GAL_LON,
POWER_COL_GAL_LAT,
POWER_COL_AZ,
POWER_COL_EL,
POWER_COL_VBCRS,
POWER_COL_VLSR,
POWER_COL_SOLAR_FLUX,
POWER_COL_AIR_TEMP,
POWER_COL_SENSOR_1,
POWER_COL_SENSOR_2
};
enum PowerMarkerTable {
POWER_MARKER_COL_NAME,
POWER_MARKER_COL_DATE,
POWER_MARKER_COL_TIME,
POWER_MARKER_COL_VALUE,
POWER_MARKER_COL_DELTA_X,
POWER_MARKER_COL_DELTA_Y,
POWER_MARKER_COL_DELTA_TO
};
enum PowerMarkerRow {
POWER_MARKER_ROW_PEAK_MAX,
POWER_MARKER_ROW_PEAK_MIN,
POWER_MARKER_ROW_M1,
POWER_MARKER_ROW_M2,
POWER_MARKER_ROWS
};
enum SpectrumMarkerTable {
SPECTRUM_MARKER_COL_NAME,
SPECTRUM_MARKER_COL_FREQ,
SPECTRUM_MARKER_COL_VALUE,
SPECTRUM_MARKER_COL_DELTA_X,
SPECTRUM_MARKER_COL_DELTA_Y,
SPECTRUM_MARKER_COL_DELTA_TO,
SPECTRUM_MARKER_COL_VR,
SPECTRUM_MARKER_COL_R,
SPECTRUM_MARKER_COL_D,
SPECTRUM_MARKER_COL_PLOT_MAX,
SPECTRUM_MARKER_COL_R_MIN,
SPECTRUM_MARKER_COL_V
};
enum SpecrumMarkerRow {
SPECTRUM_MARKER_ROW_PEAK,
SPECTRUM_MARKER_ROW_M1,
SPECTRUM_MARKER_ROW_M2,
SPECTRUM_MARKER_ROWS
};
protected:
void resizeEvent(QResizeEvent* size);
private slots:
void on_deltaFrequency_changed(qint64 value);
void on_sampleRate_changed(qint64 index);
void on_rfBW_changed(qint64 index);
void on_integration_changed(qint64 value);
void on_fftSize_currentIndexChanged(int index);
void on_fftWindow_currentIndexChanged(int index);
void on_filterFreqs_editingFinished();
void on_starTracker_currentTextChanged(const QString& text);
void on_rotator_currentTextChanged(const QString& text);
void on_showSensors_clicked();
void on_tempRXSelect_currentIndexChanged(int value);
void on_tempRX_valueChanged(double value);
void on_tempCMB_valueChanged(double value);
void on_tempGal_valueChanged(double value);
void on_tempSP_valueChanged(double value);
void on_tempAtm_valueChanged(double value);
void on_tempAir_valueChanged(double value);
void on_zenithOpacity_valueChanged(double value);
void on_elevation_valueChanged(double value);
void on_tempAtmLink_toggled(bool checked);
void on_tempAirLink_toggled(bool checked);
void on_tempGalLink_toggled(bool checked);
void on_elevationLink_toggled(bool checked);
void on_gainVariation_valueChanged(double value);
void on_omegaAUnits_currentIndexChanged(int index);
void on_sourceType_currentIndexChanged(int index);
void on_omegaS_valueChanged(double value);
void on_omegaSUnits_currentIndexChanged(int index);
void on_spectrumChartSelect_currentIndexChanged(int index);
void on_showCalSettings_clicked();
void on_startCalHot_clicked();
void on_startCalCold_clicked();
void on_recalibrate_toggled(bool checked=false);
void on_spectrumShowLegend_toggled(bool checked);
void on_spectrumShowRefLine_toggled(bool checked);
void on_spectrumTemp_toggled(bool checked);
void on_spectrumMarker_toggled(bool checked);
void on_spectrumPeak_toggled(bool checked);
void on_spectrumReverseXAxis_toggled(bool checked);
void on_savePowerData_clicked();
void on_savePowerChartImage_clicked();
void on_saveSpectrumData_clicked();
void on_loadSpectrumData_clicked();
void on_saveSpectrumChartImage_clicked();
void on_saveSpectrumChartImages_clicked();
void on_clearData_clicked();
void on_clearCal_clicked();
void spectrumSeries_clicked(const QPointF &point);
void on_spectrumAutoscale_toggled(bool checked=false);
void on_spectrumAutoscaleX_clicked();
void on_spectrumAutoscaleY_clicked();
void on_spectrumReference_valueChanged(double value);
void on_spectrumRange_valueChanged(double value);
void on_spectrumCenterFreq_valueChanged(double value);
void on_spectrumSpan_valueChanged(double value);
void on_spectrumYUnits_currentIndexChanged(int index);
void on_spectrumBaseline_currentIndexChanged(int index);
void on_spectrumIndex_valueChanged(int value);
void on_spectrumLine_currentIndexChanged(int value);
void on_spectrumLineFrequency_valueChanged(double value);
void on_refFrame_currentIndexChanged(int value);
void on_sunDistanceToGC_valueChanged(double value);
void on_sunOrbitalVelocity_valueChanged(double value);
void spectrumMarkerTableItemChanged(QTableWidgetItem *item);
void on_spectrumGaussianFreq_valueChanged(double value);
void on_spectrumGaussianAmp_valueChanged(double value);
void on_spectrumGaussianFloor_valueChanged(double value);
void on_spectrumGaussianFWHM_valueChanged(double value);
void on_spectrumGaussianTurb_valueChanged(double value);
void on_spectrumTemperature_valueChanged(double t);
void on_spectrumShowLAB_toggled(bool checked=false);
void on_spectrumShowDistance_toggled(bool checked=false);
void on_tCalHotSelect_currentIndexChanged(int index);
void on_tCalHot_valueChanged(double value);
void on_tCalColdSelect_currentIndexChanged(int index);
void on_tCalCold_valueChanged(double value);
void on_powerChartSelect_currentIndexChanged(int index);
void on_powerYUnits_currentIndexChanged(int index);
void on_powerShowMarker_toggled(bool checked);
void on_powerShowTsys0_toggled(bool checked);
void on_powerShowAirTemp_toggled(bool checked);
void on_powerShowSensor1_toggled(bool checked);
void on_powerShowSensor2_toggled(bool checked);
void on_powerShowPeak_toggled(bool checked);
void on_powerShowAvg_toggled(bool checked);
void on_powerShowLegend_toggled(bool checked);
void powerSeries_clicked(const QPointF &point);
void on_powerAutoscale_toggled(bool checked);
void on_powerAutoscaleY_clicked();
void on_powerAutoscaleX_clicked();
void on_powerReference_valueChanged(double value);
void on_powerRange_valueChanged(double value);
void on_powerStartTime_dateTimeChanged(QDateTime value);
void on_powerEndTime_dateTimeChanged(QDateTime value);
void on_powerShowGaussian_clicked(bool checked=false);
void on_powerGaussianCenter_dateTimeChanged(QDateTime dateTime);
void on_powerGaussianAmp_valueChanged(double value);
void on_powerGaussianFloor_valueChanged(double value);
void on_powerGaussianFWHM_valueChanged(double value);
void on_powerGaussianHPBW_valueChanged(double value);
void on_runMode_currentIndexChanged(int index);
void on_sweepType_currentIndexChanged(int index);
void on_startStop_clicked(bool checked=false);
void on_sweepStartAtTime_currentIndexChanged(int index);
void on_sweepStartDateTime_dateTimeChanged(const QDateTime& dateTime);
void on_sweep1Start_valueChanged(double value);
void on_sweep1Stop_valueChanged(double value);
void on_sweep1Step_valueChanged(double value);
void on_sweep1Delay_valueChanged(double value);
void on_sweep2Start_valueChanged(double value);
void on_sweep2Stop_valueChanged(double value);
void on_sweep2Step_valueChanged(double value);
void on_sweep2Delay_valueChanged(double value);
void on_power2DLinkSweep_toggled(bool checked=false);
void on_power2DAutoscale_clicked();
void on_power2DSweepType_currentIndexChanged(int index);
void on_power2DWidth_valueChanged(int value);
void on_power2DHeight_valueChanged(int value);
void on_power2DXMin_valueChanged(double value);
void on_power2DXMax_valueChanged(double value);
void on_power2DYMin_valueChanged(double value);
void on_power2DYMax_valueChanged(double value);
void on_powerColourAutoscale_toggled(bool checked=false);
void on_powerColourScaleMin_valueChanged(double value);
void on_powerColourScaleMax_valueChanged(double value);
void on_powerColourPalette_currentIndexChanged(int index);
void powerTable_sectionMoved(int logicalIndex, int oldVisualIndex, int newVisualIndex);
void powerTable_sectionResized(int logicalIndex, int oldSize, int newSize);
void powerTableColumnSelectMenu(QPoint pos);
void powerTableColumnSelectMenuChecked(bool checked = false);
void on_powerTable_cellDoubleClicked(int row, int column);
void plotPowerChart();
void plotPowerVsTimeChart();
void plot2DChart();
void plotAreaChanged(const QRectF& plotArea);
void customContextMenuRequested(QPoint point);
void onWidgetRolled(QWidget* widget, bool rollDown);
void onMenuDialogCalled(const QPoint& p);
void handleInputMessages();
void tick();
void networkManagerFinished(QNetworkReply *reply);
void downloadFinished(const QString& filename, bool success);
};
#endif // INCLUDE_RADIOASTRONOMYGUI_H

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,92 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2016 Edouard Griffiths, F4EXB //
// Copyright (C) 2021 Jon Beniston, M7RCE //
// //
// 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 "radioastronomygui.h"
#endif
#include "radioastronomy.h"
#include "radioastronomywebapiadapter.h"
#include "radioastronomyplugin.h"
const PluginDescriptor RadioAstronomyPlugin::m_pluginDescriptor = {
RadioAstronomy::m_channelId,
QStringLiteral("Radio Astronomy"),
QStringLiteral("6.17.0"),
QStringLiteral("(c) Jon Beniston, M7RCE"),
QStringLiteral("https://github.com/f4exb/sdrangel"),
true,
QStringLiteral("https://github.com/f4exb/sdrangel")
};
RadioAstronomyPlugin::RadioAstronomyPlugin(QObject* parent) :
QObject(parent),
m_pluginAPI(0)
{
}
const PluginDescriptor& RadioAstronomyPlugin::getPluginDescriptor() const
{
return m_pluginDescriptor;
}
void RadioAstronomyPlugin::initPlugin(PluginAPI* pluginAPI)
{
m_pluginAPI = pluginAPI;
m_pluginAPI->registerRxChannel(RadioAstronomy::m_channelIdURI, RadioAstronomy::m_channelId, this);
}
void RadioAstronomyPlugin::createRxChannel(DeviceAPI *deviceAPI, BasebandSampleSink **bs, ChannelAPI **cs) const
{
if (bs || cs)
{
RadioAstronomy *instance = new RadioAstronomy(deviceAPI);
if (bs) {
*bs = instance;
}
if (cs) {
*cs = instance;
}
}
}
#ifdef SERVER_MODE
ChannelGUI* RadioAstronomyPlugin::createRxChannelGUI(
DeviceUISet *deviceUISet,
BasebandSampleSink *rxChannel) const
{
(void) deviceUISet;
(void) rxChannel;
return 0;
}
#else
ChannelGUI* RadioAstronomyPlugin::createRxChannelGUI(DeviceUISet *deviceUISet, BasebandSampleSink *rxChannel) const
{
return RadioAstronomyGUI::create(m_pluginAPI, deviceUISet, rxChannel);
}
#endif
ChannelWebAPIAdapter* RadioAstronomyPlugin::createChannelWebAPIAdapter() const
{
return new RadioAstronomyWebAPIAdapter();
}

View File

@ -0,0 +1,49 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2016 Edouard Griffiths, F4EXB //
// Copyright (C) 2021 Jon Beniston, M7RCE //
// //
// 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_RADIOASTRONOMYPLUGIN_H
#define INCLUDE_RADIOASTRONOMYPLUGIN_H
#include <QObject>
#include "plugin/plugininterface.h"
class DeviceUISet;
class BasebandSampleSink;
class RadioAstronomyPlugin : public QObject, PluginInterface {
Q_OBJECT
Q_INTERFACES(PluginInterface)
Q_PLUGIN_METADATA(IID "sdrangel.channel.radioastronomy")
public:
explicit RadioAstronomyPlugin(QObject* parent = NULL);
const PluginDescriptor& getPluginDescriptor() const;
void initPlugin(PluginAPI* pluginAPI);
virtual void createRxChannel(DeviceAPI *deviceAPI, BasebandSampleSink **bs, ChannelAPI **cs) const;
virtual ChannelGUI* createRxChannelGUI(DeviceUISet *deviceUISet, BasebandSampleSink *rxChannel) const;
virtual ChannelWebAPIAdapter* createChannelWebAPIAdapter() const;
private:
static const PluginDescriptor m_pluginDescriptor;
PluginAPI* m_pluginAPI;
};
#endif // INCLUDE_RADIOASTRONOMYPLUGIN_H

View File

@ -0,0 +1,68 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2021 Jon Beniston, M7RCE //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation as version 3 of the License, or //
// (at your option) any later version. //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License V3 for more details. //
// //
// You should have received a copy of the GNU General Public License //
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#include <QDebug>
#include "util/visa.h"
#include "radioastronomysensordialog.h"
RadioAstronomySensorDialog::RadioAstronomySensorDialog(RadioAstronomySettings *settings, QWidget* parent) :
QDialog(parent),
m_settings(settings),
ui(new Ui::RadioAstronomySensorDialog)
{
ui->setupUi(this);
ui->sensor1Enabled->setChecked(settings->m_sensorEnabled[0]);
ui->sensor1Name->setText(settings->m_sensorName[0]);
ui->sensor1Device->setText(settings->m_sensorDevice[0]);
ui->sensor1Init->setPlainText(settings->m_sensorInit[0]);
ui->sensor1Measure->setText(settings->m_sensorMeasure[0]);
ui->sensor2Enabled->setChecked(settings->m_sensorEnabled[1]);
ui->sensor2Name->setText(settings->m_sensorName[1]);
ui->sensor2Device->setText(settings->m_sensorDevice[1]);
ui->sensor2Init->setPlainText(settings->m_sensorInit[1]);
ui->sensor2Measure->setText(settings->m_sensorMeasure[1]);
ui->period->setValue(settings->m_sensorMeasurePeriod);
VISA visa;
if (!visa.isAvailable())
{
ui->sensor1Group->setEnabled(false);
ui->sensor2Group->setEnabled(false);
}
}
RadioAstronomySensorDialog::~RadioAstronomySensorDialog()
{
delete ui;
}
void RadioAstronomySensorDialog::accept()
{
m_settings->m_sensorEnabled[0] = ui->sensor1Enabled->isChecked();
m_settings->m_sensorName[0] = ui->sensor1Name->text().trimmed();
m_settings->m_sensorDevice[0] = ui->sensor1Device->text().trimmed();
m_settings->m_sensorInit[0] = ui->sensor1Init->toPlainText();
m_settings->m_sensorMeasure[0] = ui->sensor1Measure->text().trimmed();
m_settings->m_sensorEnabled[1] = ui->sensor2Enabled->isChecked();
m_settings->m_sensorName[1] = ui->sensor2Name->text().trimmed();
m_settings->m_sensorDevice[1] = ui->sensor2Device->text().trimmed();
m_settings->m_sensorInit[1] = ui->sensor2Init->toPlainText();
m_settings->m_sensorMeasure[1] = ui->sensor2Measure->text().trimmed();
m_settings->m_sensorMeasurePeriod = ui->period->value();
QDialog::accept();
}

View File

@ -0,0 +1,40 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2021 Jon Beniston, M7RCE //
// //
// 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_RADIOASTRONOMYSENSORDIALOG_H
#define INCLUDE_RADIOASTRONOMYSENSORDIALOG_H
#include "ui_radioastronomysensordialog.h"
#include "radioastronomysettings.h"
class RadioAstronomySensorDialog : public QDialog {
Q_OBJECT
public:
explicit RadioAstronomySensorDialog(RadioAstronomySettings *settings, QWidget* parent = 0);
~RadioAstronomySensorDialog();
RadioAstronomySettings *m_settings;
private slots:
void accept();
private:
Ui::RadioAstronomySensorDialog* ui;
};
#endif // INCLUDE_RADIOASTRONOMYSENSORDIALOG_H

View File

@ -0,0 +1,251 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>RadioAstronomySensorDialog</class>
<widget class="QDialog" name="RadioAstronomySensorDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>514</width>
<height>746</height>
</rect>
</property>
<property name="font">
<font>
<family>Liberation Sans</family>
<pointsize>9</pointsize>
</font>
</property>
<property name="windowTitle">
<string>Sensor Control Settings</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QGroupBox" name="groupBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<widget class="QGroupBox" name="sensor1Group">
<property name="title">
<string>Sensor 1</string>
</property>
<layout class="QFormLayout" name="formLayout_4">
<item row="3" column="1">
<widget class="QLineEdit" name="sensor1Device"/>
</item>
<item row="3" column="0">
<widget class="QLabel" name="sensor1DeviceLabel">
<property name="text">
<string>Device</string>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="sensor1InitLabel">
<property name="text">
<string>Init</string>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QPlainTextEdit" name="sensor1Init"/>
</item>
<item row="5" column="0">
<widget class="QLabel" name="sensor1MeasureLabel">
<property name="text">
<string>Measure</string>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="QLineEdit" name="sensor1Measure"/>
</item>
<item row="2" column="0">
<widget class="QLabel" name="sensor1NameLabel">
<property name="text">
<string>Name</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLineEdit" name="sensor1Name"/>
</item>
<item row="1" column="0">
<widget class="QLabel" name="sensor1EnabledLabel">
<property name="text">
<string>Enabled</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QCheckBox" name="sensor1Enabled">
<property name="toolTip">
<string>Check to enable measurements from this device</string>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="sensor2Group">
<property name="title">
<string>Sensor 2</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="3" column="0">
<widget class="QLabel" name="sensor2DeviceLabel">
<property name="text">
<string>Device</string>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="sensor2InitLabel">
<property name="text">
<string>Init</string>
</property>
</widget>
</item>
<item row="4" column="2">
<widget class="QPlainTextEdit" name="sensor2Init"/>
</item>
<item row="1" column="0">
<widget class="QLabel" name="sensor2EnabledLabel">
<property name="text">
<string>Enabled</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="sensor3NameLabel">
<property name="text">
<string>Name</string>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QLabel" name="sensor2MeasureLabel">
<property name="text">
<string>Measure</string>
</property>
</widget>
</item>
<item row="3" column="2">
<widget class="QLineEdit" name="sensor2Device"/>
</item>
<item row="2" column="2">
<widget class="QLineEdit" name="sensor2Name"/>
</item>
<item row="5" column="2">
<widget class="QLineEdit" name="sensor2Measure"/>
</item>
<item row="1" column="2">
<widget class="QCheckBox" name="sensor2Enabled">
<property name="toolTip">
<string>Check to enable measurements from this device</string>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="timingGroup">
<property name="title">
<string>Timing</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QLabel" name="periodLabel">
<property name="text">
<string>Measurement period (seconds)</string>
</property>
</widget>
</item>
<item>
<widget class="QDoubleSpinBox" name="period">
<property name="toolTip">
<string>Delay in seconds between measurements being made</string>
</property>
<property name="decimals">
<number>3</number>
</property>
<property name="minimum">
<double>0.001000000000000</double>
</property>
<property name="maximum">
<double>100.000000000000000</double>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</widget>
<tabstops>
<tabstop>period</tabstop>
</tabstops>
<resources>
<include location="../../../sdrgui/resources/res.qrc"/>
</resources>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>RadioAstronomySensorDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>RadioAstronomySensorDialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@ -0,0 +1,491 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2015 Edouard Griffiths, F4EXB. //
// Copyright (C) 2021 Jon Beniston, M7RCE //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation as version 3 of the License, or //
// (at your option) any later version. //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License V3 for more details. //
// //
// You should have received a copy of the GNU General Public License //
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#include <QColor>
#include "dsp/dspengine.h"
#include "util/simpleserializer.h"
#include "settings/serializable.h"
#include "radioastronomysettings.h"
const QStringList RadioAstronomySettings::m_pipeTypes = {
QStringLiteral("StarTracker")
};
const QStringList RadioAstronomySettings::m_pipeURIs = {
QStringLiteral("sdrangel.feature.startracker")
};
RadioAstronomySettings::RadioAstronomySettings() :
m_channelMarker(0)
{
resetToDefaults();
}
void RadioAstronomySettings::resetToDefaults()
{
m_inputFrequencyOffset = 0;
m_sampleRate = 1000000;
m_rfBandwidth = 1000000;
m_integration = 4000;
m_fftSize = 256;
m_fftWindow = HAN;
m_filterFreqs = "";
m_starTracker = "";
m_rotator = "None";
m_tempRX = 75.0f;
m_tempCMB = 2.73;
m_tempGal = 2.0;
m_tempSP = 85.0;
m_tempAtm = 2.0;
m_tempAir = 15.0;
m_zenithOpacity = 0.0055;
m_elevation = 90.0;
m_tempGalLink = true;
m_tempAtmLink = true;
m_tempAirLink = true;
m_elevationLink = true;
m_gainVariation = 0.0011f;
m_sourceType = UNKNOWN;
m_omegaS = 0.0;
m_omegaSUnits = DEGREES;
m_omegaAUnits = DEGREES;
m_spectrumPeaks = false;
m_spectrumMarkers = false;
m_spectrumTemp = false;
m_spectrumReverseXAxis = false;
m_spectrumRefLine = false;
m_spectrumLAB = false;
m_spectrumDistance = false;
m_spectrumLegend = false;
m_spectrumReference = 0.0f;
m_spectrumRange = 120.0f;
m_spectrumCenterFreqOffset = 0.0f;
m_spectrumAutoscale = true;
m_spectrumSpan = 1.0f;
m_spectrumYScale = SY_DBFS;
m_spectrumBaseline = SBL_TSYS0;
m_recalibrate = false;
m_tCalHot = 300.0f;
m_tCalCold = 10.0f;
m_line = HI;
m_lineCustomFrequency = 0.0f;
m_refFrame = LSR;
m_powerAutoscale = true;
m_powerReference = 0.0f;
m_powerRange = 100.0f;
m_powerPeaks = false;
m_powerMarkers = false;
m_powerAvg = false;
m_powerLegend = false;
m_powerYData = PY_POWER;
m_powerYUnits = PY_DBFS;
m_powerShowTsys0 = false;
m_powerShowAirTemp = false;
m_powerShowGaussian = false;
m_power2DLinkSweep = true;
m_power2DSweepType = SWP_OFFSET;
m_power2DHeight = 3;
m_power2DWidth = 3;
m_power2DXMin = 0;
m_power2DXMax = 10;
m_power2DYMin = 0;
m_power2DYMax = 10;
m_powerColourAutoscale = true;
m_powerColourScaleMin = 0.0f;
m_powerColourScaleMax = 0.0f;
m_powerColourPalette = "Colour";
m_sensorName[0] = "Temperature";
m_sensorDevice[0] = "";
m_sensorInit[0] = "UNIT:TEMP C";
m_sensorMeasure[0] = "MEAS:TEMP?";
m_sensorEnabled[0] = false;
m_sensorVisible[0] = false;
m_sensorName[1] = "Voltage";
m_sensorDevice[1] = "";
m_sensorInit[1] = "";
m_sensorMeasure[1] = "MEAS:VOLT:DC?";
m_sensorEnabled[1] = false;
m_sensorVisible[1] = false;
m_sensorMeasurePeriod = 1.0f;
m_sunDistanceToGC = 8.1f;
m_sunOrbitalVelocity = 248.0f;
m_runMode = CONTINUOUS;
m_sweepStartAtTime = false;
m_sweepStartDateTime = QDateTime::currentDateTime();
m_sweepType = SWP_OFFSET;
m_sweep1Start = -5.0;
m_sweep1Stop = 5.0;
m_sweep1Step = 5.0;
m_sweep1Delay = 0.0;
m_sweep2Start = -5.0;
m_sweep2Stop = 5.0;
m_sweep2Step = 5.0;
m_sweep2Delay = 0.0;
m_gpioEnabled = false;
m_gpioPin = 0;
m_gpioSense = 1;
m_startCalCommand = "";
m_stopCalCommand = "";
m_calCommandDelay = 1.0f;
m_rgbColor = QColor(102, 0, 0).rgb();
m_title = "Radio Astronomy";
m_streamIndex = 0;
m_useReverseAPI = false;
m_reverseAPIAddress = "127.0.0.1";
m_reverseAPIPort = 8888;
m_reverseAPIDeviceIndex = 0;
m_reverseAPIChannelIndex = 0;
for (int i = 0; i < RADIOASTRONOMY_POWERTABLE_COLUMNS; i++)
{
m_powerTableColumnIndexes[i] = i;
m_powerTableColumnSizes[i] = -1; // Autosize
}
}
QByteArray RadioAstronomySettings::serialize() const
{
SimpleSerializer s(1);
s.writeS32(1, m_inputFrequencyOffset);
s.writeS32(2, m_sampleRate);
s.writeS32(3, m_rfBandwidth);
s.writeS32(4, m_integration);
s.writeS32(5, m_fftSize);
s.writeS32(6, (int)m_fftWindow);
s.writeString(7, m_filterFreqs);
s.writeString(10, m_starTracker);
s.writeString(11, m_rotator);
s.writeFloat(20, m_tempRX);
s.writeFloat(21, m_tempCMB);
s.writeFloat(22, m_tempGal);
s.writeFloat(23, m_tempSP);
s.writeFloat(24, m_tempAtm);
s.writeFloat(25, m_tempAir);
s.writeFloat(26, m_zenithOpacity);
s.writeFloat(27, m_elevation);
s.writeBool(28, m_tempGalLink);
s.writeBool(29, m_tempAtmLink);
s.writeBool(30, m_tempAirLink);
s.writeBool(31, m_elevationLink);
s.writeFloat(40, m_gainVariation);
s.writeS32(41, (int)m_sourceType);
s.writeFloat(42, m_omegaS);
s.writeS32(43, (int)m_omegaSUnits);
s.writeS32(44, (int)m_omegaAUnits);
s.writeBool(50, m_spectrumPeaks);
s.writeBool(51, m_spectrumMarkers);
s.writeBool(52, m_spectrumTemp);
s.writeBool(53, m_spectrumReverseXAxis);
s.writeBool(54, m_spectrumRefLine);
s.writeBool(55, m_spectrumLegend);
s.writeBool(56, m_spectrumDistance);
s.writeBool(57, m_spectrumLAB);
s.writeFloat(60, m_spectrumReference);
s.writeFloat(61, m_spectrumRange);
s.writeFloat(62, m_spectrumSpan);
s.writeFloat(63, m_spectrumCenterFreqOffset);
s.writeBool(64, m_spectrumAutoscale);
s.writeS32(65, (int)m_spectrumYScale);
s.writeS32(66, (int)m_spectrumBaseline);
s.writeBool(70, m_recalibrate);
s.writeFloat(71, m_tCalHot);
s.writeFloat(72, m_tCalCold);
s.writeS32(73, (int)m_line);
s.writeFloat(74, m_lineCustomFrequency);
s.writeS32(75, (int)m_refFrame);
s.writeFloat(76, m_sunDistanceToGC);
s.writeFloat(77, m_sunOrbitalVelocity);
s.writeBool(80, m_powerPeaks);
s.writeBool(81, m_powerMarkers);
s.writeBool(82, m_powerAvg);
s.writeBool(83, m_powerLegend);
s.writeBool(84, m_powerShowTsys0);
s.writeBool(85, m_powerShowAirTemp);
s.writeBool(86, m_powerShowGaussian);
s.writeFloat(87, m_powerReference);
s.writeFloat(88, m_powerRange);
s.writeBool(89, m_powerAutoscale);
s.writeS32(90, (int)m_powerYData);
s.writeS32(91, (int)m_powerYUnits);
s.writeBool(100, m_power2DLinkSweep);
s.writeS32(102, (int)m_power2DSweepType);
s.writeS32(103, m_power2DWidth);
s.writeS32(104, m_power2DHeight);
s.writeFloat(105, m_power2DXMin);
s.writeFloat(106, m_power2DXMax);
s.writeFloat(107, m_power2DYMin);
s.writeFloat(108, m_power2DYMax);
s.writeBool(109, m_powerColourAutoscale);
s.writeFloat(110, m_powerColourScaleMin);
s.writeFloat(111, m_powerColourScaleMax);
s.writeString(112, m_powerColourPalette);
s.writeS32(120, m_runMode);
s.writeBool(121, m_sweepStartAtTime);
s.writeS64(122, m_sweepStartDateTime.toMSecsSinceEpoch());
s.writeS32(123, (int)m_sweepType);
s.writeFloat(124, m_sweep1Start);
s.writeFloat(125, m_sweep1Stop);
s.writeFloat(126, m_sweep1Step);
s.writeFloat(127, m_sweep1Delay);
s.writeFloat(128, m_sweep2Start);
s.writeFloat(129, m_sweep2Stop);
s.writeFloat(130, m_sweep2Step);
s.writeFloat(131, m_sweep2Delay);
s.writeString(140, m_sensorName[0]);
s.writeString(141, m_sensorDevice[0]);
s.writeString(142, m_sensorInit[0]);
s.writeString(143, m_sensorMeasure[0]);
s.writeBool(144, m_sensorEnabled[0]);
s.writeBool(145, m_sensorVisible[0]);
s.writeString(146, m_sensorName[1]);
s.writeString(147, m_sensorDevice[1]);
s.writeString(148, m_sensorInit[1]);
s.writeString(149, m_sensorMeasure[1]);
s.writeBool(150, m_sensorEnabled[1]);
s.writeBool(151, m_sensorVisible[1]);
s.writeFloat(152, m_sensorMeasurePeriod);
s.writeBool(160, m_gpioEnabled);
s.writeS32(161, m_gpioPin);
s.writeS32(162, m_gpioSense);
s.writeString(167, m_startCalCommand);
s.writeString(168, m_stopCalCommand);
s.writeFloat(169, m_calCommandDelay);
s.writeU32(180, m_rgbColor);
s.writeString(181, m_title);
if (m_channelMarker) {
s.writeBlob(182, m_channelMarker->serialize());
}
s.writeS32(183, m_streamIndex);
s.writeBool(184, m_useReverseAPI);
s.writeString(185, m_reverseAPIAddress);
s.writeU32(186, m_reverseAPIPort);
s.writeU32(187, m_reverseAPIDeviceIndex);
s.writeU32(188, m_reverseAPIChannelIndex);
for (int i = 0; i < RADIOASTRONOMY_POWERTABLE_COLUMNS; i++) {
s.writeS32(400 + i, m_powerTableColumnIndexes[i]);
}
for (int i = 0; i < RADIOASTRONOMY_POWERTABLE_COLUMNS; i++) {
s.writeS32(500 + i, m_powerTableColumnSizes[i]);
}
return s.final();
}
bool RadioAstronomySettings::deserialize(const QByteArray& data)
{
SimpleDeserializer d(data);
if(!d.isValid())
{
resetToDefaults();
return false;
}
if(d.getVersion() == 1)
{
QByteArray bytetmp;
uint32_t utmp;
QString strtmp;
qint64 dttmp;
d.readS32(1, &m_inputFrequencyOffset, 0);
d.readS32(2, &m_sampleRate, 1000000);
d.readS32(3, &m_rfBandwidth, 1000000);
d.readS32(4, &m_integration, 4000);
d.readS32(5, &m_fftSize, 256);
d.readS32(6, (int*)&m_fftWindow, (int)HAN);
d.readString(7, &m_filterFreqs, "");
d.readString(10, &m_starTracker, "");
d.readString(11, &m_rotator, "None");
d.readFloat(20, &m_tempRX, 75.0f);
d.readFloat(21, &m_tempCMB, 2.73f);
d.readFloat(22, &m_tempGal, 2.0f);
d.readFloat(23, &m_tempSP, 85.0f);
d.readFloat(24, &m_tempAtm, 2.0f);
d.readFloat(25, &m_tempAir, 15.0f);
d.readFloat(26, &m_zenithOpacity, 0.0055f);
d.readFloat(27, &m_elevation, 90.0f);
d.readBool(28, &m_tempGalLink, true);
d.readBool(29, &m_tempAtmLink, true);
d.readBool(30, &m_tempAirLink, true);
d.readBool(31, &m_elevationLink, true);
d.readFloat(40, &m_gainVariation, 0.0011f);
d.readS32(41, (int*)&m_sourceType, UNKNOWN);
d.readFloat(42, &m_omegaS, 0.0f);
d.readS32(43, (int*)&m_omegaSUnits, DEGREES);
d.readS32(44, (int*)&m_omegaAUnits, DEGREES);
d.readBool(50, &m_spectrumPeaks, false);
d.readBool(51, &m_spectrumMarkers, false);
d.readBool(52, &m_spectrumTemp, false);
d.readBool(53, &m_spectrumReverseXAxis, false);
d.readBool(54, &m_spectrumRefLine, false);
d.readBool(55, &m_spectrumLegend, false);
d.readBool(56, &m_spectrumDistance, false);
d.readBool(57, &m_spectrumLAB, false);
d.readFloat(60, &m_spectrumReference, 0.0f);
d.readFloat(61, &m_spectrumRange, 120.0f);
d.readFloat(62, &m_spectrumSpan, 1.0f);
d.readFloat(63, &m_spectrumCenterFreqOffset, 0.0f);
d.readBool(64, &m_spectrumAutoscale, false);
d.readS32(65, (int*)&m_spectrumYScale, SY_DBFS);
d.readS32(66, (int*)&m_spectrumBaseline, SBL_TSYS0);
d.readBool(70, &m_recalibrate, false);
d.readFloat(71, &m_tCalHot, 300.0f);
d.readFloat(72, &m_tCalCold, 10.0f);
d.readS32(73, (int*)&m_line, (int)HI);
d.readFloat(74, &m_lineCustomFrequency, 0.0f);
d.readS32(75, (int*)&m_refFrame, LSR);
d.readFloat(76, &m_sunDistanceToGC, 8.1f);
d.readFloat(77, &m_sunOrbitalVelocity, 248.0f);
d.readBool(80, &m_powerPeaks, false);
d.readBool(81, &m_powerMarkers, false);
d.readBool(82, &m_powerAvg, false);
d.readBool(83, &m_powerLegend, false);
d.readBool(84, &m_powerShowTsys0, false);
d.readBool(85, &m_powerShowAirTemp, false);
d.readBool(86, &m_powerShowGaussian, false);
d.readFloat(87, &m_powerReference, 0.0f);
d.readFloat(88, &m_powerRange, 100.0f);
d.readBool(89, &m_powerAutoscale, true);
d.readS32(90, (int*)&m_powerYData, PY_POWER);
d.readS32(91, (int*)&m_powerYUnits, PY_DBFS);
d.readBool(100, &m_power2DLinkSweep, true);
d.readS32(102, (int*)&m_power2DSweepType, SWP_OFFSET);
d.readS32(103, &m_power2DWidth, 3);
d.readS32(104, &m_power2DHeight, 3);
d.readFloat(105, &m_power2DXMin, 0);
d.readFloat(106, &m_power2DXMax, 10);
d.readFloat(107, &m_power2DYMin, 0);
d.readFloat(108, &m_power2DYMax, 10);
d.readBool(109, &m_powerColourAutoscale, true);
d.readFloat(110, &m_powerColourScaleMin, 0.0f);
d.readFloat(111, &m_powerColourScaleMax, 0.0f);
d.readString(112, &m_powerColourPalette, "Colour");
d.readS32(120, (int *)&m_runMode, CONTINUOUS);
d.readBool(121, &m_sweepStartAtTime, false);
d.readS64(122, &dttmp, QDateTime::currentDateTime().toMSecsSinceEpoch());
m_sweepStartDateTime = QDateTime::fromMSecsSinceEpoch(dttmp);
d.readS32(123, (int*)&m_sweepType, SWP_OFFSET);
d.readFloat(124, &m_sweep1Start, -5.0f);
d.readFloat(125, &m_sweep1Stop, 5.0f);
d.readFloat(126, &m_sweep1Step, 5.0f);
d.readFloat(127, &m_sweep1Delay, 0.0f);
d.readFloat(128, &m_sweep2Start, -5.0f);
d.readFloat(129, &m_sweep2Stop, 5.0);
d.readFloat(130, &m_sweep2Step, 5.0f);
d.readFloat(131, &m_sweep2Delay, 0.0f);
d.readString(140, &m_sensorName[0], "");
d.readString(141, &m_sensorDevice[0], "");
d.readString(142, &m_sensorInit[0], "");
d.readString(143, &m_sensorMeasure[0], "");
d.readBool(144, &m_sensorEnabled[0], false);
d.readBool(145, &m_sensorVisible[0], false);
d.readString(146, &m_sensorName[1], "");
d.readString(147, &m_sensorDevice[1], "");
d.readString(148, &m_sensorInit[1], "");
d.readString(149, &m_sensorMeasure[1], "");
d.readBool(150, &m_sensorEnabled[1], false);
d.readBool(151, &m_sensorVisible[1], false);
d.readFloat(152, &m_sensorMeasurePeriod, 1.0f);
d.readBool(160, &m_gpioEnabled, false);
d.readS32(161, &m_gpioPin, 0);
d.readS32(162, &m_gpioSense, 1);
d.readString(167, &m_startCalCommand, "");
d.readString(168, &m_stopCalCommand, "");
d.readFloat(169, &m_calCommandDelay, 1.0f);
d.readU32(180, &m_rgbColor, QColor(102, 0, 0).rgb());
d.readString(181, &m_title, "Radio Astronomy");
d.readBlob(182, &bytetmp);
if (m_channelMarker) {
m_channelMarker->deserialize(bytetmp);
}
d.readS32(183, &m_streamIndex, 0);
d.readBool(184, &m_useReverseAPI, false);
d.readString(185, &m_reverseAPIAddress, "127.0.0.1");
d.readU32(186, &utmp, 0);
if ((utmp > 1023) && (utmp < 65535)) {
m_reverseAPIPort = utmp;
} else {
m_reverseAPIPort = 8888;
}
d.readU32(187, &utmp, 0);
m_reverseAPIDeviceIndex = utmp > 99 ? 99 : utmp;
d.readU32(188, &utmp, 0);
m_reverseAPIChannelIndex = utmp > 99 ? 99 : utmp;
for (int i = 0; i < RADIOASTRONOMY_POWERTABLE_COLUMNS; i++) {
d.readS32(400 + i, &m_powerTableColumnIndexes[i], i);
}
for (int i = 0; i < RADIOASTRONOMY_POWERTABLE_COLUMNS; i++) {
d.readS32(500 + i, &m_powerTableColumnSizes[i], -1);
}
return true;
}
else
{
resetToDefaults();
return false;
}
}

View File

@ -0,0 +1,225 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2017 Edouard Griffiths, F4EXB. //
// Copyright (C) 2021 Jon Beniston, M7RCE //
// //
// 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_RADIOASTRONOMYSETTINGS_H
#define INCLUDE_RADIOASTRONOMYSETTINGS_H
#include <QByteArray>
#include <QString>
#include <QDateTime>
#include "dsp/dsptypes.h"
class Serializable;
// Number of columns in the tables
#define RADIOASTRONOMY_POWERTABLE_COLUMNS 27
// Number of sensors
#define RADIOASTRONOMY_SENSORS 2
struct RadioAstronomySettings
{
int m_inputFrequencyOffset;
int m_sampleRate;
int m_rfBandwidth;
int m_integration; //!< Number of samples to integrate
int m_fftSize;
enum FFTWindow {
REC,
HAN
} m_fftWindow; //!< FFT windowing function
QString m_filterFreqs; //!< List of channels (bin indices) to filter in FFT to remove RFI
QString m_starTracker; //!< Name of Star Tracker plugin to link with
QString m_rotator; //!< Name of antenna rotator
float m_tempRX; //!< Receiver noise temperature in K (Front end NF)
float m_tempCMB; //!< Cosmic microwave background temperature in K
float m_tempGal; //!< Galactic background temperature in K
float m_tempSP; //!< Spillover temperature in K
float m_tempAtm; //!< Atmospheric temperature in K
float m_tempAir; //!< Surface air temperature in C
float m_zenithOpacity; //!< Opacity of atmosphere at zenith
float m_elevation; //!< Elevation in degrees, if not using value from Star Tracker
bool m_tempGalLink;
bool m_tempAtmLink;
bool m_tempAirLink;
bool m_elevationLink;
float m_gainVariation; //!< delta G/G
enum SourceType {
UNKNOWN,
COMPACT,
EXTENDED,
SUN,
CAS_A
} m_sourceType; //!< Whether the source it smaller than the beam
float m_omegaS; //!< Source angle
enum AngleUnits {
DEGREES,
STERRADIANS
} m_omegaSUnits;
enum AngleUnits m_omegaAUnits;
bool m_spectrumPeaks;
bool m_spectrumMarkers;
bool m_spectrumTemp;
bool m_spectrumReverseXAxis;
bool m_spectrumRefLine;
bool m_spectrumLAB;
bool m_spectrumDistance;
bool m_spectrumLegend;
float m_spectrumReference; //!< In dB
float m_spectrumRange; //!< In dB
float m_spectrumSpan; //!< In Mhz
float m_spectrumCenterFreqOffset; //!< Offset - rather than absolute - In Mhz
bool m_spectrumAutoscale;
enum SpectrumYScale {
SY_DBFS,
SY_SNR,
SY_DBM,
SY_TSYS,
SY_TSOURCE
} m_spectrumYScale;
enum SpectrumBaseline {
SBL_TSYS0,
SBL_TMIN,
SBL_CAL_COLD
} m_spectrumBaseline;
bool m_recalibrate;
float m_tCalHot; //!< Hot calibration antenna noise temperature in K (Sky + Spillover?)
float m_tCalCold; //!< Cold calibration antenna noise temperature in K
enum Line {
HI,
OH,
DI,
CUSTOM_LINE
} m_line; //!< Spectral line to plot and use as Doppler reference
float m_lineCustomFrequency; //!< Spectral line frequency when m_line==CUSTOM
enum RefFrame {
TOPOCENTRIC,
BCRS,
LSR
} m_refFrame; //!< Reference frame for velocities
float m_sunDistanceToGC; //!< Sun distance to Galactic Center In kpc
float m_sunOrbitalVelocity; //!< In km/s around GC
bool m_powerPeaks;
bool m_powerMarkers;
bool m_powerAvg;
bool m_powerLegend;
bool m_powerShowTsys0; //!< Plot total noise temperature
bool m_powerShowAirTemp;
bool m_powerShowGaussian;
float m_powerReference; //!< In dB
float m_powerRange; //!< In dB
bool m_powerAutoscale;
enum PowerYData {
PY_POWER,
PY_TSYS,
PY_TSOURCE,
PY_FLUX,
PY_2D_MAP
} m_powerYData;
enum PowerYUnits {
PY_DBFS,
PY_DBM,
PY_WATTS,
PY_KELVIN,
PY_SFU,
PY_JANSKY
} m_powerYUnits;
enum SweepType {
SWP_AZEL,
SWP_LB,
SWP_OFFSET
};
bool m_power2DLinkSweep; //<! Update setting below to match sweep parameters
SweepType m_power2DSweepType;
int m_power2DWidth;
int m_power2DHeight;
float m_power2DXMin;
float m_power2DXMax;
float m_power2DYMin;
float m_power2DYMax;
bool m_powerColourAutoscale;
float m_powerColourScaleMin;
float m_powerColourScaleMax;
QString m_powerColourPalette;
enum RunMode {
SINGLE,
CONTINUOUS,
SWEEP
} m_runMode;
bool m_sweepStartAtTime;
QDateTime m_sweepStartDateTime;
SweepType m_sweepType;
float m_sweep1Start;
float m_sweep1Stop;
float m_sweep1Step;
float m_sweep1Delay; //!< Delay after rotation before a measurement
float m_sweep2Start;
float m_sweep2Stop;
float m_sweep2Step;
float m_sweep2Delay; //!< Delay after a measurement before starting the next
QString m_sensorName[RADIOASTRONOMY_SENSORS];
QString m_sensorDevice[RADIOASTRONOMY_SENSORS];
QString m_sensorInit[RADIOASTRONOMY_SENSORS];
QString m_sensorMeasure[RADIOASTRONOMY_SENSORS];
bool m_sensorEnabled[RADIOASTRONOMY_SENSORS];
bool m_sensorVisible[RADIOASTRONOMY_SENSORS];
float m_sensorMeasurePeriod;
bool m_gpioEnabled;
int m_gpioPin;
int m_gpioSense;
QString m_startCalCommand;
QString m_stopCalCommand;
float m_calCommandDelay; //!< Delay in seconds after command before starting cal
quint32 m_rgbColor;
QString m_title;
Serializable *m_channelMarker;
int m_streamIndex; //!< MIMO channel. Not relevant when connected to SI (single Rx).
bool m_useReverseAPI;
QString m_reverseAPIAddress;
uint16_t m_reverseAPIPort;
uint16_t m_reverseAPIDeviceIndex;
uint16_t m_reverseAPIChannelIndex;
int m_powerTableColumnIndexes[RADIOASTRONOMY_POWERTABLE_COLUMNS];//!< How the columns are ordered in the table
int m_powerTableColumnSizes[RADIOASTRONOMY_POWERTABLE_COLUMNS]; //!< Size of the columns in the table
RadioAstronomySettings();
void resetToDefaults();
void setChannelMarker(Serializable *channelMarker) { m_channelMarker = channelMarker; }
QByteArray serialize() const;
bool deserialize(const QByteArray& data);
static const QStringList m_pipeTypes;
static const QStringList m_pipeURIs;
};
#endif /* INCLUDE_RADIOASTRONOMYSETTINGS_H */

View File

@ -0,0 +1,304 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2019 Edouard Griffiths, F4EXB //
// Copyright (C) 2021 Jon Beniston, M7RCE //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation as version 3 of the License, or //
// (at your option) any later version. //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License V3 for more details. //
// //
// You should have received a copy of the GNU General Public License //
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#include <QDebug>
#include "dsp/dspengine.h"
#include "radioastronomy.h"
#include "radioastronomysink.h"
RadioAstronomySink::RadioAstronomySink(RadioAstronomy *aisDemod) :
m_radioAstronomy(aisDemod),
m_channelSampleRate(1000000),
m_channelFrequencyOffset(0),
m_fftSequence(-1),
m_fft(nullptr),
m_fftCounter(0),
m_fftSum(nullptr),
m_fftTemp(nullptr),
m_fftSumCount(0),
m_enabled(false),
m_cal(false),
m_magsqSum(0.0f),
m_magsqPeak(0.0f),
m_magsqCount(0),
m_messageQueueToChannel(nullptr)
{
m_magsq = 0.0;
applySettings(m_settings, true);
applyChannelSettings(m_channelSampleRate, m_channelFrequencyOffset, true);
}
RadioAstronomySink::~RadioAstronomySink()
{
delete[] m_fftSum;
delete[] m_fftTemp;
}
void RadioAstronomySink::feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end)
{
Complex ci;
for (SampleVector::const_iterator it = begin; it != end; ++it)
{
Complex c(it->real(), it->imag());
c *= m_nco.nextIQ();
if (m_interpolatorDistance < 1.0f) // interpolate
{
while (!m_interpolator.interpolate(&m_interpolatorDistanceRemain, c, &ci))
{
processOneSample(ci);
m_interpolatorDistanceRemain += m_interpolatorDistance;
}
}
else // decimate
{
if (m_interpolator.decimate(&m_interpolatorDistanceRemain, c, &ci))
{
processOneSample(ci);
m_interpolatorDistanceRemain += m_interpolatorDistance;
}
}
}
}
void RadioAstronomySink::processOneSample(Complex &ci)
{
// Calculate power
double magsqRaw = ci.real()*ci.real() + ci.imag()*ci.imag();
double magsq = (magsqRaw / (SDR_RX_SCALED*SDR_RX_SCALED));
// Calculate average and peak levels for level meter
m_movingAverage(magsq);
m_magsq = m_movingAverage.asDouble();
m_magsqSum += magsq;
if (magsq > m_magsqPeak)
{
m_magsqPeak = magsq;
}
m_magsqCount++;
if (m_enabled || m_cal)
{
// Add to FFT input buffer
m_fft->in()[m_fftCounter] = Complex(ci.real() / SDR_RX_SCALEF, ci.imag() / SDR_RX_SCALEF);
m_fftCounter++;
if (m_fftCounter >= m_settings.m_fftSize)
{
// Calculate FFT
m_fftWindow.apply(m_fft->in());
m_fft->transform();
m_fftCounter = 0;
// Calculate power and accumulate
for (int i = 0; i < m_settings.m_fftSize; i++)
{
Complex s = m_fft->out()[i];
Real v = s.real() * s.real() + s.imag() * s.imag();
Real enbw = 1.0f;
/*if (m_settings.m_fftWindow == RadioAstronomySettings::HAN && m_settings.m_fftCorrection == RadioAstronomySettings::POWER) {
enbw = 1.5; // FIXME: Small dependence on fftSize in Matlab
}*/
m_fftSum[i] += v / (enbw * m_settings.m_fftSize * m_settings.m_fftSize); // Why FFT size here and not Fs?
}
m_fftSumCount++;
if (m_fftSumCount >= m_settings.m_integration)
{
// Average
for (int i = 0; i < m_settings.m_fftSize; i++) {
m_fftSum[i] /= m_fftSumCount;
}
// Put negative frequencies first
std::copy(m_fftSum + m_settings.m_fftSize/2, m_fftSum + m_settings.m_fftSize, m_fftTemp);
std::copy(m_fftSum, m_fftSum + m_settings.m_fftSize/2, m_fftTemp + m_settings.m_fftSize/2);
// Filter freqs with RFI
if (m_filterBins.size() > 0)
{
// Find minimum value to use as replacement
// Should possibly use an average of the n lowest values or something
float minVal = std::numeric_limits<float>::max();
for (int i = 0; i < m_settings.m_fftSize; i++) {
minVal = std::min(minVal, m_fftTemp[i]);
}
for (int i = 0; i < m_filterBins.size(); i++)
{
int bin = m_filterBins[i];
if (bin < m_settings.m_fftSize) {
m_fftTemp[bin] = minVal;
}
}
}
getMessageQueueToChannel()->push(RadioAstronomy::MsgMeasurementProgress::create(100));
if (m_cal)
{
// Indicate calibration complete
if (getMessageQueueToChannel())
{
RadioAstronomy::MsgCalComplete *msg = RadioAstronomy::MsgCalComplete::create(m_fftTemp, m_settings.m_fftSize, QDateTime::currentDateTime(), m_hot);
getMessageQueueToChannel()->push(msg);
}
// Cal complete
m_cal = false;
}
else
{
// Send averaged FFT to channel
if (getMessageQueueToChannel())
{
RadioAstronomy::MsgFFTMeasurement *msg = RadioAstronomy::MsgFFTMeasurement::create(m_fftTemp, m_settings.m_fftSize, QDateTime::currentDateTime());
getMessageQueueToChannel()->push(msg);
}
m_enabled = (m_settings.m_runMode == RadioAstronomySettings::CONTINUOUS);
if (m_enabled) {
getMessageQueueToChannel()->push(RadioAstronomy::MsgMeasurementProgress::create(0));
}
}
m_fftSumCount = 0;
std::fill(m_fftSum, m_fftSum + m_settings.m_fftSize, 0.0f);
}
else
{
// Don't send more than ~4 updates per second
int fftsPerSecond = m_settings.m_sampleRate / m_settings.m_fftSize;
if ((m_fftSumCount % (fftsPerSecond/4)) == 0) {
getMessageQueueToChannel()->push(RadioAstronomy::MsgMeasurementProgress::create(100 * m_fftSumCount / m_settings.m_integration));
}
}
}
}
}
void RadioAstronomySink::startMeasurements()
{
getMessageQueueToChannel()->push(RadioAstronomy::MsgMeasurementProgress::create(0));
m_enabled = true;
m_fftSumCount = 0;
std::fill(m_fftSum, m_fftSum + m_settings.m_fftSize, 0.0f);
}
void RadioAstronomySink::stopMeasurements()
{
m_enabled = false;
}
void RadioAstronomySink::startCal(bool hot)
{
getMessageQueueToChannel()->push(RadioAstronomy::MsgMeasurementProgress::create(0));
m_cal = true;
m_hot = hot;
m_fftSumCount = 0;
std::fill(m_fftSum, m_fftSum + m_settings.m_fftSize, 0.0f);
}
void RadioAstronomySink::applyChannelSettings(int channelSampleRate, int channelFrequencyOffset, bool force)
{
qDebug() << "RadioAstronomySink::applyChannelSettings:"
<< " channelSampleRate: " << channelSampleRate
<< " channelFrequencyOffset: " << channelFrequencyOffset;
if ((m_channelFrequencyOffset != channelFrequencyOffset) ||
(m_channelSampleRate != channelSampleRate) || force)
{
m_nco.setFreq(-channelFrequencyOffset, channelSampleRate);
}
if ((m_channelSampleRate != channelSampleRate) || force)
{
m_interpolator.create(16, channelSampleRate, m_settings.m_rfBandwidth / 2.0f);
m_interpolatorDistance = (Real) channelSampleRate / (Real) m_settings.m_sampleRate;
m_interpolatorDistanceRemain = m_interpolatorDistance;
}
m_channelSampleRate = channelSampleRate;
m_channelFrequencyOffset = channelFrequencyOffset;
}
void RadioAstronomySink::applySettings(const RadioAstronomySettings& settings, bool force)
{
qDebug() << "RadioAstronomySink::applySettings:"
<< " m_sampleRate: " << settings.m_sampleRate
<< " m_rfBandwidth: " << settings.m_rfBandwidth
<< " m_fftSize: " << settings.m_fftSize
<< " m_fftWindow: " << settings.m_fftWindow
<< " m_filterFreqs: " << settings.m_filterFreqs
<< " force: " << force;
if ((settings.m_rfBandwidth != m_settings.m_rfBandwidth)
|| (settings.m_sampleRate != m_settings.m_sampleRate)
|| force)
{
m_interpolator.create(16, m_channelSampleRate, settings.m_rfBandwidth / 2.0f); // 2.0 rather than 2.2 as in other plugins, to reduce rolloff at edge of band
m_interpolatorDistance = (Real) m_channelSampleRate / (Real) settings.m_sampleRate;
m_interpolatorDistanceRemain = m_interpolatorDistance;
}
if ((settings.m_fftSize != m_settings.m_fftSize) || force)
{
FFTFactory *fftFactory = DSPEngine::instance()->getFFTFactory();
if (m_fftSequence >= 0) {
fftFactory->releaseEngine(m_settings.m_fftSize, false, m_fftSequence);
}
m_fftSequence = fftFactory->getEngine(settings.m_fftSize, false, &m_fft);
m_fftCounter = 0;
delete[] m_fftSum;
delete[] m_fftTemp;
m_fftSum = new Real[settings.m_fftSize]();
m_fftTemp = new Real[settings.m_fftSize]();
m_fftSumCount = 0;
}
if ((settings.m_fftSize != m_settings.m_fftSize)
|| (settings.m_fftWindow != m_settings.m_fftWindow)
|| force)
{
if (settings.m_fftWindow == RadioAstronomySettings::HAN) {
m_fftWindow.create(FFTWindow::Hanning, settings.m_fftSize);
} else {
m_fftWindow.create(FFTWindow::Rectangle, settings.m_fftSize);
}
}
if ((settings.m_filterFreqs != m_settings.m_filterFreqs) || force)
{
m_filterBins.clear();
QStringList filterFreqs = settings.m_filterFreqs.split(" ");
for (int i = 0; i < filterFreqs.size(); i++)
{
bool ok;
int bin = filterFreqs[i].toInt(&ok);
if (ok) {
m_filterBins.append(bin);
}
}
}
m_settings = settings;
}

View File

@ -0,0 +1,123 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2019 Edouard Griffiths, F4EXB //
// Copyright (C) 2021 Jon Beniston, M7RCE //
// //
// 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_RADIOASTRONOMYSINK_H
#define INCLUDE_RADIOASTRONOMYSINK_H
#include "dsp/channelsamplesink.h"
#include "dsp/nco.h"
#include "dsp/interpolator.h"
#include "dsp/fftfactory.h"
#include "dsp/fftengine.h"
#include "dsp/fftwindow.h"
#include "util/movingaverage.h"
#include "util/messagequeue.h"
#include "radioastronomysettings.h"
class ChannelAPI;
class RadioAstronomy;
class RadioAstronomySink : public ChannelSampleSink {
public:
RadioAstronomySink(RadioAstronomy *aisDemod);
~RadioAstronomySink();
virtual void feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end);
void applyChannelSettings(int channelSampleRate, int channelFrequencyOffset, bool force = false);
void applySettings(const RadioAstronomySettings& settings, bool force = false);
void setMessageQueueToChannel(MessageQueue *messageQueue) { m_messageQueueToChannel = messageQueue; }
void setChannel(ChannelAPI *channel) { m_channel = channel; }
void startMeasurements();
void stopMeasurements();
void startCal(bool hot);
void clearCal();
double getMagSq() const { return m_magsq; }
void getMagSqLevels(double& avg, double& peak, int& nbSamples)
{
if (m_magsqCount > 0)
{
m_magsq = m_magsqSum / m_magsqCount;
m_magSqLevelStore.m_magsq = m_magsq;
m_magSqLevelStore.m_magsqPeak = m_magsqPeak;
}
avg = m_magSqLevelStore.m_magsq;
peak = m_magSqLevelStore.m_magsqPeak;
nbSamples = m_magsqCount == 0 ? 1 : m_magsqCount;
m_magsqSum = 0.0f;
m_magsqPeak = 0.0f;
m_magsqCount = 0;
}
private:
struct MagSqLevelsStore
{
MagSqLevelsStore() :
m_magsq(1e-12),
m_magsqPeak(1e-12)
{}
double m_magsq;
double m_magsqPeak;
};
RadioAstronomy *m_radioAstronomy;
RadioAstronomySettings m_settings;
ChannelAPI *m_channel;
int m_channelSampleRate;
int m_channelFrequencyOffset;
int m_fftSequence;
FFTEngine *m_fft;
FFTWindow m_fftWindow;
int m_fftCounter;
QList<int> m_filterBins;
Real *m_fftSum;
Real *m_fftTemp;
int m_fftSumCount;
bool m_enabled;
bool m_cal;
bool m_hot;
NCO m_nco;
Interpolator m_interpolator;
Real m_interpolatorDistance;
Real m_interpolatorDistanceRemain;
double m_magsq;
double m_magsqSum;
double m_magsqPeak;
int m_magsqCount;
MagSqLevelsStore m_magSqLevelStore;
MessageQueue *m_messageQueueToChannel;
MovingAverageUtil<Real, double, 16> m_movingAverage;
void processOneSample(Complex &ci);
MessageQueue *getMessageQueueToChannel() { return m_messageQueueToChannel; }
};
#endif // INCLUDE_RADIOASTRONOMYSINK_H

View File

@ -0,0 +1,52 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2019 Edouard Griffiths, F4EXB. //
// Copyright (C) 2021 Jon Beniston, M7RCE //
// //
// 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 "radioastronomy.h"
#include "radioastronomywebapiadapter.h"
RadioAstronomyWebAPIAdapter::RadioAstronomyWebAPIAdapter()
{}
RadioAstronomyWebAPIAdapter::~RadioAstronomyWebAPIAdapter()
{}
int RadioAstronomyWebAPIAdapter::webapiSettingsGet(
SWGSDRangel::SWGChannelSettings& response,
QString& errorMessage)
{
(void) errorMessage;
response.setRadioAstronomySettings(new SWGSDRangel::SWGRadioAstronomySettings());
response.getRadioAstronomySettings()->init();
RadioAstronomy::webapiFormatChannelSettings(response, m_settings);
return 200;
}
int RadioAstronomyWebAPIAdapter::webapiSettingsPutPatch(
bool force,
const QStringList& channelSettingsKeys,
SWGSDRangel::SWGChannelSettings& response,
QString& errorMessage)
{
(void) force;
(void) errorMessage;
RadioAstronomy::webapiUpdateChannelSettings(m_settings, channelSettingsKeys, response);
return 200;
}

View File

@ -0,0 +1,50 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2019 Edouard Griffiths, F4EXB. //
// Copyright (C) 2020 Jon Beniston, M7RCE //
// //
// 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_RADIOASTRONOMY_WEBAPIADAPTER_H
#define INCLUDE_RADIOASTRONOMY_WEBAPIADAPTER_H
#include "channel/channelwebapiadapter.h"
#include "radioastronomysettings.h"
/**
* Standalone API adapter only for the settings
*/
class RadioAstronomyWebAPIAdapter : public ChannelWebAPIAdapter {
public:
RadioAstronomyWebAPIAdapter();
virtual ~RadioAstronomyWebAPIAdapter();
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:
RadioAstronomySettings m_settings;
};
#endif // INCLUDE_RADIOASTRONOMY_WEBAPIADAPTER_H

View File

@ -0,0 +1,160 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2021 Jon Beniston, M7RCE //
// Copyright (C) 2020 Edouard Griffiths, F4EXB //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation as version 3 of the License, or //
// (at your option) any later version. //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License V3 for more details. //
// //
// You should have received a copy of the GNU General Public License //
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#include <cmath>
#include <QDebug>
#include "radioastronomy.h"
#include "radioastronomyworker.h"
MESSAGE_CLASS_DEFINITION(RadioAstronomyWorker::MsgConfigureRadioAstronomyWorker, Message)
RadioAstronomyWorker::RadioAstronomyWorker(RadioAstronomy* radioAstronomy) :
m_radioAstronomy(radioAstronomy),
m_msgQueueToChannel(nullptr),
m_msgQueueToGUI(nullptr),
m_running(false),
m_mutex(QMutex::Recursive),
m_sensorTimer(this)
{
connect(&m_sensorTimer, SIGNAL(timeout()), this, SLOT(measureSensors()));
m_sensorTimer.start((int)round(m_settings.m_sensorMeasurePeriod*1000.0));
for (int i = 0; i < RADIOASTRONOMY_SENSORS; i++) {
m_session[i] = VI_NULL;
}
}
RadioAstronomyWorker::~RadioAstronomyWorker()
{
m_inputMessageQueue.clear();
m_visa.closeDefault();
}
void RadioAstronomyWorker::reset()
{
QMutexLocker mutexLocker(&m_mutex);
m_inputMessageQueue.clear();
}
bool RadioAstronomyWorker::startWork()
{
QMutexLocker mutexLocker(&m_mutex);
connect(&m_inputMessageQueue, SIGNAL(messageEnqueued()), this, SLOT(handleInputMessages()));
m_running = true;
return m_running;
}
void RadioAstronomyWorker::stopWork()
{
QMutexLocker mutexLocker(&m_mutex);
disconnect(&m_inputMessageQueue, SIGNAL(messageEnqueued()), this, SLOT(handleInputMessages()));
m_running = false;
}
void RadioAstronomyWorker::handleInputMessages()
{
Message* message;
while ((message = m_inputMessageQueue.pop()) != nullptr)
{
if (handleMessage(*message)) {
delete message;
}
}
}
bool RadioAstronomyWorker::handleMessage(const Message& cmd)
{
if (MsgConfigureRadioAstronomyWorker::match(cmd))
{
QMutexLocker mutexLocker(&m_mutex);
MsgConfigureRadioAstronomyWorker& cfg = (MsgConfigureRadioAstronomyWorker&) cmd;
applySettings(cfg.getSettings(), cfg.getForce());
return true;
}
else
{
return false;
}
}
void RadioAstronomyWorker::applySettings(const RadioAstronomySettings& settings, bool force)
{
qDebug() << "RadioAstronomyWorker::applySettings:"
<< " m_sensorEnabled[0]: " << settings.m_sensorEnabled[0]
<< " m_sensorDevice[0]: " << settings.m_sensorDevice[0]
<< " m_sensorInit[0]: " << settings.m_sensorInit[0]
<< " m_sensorMeasure[0]: " << settings.m_sensorMeasure[0]
<< " force: " << force;
for (int i = 0; i < RADIOASTRONOMY_SENSORS; i++)
{
if ( (settings.m_sensorEnabled[i] != m_settings.m_sensorEnabled[i])
|| (settings.m_sensorEnabled[i] && (settings.m_sensorDevice[i] != m_settings.m_sensorDevice[i]))
|| force)
{
if (!settings.m_sensorEnabled[i] && (m_session[i] != VI_NULL))
{
m_visa.close(m_session[i]);
m_session[i] = VI_NULL;
}
if (settings.m_sensorEnabled[i] && !settings.m_sensorDevice[i].trimmed().isEmpty())
{
m_visa.openDefault();
m_session[i] = m_visa.open(settings.m_sensorDevice[i]);
}
}
if ( (settings.m_sensorEnabled[i] && !m_settings.m_sensorEnabled[i])
|| (settings.m_sensorEnabled[i] && (settings.m_sensorInit[i] != m_settings.m_sensorInit[i]))
|| force)
{
if (m_session[i]) {
m_visa.processCommands(m_session[i], settings.m_sensorInit[i]);
}
}
}
if ((settings.m_sensorMeasurePeriod != m_settings.m_sensorMeasurePeriod) || force) {
m_sensorTimer.start((int)round(settings.m_sensorMeasurePeriod * 1000.0));
}
m_settings = settings;
}
void RadioAstronomyWorker::measureSensors()
{
for (int i = 0; i < RADIOASTRONOMY_SENSORS; i++)
{
if (m_settings.m_sensorEnabled[i] && m_session[i])
{
QStringList results = m_visa.processCommands(m_session[i], m_settings.m_sensorMeasure[i]);
if (results.size() >= 1)
{
double value = results[0].toDouble();
if (getMessageQueueToGUI()) {
getMessageQueueToGUI()->push(RadioAstronomy::MsgSensorMeasurement::create(i, value));
}
}
else
{
qDebug() << "RadioAstronomyWorker::measureSensors: No result for command " << m_settings.m_sensorMeasure[i];
}
}
}
}

View File

@ -0,0 +1,93 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2021 Jon Beniston, M7RCE //
// Copyright (C) 2020 Edouard Griffiths, F4EXB //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation as version 3 of the License, or //
// (at your option) any later version. //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License V3 for more details. //
// //
// You should have received a copy of the GNU General Public License //
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#ifndef INCLUDE_RADIOASTRONOMYWORKER_H
#define INCLUDE_RADIOASTRONOMYWORKER_H
#include <QObject>
#include <QTimer>
#include "util/message.h"
#include "util/messagequeue.h"
#include "util/visa.h"
#include "radioastronomysettings.h"
class RadioAstronomy;
class RadioAstronomyWorker : public QObject
{
Q_OBJECT
public:
class MsgConfigureRadioAstronomyWorker : public Message {
MESSAGE_CLASS_DECLARATION
public:
const RadioAstronomySettings& getSettings() const { return m_settings; }
bool getForce() const { return m_force; }
static MsgConfigureRadioAstronomyWorker* create(const RadioAstronomySettings& settings, bool force)
{
return new MsgConfigureRadioAstronomyWorker(settings, force);
}
private:
RadioAstronomySettings m_settings;
bool m_force;
MsgConfigureRadioAstronomyWorker(const RadioAstronomySettings& settings, bool force) :
Message(),
m_settings(settings),
m_force(force)
{ }
};
RadioAstronomyWorker(RadioAstronomy* radioAstronomy);
~RadioAstronomyWorker();
void reset();
bool startWork();
void stopWork();
bool isRunning() const { return m_running; }
MessageQueue *getInputMessageQueue() { return &m_inputMessageQueue; }
void setMessageQueueToChannel(MessageQueue *messageQueue) { m_msgQueueToChannel = messageQueue; }
void setMessageQueueToGUI(MessageQueue *messageQueue) { m_msgQueueToGUI = messageQueue; }
private:
RadioAstronomy* m_radioAstronomy;
MessageQueue m_inputMessageQueue; //!< Queue for asynchronous inbound communication
MessageQueue *m_msgQueueToChannel;
MessageQueue *m_msgQueueToGUI;
RadioAstronomySettings m_settings;
bool m_running;
QMutex m_mutex;
VISA m_visa;
ViSession m_session[RADIOASTRONOMY_SENSORS];
QTimer m_sensorTimer;
bool handleMessage(const Message& cmd);
void applySettings(const RadioAstronomySettings& settings, bool force = false);
MessageQueue *getMessageQueueToGUI() { return m_msgQueueToGUI; }
private slots:
void handleInputMessages();
void measureSensors();
};
#endif // INCLUDE_RADIOASTRONOMYWORKER_H

View File

@ -0,0 +1,864 @@
<h1>Radio Astronomy plugin</h1>
<h2>Introduction</h2>
The Radio Astronomy plugin provides a number of tools to help make radio astronomy measurements. It supports:
- A spectrometer for displaying time averaged spectra.
- A radiometer for displaying time averaged continuum measurements (total power).
- Calibration to enable measurements to be displayed as noise temperatures (K), power (dBm/Watts) and spectral flux density (Jy).
- Utilities are included for estimation and calculation of noise temperature components (Tsys, Trx, Tgal, Tatm, Tsky, Tsp) and sensitivity (sigma Tsys and sigma Sv).
- Spectra can be displayed against frequency and velocity (with a configurable reference spectral line), with the velocity adjusted to topocentric, Solar System barycentric or the Local Standard of Rest (LSR) reference frames.
- Calculation and plotting of radial and Galactocentric distance to HI clouds, based on spectral peaks.
- Position of HI clouds can be sent to Star Tracker plugin for visualisation on the Galactic line-of-sight image and created in to an animation mapping out the Milky Way's spiral arms.
- A Gaussian fitting tool in the spectrometer for HI cloud kinetic temperature and column density estimation.
- A Gaussian fitting tool in the radiometer to enable antenna HPBW measurement from Solar drift-scans.
- Ability to record and plot real-time surface air temperature and other sensor measurements (component voltages / temperatures) alongside radiometer measurements.
- Ability to export charts to animated .png files and static image files.
- Reference spectra from the LAB (Leiden/Argentine/Bonn) Galactic HI survey can be automatically downloaded and plotted for comparison against user measurements.
- 2D sweeps can be made and plotted in different coordinate systems (Az/El, Galactic, offsets around a target and drift scans).
- All spectra are held in memory and can be scrolled through.
- Data can be saved and loaded from .csv files.
- Hardware for calibration (E.g. RF switches) can be automatically controlled.
![Radio Astronomy plugin GUI](../../../doc/img/RadioAstronomy_plugin.png)
Several of the features in this plugin are tailored towards measurements of neutral hydrogen (HI) that is dispersed throughout the Milky Way's interstellar medium (ISM).
The HI in the ISM is a particularly interesting astronomical radiation source for SDR users, as the ground-state hyperfine transition of HI has a rest frequency of 1420.405MHz,
which is both quite powerful (due to the vast amount of HI spread throughout the Milky Way) and at a frequency that is easy to detect with relatively small dishes and low-cost LNAs and SDRs.
The HI spectrum can be used to determine some of the Milky Way's spiral structure and calculate rotation curves for the inner Milky Way, which suggest the presence of dark matter.
In radio astronomy it is common to use noise temperatures rather than power, via the relation:
T=P/(k*B)
Where:
T is the noise temperature in Kelvin
P is power in Watts
k is Boltzmann's constant
B is bandwidth in Hertz
Similarly, for low frequencies (where the Rayleigh-Jeans approximation is valid), brightness temperatures are used rather than intensity:
Tb=e*Iv*c^2/(2k*v^2)
Where:
Tb is the brightness temperature in Kelvin
e is the emissivity of the source
Iv is the intensity of the source (power per unit solid angle at the frequency v)
c is the speed of light
v is the frequency in Hertz
This can be convenient, as if a large astronomical source completely fills the antenna beam with a uniform brightness temperature,
there will be an equal increase in the noise temperature measured by the receiver.
For thermal sources of radiation, the brightness temperature can also correspond directly to the physical temperature of the source.
This isn't true for non-thermal sources, however, such as synchrotron radiation.
In this plugin, the following notation is used for the different temperature sources and combinations:
- Trx - Receiver noise temperature. This is the combined noise temperature due to the LNA, feed line and SDR.
- Tcmb - Cosmic Microwave Background temperature (2.73K).
- Tgal - Galactic background temperature. An estimate of the frequency dependent background that is assumed to be the same in all directions.
- Tsky - Combined CMB, Galactic background and foreground as calculated in Star Tracker plugin using all-sky survey data.
- Tatm - Atmospheric emission, dependent upon frequency, opacity (which is dependent on temperature, pressure and water vapour) and elevation.
- Tsp - Spillover temperature due to thermal ground noise and other thermal noise sources such as trees and buildings around the antenna.
- Tair - Surface air temperature (In C, unlike all other temperatures which are in K).
- Tsource - Contribution from astronomical source (What we are typically trying to measure).
- Tsys0 - Total of all unwanted noise (Trx+Tcmb+Tgal+Tatm+Tsp).
- Tsys - System noise temperature. Sum of all received noise (Tsys0+Tsource).
- Tb - Brightness temperature of the source.
- Ta - Antenna temperature (which is typically Tcmb+Tgal+Tatm+Tsp+Tsource).
Care should be taken when comparing to definitions in the literature, as these vary significantly. In particular, Tsys can be defined to include or
exclude the astronomical source contribution and Ta can be just the source or all antenna noise.
For most astronomical observations, Tsource<<Tsys and so we need to integrate many measurements, such that Tsource is typically five times larger
than the random variations in the total noise (sigma_Tsys). The length of time and bandwidth required for this can be calculated from the
[practical radiometer equation](https://www.cv.nrao.edu/~sransom/web/Ch3.html#E158):
sigma_Tsys = Tsys * sqrt(1/(B*tau) + (deltaG/G)^2)
Where:
sigma_Tsys = Standard deviation / RMS of system noise temperature.
Tsys is system noise temperature.
B is bandwidth in Hertz.
tau is the integration time in seconds.
deltaG/G is the receiver gain variation.
<h2>Settings</h2>
![Settings GUI](../../../doc/img/RadioAstronomy_Settings.png)
<h3>1: Frequency shift from center frequency of reception</h3>
Use the wheels to adjust the frequency shift in Hz from the center frequency of reception. Left click on a digit sets the cursor position at this digit.
Right click on a digit sets all digits on the right to zero. This effectively floors value at the digit position.
Wheels are moved with the mousewheel while pointing at the wheel or by selecting the wheel with the left mouse click and using the keyboard arrows.
Pressing shift simultaneously moves digit by 5 and pressing control moves it by 2.
<h3>2: SR - Sample Rate</h3>
Sample rate in millions of samples per second. This determines the maximum bandwidth for the radiometer and spectrometer and thus the maximum Doppler shift range.
Typically this should be set to match SDRangel's baseband sample rate.
<h3>3: BW - RF Bandwidth</h3>
This specifies the bandwidth of a LPF that is applied to the input signal to limit the RF bandwidth. This can be used to eliminate RFI.
<h3>4: Channel power</h3>
Average total power in dB relative to a +/- 1.0 amplitude signal received in the pass band.
<h3>5: Integration Count</h3>
Specifies the number of FFTs that are summed in each average. Higher integration counts increase measurement time, but also increase sensitivity (up to the limit imposed by receiver gain variation).
<h3>6: Channels</h3>
Specifies the number of channels (FFT bins). A larger number means an increased resolution in the spectrometer,
however, the sensitivity per bin is decreased for a fixed measurement time.
<h3>7: Window function</h3>
A windowing function to be applied before the FFT, to compensate for spectral leakage. This can be either:
- Rec: Rectangular or no windowing function. Use for broadband / continuum sources.
- Han: Hanning window. Use for narrowband / spectral line sources for better frequency resolution.
<h3>8: Filter</h3>
Specifies a list of FFT bins that will have their values replaced with the minimum of other FFTs bins. This can be used to filter inband RFI.
<h3>9: Integration Time</h3>
Displays in seconds or minutes how long it will take to make a single measurement. This is dependent on the sample rate (2), Integration Count (5) and number of channels (6).
<h3>10: Star Tracker</h3>
Specifies the Star Tracker feature that determines the observation target.
A corresponding Star Tracker feature is required to calculate and display numerous values within the Radio Astronomy plugin and also for performing sweeps.
<h3>11: Rotator</h3>
Specifies the rotator controller feature that is controlling the antenna used for measurements by the Radio Astronomy plugin.
This setting is used when sweeps are performed, to determine when rotation is complete and the antenna is pointing at the target.
If no rotator is used (and only drift scans are performed), this can be set to None.
<h3>12: Sensors</h3>
Opens the Sensors dialog.
The Sensors dialog allows two measurements such as voltage and temperature to be recorded and plotted along with radiometer data.
The sensor measurements are made using the VISA (Virtual Instruments Software Architecture) API, which is implemented in many
benchtop multimeters, oscilloscopes and spectrum analyzers.
Sensor measurements can be used to monitor temperatures and voltages that might have an impact on measurements. For example, the gain
on the LNA will be dependent upon both, and gain variations limit the benefit of increased integration counts on sensitivity.
![Sensors dialog](../../../doc/img/RadioAstronomy_SensorSettings.png)
<h3>13: Trx/NF</h3>
Sets the receiver noise temperature in Kelvin or noise figure (NF) in dB. This is the noise temperature / figure for the combination of the LNA, feed line and SDR (at a specific gain setting).
The value set here can be measured using SDRangel's [Noise Figure plugin](https://github.com/f4exb/sdrangel/blob/master/plugins/channelrx/noisefigure/readme.md)
or estimated from datasheet values for the individual components using the [Friis formula](https://en.wikipedia.org/wiki/Friis_formulas_for_noise).
<h3>14: Tcmb</h3>
Sets the contribution to noise temperature from the Cosmic Microwave Background (CMB). This is 2.73K when an antenna is pointed at the Sky, but may be set to 0K if measurements are made
where there is no CMB contribution (E.g. if the feedhorn is covered with absorbing foam or a 50Ohm terminator or other noise source is used for calibration).
<h3>15: Tgal</h3>
Sets the contribution to the noise temperature from the Galactic background. This is frequency dependent and varies with direction. It does not include
the Galactic foreground (i.e. the increased noise temperature when looking in the Galactic plane).
If the link button to the right is unchecked, a value can be entered manually.
If the link button is checked, Tgal is calculated using:
Tgal = 25.2 * (f/f0)^-2.75
Where:
25.2 is the 50th percentile of the all-sky distribution temperature.
f is the center frequency.
f0 is 408MHz.
Tgal is used in calibration to estimate Tsp.
<h3>16: Tsp</h3>
Sets spillover noise temperature. This is unwanted noise due to thermal ground radiation or other thermal radiation sources such as buildings and trees that can be picked
up via an antenna's side and back lobes.
It can be very dependent on azimuth and elevation in urban environments.
An estimate for Tsp can be made via the hot/cold calibration process.
<h3>17: Tatm</h3>
Contribution to noise temperature due to atmospheric emission. Atmospheric emission is dependent upon frequency, opacity (which is dependent on air temperature, pressure and water vapour) and antenna elevation.
If the link button to the right is unchecked, a value can be entered manually.
If the link button is checked, Tatm is calculated using:
Tatm = Tair * (1 - exp(-tau_z*sec(el)))
Where:
Tair is the surface air temperature from (18).
tau_z is the zenith opacity from (19).
el is the elevation of the antenna from (20)
<h3>18: Tair</h3>
Tair specifies the surface air temperature at the antenna location in degrees Celsius.
If the link button to the right is unchecked, a value can be entered manually.
If the link button is checked, Tair is set to the air temperature value received from the Star Tracker plugin, which itself is periodically downloaded from openweathermap.org for the antenna's location.
<h3>19: tau_z - Zenith Opacity</h3>
tau_z specifies the Zenith opacity. This value determines atmospheric absorption and emission. It is dependent upon air temperature, pressure and water vapour.
The default value of 0.0055 roughly corresponds to clear air as per ITU-R P.372-14 figure 5 at 1.4GHz.
<h3>20: El - Antenna Elevation</h3>
This specifies the antenna elevation in degrees. It is used for calculating atmospheric emission and absorption.
If the link button to the right is unchecked, a value can be entered manually.
If the link button is checked, El is automatically set to the elevation received from the Star Tracker plugin.
<h3>21: Tsys0</h3>
This displays the value of Tsys0, the system noise temperature without an astronomical source, which is calculated as:
Tsys0=Trx+Tcmb+Tgal+Tsp+Tatm.
<h3>22: sigma Tsys0</h3>
This displays the value of sigma Tsys0, which is the standard deviation / RMS of Tsys0, and gives an indication of the sensitivity. It is calculated as:
sigma_Tsys0 = Tsys0 * sqrt(1/(B*tau) + (deltaG/G)^2)
<h3>24: Baseline</h3>
Specifies the baseline used for calculating Tsource from Tsys. This can be:
- Tsys0 - Tsource = Tsys-Tsys0.
- Tmin - Tsource = Tsys-Tmin - where Tmin is the minimum in-band temperature.
- Tcold - Tsource = Tsys-Tcold - where Tcold is the cold calibration spectrum. This can be used for on/off source observations.
<h3>25: delta G / G - Gain Variation</h3>
delta G / G specifies the gain variation of the LNA / receiver. Gain variation places a limit on the sensitvity improvement available by increased integration counts.
This value is only used for the estimation of sigma_Tsys0 and sigma_Ssys0, it does not affect any measurements.
<h3>26: HPBW / Omega A</h3>
This displays the antenna half-power (-3dB) beamwidth (HPBW) in degrees or beam solid angle in steradians, as set in the Star Tracker plugins set by (10).
<h3>27: Omega S Type</h3>
This sets the type of astronomical source, with respect to its and the antenna beam's angular size:
- Unknown - Used for when the source is unknown. Brightness temperature (Tb) will not be able to be calculated.
- Compact - The source is smaller than the antenna beam. The source angle can be entered in (28).
- Extended - The source is larger than the antenna beam.
- Sun - The source is the Sun and the source angle is set to 0.53 degrees.
- CasA - The source is Cassiopeia A and the source is set to 0.08333 degrees.
<h3>28: Omega S</h3>
Enter the angle subtended by the astronomical source. This can be a diameter entered in degrees or solid angle in steradians.
Values for many astronomical sources are available in the [SIMBAD Astronomical Database](http://simbad.u-strasbg.fr/simbad/).
<h3>29: Omega S Units</h3>
Select whether Omega S is calculated from a diameter in degrees or solid angle in steradians.
<h3>Run Control</h3>
![Run Control GUI](../../../doc/img/RadioAstronomy_RunControl.png)
<h3>Start / Stop</h3>
Starts or stops measurements.
The Radio Astronomy plugin has this button in addition to SDRangel's device acquisition Start/stop button, so that the
SDR continues to run when measurements are not being taken. This can help to reduce small gain & frequency variations that may occur in a SDR
when it is turned on from cold.
<h3>Clear Measurements</h3>
Clears all measurements from memory. Calibration data is kept.
<h3>Run Mode</h3>
The run mode field determines the number of measurements that are made then the Start button is pressed.
- Single: A single measurement is made.
- Continuous: Measurements are continuously made until the Stop button is pressed.
- Sweep: Measurements are made at each of the coordinates specified by the sweep fields.
<h3>Start Time</h3>
The start time field determines when the measurements start after the Start button is pressed:
- Now: Measurements start immediately.
- At: Measurements start at the date and time specified in the date/time editor immediately below.
Delaying the start of the measurements can be used to ensure that the target has risen to its maximum elevation.
<h3>Sweep Parameters</h3>
The Sweep Type field determines the coordinates that are swept:
- Az/El - Coordinates are swept in azimuth then elevation.
- l/b - Coordinates are swept in Galactic longitude then latitude.
- Offset - Sweep values are azimuth and elevation offsets from the center of the target set in Star Tracker.
Here are some examples:
Sweep Type: Az/El
Az Start: 100
Az Stop: 120
Az Step: 10
El Start: 80
El Stop: 85
El Step: 5
Will measure at (Az,El): 100,80 110,80, 120,80 100,85 110,85, 120,85
Sweep Type: Az/El
Az Start: 15
Az Stop: 345
Az Step: -15
El Start: 85
El Stop: 85
El Step: 0
Will measure at (Az,El): 15,85 0,85, 345,85
Sweep Type: l/b
l Start: -60
l Stop: 60
l Step: 20
b Start: 0
b Stop: 0
b Step: 0
Will measure at (l,b): 300,0 320,0 340,0 0,0 20,0 40,0, 60,0
Sweep Type: Offset
Az Start: -5
Az Stop: 5
Az Step: 5
El Start: -5
El Stop: 5
El Step: 5
Target in Star Tracker: Sun
Will measure at (Az,El): Sun-5,Sun-5 Sun,Sun-5 Sun+5,Sun-5 Sun-5,Sun Sun,Sun Sun+5,Sun Sun-5,Sun+5 Sun,Sun+5 Sun+5,Sun+5
The Settle field specifies a delay in seconds after antenna rotation has completed, before the measurement starts.
The Delay field specifies a delay in seconds after a measurement has completed, before the antenna is rotated for the next measurement.
<h3>Status</h3>
The measurement status bar shows how complete a measurement is in percent.
<h2>Spectrometer</h2>
![Spectrometer GUI](../../../doc/img/RadioAstronomy_Spectrometer.png)
<h3>Spectrum Selection</h3>
This combo box selects between the display of measurement spectra and calibration spectra.
<h3>Y Axis Units</h3>
Selects the units for the Y-axis:
- dBFS displays received power in dB relative to fullscale.
- SNR displays the signal to noise ratio (where the noise is the cold calibration spectrum).
- dBm displays the received power in dBm (requires hot calibration).
- TSys K displays the system noise temperature in Kelvin (requires hot calibration).
- TSource K displays the astronomical source temperature in Kelvin (requires hot calibration).
<h3>Display Legend</h3>
Displays a legend at the side of the chart with the colour and name of each series.
<h3>Display LAB Reference Spectrum</h3>
When checked, a reference spectrum from the Leiden/Argentine/Bonn (LAB) Galactic HI survey corresponding to the current Galactic coordinates
and antenna HPBW will be downloaded and displayed along side the measured spectrum.
This allows a comparison between your HI measurements and that from a professional survey.
![LAB Reference Spectrum](../../../doc/img/RadioAstronomy_LAB.png)
In order to reduce bandwidth to the server supplying this data, it is recommended to use this option sparingly.
If the series does not appear on Windows (and you see "SSL handshake failed" in the log file), you may need to open https://www.astro.uni-bonn.de/hisurvey/euhou/index.php in your Web browser first, so that the certificate for the website is downloaded.
<h3>Calculate and plot distance to HI gas clouds</h3>
When checked, the marker table will have six additional columns that display estimates of the distance to a HI cloud corresponding to the marker and the tangent point
along the line of sight.
- Vr is radial velocity of the cloud in km/s, relative to the selected reference frame.
- R is the distance from the cloud to the Galactic centre in kiloparsecs (kpc).
- d is the line-of-sight distance to the cloud in kpc. In some instances there can be two possible solutions.
- Plot max determines whether the smaller or larger solution to d is sent to the Star Tracker plugin for display.
- Rmin is the minimum distance to the Galactic centre in kiloparsecs (kpc) along the line of sight (i.e. at the tangent point).
- Vmax is the orbital velocity at the tangent point.
Vmax can be plotted against Rmin to determine the rotation curve of the Milky Way.
d can be plotted against Galactic longitude in Star Tracker to map out the Milky Way's spiral arms.
The spectrometer GUI will also display two additional fields, R0 and V0,
which allow you to enter the distance from the Sun to the Galactic centre and the Sun's orbital velocity
around the Galactic centre, which are used in the above calculations.
![Distance to HI Cloud](../../../doc/img/RadioAstronomy_RadioAstronomy_DistanceToHICloud.png)
<h3>Display Reference Spectral Line</h3>
When checked, a horizontal axis showing Doppler shift in km/s is added to the top of the spectrometer chart and a vertical reference spectral line is plotted at 0km/s.
The rest frequency of the spectral line can be set via the reference spectral line field or manually entered.
The relationship between the frequency and velocity axes is determined by the selected reference frame.
![Reference Spectral Line](../../../doc/img/RadioAstronomy_RefLine.png)
<h3>Display Gaussian Fitting Tools</h3>
When checked, the Gaussian fitting tools are displayed. These allow a Gaussian to be fitted to a spectral peak for kinetic temperature and column density estimation.
![Gaussian Fit](../../../doc/img/RadioAstronomy_SpectrumGaussian.png)
<h3>Display Markers<h3>
When checked, the marker table is displayed and the user may place two markers (M1 and M2) on the chart for accurate display of the corresponding values.
<h3>Display Peaks</h3>
When checked, the peak table is displayed and the peak Max marker is displayed at the maximum value in the spectrum.
<h3>Reverse X axis</h3>
When checked, the X axis is reversed. This allows switching between an axis that increases with frequency (which is most common in engineering) or increases with velocity (which is most common in radio astronomy).
<h3>Save Charts to an Animation File</h3>
Click to export all of the spectral measurements to a animated .png file.
<h3>Save Chart to an Image File</h3>
Click to save the current chart to an image file.
<h3>Load Data from a .csv File</h3>
Click to restore data that had been saved to a .csv file. All existing data will be cleared.
<h3>Save Data from a .csv File</h3>
Click to save all data to a .csv file.
<h3>Autoscale</h3>
When checked, continuously automatically scales both X and Y axis so all data is visible. When unchecked, the axis scales can be set manually.
<h3>Autoscale X</h3>
When clicked, automatically scales the X axis so all data is visible.
<h3>Autoscale Y</h3>
When clicked, automatically scales the Y axis so all data is visible.
<h3>Ref</h3>
Sets the reference level (maximum value) of the Y axis.
<h3>Range</h3>
Sets the range of the Y axis.
<h3>CF</h3>
Sets the centre frequency of the X axis.
<h3>Span</h3>
Sets the span (range) of the X axis.
<h3>Sel</h3>
Selects what is selected when clicking on the chart:
- M1 sets position of marker 1
- M2 sets position of marker 2
- Gaussian sets peak of Gaussian
<h3>Date & Time</h3>
Allows the user to scroll through and select the recorded spectra, showing the date and time they were measured at.
<h3>Line</h3>
Specifies the rest frequency of the reference spectral line:
- HI neutral hydrogen at 1420.405760MHz.
- OH hydroxyl at 1612.231040Mhz.
- DI neutral deuterium at 327.384MHz.
- Custom allows a user-defined frequency in MHz to be entered.
<h3>Reference Frame</h3>
Determines the reference frame used for calculating velocities from frequency.
- Topo is a topocentric reference frame (i.e. relative to the observation location).
- BCRS is the barycentric celestial reference system (i.e. relative to the Solar System's barycenter (centre of mass)).
- LSR is the local standard of rest (i.e. relative to the local standard of rest, which accounts for the Sun's movements relative to other nearby stars).
Professional astronomers tend to plot spectra using the LSR, so any observed Doppler shift can assumed to be due to the source moving.
<h3>R0</h3>
Specifies the distance of the Sun from the Galactic centre in kpc.
<h3>V0</h3>
Specifies the orbital velocity of the Sun around the Galactic centre in km/s.
<h3>f0</h3>
Specifies the frequency of the centre of the Gaussian in MHz.
<h3>a</h3>
Specifies the amplitude of the Gaussian. Units correspond to the Y axis units.
<h3>f</h3>
Specifies the floor (minimum value of the Gaussian). Units correspond to the Y axis units.
<h3>Delta f FHWM</h3>
Specifies the full-width at half maximum of the Gaussian in Hertz.
<h3>Tk</h3>
An estimate of kinetic temperature in Kelvin of a HI cloud whose spectral profile matches the Gaussian.
Note that it's not possible to determine how much spectral broadening is due to kinetic temperature and
how much is due to turbulent velocity, as from a single measurement, there is no way
to distinguish between the two.
<h3>Vt</h3>
An estimate of the turbulent velocity within a HI cloud whose spectral profile matches the Gaussian.
<h3>NH</h3>
Estimated column density of an optically thin HI cloud whose spectral profile matches the Gaussian,
measured in HI atoms per square centimetre.
<h3>Marker Table</h3>
The marker table displays corresponding values for markers that are placed on the chart.
<h2>Radiometer</h2>
![Radiometer GUI](../../../doc/img/RadioAstronomy_Radiometer.png)
<h3>Chart Selection</h3>
This field selects between the display of power, temperature and flux in one or two dimensions.
<h3>Y Axis Units</h3>
Selects the units for the Y-axis:
- dBFS displays received power in dB relative to fullscale.
- dBm displays the received power in dBm (requires hot calibration).
- dBm displays the received power in Watts (requires hot calibration).
- K displays the temperature in Kelvin (requires hot calibration).
- SFU displays the flux in Solar Flux units (requires hot calibration).
- Jy displays the flux in Jansky (requires hot calibration).
<h3>Display Legend</h3>
Displays a legend at the side of the chart with the colour and name of each series.
<h3>Plot Sensor 2</h3>
Plot the data recorded for sensor 2 on the chart.
<h3>Plot Sensor 1</h3>
Plot the data recorded for sensor 1 on the chart.
<h3>Plot Air Temperature</h3>
Plot the surface air temperature data received from Star Tracker on the chart.
<h3>Plot Tsys0</h3>
Plot Tsys0 on the chart.
<h3>Display Statistics</h3>
Displays statistics calculated across all measurements (not just those visible on the chart), including the mean, RMS and standard deviation.
<h3>Display Gaussian Fitting Tools</h3>
When checked, the Gaussian fitting tools are displayed. These allow a Gaussian to be fitted to the data, allowing measurement of the HPBW of the antenna.
<h3>Display Markers<h3>
When checked, the marker table is displayed and the user may place two markers (M1 and M2) on the chart for accurate display of the corresponding values from the measurement series.
<h3>Display Peaks</h3>
When checked, the marker table is displayed and the peak Max and Min markers are displayed at the maximum and minimum values on the measurement series.
<h3>Save Chart to an Image File</h3>
Click to save the current chart to an image file.
<h3>Save Data to a .csv File</h3>
Click to save data from the Radiometer Data table to a .csv file.
<h3>Autoscale</h3>
When checked, continuously automatically scales both X and Y axis so all data is visible. When unchecked, the axis scales can be set manually.
<h3>Autoscale X</h3>
When clicked, automatically scales the X axis so all data is visible.
<h3>Autoscale Y</h3>
When clicked, automatically scales the Y axis so all data is visible.
<h3>Ref</h3>
Sets the reference level (maximum value) of the Y axis.
<h3>Range</h3>
Sets the range of the Y axis.
<h3>Start</h3>
Sets the start time of the X axis.
<h3>End</h3>
Sets the end time of the X axis.
<h3>Sel</h3>
Selects what is selected when clicking on the chart:
- Row highlights the corresponding row in the Radiometer Data table to the point clicked.
- M1 sets position of marker 1
- M2 sets position of marker 2
- Gaussian sets peak of Gaussian
<h3>Center</h3>
Specifies the date and time of the center of the Gaussian.
<h3>a</h3>
Specifies the amplitude of the Gaussian. Units correspond to the Y axis units.
<h3>f</h3>
Specifies the floor (minimum value of the Gaussian). Units correspond to the Y axis units.
<h3>Delta t FHWM</h3>
Specifies the full-width at half maximum of the Gaussian in seconds.
<h3>HPBW</h3>
An estimate of the HPBW in degrees of an antenna whose main lobe corresponds to the Gaussian profile of a drift scan of the Sun, using a linear scale (E.g. Y axis must not be in not dB).
![Radiometer Gaussian Fit](../../../doc/img/RadioAstronomy_RadiometerGaussian.png)
<h3>Marker Table</h3>
The marker table displays corresponding values for markers that are placed on the chart.
<h2>Radiometer 2D Map</h2>
![Radiometer 2D Map](../../../doc/img/RadioAstronomy_Radiometer2D.png)
<h3>Link Sweep</h3>
When checked, the parameters for the 2D Map will be automatically updated based on the Run Control sweep parameters.
<h3>Sweep Type</h3>
Sets the coordinates used for the axes of the map.
<h3>Width</h3>
Width in pixels of the map. Typically there should be one pixel per measurement.
<h3>Height</h3>
Height in pixels of the map.
<h3>X Range</h3>
Specifies the range of the 2D map's horizontal axis. This determines how measurements map to pixels.
<h3>Y Range</h3>
Specifies the range of the 2D map's vertical axis.
<h3>Autoscale</h3>
Automatically scales the X and Y axes to fit the Radiometer data in the table.
<h3>Colour Autoscale</h3>
Automatically scales the colour palette to the range of existing values in the Radiometer data table.
<h3>Min</h3>
Specifies the value that maps to the first colour in the palette. All values lower than this will be clipped to the first colour.
<h3>Max</h3>
Specifies the value that maps to the last colour in the palette. All values higher than this will be clipped to the last colour.
<h3>Palette</h3>
Specifies the palette / gradient used to plot the 2D map. This can either be colour or greyscale. The gradient is applied linearly between the Min and Max values.
<h2>Radiometer Data</h2>
The Radiometer Data table shows measurement results and settings at the time of measurement in tabular form.
![Radiometer Data GUI](../../../doc/img/RadioAstronomy_RadiometerData.png)
The columns in the table include:
- Date - Date at the end of the measurement.
- Time - Time at the end of the measurement.
- Power (FFT) - Power relative to fullscale (sum of FFT absolute magnitude).
- Power (dBFS) - Power in dBFS.
- Power (dBm) - Power in dBm.
- Tsys (K) - System noise temperature in Kelvin.
- Tsys0 (K) - System noise temperature (excluding Tsource) in Kelvin.
- Tsource (K) - Source noise temperature in Kelvin.
- Tb (K) - Source brightness temperature in Kelvin.
- Tsky (K) - Sky temperature in Kelvin towards the target from Star Tracker.
- Sv (Jy) - Spectral flux density in Jansky.
- sigmaTsys (K) - Standard deviation of Tsys in Kelvin.
- sigmaSsys (Jy) - Standard deviation of Sv in Jansky.
- omegaA (sr) - Antenna beam solid angle.
- omegaS (sr) - Source solid angle.
- RA - Right ascension of target from Star Tracker.
- Dec - Declination of target from Star Tracker.
- l - Galactic longitude of target from Star Tracker.
- b - Galactic latitude of target from Star Tracker.
- Az - Azimuth of target from Star Tracker.
- El - Elevation of target from Star Tracker.
- Vbcrs - Observer velocity relative to barycentric celestial reference system (BCRS).
- Vlsr - Observer velocity relative to local standard of rest (LSR).
- Solar Flux (jy) - Solar flux from Star Tracker.
- Air Temp (C) - Surface air temperature at observation point in Celsius from Star Tracker.
- Sensor 1 - Data recorded for Sensor 1.
- Sensor 2 - Data recorded for Sensor 2.
Right clicking on the table shows a popup menu that supports:
- Copying the value in the cell to the clipboard
- Deleting the selected rows
- Applying the current values of Tsys0, baseline and omega S to recalculate Tsource, Tb and Sv.
<h2>Calibration</h2>
Power measurements in SDRs are typically relative (E.g. dBFS) rather than absolute (E.g. dBm). In order to produce absolute power measurements,
and thus noise temperature measurements, we need to perform a calibration process that calculates a mapping from the relative power value to an absolute value.
Also, there are multiple unwanted noise sources that contribute to the measured power (LNA and receiver noise, for example),
that we wish to subtract from our power measurement, to get a measurement of the power of the radiation received from the astronomical object we are observing.
The first step is to measure the noise of the receiver, Trx. This is the combined noise of the LNA, feed line and SDR, for a particular gain setting.
This can be measured with a calibrated noise source connected to the LNA input using SDRangel's [Noise Figure plugin](https://github.com/f4exb/sdrangel/blob/master/plugins/channelrx/noisefigure/readme.md),
or estimated from datasheet values for the individual components using the [Friis formula](https://en.wikipedia.org/wiki/Friis_formulas_for_noise).
It is also possible to calculate this within the Radio Astronomy plugin by running a hot and cold calibration. The plugin will then use the Y factor method
to estimate Trx, and this will be displayed in the Trx field, below the chart. Whatever method is used, the value should be entered in to the Trx field in the Settings area.
In order to map relative powers to absolute powers (and temperatures), a hot calibration should be run. To run a hot calibration, the noise
temperature of the calibration source is entered in to the Thot field (or power into Phot) and then press the "Start hot calibration" button. (The process
is likewise to run a cold calibration). The main consideration for a user, is what can be used as a calibration source and how is it connected to the antenna/receiver.
There are two ways, with and without an antenna:
For parabolic dishes or horn antennas, an object at a known temperature can be used, so long as it completely covers the feed horn aperture.
The object needs to be as close to an ideal blackbody as possible, with high emissivity at the frequencies of interest, so that the temperature
of the object results in an identical increase in noise temperature in the antenna. If the dish is steerable to point towards the ground, the temperature
of the ground may be used.
It is also possible to calibrate by directly connecting a noise source to the LNA input. This could be as simple as 50Ohm termination resistor,
which should result in a noise temperature corresponding to the physical temperature of the resistor, assuming good impedance matching and very low insertion loss.
One large unknown can be the spillover temperature, Tsp. This is the noise contribution due to ground or building thermal radiation leaking in
to the feed horn from the back or side lobes. Once Trx is known, is possible to estimate Tsp by performing a hot and cold calibration,
where the hot calibration uses an object blocking the feed, but the cold calibration has the feed unblocked pointing to a cold part of the sky.
The temperature of the cold sky can be estimated from an all-sky survey in Star Tracker, and this is displayed under the calibration chart as Tsky.
If Thot is measured with Tsp=0, Tcold is Tsky, and Trx is known, then the plugin can estimate Tsp for the cold measurement. Note that Tsp is typically strongly
dependent on the antenna's elevation and azimuth, as this changes the amount of ground thermal radiation that gets in to the antenna.
![Calibration Settings dialog](../../../doc/img/RadioAstronomy_Calibration.png)
<h3>Show Calibration Settings Dialog</h3>
When clicked, shows the Calibration Settings dialog.
The Calibration Settings dialog allows a user to control hardware used for calibration. It supports two methods: GPIO pins in a SDR can be toggled during calibration and/or
commands/scripts can be run before and after calibration. The pre-calibration delay setting specifies a delay in seconds between the GPIO being toggled or start command
being executed, before the calibration routine in the plugin starts.
An example of its use would be to electronically switch in a 50Ohm resistor to the LNA input when calibration is run, using one of the SDR's GPIO pins to control the RF switch.
![Calibration Settings dialog](../../../doc/img/RadioAstronomy_CalibrationSettings.png)
<h3>Clear Calibration Data</h3>
Clears all calibration data.
<h3>Start Hot Calibration</h3>
Starts a measurement that will be used as the hot calibration data.
<h3>Start Cold Calibration</h3>
Starts a measurement that will be used as the cold calibration data.
<h3>Recalibrate All Measurements</h3>
When checked, results of a new calibration will be applied to all existing measurements. When unchecked, the calibration will only apply to new measurements.
<h2>API</h2>
Full details of the API can be found in the Swagger documentation. Here is a quick example of how to start a measurement from the command line:
curl -X POST "http://127.0.0.1:8091/sdrangel/deviceset/0/channel/0/actions" -d '{"channelType": "RadioAstronomy", "direction": 0, "RadioAstronomyActions": { "start": {"sampleRate": 2000000} }}'
Or to set the sample rate:
curl -X PATCH "http://127.0.0.1:8091/sdrangel/deviceset/0/channel/0/settings" -d '{"channelType": "RadioAstronomy", "direction": 0, "RadioAstronomySettings": {"sampleRate": 2000000}}'
<h2>Attribution</h2>
Many equations are from Essential Radio Astronomy by James Condon and Scott Ransom: https://www.cv.nrao.edu/~sransom/web/xxx.html
The Leiden/Argentine/Bonn (LAB) Survey of Galactic HI: https://arxiv.org/abs/astro-ph/0504140 and EU-HOU project: https://www.astro.uni-bonn.de/hisurvey/euhou/index.php
Thermometer icons are by Freepik from https://www.flaticon.com/
Reverse icon by Creaticca Creative Agency from https://www.flaticon.com/

View File

@ -662,13 +662,13 @@ void StarTracker::networkManagerFinished(QNetworkReply *reply)
void StarTracker::weatherUpdated(float temperature, float pressure, float humidity)
{
if (!isnan(temperature)) {
if (!std::isnan(temperature)) {
m_settings.m_temperature = temperature;
}
if (!isnan(pressure)) {
if (!std::isnan(pressure)) {
m_settings.m_pressure = pressure;
}
if (!isnan(humidity)) {
if (!std::isnan(humidity)) {
m_settings.m_humidity = humidity;
}

View File

@ -27,6 +27,8 @@
#include "SWGDeviceSet.h"
#include "SWGChannelActions.h"
#include "SWGFileSinkActions.h"
#include "SWGFeatureSettings.h"
#include "SWGFeatureReport.h"
#include "maincore.h"
#include "device/deviceset.h"
@ -37,14 +39,13 @@
#include "dsp/devicesamplemimo.h"
#include "webapi/webapiadapterinterface.h"
#include "webapi/webapiutils.h"
#include "feature/featureset.h"
#include "feature/feature.h"
// Get device center frequency
bool ChannelWebAPIUtils::getCenterFrequency(unsigned int deviceIndex, double &frequencyInHz)
bool ChannelWebAPIUtils::getDeviceSettings(unsigned int deviceIndex, SWGSDRangel::SWGDeviceSettings &deviceSettingsResponse, DeviceSet *&deviceSet)
{
SWGSDRangel::SWGDeviceSettings deviceSettingsResponse;
QString errorResponse;
int httpRC;
DeviceSet *deviceSet;
// Get current device settings
std::vector<DeviceSet*> deviceSets = MainCore::instance()->getDeviceSets();
@ -74,114 +75,129 @@ bool ChannelWebAPIUtils::getCenterFrequency(unsigned int deviceIndex, double &fr
}
else
{
qDebug() << "ChannelWebAPIUtils::getCenterFrequency - not a sample source device " << deviceIndex;
qDebug() << "ChannelWebAPIUtils::getDeviceSettings - not a sample source device " << deviceIndex;
return false;
}
}
else
{
qDebug() << "ChannelWebAPIUtils::getCenterFrequency - no device " << deviceIndex;
qDebug() << "ChannelWebAPIUtils::getDeviceSettings - no device " << deviceIndex;
return false;
}
if (httpRC/100 != 2)
{
qWarning("ChannelWebAPIUtils::getCenterFrequency: get device frequency error %d: %s",
qWarning("ChannelWebAPIUtils::getDeviceSettings: get device settings error %d: %s",
httpRC, qPrintable(errorResponse));
return false;
}
QJsonObject *jsonObj = deviceSettingsResponse.asJsonObject();
return WebAPIUtils::getSubObjectDouble(*jsonObj, "centerFrequency", frequencyInHz);
return true;
}
bool ChannelWebAPIUtils::getFeatureSettings(unsigned int featureSetIndex, unsigned int featureIndex, SWGSDRangel::SWGFeatureSettings &featureSettingsResponse, Feature *&feature)
{
QString errorResponse;
int httpRC;
FeatureSet *featureSet;
// Get current feature settings
std::vector<FeatureSet*> featureSets = MainCore::instance()->getFeatureeSets();
if (featureSetIndex < featureSets.size())
{
featureSet = featureSets[featureSetIndex];
if (featureIndex < featureSet->getNumberOfFeatures())
{
feature = featureSet->getFeatureAt(featureIndex);
httpRC = feature->webapiSettingsGet(featureSettingsResponse, errorResponse);
}
else
{
qDebug() << "ChannelWebAPIUtils::getFeatureSettings: no feature " << featureSetIndex << ":" << featureIndex;
return false;
}
}
else
{
qDebug() << "ChannelWebAPIUtils::getFeatureSettings: no feature set " << featureSetIndex;
return false;
}
if (httpRC/100 != 2)
{
qWarning("ChannelWebAPIUtils::getFeatureSettings: get feature settings error %d: %s",
httpRC, qPrintable(errorResponse));
return false;
}
return true;
}
// Get device center frequency
bool ChannelWebAPIUtils::getCenterFrequency(unsigned int deviceIndex, double &frequencyInHz)
{
SWGSDRangel::SWGDeviceSettings deviceSettingsResponse;
DeviceSet *deviceSet;
if (getDeviceSettings(deviceIndex, deviceSettingsResponse, deviceSet))
{
QJsonObject *jsonObj = deviceSettingsResponse.asJsonObject();
return WebAPIUtils::getSubObjectDouble(*jsonObj, "centerFrequency", frequencyInHz);
}
else
{
return false;
}
}
// Set device center frequency
bool ChannelWebAPIUtils::setCenterFrequency(unsigned int deviceIndex, double frequencyInHz)
{
SWGSDRangel::SWGDeviceSettings deviceSettingsResponse;
QString errorResponse;
int httpRC;
DeviceSet *deviceSet;
// Get current device settings
std::vector<DeviceSet*> deviceSets = MainCore::instance()->getDeviceSets();
if (deviceIndex < deviceSets.size())
if (getDeviceSettings(deviceIndex, deviceSettingsResponse, deviceSet))
{
deviceSet = deviceSets[deviceIndex];
if (deviceSet->m_deviceSourceEngine)
// Patch centerFrequency
QJsonObject *jsonObj = deviceSettingsResponse.asJsonObject();
double freq;
if (WebAPIUtils::getSubObjectDouble(*jsonObj, "centerFrequency", freq))
{
deviceSettingsResponse.setDeviceHwType(new QString(deviceSet->m_deviceAPI->getHardwareId()));
deviceSettingsResponse.setDirection(0);
WebAPIUtils::setSubObjectDouble(*jsonObj, "centerFrequency", frequencyInHz);
QStringList deviceSettingsKeys;
deviceSettingsKeys.append("centerFrequency");
deviceSettingsResponse.init();
deviceSettingsResponse.fromJsonObject(*jsonObj);
SWGSDRangel::SWGErrorResponse errorResponse2;
DeviceSampleSource *source = deviceSet->m_deviceAPI->getSampleSource();
httpRC = source->webapiSettingsGet(deviceSettingsResponse, errorResponse);
}
else if (deviceSet->m_deviceSinkEngine)
{
deviceSettingsResponse.setDeviceHwType(new QString(deviceSet->m_deviceAPI->getHardwareId()));
deviceSettingsResponse.setDirection(1);
DeviceSampleSink *sink = deviceSet->m_deviceAPI->getSampleSink();
httpRC = sink->webapiSettingsGet(deviceSettingsResponse, errorResponse);
}
else if (deviceSet->m_deviceMIMOEngine)
{
deviceSettingsResponse.setDeviceHwType(new QString(deviceSet->m_deviceAPI->getHardwareId()));
deviceSettingsResponse.setDirection(2);
DeviceSampleMIMO *mimo = deviceSet->m_deviceAPI->getSampleMIMO();
httpRC = mimo->webapiSettingsGet(deviceSettingsResponse, errorResponse);
httpRC = source->webapiSettingsPutPatch(false, deviceSettingsKeys, deviceSettingsResponse, *errorResponse2.getMessage());
if (httpRC/100 == 2)
{
qDebug("ChannelWebAPIUtils::setCenterFrequency: set device frequency %f OK", frequencyInHz);
return true;
}
else
{
qWarning("ChannelWebAPIUtils::setCenterFrequency: set device frequency error %d: %s",
httpRC, qPrintable(*errorResponse2.getMessage()));
return false;
}
}
else
{
qDebug() << "ChannelWebAPIUtils::setCenterFrequency: not a sample source device " << deviceIndex;
qWarning("ChannelWebAPIUtils::setCenterFrequency: no centerFrequency key in device settings");
return false;
}
}
else
{
qDebug() << "ChannelWebAPIUtils::setCenterFrequency: no device " << deviceIndex;
return false;
}
if (httpRC/100 != 2)
{
qWarning("ChannelWebAPIUtils::setCenterFrequency: get device frequency error %d: %s",
httpRC, qPrintable(errorResponse));
return false;
}
// Patch centerFrequency
QJsonObject *jsonObj = deviceSettingsResponse.asJsonObject();
double freq;
if (WebAPIUtils::getSubObjectDouble(*jsonObj, "centerFrequency", freq))
{
WebAPIUtils::setSubObjectDouble(*jsonObj, "centerFrequency", frequencyInHz);
QStringList deviceSettingsKeys;
deviceSettingsKeys.append("centerFrequency");
deviceSettingsResponse.init();
deviceSettingsResponse.fromJsonObject(*jsonObj);
SWGSDRangel::SWGErrorResponse errorResponse2;
DeviceSampleSource *source = deviceSet->m_deviceAPI->getSampleSource();
httpRC = source->webapiSettingsPutPatch(false, deviceSettingsKeys, deviceSettingsResponse, *errorResponse2.getMessage());
if (httpRC/100 == 2)
{
qDebug("ChannelWebAPIUtils::setCenterFrequency: set device frequency %f OK", frequencyInHz);
}
else
{
qWarning("ChannelWebAPIUtils::setCenterFrequency: set device frequency error %d: %s",
httpRC, qPrintable(*errorResponse2.getMessage()));
return false;
}
}
else
{
qWarning("ChannelWebAPIUtils::setCenterFrequency: no centerFrequency key in device settings");
return false;
}
return true;
}
// Start acquisition
@ -462,3 +478,214 @@ bool ChannelWebAPIUtils::satelliteLOS(const QString name)
}
return true;
}
bool ChannelWebAPIUtils::getDeviceSetting(unsigned int deviceIndex, const QString &setting, int &value)
{
SWGSDRangel::SWGDeviceSettings deviceSettingsResponse;
DeviceSet *deviceSet;
if (getDeviceSettings(deviceIndex, deviceSettingsResponse, deviceSet))
{
QJsonObject *jsonObj = deviceSettingsResponse.asJsonObject();
return WebAPIUtils::getSubObjectInt(*jsonObj, setting, value);
}
else
{
return false;
}
}
bool ChannelWebAPIUtils::patchDeviceSetting(unsigned int deviceIndex, const QString &setting, int value)
{
SWGSDRangel::SWGDeviceSettings deviceSettingsResponse;
QString errorResponse;
int httpRC;
DeviceSet *deviceSet;
if (getDeviceSettings(deviceIndex, deviceSettingsResponse, deviceSet))
{
// Patch centerFrequency
QJsonObject *jsonObj = deviceSettingsResponse.asJsonObject();
int oldValue;
if (WebAPIUtils::getSubObjectInt(*jsonObj, setting, oldValue))
{
WebAPIUtils::setSubObjectInt(*jsonObj, setting, value);
QStringList deviceSettingsKeys;
deviceSettingsKeys.append(setting);
deviceSettingsResponse.init();
deviceSettingsResponse.fromJsonObject(*jsonObj);
SWGSDRangel::SWGErrorResponse errorResponse2;
DeviceSampleSource *source = deviceSet->m_deviceAPI->getSampleSource();
httpRC = source->webapiSettingsPutPatch(false, deviceSettingsKeys, deviceSettingsResponse, *errorResponse2.getMessage());
if (httpRC/100 == 2)
{
qDebug("ChannelWebAPIUtils::patchDeviceSetting: set device setting %s OK", setting);
return true;
}
else
{
qWarning("ChannelWebAPIUtils::patchDeviceSetting: set device setting error %d: %s",
httpRC, qPrintable(*errorResponse2.getMessage()));
return false;
}
}
else
{
qWarning("ChannelWebAPIUtils::patchDeviceSetting: no key %s in device settings", setting);
return false;
}
}
else
{
return false;
}
}
// Set feature setting
bool ChannelWebAPIUtils::patchFeatureSetting(unsigned int featureSetIndex, unsigned int featureIndex, const QString &setting, const QString &value)
{
SWGSDRangel::SWGFeatureSettings featureSettingsResponse;
int httpRC;
Feature *feature;
if (getFeatureSettings(featureSetIndex, featureIndex, featureSettingsResponse, feature))
{
// Patch settings
QJsonObject *jsonObj = featureSettingsResponse.asJsonObject();
QString oldValue;
if (WebAPIUtils::getSubObjectString(*jsonObj, setting, oldValue))
{
WebAPIUtils::setSubObjectString(*jsonObj, setting, value);
QStringList featureSettingsKeys;
featureSettingsKeys.append(setting);
featureSettingsResponse.init();
featureSettingsResponse.fromJsonObject(*jsonObj);
SWGSDRangel::SWGErrorResponse errorResponse2;
httpRC = feature->webapiSettingsPutPatch(false, featureSettingsKeys, featureSettingsResponse, *errorResponse2.getMessage());
if (httpRC/100 == 2)
{
qDebug("ChannelWebAPIUtils::patchFeatureSetting: set feature setting %s to %s OK", setting, value);
return true;
}
else
{
qWarning("ChannelWebAPIUtils::patchFeatureSetting: set feature setting %s to %s error %d: %s",
setting, value, httpRC, qPrintable(*errorResponse2.getMessage()));
return false;
}
}
else
{
qWarning("ChannelWebAPIUtils::patchFeatureSetting: no key %s in feature settings", setting);
return false;
}
}
else
{
return false;
}
}
bool ChannelWebAPIUtils::patchFeatureSetting(unsigned int featureSetIndex, unsigned int featureIndex, const QString &setting, double value)
{
SWGSDRangel::SWGFeatureSettings featureSettingsResponse;
QString errorResponse;
int httpRC;
FeatureSet *featureSet;
Feature *feature;
if (getFeatureSettings(featureSetIndex, featureIndex, featureSettingsResponse, feature))
{
// Patch settings
QJsonObject *jsonObj = featureSettingsResponse.asJsonObject();
double oldValue;
if (WebAPIUtils::getSubObjectDouble(*jsonObj, setting, oldValue))
{
WebAPIUtils::setSubObjectDouble(*jsonObj, setting, value);
QStringList featureSettingsKeys;
featureSettingsKeys.append(setting);
featureSettingsResponse.init();
featureSettingsResponse.fromJsonObject(*jsonObj);
SWGSDRangel::SWGErrorResponse errorResponse2;
httpRC = feature->webapiSettingsPutPatch(false, featureSettingsKeys, featureSettingsResponse, *errorResponse2.getMessage());
if (httpRC/100 == 2)
{
qDebug("ChannelWebAPIUtils::patchFeatureSetting: set feature setting %s to %f OK", setting, value);
return true;
}
else
{
qWarning("ChannelWebAPIUtils::patchFeatureSetting: set feature setting %s to %s error %d: %s",
setting, value, httpRC, qPrintable(*errorResponse2.getMessage()));
return false;
}
}
else
{
qWarning("ChannelWebAPIUtils::patchFeatureSetting: no key %s in feature settings", setting);
return false;
}
}
else
{
return false;
}
}
bool ChannelWebAPIUtils::getFeatureReportValue(unsigned int featureSetIndex, unsigned int featureIndex, const QString &key, int &value)
{
SWGSDRangel::SWGFeatureReport featureReport;
QString errorResponse;
int httpRC;
FeatureSet *featureSet;
Feature *feature;
// Get feature report
std::vector<FeatureSet*> featureSets = MainCore::instance()->getFeatureeSets();
if (featureSetIndex < featureSets.size())
{
featureSet = featureSets[featureSetIndex];
if (featureIndex < featureSet->getNumberOfFeatures())
{
feature = featureSet->getFeatureAt(featureIndex);
httpRC = feature->webapiReportGet(featureReport, errorResponse);
}
else
{
qDebug() << "ChannelWebAPIUtils::getFeatureReportValue: no feature " << featureSetIndex << ":" << featureIndex;
return false;
}
}
else
{
qDebug() << "ChannelWebAPIUtils::getFeatureReportValue: no feature set " << featureSetIndex;
return false;
}
if (httpRC/100 != 2)
{
qWarning("ChannelWebAPIUtils::getFeatureReportValue: get feature report error %d: %s",
httpRC, qPrintable(errorResponse));
return false;
}
// Get value of requested key
QJsonObject *jsonObj = featureReport.asJsonObject();
if (WebAPIUtils::getSubObjectInt(*jsonObj, key, value))
{
// Done
return true;
}
else
{
qWarning("ChannelWebAPIUtils::getFeatureReportValue: no key %s in feature report", key);
return false;
}
}

View File

@ -20,8 +20,14 @@
#include <QString>
#include "SWGDeviceSettings.h"
#include "SWGFeatureSettings.h"
#include "export.h"
class DeviceSet;
class Feature;
class SDRBASE_API ChannelWebAPIUtils
{
public:
@ -34,6 +40,14 @@ public:
static bool startStopFileSinks(unsigned int deviceIndex, bool start);
static bool satelliteAOS(const QString name, bool northToSouthPass);
static bool satelliteLOS(const QString name);
static bool getDeviceSetting(unsigned int deviceIndex, const QString &setting, int &value);
static bool patchDeviceSetting(unsigned int deviceIndex, const QString &setting, int value);
static bool patchFeatureSetting(unsigned int featureSetIndex, unsigned int featureIndex, const QString &setting, const QString &value);
static bool patchFeatureSetting(unsigned int featureSetIndex, unsigned int featureIndex, const QString &setting, double value);
static bool getFeatureReportValue(unsigned int featureSetIndex, unsigned int featureIndex, const QString &key, int &value);
protected:
static bool getDeviceSettings(unsigned int deviceIndex, SWGSDRangel::SWGDeviceSettings &deviceSettingsResponse, DeviceSet *&deviceSet);
static bool getFeatureSettings(unsigned int featureSetIndex, unsigned int featureIndex, SWGSDRangel::SWGFeatureSettings &featureSettingsResponse, Feature *&feature);
};
#endif // SDRBASE_CHANNEL_CHANNELWEBAPIUTILS_H_

View File

@ -298,6 +298,30 @@ public:
return sfu * 1e-22f;
}
template <class T>
static T wattsPerMetrePerHertzToSolarFluxUnits(T w)
{
return w / 1e-22f;
}
template <class T>
static T wattsPerMetrePerHertzToJansky(T w)
{
return w / 1e-26f;
}
template <class T>
static T noiseFigureToNoiseTemp(T nfdB, T refTempK=T(290.0))
{
return refTempK * (std::pow(T(10.0), nfdB/T(10.0)) - T(1.0));
}
template <class T>
static T noiseTempToNoiseFigureTo(T tempK, T refTempK=T(290.0))
{
return T(10.0) * std::log10(tempK/refTempK+T(1.0));
}
};
#endif // INCLUDE_UNITS_H

View File

@ -106,6 +106,31 @@ void VISA::close(ViSession session)
}
}
QStringList VISA::processCommands(ViSession session, const QString& commands)
{
QStringList list = commands.split("\n");
QStringList results;
for (int i = 0; i < list.size(); i++)
{
QString command = list[i].trimmed();
if (!command.isEmpty() && !command.startsWith("#")) // Allow # to comment out lines
{
qDebug() << "VISA ->: " << command;
QByteArray bytes = QString("%1\n").arg(command).toLatin1();
char *cmd = bytes.data();
viPrintf(session, cmd);
if (command.endsWith("?"))
{
char buf[1024] = "";
char format[] = "%t";
viScanf(session, format, buf);
results.append(buf);
qDebug() << "VISA <-: " << QString(buf).trimmed();
}
}
}
return results;
}
#ifdef _MSC_VER

View File

@ -61,6 +61,7 @@ public:
void closeDefault();
ViSession open(const QString& device);
void close(ViSession session);
QStringList processCommands(ViSession session, const QString& commands);
// Is the VISA library available
bool isAvailable() const

View File

@ -4305,6 +4305,11 @@ bool WebAPIRequestMapper::getChannelSettings(
channelSettings->setPagerDemodSettings(new SWGSDRangel::SWGPagerDemodSettings());
channelSettings->getPagerDemodSettings()->fromJsonObject(settingsJsonObject);
}
else if (channelSettingsKey == "RadioAstronomySettings")
{
channelSettings->setRadioAstronomySettings(new SWGSDRangel::SWGRadioAstronomySettings());
channelSettings->getRadioAstronomySettings()->fromJsonObject(settingsJsonObject);
}
else if (channelSettingsKey == "RadioClockSettings")
{
channelSettings->setRadioClockSettings(new SWGSDRangel::SWGRadioClockSettings());
@ -4412,6 +4417,11 @@ bool WebAPIRequestMapper::getChannelActions(
channelActions->setIeee802154ModActions(new SWGSDRangel::SWGIEEE_802_15_4_ModActions());
channelActions->getIeee802154ModActions()->fromJsonObject(actionsJsonObject);
}
else if (channelActionsKey == "RadioAstronomyActions")
{
channelActions->setRadioAstronomyActions(new SWGSDRangel::SWGRadioAstronomyActions());
channelActions->getRadioAstronomyActions()->fromJsonObject(actionsJsonObject);
}
else if (channelActionsKey == "PacketModActions")
{
channelActions->setPacketModActions(new SWGSDRangel::SWGPacketModActions());
@ -5004,6 +5014,8 @@ void WebAPIRequestMapper::resetChannelSettings(SWGSDRangel::SWGChannelSettings&
channelSettings.setPacketDemodSettings(nullptr);
channelSettings.setPacketModSettings(nullptr);
channelSettings.setPagerDemodSettings(nullptr);
channelSettings.setRadioAstronomySettings(nullptr);
channelSettings.setRadioClockSettings(nullptr);
channelSettings.setRemoteSinkSettings(nullptr);
channelSettings.setRemoteSourceSettings(nullptr);
channelSettings.setSsbDemodSettings(nullptr);
@ -5033,6 +5045,8 @@ void WebAPIRequestMapper::resetChannelReport(SWGSDRangel::SWGChannelReport& chan
channelReport.setNoiseFigureReport(nullptr);
channelReport.setIeee802154ModReport(nullptr);
channelReport.setPacketModReport(nullptr);
channelReport.setRadioAstronomyReport(nullptr);
channelReport.setRadioClockReport(nullptr);
channelReport.setRemoteSourceReport(nullptr);
channelReport.setSsbDemodReport(nullptr);
channelReport.setSsbModReport(nullptr);
@ -5051,6 +5065,7 @@ void WebAPIRequestMapper::resetChannelActions(SWGSDRangel::SWGChannelActions& ch
channelActions.setChannelType(nullptr);
channelActions.setFileSourceActions(nullptr);
channelActions.setIeee802154ModActions(nullptr);
channelActions.setRadioAstronomyActions(nullptr);
channelActions.setPacketModActions(nullptr);
}

View File

@ -25,7 +25,6 @@ const QMap<QString, QString> WebAPIUtils::m_channelURIToSettingsKey = {
{"sdrangel.channel.adsbdemod", "ADSBDemodSettings"},
{"sdrangel.channel.modais", "AISModSettings"},
{"sdrangel.channel.aisdemod", "AISDemodSettings"},
{"sdrangel.channel.aptdemod", "APTDemodSettings"},
{"sdrangel.channel.amdemod", "AMDemodSettings"},
{"sdrangel.channel.aptdemod", "APTDemodSettings"},
{"de.maintech.sdrangelove.channel.am", "AMDemodSettings"}, // remap
@ -64,6 +63,7 @@ const QMap<QString, QString> WebAPIUtils::m_channelURIToSettingsKey = {
{"sdrangel.channeltx.modssb", "SSBModSettings"},
{"sdrangel.channel.ssbdemod", "SSBDemodSettings"},
{"de.maintech.sdrangelove.channel.ssb", "SSBDemodSettings"}, // remap
{"sdrangel.channel.radioastronomy", "RadioAstronomySettings"},
{"sdrangel.channeltx.udpsource", "UDPSourceSettings"},
{"sdrangel.channeltx.udpsink", "UDPSinkSettings"}, // remap
{"sdrangel.channel.udpsink", "UDPSinkSettings"},
@ -157,6 +157,7 @@ const QMap<QString, QString> WebAPIUtils::m_channelTypeToSettingsKey = {
{"PagerDemod", "PagerDemodSettings"},
{"LocalSink", "LocalSinkSettings"},
{"LocalSource", "LocalSourceSettings"},
{"RadioAstronomy", "RadioAstronomySettings"},
{"RadioClock", "RadioClockSettings"},
{"RemoteSink", "RemoteSinkSettings"},
{"RemoteSource", "RemoteSourceSettings"},
@ -179,6 +180,7 @@ const QMap<QString, QString> WebAPIUtils::m_channelTypeToActionsKey = {
{"FileSource", "FileSourceActions"},
{"SigMFFileSink", "SigMFFileSinkActions"},
{"IEEE_802_15_4_Mod", "IEEE_802_15_4_ModActions"},
{"RadioAstronomy", "RadioAstronomyActions"},
{"PacketMod", "PacketModActions"}
};
@ -431,6 +433,51 @@ bool WebAPIUtils::setSubObjectInt(QJsonObject &json, const QString &key, int val
return false;
}
// Get string value from within nested JSON object
bool WebAPIUtils::getSubObjectString(const QJsonObject &json, const QString &key, QString &value)
{
for (QJsonObject::const_iterator it = json.begin(); it != json.end(); it++)
{
QJsonValue jsonValue = it.value();
if (jsonValue.isObject())
{
QJsonObject subObject = jsonValue.toObject();
if (subObject.contains(key))
{
value = subObject[key].toString();
return true;
}
}
}
return false;
}
// Set string value withing nested JSON object
bool WebAPIUtils::setSubObjectString(QJsonObject &json, const QString &key, const QString &value)
{
for (QJsonObject::iterator it = json.begin(); it != json.end(); it++)
{
QJsonValue jsonValue = it.value();
if (jsonValue.isObject())
{
QJsonObject subObject = jsonValue.toObject();
if (subObject.contains(key))
{
subObject[key] = value;
it.value() = subObject;
return true;
}
}
}
return false;
}
// look for value in key=value
bool WebAPIUtils::extractValue(const QJsonObject &json, const QString &key, QJsonValue &value)
{

View File

@ -49,6 +49,8 @@ public:
static bool setSubObjectDouble(QJsonObject &json, const QString &key, double value);
static bool getSubObjectInt(const QJsonObject &json, const QString &key, int &value);
static bool setSubObjectInt(QJsonObject &json, const QString &key, int value);
static bool getSubObjectString(const QJsonObject &json, const QString &key, QString &value);
static bool setSubObjectString(QJsonObject &json, const QString &key, const QString &value);
static bool extractValue(const QJsonObject &json, const QString &key, QJsonValue &value);
static bool extractArray(const QJsonObject &json, const QString &key, QJsonArray &value);
static bool extractObject(const QJsonObject &json, const QString &key, QJsonObject &value);

View File

@ -20,52 +20,61 @@
WrappingDateTimeEdit::WrappingDateTimeEdit(QWidget *parent) :
QDateTimeEdit(parent)
{
// We need to set this true in order for stepBy to be called
// when minutes are at 59
// However, this also causes dates/times to wrap from max to min
// which we don't want, so in stepBy, we clip to max/min ourselves
setWrapping(true);
}
void WrappingDateTimeEdit::stepBy(int steps)
{
if (currentSection() == QDateTimeEdit::MonthSection)
setDate(date().addMonths(steps));
{
clipAndSetDate(date().addMonths(steps));
}
else if (currentSection() == QDateTimeEdit::DaySection)
setDate(date().addDays(steps));
{
clipAndSetDate(date().addDays(steps));
}
else if (currentSection() == QDateTimeEdit::HourSection)
{
QTime t = time();
int h = t.hour();
setTime(time().addSecs(steps*3600));
if ((h < -steps) && (steps < 0))
setDate(date().addDays(-1));
else if ((h + steps > 23) && (steps > 0))
setDate(date().addDays(1));
clipAndSetDateTime(dateTime().addSecs(steps*3600));
}
else if (currentSection() == QDateTimeEdit::MinuteSection)
{
QTime t = time();
int h = t.hour();
int m = t.minute();
setTime(time().addSecs(steps*60));
if ((m < -steps) && (steps < 0) && (h == 0))
setDate(date().addDays(-1));
else if ((m + steps > 59) && (steps > 0) && (h == 23))
setDate(date().addDays(1));
clipAndSetDateTime(dateTime().addSecs(steps*60));
}
else if (currentSection() == QDateTimeEdit::SecondSection)
{
QTime t = time();
int h = t.hour();
int m = t.minute();
int s = t.second();
setTime(time().addSecs(steps));
if ((s < -steps) && (steps < 0) && (h == 0) && (m == 0))
setDate(date().addDays(-1));
else if ((s + steps > 59) && (steps > 0) && (h == 23) && (m == 59))
setDate(date().addDays(1));
clipAndSetDateTime(dateTime().addSecs(steps));
}
}
void WrappingDateTimeEdit::clipAndSetDate(QDate date)
{
QDate max = maximumDate();
QDate min = minimumDate();
if (date > max) {
setDate(max);
} else if (date < min) {
setDate(min);
} else {
setDate(date);
}
}
void WrappingDateTimeEdit::clipAndSetDateTime(QDateTime dateTime)
{
// We have set wrapping as described in the constructor, but we don't want
// to wrap from max to min, so clip to this outself
QDateTime max = maximumDateTime();
QDateTime min = minimumDateTime();
if (dateTime > max) {
setDateTime(max);
} else if (dateTime < min) {
setDateTime(min);
} else {
setDateTime(dateTime);
}
}

View File

@ -30,6 +30,10 @@ public:
explicit WrappingDateTimeEdit(QWidget *parent = nullptr);
void stepBy(int steps) override;
protected:
void clipAndSetDate(QDate date);
void clipAndSetDateTime(QDateTime dateTime);
};
#endif // SDRGUI_GUI_WRAPPINGDATETIMEEDIT_H

View File

@ -29,5 +29,7 @@ ChannelActions:
$ref: "http://swgserver:8081/api/swagger/include/IEEE_802_15_4_Mod.yaml#/IEEE_802_15_4_ModActions"
PacketModActions:
$ref: "http://swgserver:8081/api/swagger/include/PacketMod.yaml#/PacketModActions"
RadioAstronomyActions:
$ref: "http://swgserver:8081/api/swagger/include/RadioAstronomy.yaml#/RadioAstronomyActions"
SigMFFileSinkActions:
$ref: "http://swgserver:8081/api/swagger/include/SigMFFileSink.yaml#/SigMFFileSinkActions"

View File

@ -53,6 +53,8 @@ ChannelReport:
$ref: "http://swgserver:8081/api/swagger/include/NoiseFigure.yaml#/NoiseFigureReport"
SSBDemodReport:
$ref: "http://swgserver:8081/api/swagger/include/SSBDemod.yaml#/SSBDemodReport"
RadioAstronomyReport:
$ref: "http://swgserver:8081/api/swagger/include/RadioAstronomy.yaml#/RadioAstronomyReport"
RadioClockReport:
$ref: "http://swgserver:8081/api/swagger/include/RadioClock.yaml#/RadioClockReport"
RemoteSourceReport:

View File

@ -81,6 +81,8 @@ ChannelSettings:
$ref: "http://swgserver:8081/api/swagger/include/PacketMod.yaml#/PacketModSettings"
PagerDemodSettings:
$ref: "http://swgserver:8081/api/swagger/include/PagerDemod.yaml#/PagerDemodSettings"
RadioAstronomySettings:
$ref: "http://swgserver:8081/api/swagger/include/RadioAstronomy.yaml#/RadioAstronomySettings"
RadioClockSettings:
$ref: "http://swgserver:8081/api/swagger/include/RadioClock.yaml#/RadioClockSettings"
RemoteSinkSettings:

View File

@ -0,0 +1,92 @@
RadioAstronomySettings:
description: RadioAstronomy
properties:
inputFrequencyOffset:
type: integer
format: int64
sampleRate:
type: integer
rfBandwidth:
type: integer
integration:
type: integer
fftSize:
type: integer
fftWindow:
type: integer
filterFreqs:
type: string
starTracker:
type: string
rotator:
type: string
runMode:
description: "(0 for single, 1 for continuous, 2 for sweep)"
type: integer
sweepStartAtTime:
description: "(0 for now, 1 for at sweepStartDateTime)"
type: integer
sweepStartDateTime:
type: string
sweepType:
description: "(0 for Az/El, 1 for l/b, 2 for offset)"
type: integer
sweep1Start:
type: number
format: float
sweep1Stop:
type: number
format: float
sweep1Step:
type: number
format: float
sweep1Delay:
type: number
format: float
sweep2Start:
type: number
format: float
sweep2Stop:
type: number
format: float
sweep2Step:
type: number
format: float
sweep2Delay:
type: number
format: float
rgbColor:
type: integer
title:
type: string
streamIndex:
description: MIMO channel. Not relevant when connected to SI (single Rx).
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
RadioAstronomyReport:
description: RadioAstronomy
properties:
channelPowerDB:
description: power received in channel (dB)
type: number
format: float
channelSampleRate:
type: integer
RadioAstronomyActions:
description: RadioAstronomy
properties:
start:
type: object
description: "Start measurement(s)"

View File

@ -3079,6 +3079,16 @@ definitions:
MapItem:
$ref: "http://swgserver:8081/api/swagger/include/Map.yaml#/MapItem"
# StarTracker settings passed to/from Radio Astronomy plugin
StarTrackerTarget:
$ref: "http://swgserver:8081/api/swagger/include/StarTracker.yaml#/StarTrackerTarget"
StarTrackerDisplaySettings:
$ref: "http://swgserver:8081/api/swagger/include/StarTracker.yaml#/StarTrackerDisplaySettings"
StarTrackerDisplayLoSSettings:
$ref: "http://swgserver:8081/api/swagger/include/StarTracker.yaml#/StarTrackerDisplayLoSSettings"
# This isn't in GS232Controller, as it may eventually be used by other controllers or features
TargetAzimuthElevation:
description: "A target azimuth and elevation"

View File

@ -48,6 +48,8 @@ SWGChannelActions::SWGChannelActions() {
m_ieee_802_15_4_mod_actions_isSet = false;
packet_mod_actions = nullptr;
m_packet_mod_actions_isSet = false;
radio_astronomy_actions = nullptr;
m_radio_astronomy_actions_isSet = false;
sig_mf_file_sink_actions = nullptr;
m_sig_mf_file_sink_actions_isSet = false;
}
@ -78,6 +80,8 @@ SWGChannelActions::init() {
m_ieee_802_15_4_mod_actions_isSet = false;
packet_mod_actions = new SWGPacketModActions();
m_packet_mod_actions_isSet = false;
radio_astronomy_actions = new SWGRadioAstronomyActions();
m_radio_astronomy_actions_isSet = false;
sig_mf_file_sink_actions = new SWGSigMFFileSinkActions();
m_sig_mf_file_sink_actions_isSet = false;
}
@ -108,6 +112,9 @@ SWGChannelActions::cleanup() {
if(packet_mod_actions != nullptr) {
delete packet_mod_actions;
}
if(radio_astronomy_actions != nullptr) {
delete radio_astronomy_actions;
}
if(sig_mf_file_sink_actions != nullptr) {
delete sig_mf_file_sink_actions;
}
@ -144,6 +151,8 @@ SWGChannelActions::fromJsonObject(QJsonObject &pJson) {
::SWGSDRangel::setValue(&packet_mod_actions, pJson["PacketModActions"], "SWGPacketModActions", "SWGPacketModActions");
::SWGSDRangel::setValue(&radio_astronomy_actions, pJson["RadioAstronomyActions"], "SWGRadioAstronomyActions", "SWGRadioAstronomyActions");
::SWGSDRangel::setValue(&sig_mf_file_sink_actions, pJson["SigMFFileSinkActions"], "SWGSigMFFileSinkActions", "SWGSigMFFileSinkActions");
}
@ -192,6 +201,9 @@ SWGChannelActions::asJsonObject() {
if((packet_mod_actions != nullptr) && (packet_mod_actions->isSet())){
toJsonValue(QString("PacketModActions"), packet_mod_actions, obj, QString("SWGPacketModActions"));
}
if((radio_astronomy_actions != nullptr) && (radio_astronomy_actions->isSet())){
toJsonValue(QString("RadioAstronomyActions"), radio_astronomy_actions, obj, QString("SWGRadioAstronomyActions"));
}
if((sig_mf_file_sink_actions != nullptr) && (sig_mf_file_sink_actions->isSet())){
toJsonValue(QString("SigMFFileSinkActions"), sig_mf_file_sink_actions, obj, QString("SWGSigMFFileSinkActions"));
}
@ -299,6 +311,16 @@ SWGChannelActions::setPacketModActions(SWGPacketModActions* packet_mod_actions)
this->m_packet_mod_actions_isSet = true;
}
SWGRadioAstronomyActions*
SWGChannelActions::getRadioAstronomyActions() {
return radio_astronomy_actions;
}
void
SWGChannelActions::setRadioAstronomyActions(SWGRadioAstronomyActions* radio_astronomy_actions) {
this->radio_astronomy_actions = radio_astronomy_actions;
this->m_radio_astronomy_actions_isSet = true;
}
SWGSigMFFileSinkActions*
SWGChannelActions::getSigMfFileSinkActions() {
return sig_mf_file_sink_actions;
@ -344,6 +366,9 @@ SWGChannelActions::isSet(){
if(packet_mod_actions && packet_mod_actions->isSet()){
isObjectUpdated = true; break;
}
if(radio_astronomy_actions && radio_astronomy_actions->isSet()){
isObjectUpdated = true; break;
}
if(sig_mf_file_sink_actions && sig_mf_file_sink_actions->isSet()){
isObjectUpdated = true; break;
}

View File

@ -28,6 +28,7 @@
#include "SWGFileSourceActions.h"
#include "SWGIEEE_802_15_4_ModActions.h"
#include "SWGPacketModActions.h"
#include "SWGRadioAstronomyActions.h"
#include "SWGSigMFFileSinkActions.h"
#include <QString>
@ -79,6 +80,9 @@ public:
SWGPacketModActions* getPacketModActions();
void setPacketModActions(SWGPacketModActions* packet_mod_actions);
SWGRadioAstronomyActions* getRadioAstronomyActions();
void setRadioAstronomyActions(SWGRadioAstronomyActions* radio_astronomy_actions);
SWGSigMFFileSinkActions* getSigMfFileSinkActions();
void setSigMfFileSinkActions(SWGSigMFFileSinkActions* sig_mf_file_sink_actions);
@ -116,6 +120,9 @@ private:
SWGPacketModActions* packet_mod_actions;
bool m_packet_mod_actions_isSet;
SWGRadioAstronomyActions* radio_astronomy_actions;
bool m_radio_astronomy_actions_isSet;
SWGSigMFFileSinkActions* sig_mf_file_sink_actions;
bool m_sig_mf_file_sink_actions_isSet;

View File

@ -74,6 +74,8 @@ SWGChannelReport::SWGChannelReport() {
m_noise_figure_report_isSet = false;
ssb_demod_report = nullptr;
m_ssb_demod_report_isSet = false;
radio_astronomy_report = nullptr;
m_radio_astronomy_report_isSet = false;
radio_clock_report = nullptr;
m_radio_clock_report_isSet = false;
remote_source_report = nullptr;
@ -152,6 +154,8 @@ SWGChannelReport::init() {
m_noise_figure_report_isSet = false;
ssb_demod_report = new SWGSSBDemodReport();
m_ssb_demod_report_isSet = false;
radio_astronomy_report = new SWGRadioAstronomyReport();
m_radio_astronomy_report_isSet = false;
radio_clock_report = new SWGRadioClockReport();
m_radio_clock_report_isSet = false;
remote_source_report = new SWGRemoteSourceReport();
@ -247,6 +251,9 @@ SWGChannelReport::cleanup() {
if(ssb_demod_report != nullptr) {
delete ssb_demod_report;
}
if(radio_astronomy_report != nullptr) {
delete radio_astronomy_report;
}
if(radio_clock_report != nullptr) {
delete radio_clock_report;
}
@ -342,6 +349,8 @@ SWGChannelReport::fromJsonObject(QJsonObject &pJson) {
::SWGSDRangel::setValue(&ssb_demod_report, pJson["SSBDemodReport"], "SWGSSBDemodReport", "SWGSSBDemodReport");
::SWGSDRangel::setValue(&radio_astronomy_report, pJson["RadioAstronomyReport"], "SWGRadioAstronomyReport", "SWGRadioAstronomyReport");
::SWGSDRangel::setValue(&radio_clock_report, pJson["RadioClockReport"], "SWGRadioClockReport", "SWGRadioClockReport");
::SWGSDRangel::setValue(&remote_source_report, pJson["RemoteSourceReport"], "SWGRemoteSourceReport", "SWGRemoteSourceReport");
@ -451,6 +460,9 @@ SWGChannelReport::asJsonObject() {
if((ssb_demod_report != nullptr) && (ssb_demod_report->isSet())){
toJsonValue(QString("SSBDemodReport"), ssb_demod_report, obj, QString("SWGSSBDemodReport"));
}
if((radio_astronomy_report != nullptr) && (radio_astronomy_report->isSet())){
toJsonValue(QString("RadioAstronomyReport"), radio_astronomy_report, obj, QString("SWGRadioAstronomyReport"));
}
if((radio_clock_report != nullptr) && (radio_clock_report->isSet())){
toJsonValue(QString("RadioClockReport"), radio_clock_report, obj, QString("SWGRadioClockReport"));
}
@ -721,6 +733,16 @@ SWGChannelReport::setSsbDemodReport(SWGSSBDemodReport* ssb_demod_report) {
this->m_ssb_demod_report_isSet = true;
}
SWGRadioAstronomyReport*
SWGChannelReport::getRadioAstronomyReport() {
return radio_astronomy_report;
}
void
SWGChannelReport::setRadioAstronomyReport(SWGRadioAstronomyReport* radio_astronomy_report) {
this->radio_astronomy_report = radio_astronomy_report;
this->m_radio_astronomy_report_isSet = true;
}
SWGRadioClockReport*
SWGChannelReport::getRadioClockReport() {
return radio_clock_report;
@ -915,6 +937,9 @@ SWGChannelReport::isSet(){
if(ssb_demod_report && ssb_demod_report->isSet()){
isObjectUpdated = true; break;
}
if(radio_astronomy_report && radio_astronomy_report->isSet()){
isObjectUpdated = true; break;
}
if(radio_clock_report && radio_clock_report->isSet()){
isObjectUpdated = true; break;
}

View File

@ -44,6 +44,7 @@
#include "SWGNoiseFigureReport.h"
#include "SWGPacketModReport.h"
#include "SWGPagerDemodReport.h"
#include "SWGRadioAstronomyReport.h"
#include "SWGRadioClockReport.h"
#include "SWGRemoteSourceReport.h"
#include "SWGSSBDemodReport.h"
@ -144,6 +145,9 @@ public:
SWGSSBDemodReport* getSsbDemodReport();
void setSsbDemodReport(SWGSSBDemodReport* ssb_demod_report);
SWGRadioAstronomyReport* getRadioAstronomyReport();
void setRadioAstronomyReport(SWGRadioAstronomyReport* radio_astronomy_report);
SWGRadioClockReport* getRadioClockReport();
void setRadioClockReport(SWGRadioClockReport* radio_clock_report);
@ -253,6 +257,9 @@ private:
SWGSSBDemodReport* ssb_demod_report;
bool m_ssb_demod_report_isSet;
SWGRadioAstronomyReport* radio_astronomy_report;
bool m_radio_astronomy_report_isSet;
SWGRadioClockReport* radio_clock_report;
bool m_radio_clock_report_isSet;

View File

@ -100,6 +100,8 @@ SWGChannelSettings::SWGChannelSettings() {
m_packet_mod_settings_isSet = false;
pager_demod_settings = nullptr;
m_pager_demod_settings_isSet = false;
radio_astronomy_settings = nullptr;
m_radio_astronomy_settings_isSet = false;
radio_clock_settings = nullptr;
m_radio_clock_settings_isSet = false;
remote_sink_settings = nullptr;
@ -204,6 +206,8 @@ SWGChannelSettings::init() {
m_packet_mod_settings_isSet = false;
pager_demod_settings = new SWGPagerDemodSettings();
m_pager_demod_settings_isSet = false;
radio_astronomy_settings = new SWGRadioAstronomySettings();
m_radio_astronomy_settings_isSet = false;
radio_clock_settings = new SWGRadioClockSettings();
m_radio_clock_settings_isSet = false;
remote_sink_settings = new SWGRemoteSinkSettings();
@ -334,6 +338,9 @@ SWGChannelSettings::cleanup() {
if(pager_demod_settings != nullptr) {
delete pager_demod_settings;
}
if(radio_astronomy_settings != nullptr) {
delete radio_astronomy_settings;
}
if(radio_clock_settings != nullptr) {
delete radio_clock_settings;
}
@ -455,6 +462,8 @@ SWGChannelSettings::fromJsonObject(QJsonObject &pJson) {
::SWGSDRangel::setValue(&pager_demod_settings, pJson["PagerDemodSettings"], "SWGPagerDemodSettings", "SWGPagerDemodSettings");
::SWGSDRangel::setValue(&radio_astronomy_settings, pJson["RadioAstronomySettings"], "SWGRadioAstronomySettings", "SWGRadioAstronomySettings");
::SWGSDRangel::setValue(&radio_clock_settings, pJson["RadioClockSettings"], "SWGRadioClockSettings", "SWGRadioClockSettings");
::SWGSDRangel::setValue(&remote_sink_settings, pJson["RemoteSinkSettings"], "SWGRemoteSinkSettings", "SWGRemoteSinkSettings");
@ -603,6 +612,9 @@ SWGChannelSettings::asJsonObject() {
if((pager_demod_settings != nullptr) && (pager_demod_settings->isSet())){
toJsonValue(QString("PagerDemodSettings"), pager_demod_settings, obj, QString("SWGPagerDemodSettings"));
}
if((radio_astronomy_settings != nullptr) && (radio_astronomy_settings->isSet())){
toJsonValue(QString("RadioAstronomySettings"), radio_astronomy_settings, obj, QString("SWGRadioAstronomySettings"));
}
if((radio_clock_settings != nullptr) && (radio_clock_settings->isSet())){
toJsonValue(QString("RadioClockSettings"), radio_clock_settings, obj, QString("SWGRadioClockSettings"));
}
@ -1003,6 +1015,16 @@ SWGChannelSettings::setPagerDemodSettings(SWGPagerDemodSettings* pager_demod_set
this->m_pager_demod_settings_isSet = true;
}
SWGRadioAstronomySettings*
SWGChannelSettings::getRadioAstronomySettings() {
return radio_astronomy_settings;
}
void
SWGChannelSettings::setRadioAstronomySettings(SWGRadioAstronomySettings* radio_astronomy_settings) {
this->radio_astronomy_settings = radio_astronomy_settings;
this->m_radio_astronomy_settings_isSet = true;
}
SWGRadioClockSettings*
SWGChannelSettings::getRadioClockSettings() {
return radio_clock_settings;
@ -1236,6 +1258,9 @@ SWGChannelSettings::isSet(){
if(pager_demod_settings && pager_demod_settings->isSet()){
isObjectUpdated = true; break;
}
if(radio_astronomy_settings && radio_astronomy_settings->isSet()){
isObjectUpdated = true; break;
}
if(radio_clock_settings && radio_clock_settings->isSet()){
isObjectUpdated = true; break;
}

View File

@ -54,6 +54,7 @@
#include "SWGPacketDemodSettings.h"
#include "SWGPacketModSettings.h"
#include "SWGPagerDemodSettings.h"
#include "SWGRadioAstronomySettings.h"
#include "SWGRadioClockSettings.h"
#include "SWGRemoteSinkSettings.h"
#include "SWGRemoteSourceSettings.h"
@ -194,6 +195,9 @@ public:
SWGPagerDemodSettings* getPagerDemodSettings();
void setPagerDemodSettings(SWGPagerDemodSettings* pager_demod_settings);
SWGRadioAstronomySettings* getRadioAstronomySettings();
void setRadioAstronomySettings(SWGRadioAstronomySettings* radio_astronomy_settings);
SWGRadioClockSettings* getRadioClockSettings();
void setRadioClockSettings(SWGRadioClockSettings* radio_clock_settings);
@ -342,6 +346,9 @@ private:
SWGPagerDemodSettings* pager_demod_settings;
bool m_pager_demod_settings_isSet;
SWGRadioAstronomySettings* radio_astronomy_settings;
bool m_radio_astronomy_settings_isSet;
SWGRadioClockSettings* radio_clock_settings;
bool m_radio_clock_settings_isSet;

View File

@ -210,6 +210,9 @@
#include "SWGPresets.h"
#include "SWGRDSReport.h"
#include "SWGRDSReport_altFrequencies.h"
#include "SWGRadioAstronomyActions.h"
#include "SWGRadioAstronomyReport.h"
#include "SWGRadioAstronomySettings.h"
#include "SWGRadioClockReport.h"
#include "SWGRadioClockSettings.h"
#include "SWGRange.h"
@ -253,7 +256,13 @@
#include "SWGSoapySDRReport.h"
#include "SWGSpectrumServer.h"
#include "SWGSpectrumServer_clients.h"
#include "SWGStarTrackerDisplayLoSSettings.h"
#include "SWGStarTrackerDisplayLoSSettings_2.h"
#include "SWGStarTrackerDisplaySettings.h"
#include "SWGStarTrackerDisplaySettings_2.h"
#include "SWGStarTrackerSettings.h"
#include "SWGStarTrackerTarget.h"
#include "SWGStarTrackerTarget_2.h"
#include "SWGSuccessResponse.h"
#include "SWGTargetAzimuthElevation.h"
#include "SWGTestMISettings.h"
@ -1269,6 +1278,21 @@ namespace SWGSDRangel {
obj->init();
return obj;
}
if(QString("SWGRadioAstronomyActions").compare(type) == 0) {
SWGRadioAstronomyActions *obj = new SWGRadioAstronomyActions();
obj->init();
return obj;
}
if(QString("SWGRadioAstronomyReport").compare(type) == 0) {
SWGRadioAstronomyReport *obj = new SWGRadioAstronomyReport();
obj->init();
return obj;
}
if(QString("SWGRadioAstronomySettings").compare(type) == 0) {
SWGRadioAstronomySettings *obj = new SWGRadioAstronomySettings();
obj->init();
return obj;
}
if(QString("SWGRadioClockReport").compare(type) == 0) {
SWGRadioClockReport *obj = new SWGRadioClockReport();
obj->init();
@ -1484,11 +1508,41 @@ namespace SWGSDRangel {
obj->init();
return obj;
}
if(QString("SWGStarTrackerDisplayLoSSettings").compare(type) == 0) {
SWGStarTrackerDisplayLoSSettings *obj = new SWGStarTrackerDisplayLoSSettings();
obj->init();
return obj;
}
if(QString("SWGStarTrackerDisplayLoSSettings_2").compare(type) == 0) {
SWGStarTrackerDisplayLoSSettings_2 *obj = new SWGStarTrackerDisplayLoSSettings_2();
obj->init();
return obj;
}
if(QString("SWGStarTrackerDisplaySettings").compare(type) == 0) {
SWGStarTrackerDisplaySettings *obj = new SWGStarTrackerDisplaySettings();
obj->init();
return obj;
}
if(QString("SWGStarTrackerDisplaySettings_2").compare(type) == 0) {
SWGStarTrackerDisplaySettings_2 *obj = new SWGStarTrackerDisplaySettings_2();
obj->init();
return obj;
}
if(QString("SWGStarTrackerSettings").compare(type) == 0) {
SWGStarTrackerSettings *obj = new SWGStarTrackerSettings();
obj->init();
return obj;
}
if(QString("SWGStarTrackerTarget").compare(type) == 0) {
SWGStarTrackerTarget *obj = new SWGStarTrackerTarget();
obj->init();
return obj;
}
if(QString("SWGStarTrackerTarget_2").compare(type) == 0) {
SWGStarTrackerTarget_2 *obj = new SWGStarTrackerTarget_2();
obj->init();
return obj;
}
if(QString("SWGSuccessResponse").compare(type) == 0) {
SWGSuccessResponse *obj = new SWGSuccessResponse();
obj->init();

View File

@ -0,0 +1,110 @@
/**
* 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 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: 6.0.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 "SWGRadioAstronomyActions.h"
#include "SWGHelpers.h"
#include <QJsonDocument>
#include <QJsonArray>
#include <QObject>
#include <QDebug>
namespace SWGSDRangel {
SWGRadioAstronomyActions::SWGRadioAstronomyActions(QString* json) {
init();
this->fromJson(*json);
}
SWGRadioAstronomyActions::SWGRadioAstronomyActions() {
start = nullptr;
m_start_isSet = false;
}
SWGRadioAstronomyActions::~SWGRadioAstronomyActions() {
this->cleanup();
}
void
SWGRadioAstronomyActions::init() {
start = NULL;
m_start_isSet = false;
}
void
SWGRadioAstronomyActions::cleanup() {
if(start != nullptr) {
delete start;
}
}
SWGRadioAstronomyActions*
SWGRadioAstronomyActions::fromJson(QString &json) {
QByteArray array (json.toStdString().c_str());
QJsonDocument doc = QJsonDocument::fromJson(array);
QJsonObject jsonObject = doc.object();
this->fromJsonObject(jsonObject);
return this;
}
void
SWGRadioAstronomyActions::fromJsonObject(QJsonObject &pJson) {
::SWGSDRangel::setValue(&start, pJson["start"], "SWGObject", "SWGObject");
}
QString
SWGRadioAstronomyActions::asJson ()
{
QJsonObject* obj = this->asJsonObject();
QJsonDocument doc(*obj);
QByteArray bytes = doc.toJson();
delete obj;
return QString(bytes);
}
QJsonObject*
SWGRadioAstronomyActions::asJsonObject() {
QJsonObject* obj = new QJsonObject();
if((start != nullptr) && (start->isSet())){
toJsonValue(QString("start"), start, obj, QString("SWGObject"));
}
return obj;
}
SWGObject*
SWGRadioAstronomyActions::getStart() {
return start;
}
void
SWGRadioAstronomyActions::setStart(SWGObject* start) {
this->start = start;
this->m_start_isSet = true;
}
bool
SWGRadioAstronomyActions::isSet(){
bool isObjectUpdated = false;
do{
if(start && start->isSet()){
isObjectUpdated = true; break;
}
}while(false);
return isObjectUpdated;
}
}

View File

@ -0,0 +1,59 @@
/**
* 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 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: 6.0.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.
*/
/*
* SWGRadioAstronomyActions.h
*
* RadioAstronomy
*/
#ifndef SWGRadioAstronomyActions_H_
#define SWGRadioAstronomyActions_H_
#include <QJsonObject>
#include "SWGObject.h"
#include "SWGObject.h"
#include "export.h"
namespace SWGSDRangel {
class SWG_API SWGRadioAstronomyActions: public SWGObject {
public:
SWGRadioAstronomyActions();
SWGRadioAstronomyActions(QString* json);
virtual ~SWGRadioAstronomyActions();
void init();
void cleanup();
virtual QString asJson () override;
virtual QJsonObject* asJsonObject() override;
virtual void fromJsonObject(QJsonObject &json) override;
virtual SWGRadioAstronomyActions* fromJson(QString &jsonString) override;
SWGObject* getStart();
void setStart(SWGObject* start);
virtual bool isSet() override;
private:
SWGObject* start;
bool m_start_isSet;
};
}
#endif /* SWGRadioAstronomyActions_H_ */

View File

@ -0,0 +1,131 @@
/**
* 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 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: 6.0.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 "SWGRadioAstronomyReport.h"
#include "SWGHelpers.h"
#include <QJsonDocument>
#include <QJsonArray>
#include <QObject>
#include <QDebug>
namespace SWGSDRangel {
SWGRadioAstronomyReport::SWGRadioAstronomyReport(QString* json) {
init();
this->fromJson(*json);
}
SWGRadioAstronomyReport::SWGRadioAstronomyReport() {
channel_power_db = 0.0f;
m_channel_power_db_isSet = false;
channel_sample_rate = 0;
m_channel_sample_rate_isSet = false;
}
SWGRadioAstronomyReport::~SWGRadioAstronomyReport() {
this->cleanup();
}
void
SWGRadioAstronomyReport::init() {
channel_power_db = 0.0f;
m_channel_power_db_isSet = false;
channel_sample_rate = 0;
m_channel_sample_rate_isSet = false;
}
void
SWGRadioAstronomyReport::cleanup() {
}
SWGRadioAstronomyReport*
SWGRadioAstronomyReport::fromJson(QString &json) {
QByteArray array (json.toStdString().c_str());
QJsonDocument doc = QJsonDocument::fromJson(array);
QJsonObject jsonObject = doc.object();
this->fromJsonObject(jsonObject);
return this;
}
void
SWGRadioAstronomyReport::fromJsonObject(QJsonObject &pJson) {
::SWGSDRangel::setValue(&channel_power_db, pJson["channelPowerDB"], "float", "");
::SWGSDRangel::setValue(&channel_sample_rate, pJson["channelSampleRate"], "qint32", "");
}
QString
SWGRadioAstronomyReport::asJson ()
{
QJsonObject* obj = this->asJsonObject();
QJsonDocument doc(*obj);
QByteArray bytes = doc.toJson();
delete obj;
return QString(bytes);
}
QJsonObject*
SWGRadioAstronomyReport::asJsonObject() {
QJsonObject* obj = new QJsonObject();
if(m_channel_power_db_isSet){
obj->insert("channelPowerDB", QJsonValue(channel_power_db));
}
if(m_channel_sample_rate_isSet){
obj->insert("channelSampleRate", QJsonValue(channel_sample_rate));
}
return obj;
}
float
SWGRadioAstronomyReport::getChannelPowerDb() {
return channel_power_db;
}
void
SWGRadioAstronomyReport::setChannelPowerDb(float channel_power_db) {
this->channel_power_db = channel_power_db;
this->m_channel_power_db_isSet = true;
}
qint32
SWGRadioAstronomyReport::getChannelSampleRate() {
return channel_sample_rate;
}
void
SWGRadioAstronomyReport::setChannelSampleRate(qint32 channel_sample_rate) {
this->channel_sample_rate = channel_sample_rate;
this->m_channel_sample_rate_isSet = true;
}
bool
SWGRadioAstronomyReport::isSet(){
bool isObjectUpdated = false;
do{
if(m_channel_power_db_isSet){
isObjectUpdated = true; break;
}
if(m_channel_sample_rate_isSet){
isObjectUpdated = true; break;
}
}while(false);
return isObjectUpdated;
}
}

View File

@ -0,0 +1,64 @@
/**
* 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 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: 6.0.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.
*/
/*
* SWGRadioAstronomyReport.h
*
* RadioAstronomy
*/
#ifndef SWGRadioAstronomyReport_H_
#define SWGRadioAstronomyReport_H_
#include <QJsonObject>
#include "SWGObject.h"
#include "export.h"
namespace SWGSDRangel {
class SWG_API SWGRadioAstronomyReport: public SWGObject {
public:
SWGRadioAstronomyReport();
SWGRadioAstronomyReport(QString* json);
virtual ~SWGRadioAstronomyReport();
void init();
void cleanup();
virtual QString asJson () override;
virtual QJsonObject* asJsonObject() override;
virtual void fromJsonObject(QJsonObject &json) override;
virtual SWGRadioAstronomyReport* fromJson(QString &jsonString) override;
float getChannelPowerDb();
void setChannelPowerDb(float channel_power_db);
qint32 getChannelSampleRate();
void setChannelSampleRate(qint32 channel_sample_rate);
virtual bool isSet() override;
private:
float channel_power_db;
bool m_channel_power_db_isSet;
qint32 channel_sample_rate;
bool m_channel_sample_rate_isSet;
};
}
#endif /* SWGRadioAstronomyReport_H_ */

View File

@ -0,0 +1,764 @@
/**
* 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 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: 6.0.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 "SWGRadioAstronomySettings.h"
#include "SWGHelpers.h"
#include <QJsonDocument>
#include <QJsonArray>
#include <QObject>
#include <QDebug>
namespace SWGSDRangel {
SWGRadioAstronomySettings::SWGRadioAstronomySettings(QString* json) {
init();
this->fromJson(*json);
}
SWGRadioAstronomySettings::SWGRadioAstronomySettings() {
input_frequency_offset = 0L;
m_input_frequency_offset_isSet = false;
sample_rate = 0;
m_sample_rate_isSet = false;
rf_bandwidth = 0;
m_rf_bandwidth_isSet = false;
integration = 0;
m_integration_isSet = false;
fft_size = 0;
m_fft_size_isSet = false;
fft_window = 0;
m_fft_window_isSet = false;
filter_freqs = nullptr;
m_filter_freqs_isSet = false;
star_tracker = nullptr;
m_star_tracker_isSet = false;
rotator = nullptr;
m_rotator_isSet = false;
run_mode = 0;
m_run_mode_isSet = false;
sweep_start_at_time = 0;
m_sweep_start_at_time_isSet = false;
sweep_start_date_time = nullptr;
m_sweep_start_date_time_isSet = false;
sweep_type = 0;
m_sweep_type_isSet = false;
sweep1_start = 0.0f;
m_sweep1_start_isSet = false;
sweep1_stop = 0.0f;
m_sweep1_stop_isSet = false;
sweep1_step = 0.0f;
m_sweep1_step_isSet = false;
sweep1_delay = 0.0f;
m_sweep1_delay_isSet = false;
sweep2_start = 0.0f;
m_sweep2_start_isSet = false;
sweep2_stop = 0.0f;
m_sweep2_stop_isSet = false;
sweep2_step = 0.0f;
m_sweep2_step_isSet = false;
sweep2_delay = 0.0f;
m_sweep2_delay_isSet = false;
rgb_color = 0;
m_rgb_color_isSet = false;
title = nullptr;
m_title_isSet = false;
stream_index = 0;
m_stream_index_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;
}
SWGRadioAstronomySettings::~SWGRadioAstronomySettings() {
this->cleanup();
}
void
SWGRadioAstronomySettings::init() {
input_frequency_offset = 0L;
m_input_frequency_offset_isSet = false;
sample_rate = 0;
m_sample_rate_isSet = false;
rf_bandwidth = 0;
m_rf_bandwidth_isSet = false;
integration = 0;
m_integration_isSet = false;
fft_size = 0;
m_fft_size_isSet = false;
fft_window = 0;
m_fft_window_isSet = false;
filter_freqs = new QString("");
m_filter_freqs_isSet = false;
star_tracker = new QString("");
m_star_tracker_isSet = false;
rotator = new QString("");
m_rotator_isSet = false;
run_mode = 0;
m_run_mode_isSet = false;
sweep_start_at_time = 0;
m_sweep_start_at_time_isSet = false;
sweep_start_date_time = new QString("");
m_sweep_start_date_time_isSet = false;
sweep_type = 0;
m_sweep_type_isSet = false;
sweep1_start = 0.0f;
m_sweep1_start_isSet = false;
sweep1_stop = 0.0f;
m_sweep1_stop_isSet = false;
sweep1_step = 0.0f;
m_sweep1_step_isSet = false;
sweep1_delay = 0.0f;
m_sweep1_delay_isSet = false;
sweep2_start = 0.0f;
m_sweep2_start_isSet = false;
sweep2_stop = 0.0f;
m_sweep2_stop_isSet = false;
sweep2_step = 0.0f;
m_sweep2_step_isSet = false;
sweep2_delay = 0.0f;
m_sweep2_delay_isSet = false;
rgb_color = 0;
m_rgb_color_isSet = false;
title = new QString("");
m_title_isSet = false;
stream_index = 0;
m_stream_index_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
SWGRadioAstronomySettings::cleanup() {
if(filter_freqs != nullptr) {
delete filter_freqs;
}
if(star_tracker != nullptr) {
delete star_tracker;
}
if(rotator != nullptr) {
delete rotator;
}
if(sweep_start_date_time != nullptr) {
delete sweep_start_date_time;
}
if(title != nullptr) {
delete title;
}
if(reverse_api_address != nullptr) {
delete reverse_api_address;
}
}
SWGRadioAstronomySettings*
SWGRadioAstronomySettings::fromJson(QString &json) {
QByteArray array (json.toStdString().c_str());
QJsonDocument doc = QJsonDocument::fromJson(array);
QJsonObject jsonObject = doc.object();
this->fromJsonObject(jsonObject);
return this;
}
void
SWGRadioAstronomySettings::fromJsonObject(QJsonObject &pJson) {
::SWGSDRangel::setValue(&input_frequency_offset, pJson["inputFrequencyOffset"], "qint64", "");
::SWGSDRangel::setValue(&sample_rate, pJson["sampleRate"], "qint32", "");
::SWGSDRangel::setValue(&rf_bandwidth, pJson["rfBandwidth"], "qint32", "");
::SWGSDRangel::setValue(&integration, pJson["integration"], "qint32", "");
::SWGSDRangel::setValue(&fft_size, pJson["fftSize"], "qint32", "");
::SWGSDRangel::setValue(&fft_window, pJson["fftWindow"], "qint32", "");
::SWGSDRangel::setValue(&filter_freqs, pJson["filterFreqs"], "QString", "QString");
::SWGSDRangel::setValue(&star_tracker, pJson["starTracker"], "QString", "QString");
::SWGSDRangel::setValue(&rotator, pJson["rotator"], "QString", "QString");
::SWGSDRangel::setValue(&run_mode, pJson["runMode"], "qint32", "");
::SWGSDRangel::setValue(&sweep_start_at_time, pJson["sweepStartAtTime"], "qint32", "");
::SWGSDRangel::setValue(&sweep_start_date_time, pJson["sweepStartDateTime"], "QString", "QString");
::SWGSDRangel::setValue(&sweep_type, pJson["sweepType"], "qint32", "");
::SWGSDRangel::setValue(&sweep1_start, pJson["sweep1Start"], "float", "");
::SWGSDRangel::setValue(&sweep1_stop, pJson["sweep1Stop"], "float", "");
::SWGSDRangel::setValue(&sweep1_step, pJson["sweep1Step"], "float", "");
::SWGSDRangel::setValue(&sweep1_delay, pJson["sweep1Delay"], "float", "");
::SWGSDRangel::setValue(&sweep2_start, pJson["sweep2Start"], "float", "");
::SWGSDRangel::setValue(&sweep2_stop, pJson["sweep2Stop"], "float", "");
::SWGSDRangel::setValue(&sweep2_step, pJson["sweep2Step"], "float", "");
::SWGSDRangel::setValue(&sweep2_delay, pJson["sweep2Delay"], "float", "");
::SWGSDRangel::setValue(&rgb_color, pJson["rgbColor"], "qint32", "");
::SWGSDRangel::setValue(&title, pJson["title"], "QString", "QString");
::SWGSDRangel::setValue(&stream_index, pJson["streamIndex"], "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
SWGRadioAstronomySettings::asJson ()
{
QJsonObject* obj = this->asJsonObject();
QJsonDocument doc(*obj);
QByteArray bytes = doc.toJson();
delete obj;
return QString(bytes);
}
QJsonObject*
SWGRadioAstronomySettings::asJsonObject() {
QJsonObject* obj = new QJsonObject();
if(m_input_frequency_offset_isSet){
obj->insert("inputFrequencyOffset", QJsonValue(input_frequency_offset));
}
if(m_sample_rate_isSet){
obj->insert("sampleRate", QJsonValue(sample_rate));
}
if(m_rf_bandwidth_isSet){
obj->insert("rfBandwidth", QJsonValue(rf_bandwidth));
}
if(m_integration_isSet){
obj->insert("integration", QJsonValue(integration));
}
if(m_fft_size_isSet){
obj->insert("fftSize", QJsonValue(fft_size));
}
if(m_fft_window_isSet){
obj->insert("fftWindow", QJsonValue(fft_window));
}
if(filter_freqs != nullptr && *filter_freqs != QString("")){
toJsonValue(QString("filterFreqs"), filter_freqs, obj, QString("QString"));
}
if(star_tracker != nullptr && *star_tracker != QString("")){
toJsonValue(QString("starTracker"), star_tracker, obj, QString("QString"));
}
if(rotator != nullptr && *rotator != QString("")){
toJsonValue(QString("rotator"), rotator, obj, QString("QString"));
}
if(m_run_mode_isSet){
obj->insert("runMode", QJsonValue(run_mode));
}
if(m_sweep_start_at_time_isSet){
obj->insert("sweepStartAtTime", QJsonValue(sweep_start_at_time));
}
if(sweep_start_date_time != nullptr && *sweep_start_date_time != QString("")){
toJsonValue(QString("sweepStartDateTime"), sweep_start_date_time, obj, QString("QString"));
}
if(m_sweep_type_isSet){
obj->insert("sweepType", QJsonValue(sweep_type));
}
if(m_sweep1_start_isSet){
obj->insert("sweep1Start", QJsonValue(sweep1_start));
}
if(m_sweep1_stop_isSet){
obj->insert("sweep1Stop", QJsonValue(sweep1_stop));
}
if(m_sweep1_step_isSet){
obj->insert("sweep1Step", QJsonValue(sweep1_step));
}
if(m_sweep1_delay_isSet){
obj->insert("sweep1Delay", QJsonValue(sweep1_delay));
}
if(m_sweep2_start_isSet){
obj->insert("sweep2Start", QJsonValue(sweep2_start));
}
if(m_sweep2_stop_isSet){
obj->insert("sweep2Stop", QJsonValue(sweep2_stop));
}
if(m_sweep2_step_isSet){
obj->insert("sweep2Step", QJsonValue(sweep2_step));
}
if(m_sweep2_delay_isSet){
obj->insert("sweep2Delay", QJsonValue(sweep2_delay));
}
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_stream_index_isSet){
obj->insert("streamIndex", QJsonValue(stream_index));
}
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;
}
qint64
SWGRadioAstronomySettings::getInputFrequencyOffset() {
return input_frequency_offset;
}
void
SWGRadioAstronomySettings::setInputFrequencyOffset(qint64 input_frequency_offset) {
this->input_frequency_offset = input_frequency_offset;
this->m_input_frequency_offset_isSet = true;
}
qint32
SWGRadioAstronomySettings::getSampleRate() {
return sample_rate;
}
void
SWGRadioAstronomySettings::setSampleRate(qint32 sample_rate) {
this->sample_rate = sample_rate;
this->m_sample_rate_isSet = true;
}
qint32
SWGRadioAstronomySettings::getRfBandwidth() {
return rf_bandwidth;
}
void
SWGRadioAstronomySettings::setRfBandwidth(qint32 rf_bandwidth) {
this->rf_bandwidth = rf_bandwidth;
this->m_rf_bandwidth_isSet = true;
}
qint32
SWGRadioAstronomySettings::getIntegration() {
return integration;
}
void
SWGRadioAstronomySettings::setIntegration(qint32 integration) {
this->integration = integration;
this->m_integration_isSet = true;
}
qint32
SWGRadioAstronomySettings::getFftSize() {
return fft_size;
}
void
SWGRadioAstronomySettings::setFftSize(qint32 fft_size) {
this->fft_size = fft_size;
this->m_fft_size_isSet = true;
}
qint32
SWGRadioAstronomySettings::getFftWindow() {
return fft_window;
}
void
SWGRadioAstronomySettings::setFftWindow(qint32 fft_window) {
this->fft_window = fft_window;
this->m_fft_window_isSet = true;
}
QString*
SWGRadioAstronomySettings::getFilterFreqs() {
return filter_freqs;
}
void
SWGRadioAstronomySettings::setFilterFreqs(QString* filter_freqs) {
this->filter_freqs = filter_freqs;
this->m_filter_freqs_isSet = true;
}
QString*
SWGRadioAstronomySettings::getStarTracker() {
return star_tracker;
}
void
SWGRadioAstronomySettings::setStarTracker(QString* star_tracker) {
this->star_tracker = star_tracker;
this->m_star_tracker_isSet = true;
}
QString*
SWGRadioAstronomySettings::getRotator() {
return rotator;
}
void
SWGRadioAstronomySettings::setRotator(QString* rotator) {
this->rotator = rotator;
this->m_rotator_isSet = true;
}
qint32
SWGRadioAstronomySettings::getRunMode() {
return run_mode;
}
void
SWGRadioAstronomySettings::setRunMode(qint32 run_mode) {
this->run_mode = run_mode;
this->m_run_mode_isSet = true;
}
qint32
SWGRadioAstronomySettings::getSweepStartAtTime() {
return sweep_start_at_time;
}
void
SWGRadioAstronomySettings::setSweepStartAtTime(qint32 sweep_start_at_time) {
this->sweep_start_at_time = sweep_start_at_time;
this->m_sweep_start_at_time_isSet = true;
}
QString*
SWGRadioAstronomySettings::getSweepStartDateTime() {
return sweep_start_date_time;
}
void
SWGRadioAstronomySettings::setSweepStartDateTime(QString* sweep_start_date_time) {
this->sweep_start_date_time = sweep_start_date_time;
this->m_sweep_start_date_time_isSet = true;
}
qint32
SWGRadioAstronomySettings::getSweepType() {
return sweep_type;
}
void
SWGRadioAstronomySettings::setSweepType(qint32 sweep_type) {
this->sweep_type = sweep_type;
this->m_sweep_type_isSet = true;
}
float
SWGRadioAstronomySettings::getSweep1Start() {
return sweep1_start;
}
void
SWGRadioAstronomySettings::setSweep1Start(float sweep1_start) {
this->sweep1_start = sweep1_start;
this->m_sweep1_start_isSet = true;
}
float
SWGRadioAstronomySettings::getSweep1Stop() {
return sweep1_stop;
}
void
SWGRadioAstronomySettings::setSweep1Stop(float sweep1_stop) {
this->sweep1_stop = sweep1_stop;
this->m_sweep1_stop_isSet = true;
}
float
SWGRadioAstronomySettings::getSweep1Step() {
return sweep1_step;
}
void
SWGRadioAstronomySettings::setSweep1Step(float sweep1_step) {
this->sweep1_step = sweep1_step;
this->m_sweep1_step_isSet = true;
}
float
SWGRadioAstronomySettings::getSweep1Delay() {
return sweep1_delay;
}
void
SWGRadioAstronomySettings::setSweep1Delay(float sweep1_delay) {
this->sweep1_delay = sweep1_delay;
this->m_sweep1_delay_isSet = true;
}
float
SWGRadioAstronomySettings::getSweep2Start() {
return sweep2_start;
}
void
SWGRadioAstronomySettings::setSweep2Start(float sweep2_start) {
this->sweep2_start = sweep2_start;
this->m_sweep2_start_isSet = true;
}
float
SWGRadioAstronomySettings::getSweep2Stop() {
return sweep2_stop;
}
void
SWGRadioAstronomySettings::setSweep2Stop(float sweep2_stop) {
this->sweep2_stop = sweep2_stop;
this->m_sweep2_stop_isSet = true;
}
float
SWGRadioAstronomySettings::getSweep2Step() {
return sweep2_step;
}
void
SWGRadioAstronomySettings::setSweep2Step(float sweep2_step) {
this->sweep2_step = sweep2_step;
this->m_sweep2_step_isSet = true;
}
float
SWGRadioAstronomySettings::getSweep2Delay() {
return sweep2_delay;
}
void
SWGRadioAstronomySettings::setSweep2Delay(float sweep2_delay) {
this->sweep2_delay = sweep2_delay;
this->m_sweep2_delay_isSet = true;
}
qint32
SWGRadioAstronomySettings::getRgbColor() {
return rgb_color;
}
void
SWGRadioAstronomySettings::setRgbColor(qint32 rgb_color) {
this->rgb_color = rgb_color;
this->m_rgb_color_isSet = true;
}
QString*
SWGRadioAstronomySettings::getTitle() {
return title;
}
void
SWGRadioAstronomySettings::setTitle(QString* title) {
this->title = title;
this->m_title_isSet = true;
}
qint32
SWGRadioAstronomySettings::getStreamIndex() {
return stream_index;
}
void
SWGRadioAstronomySettings::setStreamIndex(qint32 stream_index) {
this->stream_index = stream_index;
this->m_stream_index_isSet = true;
}
qint32
SWGRadioAstronomySettings::getUseReverseApi() {
return use_reverse_api;
}
void
SWGRadioAstronomySettings::setUseReverseApi(qint32 use_reverse_api) {
this->use_reverse_api = use_reverse_api;
this->m_use_reverse_api_isSet = true;
}
QString*
SWGRadioAstronomySettings::getReverseApiAddress() {
return reverse_api_address;
}
void
SWGRadioAstronomySettings::setReverseApiAddress(QString* reverse_api_address) {
this->reverse_api_address = reverse_api_address;
this->m_reverse_api_address_isSet = true;
}
qint32
SWGRadioAstronomySettings::getReverseApiPort() {
return reverse_api_port;
}
void
SWGRadioAstronomySettings::setReverseApiPort(qint32 reverse_api_port) {
this->reverse_api_port = reverse_api_port;
this->m_reverse_api_port_isSet = true;
}
qint32
SWGRadioAstronomySettings::getReverseApiDeviceIndex() {
return reverse_api_device_index;
}
void
SWGRadioAstronomySettings::setReverseApiDeviceIndex(qint32 reverse_api_device_index) {
this->reverse_api_device_index = reverse_api_device_index;
this->m_reverse_api_device_index_isSet = true;
}
qint32
SWGRadioAstronomySettings::getReverseApiChannelIndex() {
return reverse_api_channel_index;
}
void
SWGRadioAstronomySettings::setReverseApiChannelIndex(qint32 reverse_api_channel_index) {
this->reverse_api_channel_index = reverse_api_channel_index;
this->m_reverse_api_channel_index_isSet = true;
}
bool
SWGRadioAstronomySettings::isSet(){
bool isObjectUpdated = false;
do{
if(m_input_frequency_offset_isSet){
isObjectUpdated = true; break;
}
if(m_sample_rate_isSet){
isObjectUpdated = true; break;
}
if(m_rf_bandwidth_isSet){
isObjectUpdated = true; break;
}
if(m_integration_isSet){
isObjectUpdated = true; break;
}
if(m_fft_size_isSet){
isObjectUpdated = true; break;
}
if(m_fft_window_isSet){
isObjectUpdated = true; break;
}
if(filter_freqs && *filter_freqs != QString("")){
isObjectUpdated = true; break;
}
if(star_tracker && *star_tracker != QString("")){
isObjectUpdated = true; break;
}
if(rotator && *rotator != QString("")){
isObjectUpdated = true; break;
}
if(m_run_mode_isSet){
isObjectUpdated = true; break;
}
if(m_sweep_start_at_time_isSet){
isObjectUpdated = true; break;
}
if(sweep_start_date_time && *sweep_start_date_time != QString("")){
isObjectUpdated = true; break;
}
if(m_sweep_type_isSet){
isObjectUpdated = true; break;
}
if(m_sweep1_start_isSet){
isObjectUpdated = true; break;
}
if(m_sweep1_stop_isSet){
isObjectUpdated = true; break;
}
if(m_sweep1_step_isSet){
isObjectUpdated = true; break;
}
if(m_sweep1_delay_isSet){
isObjectUpdated = true; break;
}
if(m_sweep2_start_isSet){
isObjectUpdated = true; break;
}
if(m_sweep2_stop_isSet){
isObjectUpdated = true; break;
}
if(m_sweep2_step_isSet){
isObjectUpdated = true; break;
}
if(m_sweep2_delay_isSet){
isObjectUpdated = true; break;
}
if(m_rgb_color_isSet){
isObjectUpdated = true; break;
}
if(title && *title != QString("")){
isObjectUpdated = true; break;
}
if(m_stream_index_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,227 @@
/**
* 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 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: 6.0.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.
*/
/*
* SWGRadioAstronomySettings.h
*
* RadioAstronomy
*/
#ifndef SWGRadioAstronomySettings_H_
#define SWGRadioAstronomySettings_H_
#include <QJsonObject>
#include <QString>
#include "SWGObject.h"
#include "export.h"
namespace SWGSDRangel {
class SWG_API SWGRadioAstronomySettings: public SWGObject {
public:
SWGRadioAstronomySettings();
SWGRadioAstronomySettings(QString* json);
virtual ~SWGRadioAstronomySettings();
void init();
void cleanup();
virtual QString asJson () override;
virtual QJsonObject* asJsonObject() override;
virtual void fromJsonObject(QJsonObject &json) override;
virtual SWGRadioAstronomySettings* fromJson(QString &jsonString) override;
qint64 getInputFrequencyOffset();
void setInputFrequencyOffset(qint64 input_frequency_offset);
qint32 getSampleRate();
void setSampleRate(qint32 sample_rate);
qint32 getRfBandwidth();
void setRfBandwidth(qint32 rf_bandwidth);
qint32 getIntegration();
void setIntegration(qint32 integration);
qint32 getFftSize();
void setFftSize(qint32 fft_size);
qint32 getFftWindow();
void setFftWindow(qint32 fft_window);
QString* getFilterFreqs();
void setFilterFreqs(QString* filter_freqs);
QString* getStarTracker();
void setStarTracker(QString* star_tracker);
QString* getRotator();
void setRotator(QString* rotator);
qint32 getRunMode();
void setRunMode(qint32 run_mode);
qint32 getSweepStartAtTime();
void setSweepStartAtTime(qint32 sweep_start_at_time);
QString* getSweepStartDateTime();
void setSweepStartDateTime(QString* sweep_start_date_time);
qint32 getSweepType();
void setSweepType(qint32 sweep_type);
float getSweep1Start();
void setSweep1Start(float sweep1_start);
float getSweep1Stop();
void setSweep1Stop(float sweep1_stop);
float getSweep1Step();
void setSweep1Step(float sweep1_step);
float getSweep1Delay();
void setSweep1Delay(float sweep1_delay);
float getSweep2Start();
void setSweep2Start(float sweep2_start);
float getSweep2Stop();
void setSweep2Stop(float sweep2_stop);
float getSweep2Step();
void setSweep2Step(float sweep2_step);
float getSweep2Delay();
void setSweep2Delay(float sweep2_delay);
qint32 getRgbColor();
void setRgbColor(qint32 rgb_color);
QString* getTitle();
void setTitle(QString* title);
qint32 getStreamIndex();
void setStreamIndex(qint32 stream_index);
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:
qint64 input_frequency_offset;
bool m_input_frequency_offset_isSet;
qint32 sample_rate;
bool m_sample_rate_isSet;
qint32 rf_bandwidth;
bool m_rf_bandwidth_isSet;
qint32 integration;
bool m_integration_isSet;
qint32 fft_size;
bool m_fft_size_isSet;
qint32 fft_window;
bool m_fft_window_isSet;
QString* filter_freqs;
bool m_filter_freqs_isSet;
QString* star_tracker;
bool m_star_tracker_isSet;
QString* rotator;
bool m_rotator_isSet;
qint32 run_mode;
bool m_run_mode_isSet;
qint32 sweep_start_at_time;
bool m_sweep_start_at_time_isSet;
QString* sweep_start_date_time;
bool m_sweep_start_date_time_isSet;
qint32 sweep_type;
bool m_sweep_type_isSet;
float sweep1_start;
bool m_sweep1_start_isSet;
float sweep1_stop;
bool m_sweep1_stop_isSet;
float sweep1_step;
bool m_sweep1_step_isSet;
float sweep1_delay;
bool m_sweep1_delay_isSet;
float sweep2_start;
bool m_sweep2_start_isSet;
float sweep2_stop;
bool m_sweep2_stop_isSet;
float sweep2_step;
bool m_sweep2_step_isSet;
float sweep2_delay;
bool m_sweep2_delay_isSet;
qint32 rgb_color;
bool m_rgb_color_isSet;
QString* title;
bool m_title_isSet;
qint32 stream_index;
bool m_stream_index_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 /* SWGRadioAstronomySettings_H_ */