mirror of
https://github.com/f4exb/sdrangel.git
synced 2025-06-15 21:12:27 -04:00
VOR single channel: first working release of VOR localizer feature plugin
This commit is contained in:
parent
ffe515fb63
commit
6c02a78d62
@ -436,9 +436,17 @@ void VORDemodSC::webapiFormatChannelReport(SWGSDRangel::SWGChannelReport& respon
|
|||||||
response.getVorDemodScReport()->setChannelPowerDb(CalcDb::dbPower(magsqAvg));
|
response.getVorDemodScReport()->setChannelPowerDb(CalcDb::dbPower(magsqAvg));
|
||||||
response.getVorDemodScReport()->setSquelch(m_basebandSink->getSquelchOpen() ? 1 : 0);
|
response.getVorDemodScReport()->setSquelch(m_basebandSink->getSquelchOpen() ? 1 : 0);
|
||||||
response.getVorDemodScReport()->setAudioSampleRate(m_basebandSink->getAudioSampleRate());
|
response.getVorDemodScReport()->setAudioSampleRate(m_basebandSink->getAudioSampleRate());
|
||||||
|
response.getVorDemodScReport()->setNavId(m_settings.m_navId);
|
||||||
response.getVorDemodScReport()->setRadial(m_radial);
|
response.getVorDemodScReport()->setRadial(m_radial);
|
||||||
response.getVorDemodScReport()->setRefMag(m_refMag);
|
response.getVorDemodScReport()->setRefMag(m_refMag);
|
||||||
response.getVorDemodScReport()->setVarMag(m_varMag);
|
response.getVorDemodScReport()->setVarMag(m_varMag);
|
||||||
|
float refMagDB = std::round(20.0*std::log10(m_refMag));
|
||||||
|
float varMagDB = std::round(20.0*std::log10(m_varMag));
|
||||||
|
bool validRefMag = refMagDB > m_settings.m_refThresholdDB;
|
||||||
|
bool validVarMag = varMagDB > m_settings.m_varThresholdDB;
|
||||||
|
response.getVorDemodScReport()->setValidRadial(validRefMag && validVarMag ? 1 : 0);
|
||||||
|
response.getVorDemodScReport()->setValidRefMag(validRefMag ? 1 : 0);
|
||||||
|
response.getVorDemodScReport()->setValidVarMag(validVarMag ? 1 : 0);
|
||||||
|
|
||||||
if (response.getVorDemodScReport()->getMorseIdent()) {
|
if (response.getVorDemodScReport()->getMorseIdent()) {
|
||||||
*response.getVorDemodScReport()->getMorseIdent() = m_morseIdent;
|
*response.getVorDemodScReport()->getMorseIdent() = m_morseIdent;
|
||||||
@ -502,12 +510,15 @@ void VORDemodSC::featuresSendSettings(QList<QString>& channelSettingsKeys, const
|
|||||||
|
|
||||||
void VORDemodSC::sendChannelReport(QList<MessageQueue*> *messageQueues)
|
void VORDemodSC::sendChannelReport(QList<MessageQueue*> *messageQueues)
|
||||||
{
|
{
|
||||||
SWGSDRangel::SWGChannelReport *swgChannelReport = new SWGSDRangel::SWGChannelReport();
|
|
||||||
webapiFormatChannelReport(*swgChannelReport);
|
|
||||||
QList<MessageQueue*>::iterator it = messageQueues->begin();
|
QList<MessageQueue*>::iterator it = messageQueues->begin();
|
||||||
|
|
||||||
for (; it != messageQueues->end(); ++it)
|
for (; it != messageQueues->end(); ++it)
|
||||||
{
|
{
|
||||||
|
SWGSDRangel::SWGChannelReport *swgChannelReport = new SWGSDRangel::SWGChannelReport();
|
||||||
|
swgChannelReport->setDirection(0);
|
||||||
|
swgChannelReport->setChannelType(new QString(m_channelId));
|
||||||
|
swgChannelReport->setVorDemodScReport(new SWGSDRangel::SWGVORDemodSCReport());
|
||||||
|
webapiFormatChannelReport(*swgChannelReport);
|
||||||
MainCore::MsgChannelReport *msg = MainCore::MsgChannelReport::create(this, swgChannelReport);
|
MainCore::MsgChannelReport *msg = MainCore::MsgChannelReport::create(this, swgChannelReport);
|
||||||
(*it)->push(msg);
|
(*it)->push(msg);
|
||||||
}
|
}
|
||||||
|
@ -303,6 +303,9 @@
|
|||||||
<property name="maximum">
|
<property name="maximum">
|
||||||
<number>100</number>
|
<number>100</number>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="pageStep">
|
||||||
|
<number>1</number>
|
||||||
|
</property>
|
||||||
<property name="value">
|
<property name="value">
|
||||||
<number>0</number>
|
<number>0</number>
|
||||||
</property>
|
</property>
|
||||||
@ -367,6 +370,9 @@
|
|||||||
<property name="maximum">
|
<property name="maximum">
|
||||||
<number>0</number>
|
<number>0</number>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="pageStep">
|
||||||
|
<number>1</number>
|
||||||
|
</property>
|
||||||
<property name="value">
|
<property name="value">
|
||||||
<number>-40</number>
|
<number>-40</number>
|
||||||
</property>
|
</property>
|
||||||
@ -416,6 +422,9 @@
|
|||||||
<property name="maximum">
|
<property name="maximum">
|
||||||
<number>100</number>
|
<number>100</number>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="pageStep">
|
||||||
|
<number>1</number>
|
||||||
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
@ -655,7 +664,6 @@
|
|||||||
</tabstops>
|
</tabstops>
|
||||||
<resources>
|
<resources>
|
||||||
<include location="../../../sdrgui/resources/res.qrc"/>
|
<include location="../../../sdrgui/resources/res.qrc"/>
|
||||||
<include location="map.qrc"/>
|
|
||||||
<include location="icons.qrc"/>
|
<include location="icons.qrc"/>
|
||||||
</resources>
|
</resources>
|
||||||
<connections/>
|
<connections/>
|
||||||
|
@ -302,7 +302,7 @@ void VORDemodSCSink::processOneSample(Complex &ci)
|
|||||||
{
|
{
|
||||||
if (m_ident != "")
|
if (m_ident != "")
|
||||||
{
|
{
|
||||||
qDebug() << m_ident << " " << Morse::toString(m_ident);
|
qDebug() << "VORDemodSCSink::processOneSample:" << m_ident << " " << Morse::toString(m_ident);
|
||||||
|
|
||||||
if (getMessageQueueToChannel())
|
if (getMessageQueueToChannel())
|
||||||
{
|
{
|
||||||
@ -343,7 +343,7 @@ void VORDemodSCSink::processOneSample(Complex &ci)
|
|||||||
m_ident = m_ident.simplified();
|
m_ident = m_ident.simplified();
|
||||||
if (m_ident != "")
|
if (m_ident != "")
|
||||||
{
|
{
|
||||||
qDebug() << m_ident << " " << Morse::toString(m_ident);
|
qDebug() << "VORDemodSCSink::processOneSample:" << m_ident << " " << Morse::toString(m_ident);
|
||||||
|
|
||||||
if (getMessageQueueToChannel())
|
if (getMessageQueueToChannel())
|
||||||
{
|
{
|
||||||
|
@ -25,9 +25,16 @@
|
|||||||
#include "SWGFeatureActions.h"
|
#include "SWGFeatureActions.h"
|
||||||
#include "SWGSimplePTTReport.h"
|
#include "SWGSimplePTTReport.h"
|
||||||
#include "SWGDeviceState.h"
|
#include "SWGDeviceState.h"
|
||||||
|
#include "SWGChannelReport.h"
|
||||||
|
|
||||||
#include "dsp/dspengine.h"
|
#include "dsp/dspengine.h"
|
||||||
|
#include "dsp/dspdevicesourceengine.h"
|
||||||
|
#include "dsp/devicesamplesource.h"
|
||||||
|
#include "device/deviceset.h"
|
||||||
|
#include "channel/channelapi.h"
|
||||||
|
#include "maincore.h"
|
||||||
|
|
||||||
|
#include "vorlocalizerreport.h"
|
||||||
#include "vorlocalizerworker.h"
|
#include "vorlocalizerworker.h"
|
||||||
#include "vorlocalizer.h"
|
#include "vorlocalizer.h"
|
||||||
|
|
||||||
@ -41,8 +48,7 @@ const char* const VORLocalizer::m_featureIdURI = "sdrangel.feature.vorlocalizer"
|
|||||||
const char* const VORLocalizer::m_featureId = "VORLocalizer";
|
const char* const VORLocalizer::m_featureId = "VORLocalizer";
|
||||||
|
|
||||||
VORLocalizer::VORLocalizer(WebAPIAdapterInterface *webAPIAdapterInterface) :
|
VORLocalizer::VORLocalizer(WebAPIAdapterInterface *webAPIAdapterInterface) :
|
||||||
Feature(m_featureIdURI, webAPIAdapterInterface),
|
Feature(m_featureIdURI, webAPIAdapterInterface)
|
||||||
m_ptt(false)
|
|
||||||
{
|
{
|
||||||
setObjectName(m_featureId);
|
setObjectName(m_featureId);
|
||||||
m_worker = new VorLocalizerWorker(webAPIAdapterInterface);
|
m_worker = new VorLocalizerWorker(webAPIAdapterInterface);
|
||||||
@ -64,7 +70,8 @@ void VORLocalizer::start()
|
|||||||
qDebug("VORLocalizer::start");
|
qDebug("VORLocalizer::start");
|
||||||
|
|
||||||
m_worker->reset();
|
m_worker->reset();
|
||||||
m_worker->setMessageQueueToGUI(getMessageQueueToGUI());
|
m_worker->setMessageQueueToFeature(getInputMessageQueue());
|
||||||
|
m_worker->setAvailableChannels(&m_availableChannels);
|
||||||
bool ok = m_worker->startWork();
|
bool ok = m_worker->startWork();
|
||||||
m_state = ok ? StRunning : StError;
|
m_state = ok ? StRunning : StError;
|
||||||
m_thread.start();
|
m_thread.start();
|
||||||
@ -108,8 +115,126 @@ bool VORLocalizer::handleMessage(const Message& cmd)
|
|||||||
else if (MsgRefreshChannels::match(cmd))
|
else if (MsgRefreshChannels::match(cmd))
|
||||||
{
|
{
|
||||||
qDebug() << "VORLocalizer::handleMessage: MsgRefreshChannels";
|
qDebug() << "VORLocalizer::handleMessage: MsgRefreshChannels";
|
||||||
VorLocalizerWorker::MsgRefreshChannels *msg = VorLocalizerWorker::MsgRefreshChannels::create();
|
updateChannels();
|
||||||
m_worker->getInputMessageQueue()->push(msg);
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (MainCore::MsgChannelReport::match(cmd))
|
||||||
|
{
|
||||||
|
MainCore::MsgChannelReport& report = (MainCore::MsgChannelReport&) cmd;
|
||||||
|
SWGSDRangel::SWGChannelReport* swgChannelReport = report.getSWGReport();
|
||||||
|
QString *channelType = swgChannelReport->getChannelType();
|
||||||
|
|
||||||
|
if (*channelType == "VORDemodSC")
|
||||||
|
{
|
||||||
|
SWGSDRangel::SWGVORDemodSCReport *swgVORDemodSCReport = swgChannelReport->getVorDemodScReport();
|
||||||
|
int navId = swgVORDemodSCReport->getNavId();
|
||||||
|
|
||||||
|
if (navId < 0) { // disregard message for unallocated channels
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool singlePlan = (m_vorSinglePlans.contains(navId)) ? m_vorSinglePlans[navId] : false;
|
||||||
|
|
||||||
|
// qDebug() << "VORLocalizer::handleMessage: MainCore::MsgChannelReport(VORDemodSC): "
|
||||||
|
// << "navId:" << navId
|
||||||
|
// << "singlePlanProvided" << m_vorSinglePlans.contains(navId)
|
||||||
|
// << "singlePlan:" << singlePlan;
|
||||||
|
|
||||||
|
if (m_vorChannelReports.contains(navId))
|
||||||
|
{
|
||||||
|
m_vorChannelReports[navId].m_radial = swgVORDemodSCReport->getRadial();
|
||||||
|
m_vorChannelReports[navId].m_refMag = swgVORDemodSCReport->getRefMag();
|
||||||
|
m_vorChannelReports[navId].m_varMag = swgVORDemodSCReport->getVarMag();
|
||||||
|
m_vorChannelReports[navId].m_validRadial = swgVORDemodSCReport->getValidRadial() != 0;
|
||||||
|
m_vorChannelReports[navId].m_validRefMag = swgVORDemodSCReport->getValidRefMag() != 0;
|
||||||
|
m_vorChannelReports[navId].m_validVarMag = swgVORDemodSCReport->getValidVarMag() != 0;
|
||||||
|
m_vorChannelReports[navId].m_morseIdent = *swgVORDemodSCReport->getMorseIdent();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_vorChannelReports[navId] = VORChannelReport{
|
||||||
|
swgVORDemodSCReport->getRadial(),
|
||||||
|
swgVORDemodSCReport->getRefMag(),
|
||||||
|
swgVORDemodSCReport->getVarMag(),
|
||||||
|
AverageUtil<float, double>(),
|
||||||
|
AverageUtil<float, double>(),
|
||||||
|
AverageUtil<float, double>(),
|
||||||
|
swgVORDemodSCReport->getValidRadial() != 0,
|
||||||
|
swgVORDemodSCReport->getValidRefMag() != 0,
|
||||||
|
swgVORDemodSCReport->getValidVarMag() != 0,
|
||||||
|
*swgVORDemodSCReport->getMorseIdent()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_vorChannelReports[navId].m_validRadial) {
|
||||||
|
m_vorChannelReports[navId].m_radialAvg(swgVORDemodSCReport->getRadial());
|
||||||
|
}
|
||||||
|
if (m_vorChannelReports[navId].m_validRefMag) {
|
||||||
|
m_vorChannelReports[navId].m_refMagAvg(swgVORDemodSCReport->getRefMag());
|
||||||
|
}
|
||||||
|
if (m_vorChannelReports[navId].m_validVarMag) {
|
||||||
|
m_vorChannelReports[navId].m_varMagAvg(swgVORDemodSCReport->getVarMag());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (getMessageQueueToGUI())
|
||||||
|
{
|
||||||
|
float radial = ((m_vorChannelReports[navId].m_radialAvg.getNumSamples() == 0) || singlePlan) ?
|
||||||
|
m_vorChannelReports[navId].m_radial :
|
||||||
|
m_vorChannelReports[navId].m_radialAvg.instantAverage();
|
||||||
|
float refMag = ((m_vorChannelReports[navId].m_refMagAvg.getNumSamples() == 0) || singlePlan) ?
|
||||||
|
m_vorChannelReports[navId].m_refMag :
|
||||||
|
m_vorChannelReports[navId].m_refMagAvg.instantAverage();
|
||||||
|
float varMag = ((m_vorChannelReports[navId].m_varMagAvg.getNumSamples() == 0) || singlePlan) ?
|
||||||
|
m_vorChannelReports[navId].m_varMag :
|
||||||
|
m_vorChannelReports[navId].m_varMagAvg.instantAverage();
|
||||||
|
bool validRadial = singlePlan ? m_vorChannelReports[navId].m_validRadial :
|
||||||
|
m_vorChannelReports[navId].m_radialAvg.getNumSamples() != 0 || m_vorChannelReports[navId].m_validRadial;
|
||||||
|
bool validRefMag = singlePlan ? m_vorChannelReports[navId].m_validRefMag :
|
||||||
|
m_vorChannelReports[navId].m_refMagAvg.getNumSamples() != 0 || m_vorChannelReports[navId].m_validRefMag;
|
||||||
|
bool validVarMag = singlePlan ? m_vorChannelReports[navId].m_validVarMag :
|
||||||
|
m_vorChannelReports[navId].m_varMagAvg.getNumSamples() != 0 || m_vorChannelReports[navId].m_validVarMag;
|
||||||
|
VORLocalizerReport::MsgReportRadial *msgRadial = VORLocalizerReport::MsgReportRadial::create(
|
||||||
|
navId,
|
||||||
|
radial,
|
||||||
|
refMag,
|
||||||
|
varMag,
|
||||||
|
validRadial,
|
||||||
|
validRefMag,
|
||||||
|
validVarMag
|
||||||
|
);
|
||||||
|
getMessageQueueToGUI()->push(msgRadial);
|
||||||
|
VORLocalizerReport::MsgReportIdent *msgIdent = VORLocalizerReport::MsgReportIdent::create(
|
||||||
|
navId,
|
||||||
|
m_vorChannelReports[navId].m_morseIdent
|
||||||
|
);
|
||||||
|
getMessageQueueToGUI()->push(msgIdent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (VORLocalizerReport::MsgReportServiceddVORs::match(cmd))
|
||||||
|
{
|
||||||
|
qDebug() << "VORLocalizer::handleMessage: MsgReportServiceddVORs:";
|
||||||
|
VORLocalizerReport::MsgReportServiceddVORs& report = (VORLocalizerReport::MsgReportServiceddVORs&) cmd;
|
||||||
|
std::vector<int>& vorNavIds = report.getNavIds();
|
||||||
|
m_vorSinglePlans = report.getSinglePlans();
|
||||||
|
|
||||||
|
for (std::vector<int>::const_iterator it = vorNavIds.begin(); it != vorNavIds.end(); ++it)
|
||||||
|
{
|
||||||
|
m_vorChannelReports[*it].m_radialAvg.reset();
|
||||||
|
m_vorChannelReports[*it].m_refMagAvg.reset();
|
||||||
|
m_vorChannelReports[*it].m_varMagAvg.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (getMessageQueueToGUI())
|
||||||
|
{
|
||||||
|
VORLocalizerReport::MsgReportServiceddVORs *msgToGUI = VORLocalizerReport::MsgReportServiceddVORs::create();
|
||||||
|
msgToGUI->getNavIds() = vorNavIds;
|
||||||
|
getMessageQueueToGUI()->push(msgToGUI);
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -146,6 +271,8 @@ void VORLocalizer::applySettings(const VORLocalizerSettings& settings, bool forc
|
|||||||
<< " m_title: " << settings.m_title
|
<< " m_title: " << settings.m_title
|
||||||
<< " m_rgbColor: " << settings.m_rgbColor
|
<< " m_rgbColor: " << settings.m_rgbColor
|
||||||
<< " m_magDecAdjust: " << settings.m_magDecAdjust
|
<< " m_magDecAdjust: " << settings.m_magDecAdjust
|
||||||
|
<< " m_rrTime: " << settings.m_rrTime
|
||||||
|
<< " m_centerShift: " << settings.m_centerShift
|
||||||
<< " force: " << force;
|
<< " force: " << force;
|
||||||
|
|
||||||
QList<QString> reverseAPIKeys;
|
QList<QString> reverseAPIKeys;
|
||||||
@ -159,6 +286,12 @@ void VORLocalizer::applySettings(const VORLocalizerSettings& settings, bool forc
|
|||||||
if ((m_settings.m_magDecAdjust != settings.m_magDecAdjust) || force) {
|
if ((m_settings.m_magDecAdjust != settings.m_magDecAdjust) || force) {
|
||||||
reverseAPIKeys.append("magDecAdjust");
|
reverseAPIKeys.append("magDecAdjust");
|
||||||
}
|
}
|
||||||
|
if ((m_settings.m_rrTime != settings.m_rrTime) || force) {
|
||||||
|
reverseAPIKeys.append("rrTime");
|
||||||
|
}
|
||||||
|
if ((m_settings.m_centerShift != settings.m_centerShift) || force) {
|
||||||
|
reverseAPIKeys.append("centerShift");
|
||||||
|
}
|
||||||
|
|
||||||
VorLocalizerWorker::MsgConfigureVORLocalizerWorker *msg = VorLocalizerWorker::MsgConfigureVORLocalizerWorker::create(
|
VorLocalizerWorker::MsgConfigureVORLocalizerWorker *msg = VorLocalizerWorker::MsgConfigureVORLocalizerWorker::create(
|
||||||
settings, force
|
settings, force
|
||||||
@ -178,6 +311,75 @@ void VORLocalizer::applySettings(const VORLocalizerSettings& settings, bool forc
|
|||||||
m_settings = settings;
|
m_settings = settings;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void VORLocalizer::updateChannels()
|
||||||
|
{
|
||||||
|
MainCore *mainCore = MainCore::instance();
|
||||||
|
MessagePipes& messagePipes = mainCore->getMessagePipes();
|
||||||
|
std::vector<DeviceSet*>& deviceSets = mainCore->getDeviceSets();
|
||||||
|
std::vector<DeviceSet*>::const_iterator it = deviceSets.begin();
|
||||||
|
m_availableChannels.clear();
|
||||||
|
|
||||||
|
int deviceIndex = 0;
|
||||||
|
|
||||||
|
for (; it != deviceSets.end(); ++it, deviceIndex++)
|
||||||
|
{
|
||||||
|
DSPDeviceSourceEngine *deviceSourceEngine = (*it)->m_deviceSourceEngine;
|
||||||
|
|
||||||
|
if (deviceSourceEngine)
|
||||||
|
{
|
||||||
|
DeviceSampleSource *deviceSource = deviceSourceEngine->getSource();
|
||||||
|
quint64 deviceCenterFrequency = deviceSource->getCenterFrequency();
|
||||||
|
int basebandSampleRate = deviceSource->getSampleRate();
|
||||||
|
|
||||||
|
for (int chi = 0; chi < (*it)->getNumberOfChannels(); chi++)
|
||||||
|
{
|
||||||
|
ChannelAPI *channel = (*it)->getChannelAt(chi);
|
||||||
|
|
||||||
|
if (channel->getURI() == "sdrangel.channel.vordemodsc")
|
||||||
|
{
|
||||||
|
if (!m_availableChannels.contains(channel))
|
||||||
|
{
|
||||||
|
MessageQueue *messageQueue = messagePipes.registerChannelToFeature(channel, this, "report");
|
||||||
|
QObject::connect(
|
||||||
|
messageQueue,
|
||||||
|
&MessageQueue::messageEnqueued,
|
||||||
|
this,
|
||||||
|
[=](){ this->handleChannelMessageQueue(messageQueue); },
|
||||||
|
Qt::QueuedConnection
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
VORLocalizerSettings::AvailableChannel availableChannel =
|
||||||
|
VORLocalizerSettings::AvailableChannel{deviceIndex, chi, channel, deviceCenterFrequency, basebandSampleRate, -1};
|
||||||
|
m_availableChannels[channel] = availableChannel;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (getMessageQueueToGUI())
|
||||||
|
{
|
||||||
|
VORLocalizerReport::MsgReportChannels *msgToGUI = VORLocalizerReport::MsgReportChannels::create();
|
||||||
|
std::vector<VORLocalizerReport::MsgReportChannels::Channel>& msgChannels = msgToGUI->getChannels();
|
||||||
|
QHash<ChannelAPI*, VORLocalizerSettings::AvailableChannel>::iterator it = m_availableChannels.begin();
|
||||||
|
|
||||||
|
for (; it != m_availableChannels.end(); ++it)
|
||||||
|
{
|
||||||
|
VORLocalizerReport::MsgReportChannels::Channel msgChannel =
|
||||||
|
VORLocalizerReport::MsgReportChannels::Channel{
|
||||||
|
it->m_deviceSetIndex,
|
||||||
|
it->m_channelIndex
|
||||||
|
};
|
||||||
|
msgChannels.push_back(msgChannel);
|
||||||
|
}
|
||||||
|
|
||||||
|
getMessageQueueToGUI()->push(msgToGUI);
|
||||||
|
}
|
||||||
|
|
||||||
|
VorLocalizerWorker::MsgRefreshChannels *msgToWorker = VorLocalizerWorker::MsgRefreshChannels::create();
|
||||||
|
m_worker->getInputMessageQueue()->push(msgToWorker);
|
||||||
|
}
|
||||||
|
|
||||||
int VORLocalizer::webapiRun(bool run,
|
int VORLocalizer::webapiRun(bool run,
|
||||||
SWGSDRangel::SWGDeviceState& response,
|
SWGSDRangel::SWGDeviceState& response,
|
||||||
QString& errorMessage)
|
QString& errorMessage)
|
||||||
@ -237,6 +439,8 @@ void VORLocalizer::webapiFormatFeatureSettings(
|
|||||||
|
|
||||||
response.getVorLocalizerSettings()->setRgbColor(settings.m_rgbColor);
|
response.getVorLocalizerSettings()->setRgbColor(settings.m_rgbColor);
|
||||||
response.getVorLocalizerSettings()->setMagDecAdjust(settings.m_magDecAdjust);
|
response.getVorLocalizerSettings()->setMagDecAdjust(settings.m_magDecAdjust);
|
||||||
|
response.getVorLocalizerSettings()->setRrTime(settings.m_rrTime);
|
||||||
|
response.getVorLocalizerSettings()->setCenterShift(settings.m_centerShift);
|
||||||
|
|
||||||
response.getVorLocalizerSettings()->setUseReverseApi(settings.m_useReverseAPI ? 1 : 0);
|
response.getVorLocalizerSettings()->setUseReverseApi(settings.m_useReverseAPI ? 1 : 0);
|
||||||
|
|
||||||
@ -265,6 +469,12 @@ void VORLocalizer::webapiUpdateFeatureSettings(
|
|||||||
if (featureSettingsKeys.contains("magDecAdjust")) {
|
if (featureSettingsKeys.contains("magDecAdjust")) {
|
||||||
settings.m_magDecAdjust = response.getVorLocalizerSettings()->getMagDecAdjust();
|
settings.m_magDecAdjust = response.getVorLocalizerSettings()->getMagDecAdjust();
|
||||||
}
|
}
|
||||||
|
if (featureSettingsKeys.contains("rrTime")) {
|
||||||
|
settings.m_rrTime = response.getVorLocalizerSettings()->getRrTime();
|
||||||
|
}
|
||||||
|
if (featureSettingsKeys.contains("centerShift")) {
|
||||||
|
settings.m_centerShift = response.getVorLocalizerSettings()->getCenterShift();
|
||||||
|
}
|
||||||
if (featureSettingsKeys.contains("useReverseAPI")) {
|
if (featureSettingsKeys.contains("useReverseAPI")) {
|
||||||
settings.m_useReverseAPI = response.getVorLocalizerSettings()->getUseReverseApi() != 0;
|
settings.m_useReverseAPI = response.getVorLocalizerSettings()->getUseReverseApi() != 0;
|
||||||
}
|
}
|
||||||
@ -302,6 +512,12 @@ void VORLocalizer::webapiReverseSendSettings(QList<QString>& channelSettingsKeys
|
|||||||
if (channelSettingsKeys.contains("magDecAdjust") || force) {
|
if (channelSettingsKeys.contains("magDecAdjust") || force) {
|
||||||
swgVORLocalizerSettings->setMagDecAdjust(settings.m_magDecAdjust);
|
swgVORLocalizerSettings->setMagDecAdjust(settings.m_magDecAdjust);
|
||||||
}
|
}
|
||||||
|
if (channelSettingsKeys.contains("rrTime") || force) {
|
||||||
|
swgVORLocalizerSettings->setRrTime(settings.m_rrTime);
|
||||||
|
}
|
||||||
|
if (channelSettingsKeys.contains("centerShift") || force) {
|
||||||
|
swgVORLocalizerSettings->setCenterShift(settings.m_centerShift);
|
||||||
|
}
|
||||||
|
|
||||||
QString channelSettingsURL = QString("http://%1:%2/sdrangel/featureset/%3/feature/%4/settings")
|
QString channelSettingsURL = QString("http://%1:%2/sdrangel/featureset/%3/feature/%4/settings")
|
||||||
.arg(settings.m_reverseAPIAddress)
|
.arg(settings.m_reverseAPIAddress)
|
||||||
@ -343,3 +559,15 @@ void VORLocalizer::networkManagerFinished(QNetworkReply *reply)
|
|||||||
|
|
||||||
reply->deleteLater();
|
reply->deleteLater();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void VORLocalizer::handleChannelMessageQueue(MessageQueue* messageQueue)
|
||||||
|
{
|
||||||
|
Message* message;
|
||||||
|
|
||||||
|
while ((message = messageQueue->pop()) != nullptr)
|
||||||
|
{
|
||||||
|
if (handleMessage(*message)) {
|
||||||
|
delete message;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
|
|
||||||
#include "feature/feature.h"
|
#include "feature/feature.h"
|
||||||
#include "util/message.h"
|
#include "util/message.h"
|
||||||
|
#include "util/average.h"
|
||||||
|
|
||||||
#include "vorlocalizersettings.h"
|
#include "vorlocalizersettings.h"
|
||||||
|
|
||||||
@ -170,10 +171,30 @@ public:
|
|||||||
static const char* const m_featureId;
|
static const char* const m_featureId;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
struct VORChannelReport
|
||||||
|
{
|
||||||
|
float m_radial; //!< current detected radial
|
||||||
|
float m_refMag; //!< current reference signal magnitude
|
||||||
|
float m_varMag; //!< current variable signal magnitude
|
||||||
|
AverageUtil<float, double> m_radialAvg;
|
||||||
|
AverageUtil<float, double> m_refMagAvg;
|
||||||
|
AverageUtil<float, double> m_varMagAvg;
|
||||||
|
bool m_validRadial;
|
||||||
|
bool m_validRefMag;
|
||||||
|
bool m_validVarMag;
|
||||||
|
QString m_morseIdent; //!< identification morse code transcript
|
||||||
|
|
||||||
|
VORChannelReport() = default;
|
||||||
|
VORChannelReport(const VORChannelReport&) = default;
|
||||||
|
VORChannelReport& operator=(const VORChannelReport&) = default;
|
||||||
|
};
|
||||||
|
|
||||||
QThread m_thread;
|
QThread m_thread;
|
||||||
VorLocalizerWorker *m_worker;
|
VorLocalizerWorker *m_worker;
|
||||||
VORLocalizerSettings m_settings;
|
VORLocalizerSettings m_settings;
|
||||||
bool m_ptt;
|
QHash<ChannelAPI*, VORLocalizerSettings::AvailableChannel> m_availableChannels;
|
||||||
|
QHash<int, VORChannelReport> m_vorChannelReports;
|
||||||
|
QHash<int, bool> m_vorSinglePlans;
|
||||||
|
|
||||||
QNetworkAccessManager *m_networkManager;
|
QNetworkAccessManager *m_networkManager;
|
||||||
QNetworkRequest m_networkRequest;
|
QNetworkRequest m_networkRequest;
|
||||||
@ -181,10 +202,13 @@ private:
|
|||||||
void start();
|
void start();
|
||||||
void stop();
|
void stop();
|
||||||
void applySettings(const VORLocalizerSettings& settings, bool force = false);
|
void applySettings(const VORLocalizerSettings& settings, bool force = false);
|
||||||
|
void updateChannels();
|
||||||
void webapiReverseSendSettings(QList<QString>& featureSettingsKeys, const VORLocalizerSettings& settings, bool force);
|
void webapiReverseSendSettings(QList<QString>& featureSettingsKeys, const VORLocalizerSettings& settings, bool force);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void networkManagerFinished(QNetworkReply *reply);
|
void networkManagerFinished(QNetworkReply *reply);
|
||||||
|
void handleChannelMessageQueue(MessageQueue* messageQueue);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // INCLUDE_FEATURE_VORLOCALIZER_H_
|
#endif // INCLUDE_FEATURE_VORLOCALIZER_H_
|
||||||
|
@ -333,8 +333,10 @@ static bool calcIntersectionPoint(float lat1, float lon1, float bearing1, float
|
|||||||
double cosLat1 = cos(lat1Rad);
|
double cosLat1 = cos(lat1Rad);
|
||||||
double cosLat2 = cos(lat2Rad);
|
double cosLat2 = cos(lat2Rad);
|
||||||
double delta12 = 2.0 * asin(sqrt(sindlat*sindlat+cosLat1*cosLat2*sindlon*sindlon));
|
double delta12 = 2.0 * asin(sqrt(sindlat*sindlat+cosLat1*cosLat2*sindlon*sindlon));
|
||||||
if (abs(delta12) < std::numeric_limits<float>::epsilon())
|
|
||||||
|
if (abs(delta12) < std::numeric_limits<float>::epsilon()) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
double sinLat1 = sin(lat1Rad);
|
double sinLat1 = sin(lat1Rad);
|
||||||
double sinLat2 = sin(lat2Rad);
|
double sinLat2 = sin(lat2Rad);
|
||||||
@ -342,8 +344,8 @@ static bool calcIntersectionPoint(float lat1, float lon1, float bearing1, float
|
|||||||
double cosDelta12 = cos(delta12);
|
double cosDelta12 = cos(delta12);
|
||||||
double thetaA = acos((sinLat2-sinLat1*cosDelta12)/(sinDelta12*cosLat1));
|
double thetaA = acos((sinLat2-sinLat1*cosDelta12)/(sinDelta12*cosLat1));
|
||||||
double thetaB = acos((sinLat1-sinLat2*cosDelta12)/(sinDelta12*cosLat2));
|
double thetaB = acos((sinLat1-sinLat2*cosDelta12)/(sinDelta12*cosLat2));
|
||||||
|
|
||||||
double theta12, theta21;
|
double theta12, theta21;
|
||||||
|
|
||||||
if (sin(lon2Rad-lon1Rad) > 0.0)
|
if (sin(lon2Rad-lon1Rad) > 0.0)
|
||||||
{
|
{
|
||||||
theta12 = thetaA;
|
theta12 = thetaA;
|
||||||
@ -354,14 +356,19 @@ static bool calcIntersectionPoint(float lat1, float lon1, float bearing1, float
|
|||||||
theta12 = 2.0*M_PI-thetaA;
|
theta12 = 2.0*M_PI-thetaA;
|
||||||
theta21 = thetaB;
|
theta21 = thetaB;
|
||||||
}
|
}
|
||||||
|
|
||||||
double alpha1 = theta13 - theta12;
|
double alpha1 = theta13 - theta12;
|
||||||
double alpha2 = theta21 - theta23;
|
double alpha2 = theta21 - theta23;
|
||||||
double sinAlpha1 = sin(alpha1);
|
double sinAlpha1 = sin(alpha1);
|
||||||
double sinAlpha2 = sin(alpha2);
|
double sinAlpha2 = sin(alpha2);
|
||||||
if ((sinAlpha1 == 0.0) && (sinAlpha2 == 0.0))
|
|
||||||
|
if ((sinAlpha1 == 0.0) && (sinAlpha2 == 0.0)) {
|
||||||
return false;
|
return false;
|
||||||
if (sinAlpha1*sinAlpha2 < 0.0)
|
}
|
||||||
|
if (sinAlpha1*sinAlpha2 < 0.0) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
double cosAlpha1 = cos(alpha1);
|
double cosAlpha1 = cos(alpha1);
|
||||||
double cosAlpha2 = cos(alpha2);
|
double cosAlpha2 = cos(alpha2);
|
||||||
double cosAlpha3 = -cosAlpha1*cosAlpha2+sinAlpha1*sinAlpha2*cos(delta12);
|
double cosAlpha3 = -cosAlpha1*cosAlpha2+sinAlpha1*sinAlpha2*cos(delta12);
|
||||||
@ -382,7 +389,7 @@ VORGUI::VORGUI(NavAid *navAid, VORLocalizerGUI *gui) :
|
|||||||
// These are deleted by QTableWidget
|
// These are deleted by QTableWidget
|
||||||
m_nameItem = new QTableWidgetItem();
|
m_nameItem = new QTableWidgetItem();
|
||||||
m_frequencyItem = new QTableWidgetItem();
|
m_frequencyItem = new QTableWidgetItem();
|
||||||
m_offsetItem = new QTableWidgetItem();
|
m_navIdItem = new QTableWidgetItem();
|
||||||
m_radialItem = new QTableWidgetItem();
|
m_radialItem = new QTableWidgetItem();
|
||||||
m_identItem = new QTableWidgetItem();
|
m_identItem = new QTableWidgetItem();
|
||||||
m_morseItem = new QTableWidgetItem();
|
m_morseItem = new QTableWidgetItem();
|
||||||
@ -412,15 +419,18 @@ VORGUI::VORGUI(NavAid *navAid, VORLocalizerGUI *gui) :
|
|||||||
|
|
||||||
void VORGUI::on_audioMute_toggled(bool checked)
|
void VORGUI::on_audioMute_toggled(bool checked)
|
||||||
{
|
{
|
||||||
m_gui->m_settings.m_subChannelSettings.value(m_navAid->m_id)->m_audioMute = checked;
|
m_gui->m_settings.m_subChannelSettings[m_navAid->m_id].m_audioMute = checked;
|
||||||
m_gui->applySettings();
|
m_gui->applySettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
QVariant VORModel::data(const QModelIndex &index, int role) const
|
QVariant VORModel::data(const QModelIndex &index, int role) const
|
||||||
{
|
{
|
||||||
int row = index.row();
|
int row = index.row();
|
||||||
if ((row < 0) || (row >= m_vors.count()))
|
|
||||||
|
if ((row < 0) || (row >= m_vors.count())) {
|
||||||
return QVariant();
|
return QVariant();
|
||||||
|
}
|
||||||
|
|
||||||
if (role == VORModel::positionRole)
|
if (role == VORModel::positionRole)
|
||||||
{
|
{
|
||||||
// Coordinates to display the VOR icon at
|
// Coordinates to display the VOR icon at
|
||||||
@ -436,15 +446,22 @@ QVariant VORModel::data(const QModelIndex &index, int role) const
|
|||||||
QStringList list;
|
QStringList list;
|
||||||
list.append(QString("Name: %1").arg(m_vors[row]->m_name));
|
list.append(QString("Name: %1").arg(m_vors[row]->m_name));
|
||||||
list.append(QString("Frequency: %1 MHz").arg(m_vors[row]->m_frequencykHz / 1000.0f, 0, 'f', 1));
|
list.append(QString("Frequency: %1 MHz").arg(m_vors[row]->m_frequencykHz / 1000.0f, 0, 'f', 1));
|
||||||
if (m_vors[row]->m_channel != "")
|
|
||||||
|
if (m_vors[row]->m_channel != "") {
|
||||||
list.append(QString("Channel: %1").arg(m_vors[row]->m_channel));
|
list.append(QString("Channel: %1").arg(m_vors[row]->m_channel));
|
||||||
|
}
|
||||||
|
|
||||||
list.append(QString("Ident: %1 %2").arg(m_vors[row]->m_ident).arg(Morse::toSpacedUnicodeMorse(m_vors[row]->m_ident)));
|
list.append(QString("Ident: %1 %2").arg(m_vors[row]->m_ident).arg(Morse::toSpacedUnicodeMorse(m_vors[row]->m_ident)));
|
||||||
list.append(QString("Range: %1 nm").arg(m_vors[row]->m_range));
|
list.append(QString("Range: %1 nm").arg(m_vors[row]->m_range));
|
||||||
if (m_vors[row]->m_alignedTrueNorth)
|
|
||||||
|
if (m_vors[row]->m_alignedTrueNorth) {
|
||||||
list.append(QString("Magnetic declination: Aligned to true North"));
|
list.append(QString("Magnetic declination: Aligned to true North"));
|
||||||
else if (m_vors[row]->m_magneticDeclination != 0.0f)
|
} else if (m_vors[row]->m_magneticDeclination != 0.0f) {
|
||||||
list.append(QString("Magnetic declination: %1%2").arg(std::round(m_vors[row]->m_magneticDeclination)).arg(QChar(0x00b0)));
|
list.append(QString("Magnetic declination: %1%2").arg(std::round(m_vors[row]->m_magneticDeclination)).arg(QChar(0x00b0)));
|
||||||
|
}
|
||||||
|
|
||||||
QString data = list.join("\n");
|
QString data = list.join("\n");
|
||||||
|
|
||||||
return QVariant::fromValue(data);
|
return QVariant::fromValue(data);
|
||||||
}
|
}
|
||||||
else if (role == VORModel::vorImageRole)
|
else if (role == VORModel::vorImageRole)
|
||||||
@ -455,11 +472,12 @@ QVariant VORModel::data(const QModelIndex &index, int role) const
|
|||||||
else if (role == VORModel::bubbleColourRole)
|
else if (role == VORModel::bubbleColourRole)
|
||||||
{
|
{
|
||||||
// Select a background colour for the text bubble next to the VOR
|
// Select a background colour for the text bubble next to the VOR
|
||||||
if (m_selected[row])
|
if (m_selected[row]) {
|
||||||
return QVariant::fromValue(QColor("lightgreen"));
|
return QVariant::fromValue(QColor("lightgreen"));
|
||||||
else
|
} else {
|
||||||
return QVariant::fromValue(QColor("lightblue"));
|
return QVariant::fromValue(QColor("lightblue"));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
else if (role == VORModel::vorRadialRole)
|
else if (role == VORModel::vorRadialRole)
|
||||||
{
|
{
|
||||||
// Draw a radial line from centre of VOR outwards at the demodulated angle
|
// Draw a radial line from centre of VOR outwards at the demodulated angle
|
||||||
@ -471,10 +489,13 @@ QVariant VORModel::data(const QModelIndex &index, int role) const
|
|||||||
|
|
||||||
float endLat, endLong;
|
float endLat, endLong;
|
||||||
float bearing;
|
float bearing;
|
||||||
if (m_gui->m_settings.m_magDecAdjust && !m_vors[row]->m_alignedTrueNorth)
|
|
||||||
|
if (m_gui->m_settings.m_magDecAdjust && !m_vors[row]->m_alignedTrueNorth) {
|
||||||
bearing = m_radials[row] - m_vors[row]->m_magneticDeclination;
|
bearing = m_radials[row] - m_vors[row]->m_magneticDeclination;
|
||||||
else
|
} else {
|
||||||
bearing = m_radials[row];
|
bearing = m_radials[row];
|
||||||
|
}
|
||||||
|
|
||||||
calcRadialEndPoint(m_vors[row]->m_latitude, m_vors[row]->m_longitude, m_vors[row]->getRangeMetres(), bearing, endLat, endLong);
|
calcRadialEndPoint(m_vors[row]->m_latitude, m_vors[row]->m_longitude, m_vors[row]->getRangeMetres(), bearing, endLat, endLong);
|
||||||
list.push_back(QVariant::fromValue(*new QGeoCoordinate(endLat, endLong, Units::feetToMetres(m_vors[row]->m_elevation))));
|
list.push_back(QVariant::fromValue(*new QGeoCoordinate(endLat, endLong, Units::feetToMetres(m_vors[row]->m_elevation))));
|
||||||
|
|
||||||
@ -484,36 +505,49 @@ QVariant VORModel::data(const QModelIndex &index, int role) const
|
|||||||
return QVariantList();
|
return QVariantList();
|
||||||
}
|
}
|
||||||
else if (role == VORModel::selectedRole)
|
else if (role == VORModel::selectedRole)
|
||||||
|
{
|
||||||
return QVariant::fromValue(m_selected[row]);
|
return QVariant::fromValue(m_selected[row]);
|
||||||
|
}
|
||||||
|
|
||||||
return QVariant();
|
return QVariant();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool VORModel::setData(const QModelIndex &index, const QVariant& value, int role)
|
bool VORModel::setData(const QModelIndex &index, const QVariant& value, int role)
|
||||||
{
|
{
|
||||||
int row = index.row();
|
int row = index.row();
|
||||||
if ((row < 0) || (row >= m_vors.count()))
|
|
||||||
|
if ((row < 0) || (row >= m_vors.count())) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (role == VORModel::selectedRole)
|
if (role == VORModel::selectedRole)
|
||||||
{
|
{
|
||||||
bool selected = value.toBool();
|
bool selected = value.toBool();
|
||||||
VORGUI *vorGUI;
|
VORGUI *vorGUI;
|
||||||
if (selected == true)
|
|
||||||
|
if (selected)
|
||||||
{
|
{
|
||||||
vorGUI = new VORGUI(m_vors[row], m_gui);
|
vorGUI = new VORGUI(m_vors[row], m_gui);
|
||||||
m_vorGUIs[row] = vorGUI;
|
m_vorGUIs[row] = vorGUI;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
vorGUI = m_vorGUIs[row];
|
vorGUI = m_vorGUIs[row];
|
||||||
|
}
|
||||||
|
|
||||||
m_gui->selectVOR(vorGUI, selected);
|
m_gui->selectVOR(vorGUI, selected);
|
||||||
m_selected[row] = selected;
|
m_selected[row] = selected;
|
||||||
emit dataChanged(index, index);
|
emit dataChanged(index, index);
|
||||||
|
|
||||||
if (!selected)
|
if (!selected)
|
||||||
{
|
{
|
||||||
delete vorGUI;
|
delete vorGUI;
|
||||||
m_vorGUIs[row] = nullptr;
|
m_vorGUIs[row] = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -533,28 +567,33 @@ bool VORModel::findIntersection(float &lat, float &lon)
|
|||||||
{
|
{
|
||||||
lat1 = m_vors[i]->m_latitude;
|
lat1 = m_vors[i]->m_latitude;
|
||||||
lon1 = m_vors[i]->m_longitude;
|
lon1 = m_vors[i]->m_longitude;
|
||||||
if (m_gui->m_settings.m_magDecAdjust && !m_vors[i]->m_alignedTrueNorth)
|
|
||||||
|
if (m_gui->m_settings.m_magDecAdjust && !m_vors[i]->m_alignedTrueNorth) {
|
||||||
bearing1 = m_radials[i] - m_vors[i]->m_magneticDeclination;
|
bearing1 = m_radials[i] - m_vors[i]->m_magneticDeclination;
|
||||||
else
|
} else {
|
||||||
bearing1 = m_radials[i];
|
bearing1 = m_radials[i];
|
||||||
|
}
|
||||||
|
|
||||||
valid1 = true;
|
valid1 = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
lat2 = m_vors[i]->m_latitude;
|
lat2 = m_vors[i]->m_latitude;
|
||||||
lon2 = m_vors[i]->m_longitude;
|
lon2 = m_vors[i]->m_longitude;
|
||||||
if (m_gui->m_settings.m_magDecAdjust && !m_vors[i]->m_alignedTrueNorth)
|
|
||||||
|
if (m_gui->m_settings.m_magDecAdjust && !m_vors[i]->m_alignedTrueNorth) {
|
||||||
bearing2 = m_radials[i] - m_vors[i]->m_magneticDeclination;
|
bearing2 = m_radials[i] - m_vors[i]->m_magneticDeclination;
|
||||||
else
|
} else {
|
||||||
bearing2 = m_radials[i];
|
bearing2 = m_radials[i];
|
||||||
|
}
|
||||||
|
|
||||||
valid2 = true;
|
valid2 = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (valid1 && valid2)
|
if (valid1 && valid2) {
|
||||||
{
|
|
||||||
return calcIntersectionPoint(lat1, lon1, bearing1, lat2, lon2, bearing2, lat, lon);
|
return calcIntersectionPoint(lat1, lon1, bearing1, lat2, lon2, bearing2, lat, lon);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -571,7 +610,7 @@ void VORLocalizerGUI::resizeTable()
|
|||||||
ui->vorData->setRowCount(row + 1);
|
ui->vorData->setRowCount(row + 1);
|
||||||
ui->vorData->setItem(row, VORLocalizerSettings::VOR_COL_NAME, new QTableWidgetItem("White Sulphur Springs"));
|
ui->vorData->setItem(row, VORLocalizerSettings::VOR_COL_NAME, new QTableWidgetItem("White Sulphur Springs"));
|
||||||
ui->vorData->setItem(row, VORLocalizerSettings::VOR_COL_FREQUENCY, new QTableWidgetItem("Freq (MHz) "));
|
ui->vorData->setItem(row, VORLocalizerSettings::VOR_COL_FREQUENCY, new QTableWidgetItem("Freq (MHz) "));
|
||||||
ui->vorData->setItem(row, VORLocalizerSettings::VOR_COL_OFFSET, new QTableWidgetItem("Offset (kHz) "));
|
ui->vorData->setItem(row, VORLocalizerSettings::VOR_COL_NAVID, new QTableWidgetItem("99999999"));
|
||||||
ui->vorData->setItem(row, VORLocalizerSettings::VOR_COL_IDENT, new QTableWidgetItem("Ident "));
|
ui->vorData->setItem(row, VORLocalizerSettings::VOR_COL_IDENT, new QTableWidgetItem("Ident "));
|
||||||
ui->vorData->setItem(row, VORLocalizerSettings::VOR_COL_MORSE, new QTableWidgetItem(Morse::toSpacedUnicode(morse)));
|
ui->vorData->setItem(row, VORLocalizerSettings::VOR_COL_MORSE, new QTableWidgetItem(Morse::toSpacedUnicode(morse)));
|
||||||
ui->vorData->setItem(row, VORLocalizerSettings::VOR_COL_RADIAL, new QTableWidgetItem("Radial (o) "));
|
ui->vorData->setItem(row, VORLocalizerSettings::VOR_COL_RADIAL, new QTableWidgetItem("Radial (o) "));
|
||||||
@ -588,7 +627,6 @@ void VORLocalizerGUI::resizeTable()
|
|||||||
void VORLocalizerGUI::vorData_sectionMoved(int logicalIndex, int oldVisualIndex, int newVisualIndex)
|
void VORLocalizerGUI::vorData_sectionMoved(int logicalIndex, int oldVisualIndex, int newVisualIndex)
|
||||||
{
|
{
|
||||||
(void) oldVisualIndex;
|
(void) oldVisualIndex;
|
||||||
|
|
||||||
m_settings.m_columnIndexes[logicalIndex] = newVisualIndex;
|
m_settings.m_columnIndexes[logicalIndex] = newVisualIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -596,7 +634,6 @@ void VORLocalizerGUI::vorData_sectionMoved(int logicalIndex, int oldVisualIndex,
|
|||||||
void VORLocalizerGUI::vorData_sectionResized(int logicalIndex, int oldSize, int newSize)
|
void VORLocalizerGUI::vorData_sectionResized(int logicalIndex, int oldSize, int newSize)
|
||||||
{
|
{
|
||||||
(void) oldSize;
|
(void) oldSize;
|
||||||
|
|
||||||
m_settings.m_columnSizes[logicalIndex] = newSize;
|
m_settings.m_columnSizes[logicalIndex] = newSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -610,9 +647,9 @@ void VORLocalizerGUI::columnSelectMenu(QPoint pos)
|
|||||||
void VORLocalizerGUI::columnSelectMenuChecked(bool checked)
|
void VORLocalizerGUI::columnSelectMenuChecked(bool checked)
|
||||||
{
|
{
|
||||||
(void) checked;
|
(void) checked;
|
||||||
|
|
||||||
QAction* action = qobject_cast<QAction*>(sender());
|
QAction* action = qobject_cast<QAction*>(sender());
|
||||||
if (action != nullptr)
|
|
||||||
|
if (action)
|
||||||
{
|
{
|
||||||
int idx = action->data().toInt(nullptr);
|
int idx = action->data().toInt(nullptr);
|
||||||
ui->vorData->setColumnHidden(idx, !action->isChecked());
|
ui->vorData->setColumnHidden(idx, !action->isChecked());
|
||||||
@ -627,6 +664,7 @@ QAction *VORLocalizerGUI::createCheckableItem(QString &text, int idx, bool check
|
|||||||
action->setChecked(checked);
|
action->setChecked(checked);
|
||||||
action->setData(QVariant(idx));
|
action->setData(QVariant(idx));
|
||||||
connect(action, SIGNAL(triggered()), this, SLOT(columnSelectMenuChecked()));
|
connect(action, SIGNAL(triggered()), this, SLOT(columnSelectMenuChecked()));
|
||||||
|
|
||||||
return action;
|
return action;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -646,7 +684,7 @@ void VORLocalizerGUI::selectVOR(VORGUI *vorGUI, bool selected)
|
|||||||
ui->vorData->setRowCount(row + 1);
|
ui->vorData->setRowCount(row + 1);
|
||||||
ui->vorData->setItem(row, VORLocalizerSettings::VOR_COL_NAME, vorGUI->m_nameItem);
|
ui->vorData->setItem(row, VORLocalizerSettings::VOR_COL_NAME, vorGUI->m_nameItem);
|
||||||
ui->vorData->setItem(row, VORLocalizerSettings::VOR_COL_FREQUENCY, vorGUI->m_frequencyItem);
|
ui->vorData->setItem(row, VORLocalizerSettings::VOR_COL_FREQUENCY, vorGUI->m_frequencyItem);
|
||||||
ui->vorData->setItem(row, VORLocalizerSettings::VOR_COL_OFFSET, vorGUI->m_offsetItem);
|
ui->vorData->setItem(row, VORLocalizerSettings::VOR_COL_NAVID, vorGUI->m_navIdItem);
|
||||||
ui->vorData->setItem(row, VORLocalizerSettings::VOR_COL_IDENT, vorGUI->m_identItem);
|
ui->vorData->setItem(row, VORLocalizerSettings::VOR_COL_IDENT, vorGUI->m_identItem);
|
||||||
ui->vorData->setItem(row, VORLocalizerSettings::VOR_COL_MORSE, vorGUI->m_morseItem);
|
ui->vorData->setItem(row, VORLocalizerSettings::VOR_COL_MORSE, vorGUI->m_morseItem);
|
||||||
ui->vorData->setItem(row, VORLocalizerSettings::VOR_COL_RADIAL, vorGUI->m_radialItem);
|
ui->vorData->setItem(row, VORLocalizerSettings::VOR_COL_RADIAL, vorGUI->m_radialItem);
|
||||||
@ -662,11 +700,11 @@ void VORLocalizerGUI::selectVOR(VORGUI *vorGUI, bool selected)
|
|||||||
ui->vorData->setSortingEnabled(true);
|
ui->vorData->setSortingEnabled(true);
|
||||||
|
|
||||||
// Add to settings to create corresponding demodulator
|
// Add to settings to create corresponding demodulator
|
||||||
VORLocalizerSubChannelSettings *subChannelSettings = new VORLocalizerSubChannelSettings();
|
m_settings.m_subChannelSettings.insert(navId, VORLocalizerSubChannelSettings{
|
||||||
subChannelSettings->m_id = navId;
|
navId,
|
||||||
subChannelSettings->m_frequency = vorGUI->m_navAid->m_frequencykHz * 1000;
|
vorGUI->m_navAid->m_frequencykHz * 1000,
|
||||||
subChannelSettings->m_audioMute = false;
|
false
|
||||||
m_settings.m_subChannelSettings.insert(navId, subChannelSettings);
|
});
|
||||||
|
|
||||||
applySettings();
|
applySettings();
|
||||||
}
|
}
|
||||||
@ -678,9 +716,7 @@ void VORLocalizerGUI::selectVOR(VORGUI *vorGUI, bool selected)
|
|||||||
m_selectedVORs.remove(navId);
|
m_selectedVORs.remove(navId);
|
||||||
ui->vorData->removeRow(vorGUI->m_nameItem->row());
|
ui->vorData->removeRow(vorGUI->m_nameItem->row());
|
||||||
// Remove from settings to remove corresponding demodulator
|
// Remove from settings to remove corresponding demodulator
|
||||||
VORLocalizerSubChannelSettings *subChannelSettings = m_settings.m_subChannelSettings.value(navId);
|
|
||||||
m_settings.m_subChannelSettings.remove(navId);
|
m_settings.m_subChannelSettings.remove(navId);
|
||||||
delete subChannelSettings;
|
|
||||||
|
|
||||||
applySettings();
|
applySettings();
|
||||||
}
|
}
|
||||||
@ -701,10 +737,10 @@ void VORLocalizerGUI::updateVORs()
|
|||||||
azEl.calculate();
|
azEl.calculate();
|
||||||
|
|
||||||
// Only display VOR if in range
|
// Only display VOR if in range
|
||||||
if (azEl.getDistance() <= 200000)
|
if (azEl.getDistance() <= 200000) {
|
||||||
{
|
|
||||||
m_vorModel.addVOR(vor);
|
m_vorModel.addVOR(vor);
|
||||||
}
|
}
|
||||||
|
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -734,11 +770,14 @@ QByteArray VORLocalizerGUI::serialize() const
|
|||||||
|
|
||||||
bool VORLocalizerGUI::deserialize(const QByteArray& data)
|
bool VORLocalizerGUI::deserialize(const QByteArray& data)
|
||||||
{
|
{
|
||||||
if(m_settings.deserialize(data)) {
|
if (m_settings.deserialize(data))
|
||||||
|
{
|
||||||
displaySettings();
|
displaySettings();
|
||||||
applySettings(true);
|
applySettings(true);
|
||||||
return true;
|
return true;
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
resetToDefaults();
|
resetToDefaults();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -775,50 +814,36 @@ bool VORLocalizerGUI::handleMessage(const Message& message)
|
|||||||
Real refMagDB = std::round(20.0*std::log10(report.getRefMag()));
|
Real refMagDB = std::round(20.0*std::log10(report.getRefMag()));
|
||||||
|
|
||||||
bool validRadial = report.getValidRadial();
|
bool validRadial = report.getValidRadial();
|
||||||
|
|
||||||
vorGUI->m_radialItem->setData(Qt::DisplayRole, std::round(report.getRadial()));
|
vorGUI->m_radialItem->setData(Qt::DisplayRole, std::round(report.getRadial()));
|
||||||
if (validRadial)
|
vorGUI->m_navIdItem->setData(Qt::DisplayRole, subChannelId);
|
||||||
|
|
||||||
|
if (validRadial) {
|
||||||
vorGUI->m_radialItem->setForeground(QBrush(Qt::white));
|
vorGUI->m_radialItem->setForeground(QBrush(Qt::white));
|
||||||
else
|
} else {
|
||||||
vorGUI->m_radialItem->setForeground(QBrush(Qt::red));
|
vorGUI->m_radialItem->setForeground(QBrush(Qt::red));
|
||||||
|
}
|
||||||
|
|
||||||
vorGUI->m_refMagItem->setData(Qt::DisplayRole, refMagDB);
|
vorGUI->m_refMagItem->setData(Qt::DisplayRole, refMagDB);
|
||||||
if (report.getValidRefMag())
|
|
||||||
|
if (report.getValidRefMag()) {
|
||||||
vorGUI->m_refMagItem->setForeground(QBrush(Qt::white));
|
vorGUI->m_refMagItem->setForeground(QBrush(Qt::white));
|
||||||
else
|
} else {
|
||||||
vorGUI->m_refMagItem->setForeground(QBrush(Qt::red));
|
vorGUI->m_refMagItem->setForeground(QBrush(Qt::red));
|
||||||
|
}
|
||||||
|
|
||||||
vorGUI->m_varMagItem->setData(Qt::DisplayRole, varMagDB);
|
vorGUI->m_varMagItem->setData(Qt::DisplayRole, varMagDB);
|
||||||
if (report.getValidVarMag())
|
|
||||||
|
if (report.getValidVarMag()) {
|
||||||
vorGUI->m_varMagItem->setForeground(QBrush(Qt::white));
|
vorGUI->m_varMagItem->setForeground(QBrush(Qt::white));
|
||||||
else
|
} else {
|
||||||
vorGUI->m_varMagItem->setForeground(QBrush(Qt::red));
|
vorGUI->m_varMagItem->setForeground(QBrush(Qt::red));
|
||||||
|
}
|
||||||
|
|
||||||
// Update radial on map
|
// Update radial on map
|
||||||
m_vorModel.setRadial(subChannelId, validRadial, report.getRadial());
|
m_vorModel.setRadial(subChannelId, validRadial, report.getRadial());
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else if (VORLocalizerReport::MsgReportFreqOffset::match(message))
|
|
||||||
{
|
|
||||||
VORLocalizerReport::MsgReportFreqOffset& report = (VORLocalizerReport::MsgReportFreqOffset&) message;
|
|
||||||
int subChannelId = report.getSubChannelId();
|
|
||||||
|
|
||||||
VORGUI *vorGUI = m_selectedVORs.value(subChannelId);
|
|
||||||
|
|
||||||
vorGUI->m_offsetItem->setData(Qt::DisplayRole, report.getFreqOffset() / 1000.0);
|
|
||||||
if (report.getOutOfBand())
|
|
||||||
{
|
|
||||||
vorGUI->m_offsetItem->setForeground(QBrush(Qt::red));
|
|
||||||
// Clear other fields as data is now invalid
|
|
||||||
vorGUI->m_radialItem->setText("");
|
|
||||||
vorGUI->m_refMagItem->setText("");
|
|
||||||
vorGUI->m_varMagItem->setText("");
|
|
||||||
m_vorModel.setRadial(subChannelId, false, -1.0f);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
vorGUI->m_offsetItem->setForeground(QBrush(Qt::white));
|
|
||||||
}
|
|
||||||
else if (VORLocalizerReport::MsgReportIdent::match(message))
|
else if (VORLocalizerReport::MsgReportIdent::match(message))
|
||||||
{
|
{
|
||||||
VORLocalizerReport::MsgReportIdent& report = (VORLocalizerReport::MsgReportIdent&) message;
|
VORLocalizerReport::MsgReportIdent& report = (VORLocalizerReport::MsgReportIdent&) message;
|
||||||
@ -835,6 +860,7 @@ bool VORLocalizerGUI::handleMessage(const Message& message)
|
|||||||
{
|
{
|
||||||
vorGUI->m_rxIdentItem->setText(identString);
|
vorGUI->m_rxIdentItem->setText(identString);
|
||||||
vorGUI->m_rxMorseItem->setText(Morse::toSpacedUnicode(ident));
|
vorGUI->m_rxMorseItem->setText(Morse::toSpacedUnicode(ident));
|
||||||
|
|
||||||
if (vorGUI->m_navAid->m_ident == identString)
|
if (vorGUI->m_navAid->m_ident == identString)
|
||||||
{
|
{
|
||||||
// Set colour to green if matching expected ident
|
// Set colour to green if matching expected ident
|
||||||
@ -868,11 +894,29 @@ bool VORLocalizerGUI::handleMessage(const Message& message)
|
|||||||
ui->channels->clear();
|
ui->channels->clear();
|
||||||
|
|
||||||
for (; it != channels.end(); ++it) {
|
for (; it != channels.end(); ++it) {
|
||||||
ui->channels->addItem(tr("%1:%2").arg(it->m_deviceSetIndex).arg(it->m_channelIndex));
|
ui->channels->addItem(tr("R%1:%2").arg(it->m_deviceSetIndex).arg(it->m_channelIndex));
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
else if (VORLocalizerReport::MsgReportServiceddVORs::match(message))
|
||||||
|
{
|
||||||
|
VORLocalizerReport::MsgReportServiceddVORs& report = (VORLocalizerReport::MsgReportServiceddVORs&) message;
|
||||||
|
std::vector<int>& servicedVORNavIds = report.getNavIds();
|
||||||
|
|
||||||
|
for (auto vorGUI : m_selectedVORs) {
|
||||||
|
vorGUI->m_frequencyItem->setForeground(QBrush(Qt::white));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto navId : servicedVORNavIds)
|
||||||
|
{
|
||||||
|
if (m_selectedVORs.contains(navId))
|
||||||
|
{
|
||||||
|
VORGUI *vorGUI = m_selectedVORs[navId];
|
||||||
|
vorGUI->m_frequencyItem->setForeground(QBrush(Qt::green));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -883,8 +927,7 @@ void VORLocalizerGUI::handleInputMessages()
|
|||||||
|
|
||||||
while ((message = getInputMessageQueue()->pop()) != 0)
|
while ((message = getInputMessageQueue()->pop()) != 0)
|
||||||
{
|
{
|
||||||
if (handleMessage(*message))
|
if (handleMessage(*message)) {
|
||||||
{
|
|
||||||
delete message;
|
delete message;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -893,31 +936,41 @@ void VORLocalizerGUI::handleInputMessages()
|
|||||||
qint64 VORLocalizerGUI::fileAgeInDays(QString filename)
|
qint64 VORLocalizerGUI::fileAgeInDays(QString filename)
|
||||||
{
|
{
|
||||||
QFile file(filename);
|
QFile file(filename);
|
||||||
|
|
||||||
if (file.exists())
|
if (file.exists())
|
||||||
{
|
{
|
||||||
QDateTime modified = file.fileTime(QFileDevice::FileModificationTime);
|
QDateTime modified = file.fileTime(QFileDevice::FileModificationTime);
|
||||||
if (modified.isValid())
|
|
||||||
|
if (modified.isValid()) {
|
||||||
return modified.daysTo(QDateTime::currentDateTime());
|
return modified.daysTo(QDateTime::currentDateTime());
|
||||||
else
|
} else {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool VORLocalizerGUI::confirmDownload(QString filename)
|
bool VORLocalizerGUI::confirmDownload(QString filename)
|
||||||
{
|
{
|
||||||
qint64 age = fileAgeInDays(filename);
|
qint64 age = fileAgeInDays(filename);
|
||||||
|
|
||||||
if ((age == -1) || (age > 100))
|
if ((age == -1) || (age > 100))
|
||||||
|
{
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
QMessageBox::StandardButton reply;
|
QMessageBox::StandardButton reply;
|
||||||
if (age == 0)
|
|
||||||
|
if (age == 0) {
|
||||||
reply = QMessageBox::question(this, "Confirm download", "This file was last downloaded today. Are you sure you wish to redownload it?", QMessageBox::Yes|QMessageBox::No);
|
reply = QMessageBox::question(this, "Confirm download", "This file was last downloaded today. Are you sure you wish to redownload it?", QMessageBox::Yes|QMessageBox::No);
|
||||||
else if (age == 1)
|
} else if (age == 1) {
|
||||||
reply = QMessageBox::question(this, "Confirm download", "This file was last downloaded yesterday. Are you sure you wish to redownload it?", QMessageBox::Yes|QMessageBox::No);
|
reply = QMessageBox::question(this, "Confirm download", "This file was last downloaded yesterday. Are you sure you wish to redownload it?", QMessageBox::Yes|QMessageBox::No);
|
||||||
else
|
} else {
|
||||||
reply = QMessageBox::question(this, "Confirm download", QString("This file was last downloaded %1 days ago. Are you sure you wish to redownload this file?").arg(age), QMessageBox::Yes|QMessageBox::No);
|
reply = QMessageBox::question(this, "Confirm download", QString("This file was last downloaded %1 days ago. Are you sure you wish to redownload this file?").arg(age), QMessageBox::Yes|QMessageBox::No);
|
||||||
|
}
|
||||||
|
|
||||||
return reply == QMessageBox::Yes;
|
return reply == QMessageBox::Yes;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -932,18 +985,20 @@ QString VORLocalizerGUI::getDataDir()
|
|||||||
|
|
||||||
QString VORLocalizerGUI::getOpenAIPVORDBFilename(int i)
|
QString VORLocalizerGUI::getOpenAIPVORDBFilename(int i)
|
||||||
{
|
{
|
||||||
if (countryCodes[i] != nullptr)
|
if (countryCodes[i] != nullptr) {
|
||||||
return getDataDir() + "/" + countryCodes[i] + "_nav.aip";
|
return getDataDir() + "/" + countryCodes[i] + "_nav.aip";
|
||||||
else
|
} else {
|
||||||
return "";
|
return "";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QString VORLocalizerGUI::getOpenAIPVORDBURL(int i)
|
QString VORLocalizerGUI::getOpenAIPVORDBURL(int i)
|
||||||
{
|
{
|
||||||
if (countryCodes[i] != nullptr)
|
if (countryCodes[i] != nullptr) {
|
||||||
return QString(OPENAIP_NAVAIDS_URL).arg(countryCodes[i]);
|
return QString(OPENAIP_NAVAIDS_URL).arg(countryCodes[i]);
|
||||||
else
|
} else {
|
||||||
return "";
|
return "";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QString VORLocalizerGUI::getVORDBFilename()
|
QString VORLocalizerGUI::getVORDBFilename()
|
||||||
@ -964,14 +1019,18 @@ void VORLocalizerGUI::downloadFinished(const QString& filename, bool success)
|
|||||||
if (filename == getVORDBFilename())
|
if (filename == getVORDBFilename())
|
||||||
{
|
{
|
||||||
m_vors = NavAid::readNavAidsDB(filename);
|
m_vors = NavAid::readNavAidsDB(filename);
|
||||||
if (m_vors != nullptr)
|
|
||||||
|
if (m_vors != nullptr) {
|
||||||
updateVORs();
|
updateVORs();
|
||||||
|
}
|
||||||
|
|
||||||
m_progressDialog->close();
|
m_progressDialog->close();
|
||||||
m_progressDialog = nullptr;
|
m_progressDialog = nullptr;
|
||||||
}
|
}
|
||||||
else if (filename == getOpenAIPVORDBFilename(m_countryIndex))
|
else if (filename == getOpenAIPVORDBFilename(m_countryIndex))
|
||||||
{
|
{
|
||||||
m_countryIndex++;
|
m_countryIndex++;
|
||||||
|
|
||||||
if (countryCodes[m_countryIndex] != nullptr)
|
if (countryCodes[m_countryIndex] != nullptr)
|
||||||
{
|
{
|
||||||
QString vorDBFile = getOpenAIPVORDBFilename(m_countryIndex);
|
QString vorDBFile = getOpenAIPVORDBFilename(m_countryIndex);
|
||||||
@ -984,8 +1043,11 @@ void VORLocalizerGUI::downloadFinished(const QString& filename, bool success)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
readNavAids();
|
readNavAids();
|
||||||
if (m_vors != nullptr)
|
|
||||||
|
if (m_vors) {
|
||||||
updateVORs();
|
updateVORs();
|
||||||
|
}
|
||||||
|
|
||||||
m_progressDialog->close();
|
m_progressDialog->close();
|
||||||
m_progressDialog = nullptr;
|
m_progressDialog = nullptr;
|
||||||
}
|
}
|
||||||
@ -1021,6 +1083,7 @@ void VORLocalizerGUI::on_getOurAirportsVORDB_clicked()
|
|||||||
if (m_progressDialog == nullptr)
|
if (m_progressDialog == nullptr)
|
||||||
{
|
{
|
||||||
QString vorDBFile = getVORDBFilename();
|
QString vorDBFile = getVORDBFilename();
|
||||||
|
|
||||||
if (confirmDownload(vorDBFile))
|
if (confirmDownload(vorDBFile))
|
||||||
{
|
{
|
||||||
// Download OurAirports navaid database to disk
|
// Download OurAirports navaid database to disk
|
||||||
@ -1039,10 +1102,11 @@ void VORLocalizerGUI::on_getOurAirportsVORDB_clicked()
|
|||||||
void VORLocalizerGUI::on_getOpenAIPVORDB_clicked()
|
void VORLocalizerGUI::on_getOpenAIPVORDB_clicked()
|
||||||
{
|
{
|
||||||
// Don't try to download while already in progress
|
// Don't try to download while already in progress
|
||||||
if (m_progressDialog == nullptr)
|
if (!m_progressDialog)
|
||||||
{
|
{
|
||||||
m_countryIndex = 0;
|
m_countryIndex = 0;
|
||||||
QString vorDBFile = getOpenAIPVORDBFilename(m_countryIndex);
|
QString vorDBFile = getOpenAIPVORDBFilename(m_countryIndex);
|
||||||
|
|
||||||
if (confirmDownload(vorDBFile))
|
if (confirmDownload(vorDBFile))
|
||||||
{
|
{
|
||||||
// Download OpenAIP XML to disk
|
// Download OpenAIP XML to disk
|
||||||
@ -1071,13 +1135,27 @@ void VORLocalizerGUI::readNavAids()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void VORLocalizerGUI::on_magDecAdjust_clicked(bool checked)
|
void VORLocalizerGUI::on_magDecAdjust_toggled(bool checked)
|
||||||
{
|
{
|
||||||
m_settings.m_magDecAdjust = checked;
|
m_settings.m_magDecAdjust = checked;
|
||||||
m_vorModel.allVORUpdated();
|
m_vorModel.allVORUpdated();
|
||||||
applySettings();
|
applySettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void VORLocalizerGUI::on_rrTime_valueChanged(int value)
|
||||||
|
{
|
||||||
|
m_settings.m_rrTime = value;
|
||||||
|
ui->rrTimeText->setText(tr("%1s").arg(m_settings.m_rrTime));
|
||||||
|
applySettings();
|
||||||
|
}
|
||||||
|
|
||||||
|
void VORLocalizerGUI::on_centerShift_valueChanged(int value)
|
||||||
|
{
|
||||||
|
m_settings.m_centerShift = value * 1000;
|
||||||
|
ui->centerShiftText->setText(tr("%1k").arg(value));
|
||||||
|
applySettings();
|
||||||
|
}
|
||||||
|
|
||||||
void VORLocalizerGUI::on_channelsRefresh_clicked()
|
void VORLocalizerGUI::on_channelsRefresh_clicked()
|
||||||
{
|
{
|
||||||
if (m_doApplySettings)
|
if (m_doApplySettings)
|
||||||
@ -1170,6 +1248,7 @@ VORLocalizerGUI::VORLocalizerGUI(PluginAPI* pluginAPI, FeatureUISet *featureUISe
|
|||||||
// Centre map at My Position
|
// Centre map at My Position
|
||||||
QQuickItem *item = ui->map->rootObject();
|
QQuickItem *item = ui->map->rootObject();
|
||||||
QObject *object = item->findChild<QObject*>("map");
|
QObject *object = item->findChild<QObject*>("map");
|
||||||
|
|
||||||
if (object)
|
if (object)
|
||||||
{
|
{
|
||||||
QGeoCoordinate coords = object->property("center").value<QGeoCoordinate>();
|
QGeoCoordinate coords = object->property("center").value<QGeoCoordinate>();
|
||||||
@ -1177,8 +1256,10 @@ VORLocalizerGUI::VORLocalizerGUI(PluginAPI* pluginAPI, FeatureUISet *featureUISe
|
|||||||
coords.setLongitude(stationLongitude);
|
coords.setLongitude(stationLongitude);
|
||||||
object->setProperty("center", QVariant::fromValue(coords));
|
object->setProperty("center", QVariant::fromValue(coords));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Move antenna icon to My Position to start with
|
// Move antenna icon to My Position to start with
|
||||||
QObject *stationObject = item->findChild<QObject*>("station");
|
QObject *stationObject = item->findChild<QObject*>("station");
|
||||||
|
|
||||||
if (stationObject)
|
if (stationObject)
|
||||||
{
|
{
|
||||||
QGeoCoordinate coords = stationObject->property("coordinate").value<QGeoCoordinate>();
|
QGeoCoordinate coords = stationObject->property("coordinate").value<QGeoCoordinate>();
|
||||||
@ -1191,6 +1272,7 @@ VORLocalizerGUI::VORLocalizerGUI(PluginAPI* pluginAPI, FeatureUISet *featureUISe
|
|||||||
|
|
||||||
// Read in VOR information if it exists
|
// Read in VOR information if it exists
|
||||||
bool useOurAirports = false;
|
bool useOurAirports = false;
|
||||||
|
|
||||||
if (useOurAirports)
|
if (useOurAirports)
|
||||||
{
|
{
|
||||||
m_vors = NavAid::readNavAidsDB(getVORDBFilename());
|
m_vors = NavAid::readNavAidsDB(getVORDBFilename());
|
||||||
@ -1201,7 +1283,8 @@ VORLocalizerGUI::VORLocalizerGUI(PluginAPI* pluginAPI, FeatureUISet *featureUISe
|
|||||||
readNavAids();
|
readNavAids();
|
||||||
ui->getOurAirportsVORDB->setVisible(false);
|
ui->getOurAirportsVORDB->setVisible(false);
|
||||||
}
|
}
|
||||||
if (m_vors != nullptr) {
|
|
||||||
|
if (m_vors) {
|
||||||
updateVORs();
|
updateVORs();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1213,11 +1296,13 @@ VORLocalizerGUI::VORLocalizerGUI(PluginAPI* pluginAPI, FeatureUISet *featureUISe
|
|||||||
ui->vorData->setSortingEnabled(true);
|
ui->vorData->setSortingEnabled(true);
|
||||||
// Add context menu to allow hiding/showing of columns
|
// Add context menu to allow hiding/showing of columns
|
||||||
menu = new QMenu(ui->vorData);
|
menu = new QMenu(ui->vorData);
|
||||||
|
|
||||||
for (int i = 0; i < ui->vorData->horizontalHeader()->count(); i++)
|
for (int i = 0; i < ui->vorData->horizontalHeader()->count(); i++)
|
||||||
{
|
{
|
||||||
QString text = ui->vorData->horizontalHeaderItem(i)->text();
|
QString text = ui->vorData->horizontalHeaderItem(i)->text();
|
||||||
menu->addAction(createCheckableItem(text, i, true));
|
menu->addAction(createCheckableItem(text, i, true));
|
||||||
}
|
}
|
||||||
|
|
||||||
ui->vorData->horizontalHeader()->setContextMenuPolicy(Qt::CustomContextMenu);
|
ui->vorData->horizontalHeader()->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||||
connect(ui->vorData->horizontalHeader(), SIGNAL(customContextMenuRequested(QPoint)), SLOT(columnSelectMenu(QPoint)));
|
connect(ui->vorData->horizontalHeader(), SIGNAL(customContextMenuRequested(QPoint)), SLOT(columnSelectMenu(QPoint)));
|
||||||
// Get signals when columns change
|
// Get signals when columns change
|
||||||
@ -1273,6 +1358,11 @@ void VORLocalizerGUI::displaySettings()
|
|||||||
header->moveSection(header->visualIndex(i), m_settings.m_columnIndexes[i]);
|
header->moveSection(header->visualIndex(i), m_settings.m_columnIndexes[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ui->rrTimeText->setText(tr("%1s").arg(m_settings.m_rrTime));
|
||||||
|
ui->rrTime->setValue(m_settings.m_rrTime);
|
||||||
|
ui->centerShiftText->setText(tr("%1k").arg(m_settings.m_centerShift/1000));
|
||||||
|
ui->centerShift->setValue(m_settings.m_centerShift/1000);
|
||||||
|
|
||||||
blockApplySettings(false);
|
blockApplySettings(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1325,6 +1415,7 @@ void VORLocalizerGUI::tick()
|
|||||||
// Move antenna icon to estimated position
|
// Move antenna icon to estimated position
|
||||||
QQuickItem *item = ui->map->rootObject();
|
QQuickItem *item = ui->map->rootObject();
|
||||||
QObject *stationObject = item->findChild<QObject*>("station");
|
QObject *stationObject = item->findChild<QObject*>("station");
|
||||||
|
|
||||||
if(stationObject != NULL)
|
if(stationObject != NULL)
|
||||||
{
|
{
|
||||||
QGeoCoordinate coords = stationObject->property("coordinate").value<QGeoCoordinate>();
|
QGeoCoordinate coords = stationObject->property("coordinate").value<QGeoCoordinate>();
|
||||||
|
@ -62,7 +62,7 @@ public:
|
|||||||
|
|
||||||
QTableWidgetItem *m_nameItem;
|
QTableWidgetItem *m_nameItem;
|
||||||
QTableWidgetItem *m_frequencyItem;
|
QTableWidgetItem *m_frequencyItem;
|
||||||
QTableWidgetItem *m_offsetItem;
|
QTableWidgetItem *m_navIdItem;
|
||||||
QTableWidgetItem *m_identItem;
|
QTableWidgetItem *m_identItem;
|
||||||
QTableWidgetItem *m_morseItem;
|
QTableWidgetItem *m_morseItem;
|
||||||
QTableWidgetItem *m_radialItem;
|
QTableWidgetItem *m_radialItem;
|
||||||
@ -269,7 +269,9 @@ private slots:
|
|||||||
void on_startStop_toggled(bool checked);
|
void on_startStop_toggled(bool checked);
|
||||||
void on_getOurAirportsVORDB_clicked();
|
void on_getOurAirportsVORDB_clicked();
|
||||||
void on_getOpenAIPVORDB_clicked();
|
void on_getOpenAIPVORDB_clicked();
|
||||||
void on_magDecAdjust_clicked(bool checked);
|
void on_magDecAdjust_toggled(bool checked);
|
||||||
|
void on_rrTime_valueChanged(int value);
|
||||||
|
void on_centerShift_valueChanged(int value);
|
||||||
void on_channelsRefresh_clicked();
|
void on_channelsRefresh_clicked();
|
||||||
void vorData_sectionMoved(int logicalIndex, int oldVisualIndex, int newVisualIndex);
|
void vorData_sectionMoved(int logicalIndex, int oldVisualIndex, int newVisualIndex);
|
||||||
void vorData_sectionResized(int logicalIndex, int oldSize, int newSize);
|
void vorData_sectionResized(int logicalIndex, int oldSize, int newSize);
|
||||||
|
@ -120,7 +120,7 @@
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QPushButton" name="magDecAdjust">
|
<widget class="ButtonSwitch" name="magDecAdjust">
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
<string>Draw radials adjusted for magnetic declination</string>
|
<string>Draw radials adjusted for magnetic declination</string>
|
||||||
</property>
|
</property>
|
||||||
@ -139,6 +139,124 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="rrTimeLabel">
|
||||||
|
<property name="text">
|
||||||
|
<string>RR</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QDial" name="rrTime">
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>24</width>
|
||||||
|
<height>24</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Round robin turn time (s)</string>
|
||||||
|
</property>
|
||||||
|
<property name="minimum">
|
||||||
|
<number>10</number>
|
||||||
|
</property>
|
||||||
|
<property name="maximum">
|
||||||
|
<number>60</number>
|
||||||
|
</property>
|
||||||
|
<property name="singleStep">
|
||||||
|
<number>5</number>
|
||||||
|
</property>
|
||||||
|
<property name="pageStep">
|
||||||
|
<number>5</number>
|
||||||
|
</property>
|
||||||
|
<property name="value">
|
||||||
|
<number>20</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="rrTimeText">
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>30</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>30</width>
|
||||||
|
<height>16777215</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Sound volume (%)</string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>20s</string>
|
||||||
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="Line" name="line">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Vertical</enum>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="centerShiftLabel">
|
||||||
|
<property name="text">
|
||||||
|
<string>Sh</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QDial" name="centerShift">
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>24</width>
|
||||||
|
<height>24</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Center frequency shift (kHz)</string>
|
||||||
|
</property>
|
||||||
|
<property name="minimum">
|
||||||
|
<number>-40</number>
|
||||||
|
</property>
|
||||||
|
<property name="maximum">
|
||||||
|
<number>40</number>
|
||||||
|
</property>
|
||||||
|
<property name="singleStep">
|
||||||
|
<number>1</number>
|
||||||
|
</property>
|
||||||
|
<property name="pageStep">
|
||||||
|
<number>1</number>
|
||||||
|
</property>
|
||||||
|
<property name="value">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="centerShiftText">
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>30</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>20k</string>
|
||||||
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<spacer name="horizontalSpacer_2">
|
<spacer name="horizontalSpacer_2">
|
||||||
<property name="orientation">
|
<property name="orientation">
|
||||||
@ -159,7 +277,7 @@
|
|||||||
<item>
|
<item>
|
||||||
<widget class="QLabel" name="channelsLabel">
|
<widget class="QLabel" name="channelsLabel">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>VORs</string>
|
<string>Chan</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@ -264,7 +382,7 @@
|
|||||||
</column>
|
</column>
|
||||||
<column>
|
<column>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Offset (kHz)</string>
|
<string>Nav Id</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
<string>Offset of the VOR's frequency from the current center frequency. Red indicates out of range.</string>
|
<string>Offset of the VOR's frequency from the current center frequency. Red indicates out of range.</string>
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
|
|
||||||
#include "vorlocalizerreport.h"
|
#include "vorlocalizerreport.h"
|
||||||
|
|
||||||
MESSAGE_CLASS_DEFINITION(VORLocalizerReport::MsgReportFreqOffset, Message)
|
|
||||||
MESSAGE_CLASS_DEFINITION(VORLocalizerReport::MsgReportRadial, Message)
|
MESSAGE_CLASS_DEFINITION(VORLocalizerReport::MsgReportRadial, Message)
|
||||||
MESSAGE_CLASS_DEFINITION(VORLocalizerReport::MsgReportIdent, Message)
|
MESSAGE_CLASS_DEFINITION(VORLocalizerReport::MsgReportIdent, Message)
|
||||||
MESSAGE_CLASS_DEFINITION(VORLocalizerReport::MsgReportChannels, Message)
|
MESSAGE_CLASS_DEFINITION(VORLocalizerReport::MsgReportChannels, Message)
|
||||||
|
MESSAGE_CLASS_DEFINITION(VORLocalizerReport::MsgReportServiceddVORs, Message)
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
#define INCLUDE_VORLOCALIZERREPORT_H
|
#define INCLUDE_VORLOCALIZERREPORT_H
|
||||||
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
|
#include <QHash>
|
||||||
|
|
||||||
#include "util/message.h"
|
#include "util/message.h"
|
||||||
|
|
||||||
@ -90,33 +91,6 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class MsgReportFreqOffset : public Message {
|
|
||||||
MESSAGE_CLASS_DECLARATION
|
|
||||||
|
|
||||||
public:
|
|
||||||
int getSubChannelId() const { return m_subChannelId; }
|
|
||||||
int getFreqOffset() const { return m_freqOffset; }
|
|
||||||
bool getOutOfBand() const { return m_outOfBand; }
|
|
||||||
|
|
||||||
static MsgReportFreqOffset* create(int subChannelId, int freqOffset, bool outOfBand)
|
|
||||||
{
|
|
||||||
return new MsgReportFreqOffset(subChannelId, freqOffset, outOfBand);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
int m_subChannelId;
|
|
||||||
int m_freqOffset;
|
|
||||||
bool m_outOfBand;
|
|
||||||
|
|
||||||
MsgReportFreqOffset(int subChannelId, int freqOffset, bool outOfBand) :
|
|
||||||
Message(),
|
|
||||||
m_subChannelId(subChannelId),
|
|
||||||
m_freqOffset(freqOffset),
|
|
||||||
m_outOfBand(outOfBand)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class MsgReportIdent : public Message {
|
class MsgReportIdent : public Message {
|
||||||
MESSAGE_CLASS_DECLARATION
|
MESSAGE_CLASS_DECLARATION
|
||||||
|
|
||||||
@ -164,6 +138,26 @@ public:
|
|||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class MsgReportServiceddVORs : public Message {
|
||||||
|
MESSAGE_CLASS_DECLARATION
|
||||||
|
|
||||||
|
public:
|
||||||
|
std::vector<int>& getNavIds() { return m_navIds; }
|
||||||
|
QHash<int, bool>& getSinglePlans() { return m_singlePlans; }
|
||||||
|
|
||||||
|
static MsgReportServiceddVORs* create() {
|
||||||
|
return new MsgReportServiceddVORs();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<int> m_navIds;
|
||||||
|
QHash<int, bool> m_singlePlans;
|
||||||
|
|
||||||
|
MsgReportServiceddVORs() :
|
||||||
|
Message()
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
VORLocalizerReport() {}
|
VORLocalizerReport() {}
|
||||||
~VORLocalizerReport() {}
|
~VORLocalizerReport() {}
|
||||||
|
@ -33,6 +33,8 @@ void VORLocalizerSettings::resetToDefaults()
|
|||||||
m_rgbColor = QColor(255, 255, 0).rgb();
|
m_rgbColor = QColor(255, 255, 0).rgb();
|
||||||
m_title = "VOR Localizer";
|
m_title = "VOR Localizer";
|
||||||
m_magDecAdjust = true;
|
m_magDecAdjust = true;
|
||||||
|
m_rrTime = 20;
|
||||||
|
m_centerShift = 20000;
|
||||||
m_useReverseAPI = false;
|
m_useReverseAPI = false;
|
||||||
m_reverseAPIAddress = "127.0.0.1";
|
m_reverseAPIAddress = "127.0.0.1";
|
||||||
m_reverseAPIPort = 8888;
|
m_reverseAPIPort = 8888;
|
||||||
@ -54,6 +56,8 @@ QByteArray VORLocalizerSettings::serialize() const
|
|||||||
s.writeU32(7, m_rgbColor);
|
s.writeU32(7, m_rgbColor);
|
||||||
s.writeString(9, m_title);
|
s.writeString(9, m_title);
|
||||||
s.writeBool(10, m_magDecAdjust);
|
s.writeBool(10, m_magDecAdjust);
|
||||||
|
s.writeS32(11, m_rrTime);
|
||||||
|
s.writeS32(12, m_centerShift);
|
||||||
s.writeBool(14, m_useReverseAPI);
|
s.writeBool(14, m_useReverseAPI);
|
||||||
s.writeString(15, m_reverseAPIAddress);
|
s.writeString(15, m_reverseAPIAddress);
|
||||||
s.writeU32(16, m_reverseAPIPort);
|
s.writeU32(16, m_reverseAPIPort);
|
||||||
@ -91,6 +95,8 @@ bool VORLocalizerSettings::deserialize(const QByteArray& data)
|
|||||||
d.readU32(7, &m_rgbColor);
|
d.readU32(7, &m_rgbColor);
|
||||||
d.readString(9, &m_title, "VOR Localizer");
|
d.readString(9, &m_title, "VOR Localizer");
|
||||||
d.readBool(10, &m_magDecAdjust, true);
|
d.readBool(10, &m_magDecAdjust, true);
|
||||||
|
d.readS32(11, &m_rrTime, 20);
|
||||||
|
d.readS32(12, &m_centerShift, 20000);
|
||||||
d.readBool(14, &m_useReverseAPI, false);
|
d.readBool(14, &m_useReverseAPI, false);
|
||||||
d.readString(15, &m_reverseAPIAddress, "127.0.0.1");
|
d.readString(15, &m_reverseAPIAddress, "127.0.0.1");
|
||||||
d.readU32(16, &utmp, 0);
|
d.readU32(16, &utmp, 0);
|
||||||
@ -123,4 +129,14 @@ bool VORLocalizerSettings::deserialize(const QByteArray& data)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool VORLocalizerSettings::VORChannel::operator<(const VORChannel& other) const
|
||||||
|
{
|
||||||
|
if (m_frequency != other.m_frequency) {
|
||||||
|
return m_frequency < other.m_frequency;
|
||||||
|
}
|
||||||
|
if (m_subChannelId != other.m_subChannelId) {
|
||||||
|
return m_subChannelId < other.m_subChannelId;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
#include <QHash>
|
#include <QHash>
|
||||||
|
|
||||||
class Serializable;
|
class Serializable;
|
||||||
|
class ChannelAPI;
|
||||||
|
|
||||||
// Number of columns in the table
|
// Number of columns in the table
|
||||||
|
|
||||||
@ -34,15 +35,38 @@ struct VORLocalizerSubChannelSettings {
|
|||||||
|
|
||||||
struct VORLocalizerSettings
|
struct VORLocalizerSettings
|
||||||
{
|
{
|
||||||
struct VORDemodChannels
|
struct VORChannel
|
||||||
|
{
|
||||||
|
int m_subChannelId; //!< Unique VOR identifier (from database)
|
||||||
|
int m_frequency; //!< Frequency the VOR is on
|
||||||
|
bool m_audioMute; //!< Mute the audio from this VOR
|
||||||
|
|
||||||
|
VORChannel() = default;
|
||||||
|
VORChannel(const VORChannel&) = default;
|
||||||
|
VORChannel& operator=(const VORChannel&) = default;
|
||||||
|
|
||||||
|
bool operator<(const VORChannel& other) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct AvailableChannel
|
||||||
{
|
{
|
||||||
int m_deviceSetIndex;
|
int m_deviceSetIndex;
|
||||||
int m_channelIndex;
|
int m_channelIndex;
|
||||||
|
ChannelAPI *m_channelAPI;
|
||||||
|
quint64 m_deviceCenterFrequency;
|
||||||
|
int m_basebandSampleRate;
|
||||||
|
int m_navId;
|
||||||
|
|
||||||
|
AvailableChannel() = default;
|
||||||
|
AvailableChannel(const AvailableChannel&) = default;
|
||||||
|
AvailableChannel& operator=(const AvailableChannel&) = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
quint32 m_rgbColor;
|
quint32 m_rgbColor;
|
||||||
QString m_title;
|
QString m_title;
|
||||||
bool m_magDecAdjust; //!< Adjust for magnetic declination when drawing radials on the map
|
bool m_magDecAdjust; //!< Adjust for magnetic declination when drawing radials on the map
|
||||||
|
int m_rrTime; //!< Round robin turn time in seconds
|
||||||
|
int m_centerShift; //!< Center frequency shift to apply to move away from DC
|
||||||
bool m_useReverseAPI;
|
bool m_useReverseAPI;
|
||||||
QString m_reverseAPIAddress;
|
QString m_reverseAPIAddress;
|
||||||
uint16_t m_reverseAPIPort;
|
uint16_t m_reverseAPIPort;
|
||||||
@ -53,7 +77,7 @@ struct VORLocalizerSettings
|
|||||||
static const int VORDEMOD_COLUMNS = 11;
|
static const int VORDEMOD_COLUMNS = 11;
|
||||||
static const int VOR_COL_NAME = 0;
|
static const int VOR_COL_NAME = 0;
|
||||||
static const int VOR_COL_FREQUENCY = 1;
|
static const int VOR_COL_FREQUENCY = 1;
|
||||||
static const int VOR_COL_OFFSET = 2;
|
static const int VOR_COL_NAVID = 2;
|
||||||
static const int VOR_COL_IDENT = 3;
|
static const int VOR_COL_IDENT = 3;
|
||||||
static const int VOR_COL_MORSE = 4;
|
static const int VOR_COL_MORSE = 4;
|
||||||
static const int VOR_COL_RX_IDENT = 5;
|
static const int VOR_COL_RX_IDENT = 5;
|
||||||
@ -66,7 +90,7 @@ struct VORLocalizerSettings
|
|||||||
int m_columnIndexes[VORDEMOD_COLUMNS];//!< How the columns are ordered in the table
|
int m_columnIndexes[VORDEMOD_COLUMNS];//!< How the columns are ordered in the table
|
||||||
int m_columnSizes[VORDEMOD_COLUMNS]; //!< Size of the coumns in the table
|
int m_columnSizes[VORDEMOD_COLUMNS]; //!< Size of the coumns in the table
|
||||||
|
|
||||||
QHash<int, VORLocalizerSubChannelSettings *> m_subChannelSettings;
|
QHash<int, VORLocalizerSubChannelSettings> m_subChannelSettings;
|
||||||
|
|
||||||
VORLocalizerSettings();
|
VORLocalizerSettings();
|
||||||
void resetToDefaults();
|
void resetToDefaults();
|
||||||
|
@ -18,12 +18,15 @@
|
|||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
|
||||||
#include "SWGDeviceState.h"
|
#include "SWGDeviceState.h"
|
||||||
|
#include "SWGDeviceSettings.h"
|
||||||
|
#include "SWGChannelSettings.h"
|
||||||
#include "SWGSuccessResponse.h"
|
#include "SWGSuccessResponse.h"
|
||||||
#include "SWGErrorResponse.h"
|
#include "SWGErrorResponse.h"
|
||||||
|
|
||||||
#include "webapi/webapiadapterinterface.h"
|
|
||||||
#include "device/deviceset.h"
|
#include "device/deviceset.h"
|
||||||
#include "channel/channelapi.h"
|
#include "channel/channelapi.h"
|
||||||
|
#include "webapi/webapiadapterinterface.h"
|
||||||
|
#include "webapi/webapiutils.h"
|
||||||
#include "maincore.h"
|
#include "maincore.h"
|
||||||
|
|
||||||
#include "vorlocalizerreport.h"
|
#include "vorlocalizerreport.h"
|
||||||
@ -36,7 +39,8 @@ class DSPDeviceSourceEngine;
|
|||||||
|
|
||||||
VorLocalizerWorker::VorLocalizerWorker(WebAPIAdapterInterface *webAPIAdapterInterface) :
|
VorLocalizerWorker::VorLocalizerWorker(WebAPIAdapterInterface *webAPIAdapterInterface) :
|
||||||
m_webAPIAdapterInterface(webAPIAdapterInterface),
|
m_webAPIAdapterInterface(webAPIAdapterInterface),
|
||||||
m_msgQueueToGUI(nullptr),
|
m_msgQueueToFeature(nullptr),
|
||||||
|
m_availableChannels(nullptr),
|
||||||
m_running(false),
|
m_running(false),
|
||||||
m_mutex(QMutex::Recursive)
|
m_mutex(QMutex::Recursive)
|
||||||
{
|
{
|
||||||
@ -59,6 +63,8 @@ bool VorLocalizerWorker::startWork()
|
|||||||
{
|
{
|
||||||
QMutexLocker mutexLocker(&m_mutex);
|
QMutexLocker mutexLocker(&m_mutex);
|
||||||
connect(&m_inputMessageQueue, SIGNAL(messageEnqueued()), this, SLOT(handleInputMessages()));
|
connect(&m_inputMessageQueue, SIGNAL(messageEnqueued()), this, SLOT(handleInputMessages()));
|
||||||
|
connect(&m_rrTimer, SIGNAL(timeout()), this, SLOT(rrNextTurn()));
|
||||||
|
m_rrTimer.start(m_settings.m_rrTime * 1000);
|
||||||
m_running = true;
|
m_running = true;
|
||||||
return m_running;
|
return m_running;
|
||||||
}
|
}
|
||||||
@ -66,6 +72,8 @@ bool VorLocalizerWorker::startWork()
|
|||||||
void VorLocalizerWorker::stopWork()
|
void VorLocalizerWorker::stopWork()
|
||||||
{
|
{
|
||||||
QMutexLocker mutexLocker(&m_mutex);
|
QMutexLocker mutexLocker(&m_mutex);
|
||||||
|
m_rrTimer.stop();
|
||||||
|
disconnect(&m_rrTimer, SIGNAL(timeout()), this, SLOT(rrNextTurn()));
|
||||||
disconnect(&m_inputMessageQueue, SIGNAL(messageEnqueued()), this, SLOT(handleInputMessages()));
|
disconnect(&m_inputMessageQueue, SIGNAL(messageEnqueued()), this, SLOT(handleInputMessages()));
|
||||||
m_running = false;
|
m_running = false;
|
||||||
}
|
}
|
||||||
@ -98,6 +106,7 @@ bool VorLocalizerWorker::handleMessage(const Message& cmd)
|
|||||||
{
|
{
|
||||||
qDebug() << "VorLocalizerWorker::handleMessage: MsgRefreshChannels";
|
qDebug() << "VorLocalizerWorker::handleMessage: MsgRefreshChannels";
|
||||||
updateChannels();
|
updateChannels();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -124,28 +133,53 @@ void VorLocalizerWorker::applySettings(const VORLocalizerSettings& settings, boo
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Add new sub channels
|
// Add new sub channels
|
||||||
QHash<int, VORLocalizerSubChannelSettings *>::const_iterator itr = settings.m_subChannelSettings.begin();
|
QHash<int, VORLocalizerSubChannelSettings>::const_iterator itr = settings.m_subChannelSettings.begin();
|
||||||
|
|
||||||
while (itr != settings.m_subChannelSettings.end())
|
while (itr != settings.m_subChannelSettings.end())
|
||||||
{
|
{
|
||||||
VORLocalizerSubChannelSettings *subChannelSettings = itr.value();
|
const VORLocalizerSubChannelSettings& subChannelSettings = itr.value();
|
||||||
|
qDebug() << "VorLocalizerWorker::applySettings: subchannel " << subChannelSettings.m_id;
|
||||||
int j = 0;
|
int j = 0;
|
||||||
|
|
||||||
for (; j < m_vorChannels.size(); j++)
|
for (; j < m_vorChannels.size(); j++)
|
||||||
{
|
{
|
||||||
if (subChannelSettings->m_id == m_vorChannels[j].m_subChannelId)
|
if (subChannelSettings.m_id == m_vorChannels[j].m_subChannelId)
|
||||||
|
{
|
||||||
|
qDebug() << "VorLocalizerWorker::applySettings: subchannel "
|
||||||
|
<< subChannelSettings.m_id
|
||||||
|
<< "already present";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (j == m_vorChannels.size())
|
if (j == m_vorChannels.size())
|
||||||
{
|
{
|
||||||
// Add a sub-channel sink
|
// Add a sub-channel sink
|
||||||
qDebug() << "VorLocalizerWorker::applySettings: Adding sink " << subChannelSettings->m_id;
|
qDebug() << "VorLocalizerWorker::applySettings: Adding subchannel " << subChannelSettings.m_id;
|
||||||
addVORChannel(subChannelSettings);
|
addVORChannel(subChannelSettings);
|
||||||
}
|
}
|
||||||
|
|
||||||
++itr;
|
++itr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (auto subChannelSetting : settings.m_subChannelSettings)
|
||||||
|
{
|
||||||
|
int navId = subChannelSetting.m_id;
|
||||||
|
|
||||||
|
if (m_settings.m_subChannelSettings.contains(navId))
|
||||||
|
{
|
||||||
|
if (subChannelSetting.m_audioMute != m_settings.m_subChannelSettings[navId].m_audioMute)
|
||||||
|
{
|
||||||
|
qDebug() << "VorLocalizerWorker::applySettings: audioMute:" << subChannelSetting.m_audioMute;
|
||||||
|
setAudioMute(navId, subChannelSetting.m_audioMute);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((settings.m_rrTime != m_settings.m_rrTime) || force) {
|
||||||
|
m_rrTimer.start(settings.m_rrTime * 1000);
|
||||||
|
}
|
||||||
|
|
||||||
m_settings = settings;
|
m_settings = settings;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -159,6 +193,8 @@ void VorLocalizerWorker::updateHardware()
|
|||||||
|
|
||||||
void VorLocalizerWorker::removeVORChannel(int navId)
|
void VorLocalizerWorker::removeVORChannel(int navId)
|
||||||
{
|
{
|
||||||
|
qDebug("VorLocalizerWorker::removeVORChannel: %d", navId);
|
||||||
|
|
||||||
for (int i = 0; i < m_vorChannels.size(); i++)
|
for (int i = 0; i < m_vorChannels.size(); i++)
|
||||||
{
|
{
|
||||||
if (m_vorChannels[i].m_subChannelId == navId)
|
if (m_vorChannels[i].m_subChannelId == navId)
|
||||||
@ -167,57 +203,538 @@ void VorLocalizerWorker::removeVORChannel(int navId)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
updateChannels();
|
||||||
}
|
}
|
||||||
|
|
||||||
void VorLocalizerWorker::addVORChannel(const VORLocalizerSubChannelSettings *subChannelSettings)
|
void VorLocalizerWorker::addVORChannel(const VORLocalizerSubChannelSettings& subChannelSettings)
|
||||||
{
|
{
|
||||||
VORChannel vorChannel = VORChannel{subChannelSettings->m_id, subChannelSettings->m_frequency, subChannelSettings->m_audioMute};
|
qDebug("VorLocalizerWorker::addVORChannel: %d at %d Hz",
|
||||||
|
subChannelSettings.m_id, subChannelSettings.m_frequency);
|
||||||
|
|
||||||
|
VORLocalizerSettings::VORChannel vorChannel =
|
||||||
|
VORLocalizerSettings::VORChannel{
|
||||||
|
subChannelSettings.m_id,
|
||||||
|
subChannelSettings.m_frequency,
|
||||||
|
subChannelSettings.m_audioMute
|
||||||
|
};
|
||||||
m_vorChannels.push_back(vorChannel);
|
m_vorChannels.push_back(vorChannel);
|
||||||
|
updateChannels();
|
||||||
}
|
}
|
||||||
|
|
||||||
void VorLocalizerWorker::updateChannels()
|
void VorLocalizerWorker::updateChannels()
|
||||||
{
|
{
|
||||||
MainCore *mainCore = MainCore::instance();
|
qDebug() << "VorLocalizerWorker::updateChannels: "
|
||||||
std::vector<DeviceSet*>& deviceSets = mainCore->getDeviceSets();
|
<< "#VORs:" << m_vorChannels.size()
|
||||||
std::vector<DeviceSet*>::const_iterator it = deviceSets.begin();
|
<< "#Chans:" << m_availableChannels->size();
|
||||||
m_availableChannels.clear();
|
|
||||||
|
|
||||||
int deviceIndex = 0;
|
if ((m_vorChannels.size() == 0) || (m_availableChannels->size() == 0)) {
|
||||||
|
return;
|
||||||
for (; it != deviceSets.end(); ++it, deviceIndex++)
|
|
||||||
{
|
|
||||||
DSPDeviceSourceEngine *deviceSourceEngine = (*it)->m_deviceSourceEngine;
|
|
||||||
|
|
||||||
if (deviceSourceEngine)
|
|
||||||
{
|
|
||||||
for (int chi = 0; chi < (*it)->getNumberOfChannels(); chi++)
|
|
||||||
{
|
|
||||||
ChannelAPI *channel = (*it)->getChannelAt(chi);
|
|
||||||
|
|
||||||
if (channel->getURI() == "sdrangel.channel.vordemodsc")
|
|
||||||
{
|
|
||||||
AvailableChannel availableChannel = AvailableChannel{deviceIndex, chi, channel};
|
|
||||||
m_availableChannels.push_back(availableChannel);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QMutexLocker mlock(&m_mutex);
|
||||||
|
std::sort(m_vorChannels.begin(), m_vorChannels.end());
|
||||||
|
std::vector<RRTurnPlan> devicesChannels;
|
||||||
|
getChannelsByDevice(m_availableChannels, devicesChannels);
|
||||||
|
QList<VORLocalizerSettings::VORChannel> unallocatedVORs(m_vorChannels);
|
||||||
|
m_rrPlans.clear();
|
||||||
|
int deviceCount = 0;
|
||||||
|
|
||||||
|
for (auto deviceChannel : devicesChannels)
|
||||||
|
{
|
||||||
|
unsigned int nbChannels = unallocatedVORs.size() < (int) deviceChannel.m_channels.size() ?
|
||||||
|
unallocatedVORs.size() :
|
||||||
|
deviceChannel.m_channels.size();
|
||||||
|
std::vector<VORRange> vorRanges;
|
||||||
|
|
||||||
|
while (nbChannels != 0)
|
||||||
|
{
|
||||||
|
getVORRanges(unallocatedVORs, nbChannels, vorRanges);
|
||||||
|
filterVORRanges(vorRanges, deviceChannel.m_bandwidth);
|
||||||
|
|
||||||
|
if (vorRanges.size() != 0) {
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nbChannels--;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<QList<VORLocalizerSettings::VORChannel>> vorLists;
|
||||||
|
|
||||||
|
for (auto vorRange : vorRanges)
|
||||||
|
{
|
||||||
|
QList<VORLocalizerSettings::VORChannel> vorList;
|
||||||
|
|
||||||
|
for (auto index : vorRange.m_vorIndices) {
|
||||||
|
vorList.append(VORLocalizerSettings::VORChannel(unallocatedVORs[index]));
|
||||||
|
}
|
||||||
|
|
||||||
|
vorLists.push_back(vorList);
|
||||||
|
}
|
||||||
|
|
||||||
|
// make one round robin turn for each VOR list for this device
|
||||||
|
std::vector<RRTurnPlan> rrDevicePlans;
|
||||||
|
|
||||||
|
for (auto vorList : vorLists)
|
||||||
|
{
|
||||||
|
RRTurnPlan turnPlan(deviceChannel);
|
||||||
|
int fMin = vorList.front().m_frequency;
|
||||||
|
int fMax = vorList.back().m_frequency;
|
||||||
|
int devFreq = (fMin + fMax) / 2;
|
||||||
|
turnPlan.m_device.m_frequency = devFreq;
|
||||||
|
int iCh = 0;
|
||||||
|
|
||||||
|
// qDebug() << "RR build plan "
|
||||||
|
// << "device:" << turnPlan.m_device.m_deviceIndex
|
||||||
|
// << "freq:" << turnPlan.m_device.m_frequency;
|
||||||
|
|
||||||
|
for (auto vorChannel : vorList)
|
||||||
|
{
|
||||||
|
RRChannel& channel = turnPlan.m_channels[iCh];
|
||||||
|
channel.m_frequencyShift = vorChannel.m_frequency - devFreq;
|
||||||
|
channel.m_navId = vorChannel.m_subChannelId;
|
||||||
|
// qDebug() << "VOR channel" << vorChannel.m_subChannelId
|
||||||
|
// << "freq:" << vorChannel.m_frequency
|
||||||
|
// << "channel:" << channel.m_channelIndex
|
||||||
|
// << "shift:" << channel.m_frequencyShift;
|
||||||
|
// remove VOR from the unallocated list
|
||||||
|
QList<VORLocalizerSettings::VORChannel>::iterator it = unallocatedVORs.begin();
|
||||||
|
while (it != unallocatedVORs.end())
|
||||||
|
{
|
||||||
|
if (it->m_subChannelId == vorChannel.m_subChannelId) {
|
||||||
|
it = unallocatedVORs.erase(it);
|
||||||
|
} else {
|
||||||
|
++it;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_msgQueueToGUI)
|
iCh++;
|
||||||
{
|
|
||||||
VORLocalizerReport::MsgReportChannels *msg = VORLocalizerReport::MsgReportChannels::create();
|
|
||||||
std::vector<VORLocalizerReport::MsgReportChannels::Channel>& msgChannels = msg->getChannels();
|
|
||||||
|
|
||||||
for (int i = 0; i < m_availableChannels.size(); i++)
|
|
||||||
{
|
|
||||||
VORLocalizerReport::MsgReportChannels::Channel msgChannel =
|
|
||||||
VORLocalizerReport::MsgReportChannels::Channel{
|
|
||||||
m_availableChannels[i].m_deviceSetIndex,
|
|
||||||
m_availableChannels[i].m_channelIndex
|
|
||||||
};
|
|
||||||
msgChannels.push_back(msgChannel);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
m_msgQueueToGUI->push(msg);
|
rrDevicePlans.push_back(turnPlan);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_rrPlans.push_back(rrDevicePlans);
|
||||||
|
deviceCount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
qDebug() << "VorLocalizerWorker::updateChannels: unallocatedVORs size:" << unallocatedVORs.size();
|
||||||
|
|
||||||
|
// Fallback for unallocated VORs: add single channel plans for all unallocated VORs
|
||||||
|
if ((unallocatedVORs.size() != 0) && (devicesChannels.size() != 0) && m_rrPlans.size() != 0)
|
||||||
|
{
|
||||||
|
VorLocalizerWorker::RRTurnPlan& deviceChannel = devicesChannels.front();
|
||||||
|
std::vector<VORRange> vorRanges;
|
||||||
|
getVORRanges(unallocatedVORs, 1, vorRanges);
|
||||||
|
std::vector<VorLocalizerWorker::RRTurnPlan>& rrPlan = m_rrPlans.front();
|
||||||
|
std::vector<QList<VORLocalizerSettings::VORChannel>> vorLists;
|
||||||
|
|
||||||
|
for (auto vorRange : vorRanges)
|
||||||
|
{
|
||||||
|
QList<VORLocalizerSettings::VORChannel> vorList;
|
||||||
|
|
||||||
|
for (auto index : vorRange.m_vorIndices) {
|
||||||
|
vorList.append(VORLocalizerSettings::VORChannel(unallocatedVORs[index]));
|
||||||
|
}
|
||||||
|
|
||||||
|
vorLists.push_back(vorList);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto vorList : vorLists)
|
||||||
|
{
|
||||||
|
RRTurnPlan turnPlan(deviceChannel);
|
||||||
|
int fMin = vorList.front().m_frequency;
|
||||||
|
int fMax = vorList.back().m_frequency;
|
||||||
|
int devFreq = (fMin + fMax) / 2;
|
||||||
|
turnPlan.m_device.m_frequency = devFreq;
|
||||||
|
int iCh = 0;
|
||||||
|
|
||||||
|
// qDebug() << "RR build plan "
|
||||||
|
// << "device:" << turnPlan.m_device.m_deviceIndex
|
||||||
|
// << "freq:" << turnPlan.m_device.m_frequency;
|
||||||
|
|
||||||
|
for (auto vorChannel : vorList)
|
||||||
|
{
|
||||||
|
RRChannel& channel = turnPlan.m_channels[iCh];
|
||||||
|
channel.m_frequencyShift = vorChannel.m_frequency - devFreq;
|
||||||
|
channel.m_navId = vorChannel.m_subChannelId;
|
||||||
|
// qDebug() << "VOR channel" << vorChannel.m_subChannelId
|
||||||
|
// << "freq:" << vorChannel.m_frequency
|
||||||
|
// << "channel:" << channel.m_channelIndex
|
||||||
|
// << "shift:" << channel.m_frequencyShift;
|
||||||
|
iCh++;
|
||||||
|
}
|
||||||
|
|
||||||
|
rrPlan.push_back(turnPlan);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto rrPlans : m_rrPlans)
|
||||||
|
{
|
||||||
|
qDebug() << "VorLocalizerWorker::updateChannels: RR plans for one device";
|
||||||
|
|
||||||
|
for (auto rrPlan : rrPlans)
|
||||||
|
{
|
||||||
|
qDebug() << "VorLocalizerWorker::updateChannels: RR plan: "
|
||||||
|
<< "device:" << rrPlan.m_device.m_deviceIndex
|
||||||
|
<< "frequency:" << rrPlan.m_device.m_frequency;
|
||||||
|
|
||||||
|
for (auto rrChannel : rrPlan.m_channels)
|
||||||
|
{
|
||||||
|
qDebug() << "VorLocalizerWorker::updateChannels: RR channel: "
|
||||||
|
<< "channel:" << rrChannel.m_channelAPI
|
||||||
|
<< "index:" << rrChannel.m_channelIndex
|
||||||
|
<< "shift:" << rrChannel.m_frequencyShift
|
||||||
|
<< "navId:" << rrChannel.m_navId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_rrTurnCounters.resize(deviceCount);
|
||||||
|
std::fill(m_rrTurnCounters.begin(), m_rrTurnCounters.end(), 0);
|
||||||
|
rrNextTurn();
|
||||||
|
}
|
||||||
|
|
||||||
|
void VorLocalizerWorker::allocateChannel(ChannelAPI *channel, int vorFrequency, int vorNavId, int channelShift)
|
||||||
|
{
|
||||||
|
VORLocalizerSettings::AvailableChannel& availableChannel = m_availableChannels->operator[](channel);
|
||||||
|
qDebug() << "VorLocalizerWorker::allocateChannel:"
|
||||||
|
<< " vorNavId:" << vorNavId
|
||||||
|
<< " vorFrequency:" << vorFrequency
|
||||||
|
<< " channelShift:" << channelShift
|
||||||
|
<< " deviceIndex:" << availableChannel.m_deviceSetIndex
|
||||||
|
<< " channelIndex:" << availableChannel.m_channelIndex;
|
||||||
|
double deviceFrequency = vorFrequency - channelShift;
|
||||||
|
setDeviceFrequency(availableChannel.m_deviceSetIndex, deviceFrequency);
|
||||||
|
setChannelShift(availableChannel.m_deviceSetIndex, availableChannel.m_channelIndex, channelShift, vorNavId);
|
||||||
|
availableChannel.m_navId = vorNavId;
|
||||||
|
}
|
||||||
|
|
||||||
|
void VorLocalizerWorker::setDeviceFrequency(int deviceIndex, double targetFrequency)
|
||||||
|
{
|
||||||
|
SWGSDRangel::SWGDeviceSettings deviceSettingsResponse;
|
||||||
|
SWGSDRangel::SWGErrorResponse errorResponse;
|
||||||
|
int httpRC;
|
||||||
|
|
||||||
|
// Get current device center frequency
|
||||||
|
httpRC = m_webAPIAdapterInterface->devicesetDeviceSettingsGet(
|
||||||
|
deviceIndex,
|
||||||
|
deviceSettingsResponse,
|
||||||
|
errorResponse
|
||||||
|
);
|
||||||
|
|
||||||
|
if (httpRC/100 != 2)
|
||||||
|
{
|
||||||
|
qWarning("VorLocalizerWorker::setDeviceFrequency: get device frequency error %d: %s",
|
||||||
|
httpRC, qPrintable(*errorResponse.getMessage()));
|
||||||
|
}
|
||||||
|
|
||||||
|
QJsonObject *jsonObj = deviceSettingsResponse.asJsonObject();
|
||||||
|
|
||||||
|
// Update centerFrequency
|
||||||
|
WebAPIUtils::setSubObjectDouble(*jsonObj, "centerFrequency", targetFrequency);
|
||||||
|
QStringList deviceSettingsKeys;
|
||||||
|
deviceSettingsKeys.append("centerFrequency");
|
||||||
|
deviceSettingsResponse.init();
|
||||||
|
deviceSettingsResponse.fromJsonObject(*jsonObj);
|
||||||
|
SWGSDRangel::SWGErrorResponse errorResponse2;
|
||||||
|
|
||||||
|
httpRC = m_webAPIAdapterInterface->devicesetDeviceSettingsPutPatch(
|
||||||
|
deviceIndex,
|
||||||
|
false, // PATCH
|
||||||
|
deviceSettingsKeys,
|
||||||
|
deviceSettingsResponse,
|
||||||
|
errorResponse2
|
||||||
|
);
|
||||||
|
|
||||||
|
if (httpRC/100 == 2)
|
||||||
|
{
|
||||||
|
qDebug("VorLocalizerWorker::setDeviceFrequency: set device frequency %f OK", targetFrequency);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
qWarning("VorLocalizerWorker::setDeviceFrequency: set device frequency error %d: %s",
|
||||||
|
httpRC, qPrintable(*errorResponse2.getMessage()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void VorLocalizerWorker::setChannelShift(int deviceIndex, int channelIndex, double targetOffset, int vorNavId)
|
||||||
|
{
|
||||||
|
SWGSDRangel::SWGChannelSettings channelSettingsResponse;
|
||||||
|
SWGSDRangel::SWGErrorResponse errorResponse;
|
||||||
|
int httpRC;
|
||||||
|
|
||||||
|
// Get channel settings containg inputFrequencyOffset, so we can patch them
|
||||||
|
httpRC = m_webAPIAdapterInterface->devicesetChannelSettingsGet(
|
||||||
|
deviceIndex,
|
||||||
|
channelIndex,
|
||||||
|
channelSettingsResponse,
|
||||||
|
errorResponse
|
||||||
|
);
|
||||||
|
|
||||||
|
if (httpRC/100 != 2)
|
||||||
|
{
|
||||||
|
qWarning("VorLocalizerWorker::setChannelShift: get channel offset frequency error %d: %s",
|
||||||
|
httpRC, qPrintable(*errorResponse.getMessage()));
|
||||||
|
}
|
||||||
|
|
||||||
|
QJsonObject *jsonObj = channelSettingsResponse.asJsonObject();
|
||||||
|
|
||||||
|
if (!WebAPIUtils::setSubObjectDouble(*jsonObj, "inputFrequencyOffset", targetOffset))
|
||||||
|
{
|
||||||
|
qWarning("VorLocalizerWorker::setChannelShift: No inputFrequencyOffset key in channel settings");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!WebAPIUtils::setSubObjectInt(*jsonObj, "navId", vorNavId))
|
||||||
|
{
|
||||||
|
qWarning("VorLocalizerWorker::setChannelShift: No navId key in channel settings");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList channelSettingsKeys;
|
||||||
|
|
||||||
|
if (m_settings.m_subChannelSettings.contains(vorNavId))
|
||||||
|
{
|
||||||
|
if (!WebAPIUtils::setSubObjectInt(*jsonObj, "audioMute", m_settings.m_subChannelSettings[vorNavId].m_audioMute ? 1 : 0)) {
|
||||||
|
qWarning("VorLocalizerWorker::setChannelShift: No audioMute key in channel settings");
|
||||||
|
} else {
|
||||||
|
channelSettingsKeys.append("audioMute");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
channelSettingsKeys.append("inputFrequencyOffset");
|
||||||
|
channelSettingsKeys.append("navId");
|
||||||
|
channelSettingsResponse.init();
|
||||||
|
channelSettingsResponse.fromJsonObject(*jsonObj);
|
||||||
|
|
||||||
|
httpRC = m_webAPIAdapterInterface->devicesetChannelSettingsPutPatch(
|
||||||
|
deviceIndex,
|
||||||
|
channelIndex,
|
||||||
|
false, // PATCH
|
||||||
|
channelSettingsKeys,
|
||||||
|
channelSettingsResponse,
|
||||||
|
errorResponse
|
||||||
|
);
|
||||||
|
|
||||||
|
if (httpRC/100 == 2)
|
||||||
|
{
|
||||||
|
qDebug("VorLocalizerWorker::setChannelShift: inputFrequencyOffset: %f navId: %d OK", targetOffset, vorNavId);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
qWarning("VorLocalizerWorker::setChannelShift: set inputFrequencyOffset and navId error %d: %s",
|
||||||
|
httpRC, qPrintable(*errorResponse.getMessage()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void VorLocalizerWorker::setAudioMute(int vorNavId, bool audioMute)
|
||||||
|
{
|
||||||
|
QMutexLocker mlock(&m_mutex);
|
||||||
|
|
||||||
|
if (!m_channelAllocations.contains(vorNavId)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
SWGSDRangel::SWGChannelSettings channelSettingsResponse;
|
||||||
|
SWGSDRangel::SWGErrorResponse errorResponse;
|
||||||
|
int httpRC;
|
||||||
|
int deviceIndex = m_channelAllocations[vorNavId].m_deviceIndex;
|
||||||
|
int channelIndex = m_channelAllocations[vorNavId].m_channelIndex;
|
||||||
|
|
||||||
|
// Get channel settings containg inputFrequencyOffset, so we can patch them
|
||||||
|
httpRC = m_webAPIAdapterInterface->devicesetChannelSettingsGet(
|
||||||
|
deviceIndex,
|
||||||
|
channelIndex,
|
||||||
|
channelSettingsResponse,
|
||||||
|
errorResponse
|
||||||
|
);
|
||||||
|
|
||||||
|
if (httpRC/100 != 2)
|
||||||
|
{
|
||||||
|
qWarning("VorLocalizerWorker::setChannelShift: get channel offset frequency error %d: %s",
|
||||||
|
httpRC, qPrintable(*errorResponse.getMessage()));
|
||||||
|
}
|
||||||
|
|
||||||
|
QJsonObject *jsonObj = channelSettingsResponse.asJsonObject();
|
||||||
|
|
||||||
|
if (!WebAPIUtils::setSubObjectInt(*jsonObj, "audioMute", audioMute ? 1 : 0))
|
||||||
|
{
|
||||||
|
qWarning("VorLocalizerWorker::setAudioMute: No audioMute key in channel settings");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList channelSettingsKeys;
|
||||||
|
channelSettingsKeys.append("audioMute");
|
||||||
|
channelSettingsResponse.init();
|
||||||
|
channelSettingsResponse.fromJsonObject(*jsonObj);
|
||||||
|
|
||||||
|
httpRC = m_webAPIAdapterInterface->devicesetChannelSettingsPutPatch(
|
||||||
|
deviceIndex,
|
||||||
|
channelIndex,
|
||||||
|
false, // PATCH
|
||||||
|
channelSettingsKeys,
|
||||||
|
channelSettingsResponse,
|
||||||
|
errorResponse
|
||||||
|
);
|
||||||
|
|
||||||
|
if (httpRC/100 == 2)
|
||||||
|
{
|
||||||
|
qDebug("VorLocalizerWorker::setAudioMute: navId: %d audioMute: %d OK", vorNavId, audioMute ? 1 : 0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
qWarning("VorLocalizerWorker::setAudioMute: navId: %d set audioMute error %d: %s",
|
||||||
|
vorNavId, httpRC, qPrintable(*errorResponse.getMessage()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void VorLocalizerWorker::generateIndexCombinations(int length, int subLength, std::vector<std::vector<int>>& indexCombinations)
|
||||||
|
{
|
||||||
|
indexCombinations.clear();
|
||||||
|
std::vector<int> sublist(subLength);
|
||||||
|
std::vector<int>::iterator first = sublist.begin(), last = sublist.end();
|
||||||
|
std::iota(first, last, 0);
|
||||||
|
indexCombinations.push_back(sublist);
|
||||||
|
|
||||||
|
while ((*first) != length - subLength)
|
||||||
|
{
|
||||||
|
std::vector<int>::iterator mt = last;
|
||||||
|
|
||||||
|
while (*(--mt) == length-(last-mt));
|
||||||
|
(*mt)++;
|
||||||
|
while (++mt != last) *mt = *(mt-1)+1;
|
||||||
|
|
||||||
|
indexCombinations.push_back(std::vector<int>(first, last));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void VorLocalizerWorker::getVORRanges(const QList<VORLocalizerSettings::VORChannel>& vors, int subLength, std::vector<VORRange>& vorRanges)
|
||||||
|
{
|
||||||
|
std::vector<std::vector<int>> indexCombinations;
|
||||||
|
generateIndexCombinations(vors.size(), subLength, indexCombinations);
|
||||||
|
vorRanges.clear();
|
||||||
|
|
||||||
|
for (auto indexCombination : indexCombinations)
|
||||||
|
{
|
||||||
|
int fMax = vors.at(indexCombination.back()).m_frequency;
|
||||||
|
int fMin = vors.at(indexCombination.front()).m_frequency;
|
||||||
|
vorRanges.push_back(VORRange{indexCombination, fMax - fMin});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void VorLocalizerWorker::filterVORRanges(std::vector<VORRange>& vorRanges, int thresholdBW)
|
||||||
|
{
|
||||||
|
std::vector<VORRange> originalVORRanges(vorRanges.size());
|
||||||
|
std::copy(vorRanges.begin(), vorRanges.end(), originalVORRanges.begin());
|
||||||
|
vorRanges.clear();
|
||||||
|
|
||||||
|
for (auto vorRange : originalVORRanges)
|
||||||
|
{
|
||||||
|
if (vorRange.m_frequencyRange < thresholdBW) {
|
||||||
|
vorRanges.push_back(vorRange);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void VorLocalizerWorker::getChannelsByDevice(
|
||||||
|
const QHash<ChannelAPI*, VORLocalizerSettings::AvailableChannel> *availableChannels,
|
||||||
|
std::vector<RRTurnPlan>& devicesChannels
|
||||||
|
)
|
||||||
|
{
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
bool operator()(const RRTurnPlan& a, const RRTurnPlan& b)
|
||||||
|
{
|
||||||
|
unsigned int nbChannelsA = a.m_channels.size();
|
||||||
|
unsigned int nbChannelsB = a.m_channels.size();
|
||||||
|
|
||||||
|
if (nbChannelsA == nbChannelsB) {
|
||||||
|
return a.m_bandwidth > b.m_bandwidth;
|
||||||
|
} else {
|
||||||
|
return nbChannelsA > nbChannelsB;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} rrTurnPlanGreater;
|
||||||
|
|
||||||
|
QHash<ChannelAPI*, VORLocalizerSettings::AvailableChannel>::const_iterator itr = availableChannels->begin();
|
||||||
|
QMap<int, RRTurnPlan> devicesChannelsMap;
|
||||||
|
|
||||||
|
for (; itr != availableChannels->end(); ++itr)
|
||||||
|
{
|
||||||
|
devicesChannelsMap[itr->m_deviceSetIndex].m_device.m_deviceIndex = itr->m_deviceSetIndex;
|
||||||
|
devicesChannelsMap[itr->m_deviceSetIndex].m_bandwidth = itr->m_basebandSampleRate;
|
||||||
|
devicesChannelsMap[itr->m_deviceSetIndex].m_channels.push_back(RRChannel{itr->m_channelAPI, itr->m_channelIndex, 0, -1});
|
||||||
|
}
|
||||||
|
|
||||||
|
QMap<int, RRTurnPlan>::const_iterator itm = devicesChannelsMap.begin();
|
||||||
|
devicesChannels.clear();
|
||||||
|
|
||||||
|
for (; itm != devicesChannelsMap.end(); ++itm) {
|
||||||
|
devicesChannels.push_back(*itm);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::sort(devicesChannels.begin(), devicesChannels.end(), rrTurnPlanGreater);
|
||||||
|
}
|
||||||
|
|
||||||
|
void VorLocalizerWorker::rrNextTurn()
|
||||||
|
{
|
||||||
|
QMutexLocker mlock(&m_mutex);
|
||||||
|
int iDevPlan = 0;
|
||||||
|
VORLocalizerReport::MsgReportServiceddVORs *msg = VORLocalizerReport::MsgReportServiceddVORs::create();
|
||||||
|
m_channelAllocations.clear();
|
||||||
|
|
||||||
|
for (auto rrPlan : m_rrPlans)
|
||||||
|
{
|
||||||
|
unsigned int turnCount = m_rrTurnCounters[iDevPlan];
|
||||||
|
int deviceIndex = rrPlan[turnCount].m_device.m_deviceIndex;
|
||||||
|
int deviceFrequency = rrPlan[turnCount].m_device.m_frequency - m_settings.m_centerShift;
|
||||||
|
qDebug() << "VorLocalizerWorker::rrNextTurn: "
|
||||||
|
<< "turn:" << turnCount
|
||||||
|
<< "device:" << deviceIndex
|
||||||
|
<< "frequency:" << deviceFrequency - m_settings.m_centerShift;
|
||||||
|
setDeviceFrequency(deviceIndex, deviceFrequency);
|
||||||
|
|
||||||
|
for (auto channel : rrPlan[turnCount].m_channels)
|
||||||
|
{
|
||||||
|
qDebug() << "VorLocalizerWorker::rrNextTurn: "
|
||||||
|
<< "device:" << deviceIndex
|
||||||
|
<< "channel:" << channel.m_channelIndex
|
||||||
|
<< "shift:" << channel.m_frequencyShift + m_settings.m_centerShift
|
||||||
|
<< "navId:" << channel.m_navId;
|
||||||
|
setChannelShift(
|
||||||
|
deviceIndex,
|
||||||
|
channel.m_channelIndex,
|
||||||
|
channel.m_frequencyShift + m_settings.m_centerShift,
|
||||||
|
channel.m_navId
|
||||||
|
);
|
||||||
|
m_channelAllocations[channel.m_navId] = ChannelAllocation{
|
||||||
|
channel.m_navId,
|
||||||
|
deviceIndex,
|
||||||
|
channel.m_channelIndex
|
||||||
|
};
|
||||||
|
|
||||||
|
if(m_availableChannels->contains(channel.m_channelAPI))
|
||||||
|
{
|
||||||
|
VORLocalizerSettings::AvailableChannel& availableChannel = m_availableChannels->operator[](channel.m_channelAPI);
|
||||||
|
availableChannel.m_navId = channel.m_navId;
|
||||||
|
}
|
||||||
|
|
||||||
|
msg->getNavIds().push_back(channel.m_navId);
|
||||||
|
msg->getSinglePlans()[channel.m_navId] = (rrPlan.size() == 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
turnCount++;
|
||||||
|
|
||||||
|
if (turnCount == rrPlan.size()) {
|
||||||
|
turnCount = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_rrTurnCounters[iDevPlan] = turnCount;
|
||||||
|
iDevPlan++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_msgQueueToFeature) {
|
||||||
|
m_msgQueueToFeature->push(msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -28,6 +28,7 @@
|
|||||||
|
|
||||||
class WebAPIAdapterInterface;
|
class WebAPIAdapterInterface;
|
||||||
class ChannelAPI;
|
class ChannelAPI;
|
||||||
|
class Feature;
|
||||||
|
|
||||||
class VorLocalizerWorker : public QObject
|
class VorLocalizerWorker : public QObject
|
||||||
{
|
{
|
||||||
@ -77,42 +78,98 @@ public:
|
|||||||
void stopWork();
|
void stopWork();
|
||||||
bool isRunning() const { return m_running; }
|
bool isRunning() const { return m_running; }
|
||||||
MessageQueue *getInputMessageQueue() { return &m_inputMessageQueue; }
|
MessageQueue *getInputMessageQueue() { return &m_inputMessageQueue; }
|
||||||
void setMessageQueueToGUI(MessageQueue *messageQueue) { m_msgQueueToGUI = messageQueue; }
|
void setMessageQueueToFeature(MessageQueue *messageQueue) { m_msgQueueToFeature = messageQueue; }
|
||||||
|
void setAvailableChannels(QHash<ChannelAPI*, VORLocalizerSettings::AvailableChannel> *avaialbleChannels) {
|
||||||
|
m_availableChannels = avaialbleChannels;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct VORChannel
|
struct VORRange
|
||||||
{
|
{
|
||||||
int m_subChannelId; //!< Unique VOR identifier (from database)
|
std::vector<int> m_vorIndices;
|
||||||
int m_frequency; //!< Frequency the VOR is on
|
int m_frequencyRange;
|
||||||
bool m_audioMute; //!< Mute the audio from this VOR
|
|
||||||
|
VORRange() = default;
|
||||||
|
VORRange(const VORRange&) = default;
|
||||||
|
VORRange& operator=(const VORRange&) = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct AvailableChannel
|
struct RRDevice
|
||||||
|
{
|
||||||
|
int m_deviceIndex;
|
||||||
|
int m_frequency;
|
||||||
|
|
||||||
|
RRDevice() = default;
|
||||||
|
RRDevice(const RRDevice&) = default;
|
||||||
|
RRDevice& operator=(const RRDevice&) = default;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct RRChannel
|
||||||
{
|
{
|
||||||
int m_deviceSetIndex;
|
|
||||||
int m_channelIndex;
|
|
||||||
ChannelAPI *m_channelAPI;
|
ChannelAPI *m_channelAPI;
|
||||||
|
int m_channelIndex;
|
||||||
|
int m_frequencyShift;
|
||||||
|
int m_navId;
|
||||||
|
|
||||||
|
RRChannel() = default;
|
||||||
|
RRChannel(const RRChannel&) = default;
|
||||||
|
RRChannel& operator=(const RRChannel&) = default;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct RRTurnPlan
|
||||||
|
{
|
||||||
|
RRDevice m_device;
|
||||||
|
int m_bandwidth;
|
||||||
|
std::vector<RRChannel> m_channels;
|
||||||
|
|
||||||
|
RRTurnPlan() = default;
|
||||||
|
RRTurnPlan(const RRTurnPlan&) = default;
|
||||||
|
RRTurnPlan& operator=(const RRTurnPlan&) = default;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ChannelAllocation
|
||||||
|
{
|
||||||
|
int m_navId;
|
||||||
|
int m_deviceIndex;
|
||||||
|
int m_channelIndex;
|
||||||
|
|
||||||
|
ChannelAllocation() = default;
|
||||||
|
ChannelAllocation(const ChannelAllocation&) = default;
|
||||||
|
ChannelAllocation& operator=(const ChannelAllocation&) = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
WebAPIAdapterInterface *m_webAPIAdapterInterface;
|
WebAPIAdapterInterface *m_webAPIAdapterInterface;
|
||||||
MessageQueue m_inputMessageQueue; //!< Queue for asynchronous inbound communication
|
MessageQueue m_inputMessageQueue; //!< Queue for asynchronous inbound communication
|
||||||
MessageQueue *m_msgQueueToGUI; //!< Queue to report state to GUI
|
MessageQueue *m_msgQueueToFeature; //!< Queue to report state to GUI
|
||||||
VORLocalizerSettings m_settings;
|
VORLocalizerSettings m_settings;
|
||||||
QList<VORChannel> m_vorChannels;
|
QList<VORLocalizerSettings::VORChannel> m_vorChannels;
|
||||||
QList<AvailableChannel> m_availableChannels;
|
QHash<int, ChannelAllocation> m_channelAllocations;
|
||||||
|
QHash<ChannelAPI*, VORLocalizerSettings::AvailableChannel> *m_availableChannels;
|
||||||
bool m_running;
|
bool m_running;
|
||||||
QTimer m_updateTimer;
|
QTimer m_updateTimer;
|
||||||
QMutex m_mutex;
|
QMutex m_mutex;
|
||||||
|
QTimer m_rrTimer;
|
||||||
|
std::vector<std::vector<RRTurnPlan>> m_rrPlans; //!< Round robin plans for each device
|
||||||
|
std::vector<int> m_rrTurnCounters; //!< Round robin turn count for each device
|
||||||
|
|
||||||
bool handleMessage(const Message& cmd);
|
bool handleMessage(const Message& cmd);
|
||||||
void applySettings(const VORLocalizerSettings& settings, bool force = false);
|
void applySettings(const VORLocalizerSettings& settings, bool force = false);
|
||||||
void updateChannels();
|
|
||||||
void removeVORChannel(int navId);
|
void removeVORChannel(int navId);
|
||||||
void addVORChannel(const VORLocalizerSubChannelSettings *subChannelSettings);
|
void addVORChannel(const VORLocalizerSubChannelSettings& subChannelSettings);
|
||||||
|
void updateChannels(); //!< (re)allocate channels to service VORs
|
||||||
|
void allocateChannel(ChannelAPI *channel, int vorFrequency, int vorNavId, int channelShift);
|
||||||
|
void setDeviceFrequency(int deviceIndex, double targetFrequency);
|
||||||
|
void setChannelShift(int deviceIndex, int channelIndex, double targetOffset, int vorNavId);
|
||||||
|
void setAudioMute(int vorNavId, bool audioMute);
|
||||||
|
static void generateIndexCombinations(int length, int subLength, std::vector<std::vector<int>>& indexCombinations);
|
||||||
|
static void getVORRanges(const QList<VORLocalizerSettings::VORChannel>& vors, int subLength, std::vector<VORRange>& vorRanges);
|
||||||
|
static void filterVORRanges(std::vector<VORRange>& vorRanges, int thresholdBW);
|
||||||
|
static void getChannelsByDevice(const QHash<ChannelAPI*, VORLocalizerSettings::AvailableChannel> *availableChannels, std::vector<RRTurnPlan>& m_deviceChannels);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void handleInputMessages();
|
void handleInputMessages();
|
||||||
void updateHardware();
|
void updateHardware();
|
||||||
|
void rrNextTurn();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // INCLUDE_FEATURE_VORLOCALIZERWORKER_H_
|
#endif // INCLUDE_FEATURE_VORLOCALIZERWORKER_H_
|
||||||
|
@ -46,7 +46,7 @@ MessagePipes::~MessagePipes()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MessagePipes::registerChannelToFeature(const ChannelAPI *source, const Feature *feature, const QString& type)
|
MessageQueue *MessagePipes::registerChannelToFeature(const ChannelAPI *source, const Feature *feature, const QString& type)
|
||||||
{
|
{
|
||||||
int typeId;
|
int typeId;
|
||||||
|
|
||||||
@ -68,8 +68,11 @@ void MessagePipes::registerChannelToFeature(const ChannelAPI *source, const Feat
|
|||||||
m_featureRegistrations.insert(regKey, QList<const Feature*>());
|
m_featureRegistrations.insert(regKey, QList<const Feature*>());
|
||||||
}
|
}
|
||||||
|
|
||||||
m_messageRegistrations[regKey].append(new MessageQueue());
|
MessageQueue *messageQueue = new MessageQueue();
|
||||||
|
m_messageRegistrations[regKey].append(messageQueue);
|
||||||
m_featureRegistrations[regKey].append(feature);
|
m_featureRegistrations[regKey].append(feature);
|
||||||
|
|
||||||
|
return messageQueue;
|
||||||
}
|
}
|
||||||
|
|
||||||
QList<MessageQueue*>* MessagePipes::getMessageQueues(const ChannelAPI *source, const QString& type)
|
QList<MessageQueue*>* MessagePipes::getMessageQueues(const ChannelAPI *source, const QString& type)
|
||||||
|
@ -45,7 +45,7 @@ public:
|
|||||||
MessagePipes& operator=(const MessagePipes&) = delete;
|
MessagePipes& operator=(const MessagePipes&) = delete;
|
||||||
~MessagePipes();
|
~MessagePipes();
|
||||||
|
|
||||||
void registerChannelToFeature(const ChannelAPI *source, const Feature *feature, const QString& type);
|
MessageQueue *registerChannelToFeature(const ChannelAPI *source, const Feature *feature, const QString& type);
|
||||||
QList<MessageQueue*>* getMessageQueues(const ChannelAPI *source, const QString& type);
|
QList<MessageQueue*>* getMessageQueues(const ChannelAPI *source, const QString& type);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -9484,20 +9484,36 @@ margin-bottom: 20px;
|
|||||||
"type" : "number",
|
"type" : "number",
|
||||||
"format" : "float"
|
"format" : "float"
|
||||||
},
|
},
|
||||||
|
"navId" : {
|
||||||
|
"type" : "integer",
|
||||||
|
"description" : "VOR unique identifier when set by VOR localizer feature"
|
||||||
|
},
|
||||||
"radial" : {
|
"radial" : {
|
||||||
"type" : "number",
|
"type" : "number",
|
||||||
"format" : "float",
|
"format" : "float",
|
||||||
"description" : "current detected radial"
|
"description" : "current detected radial (degrees)"
|
||||||
},
|
},
|
||||||
"refMag" : {
|
"refMag" : {
|
||||||
"type" : "number",
|
"type" : "number",
|
||||||
"format" : "float",
|
"format" : "float",
|
||||||
"description" : "current reference signal magnitude"
|
"description" : "current reference signal magnitude (dB)"
|
||||||
},
|
},
|
||||||
"varMag" : {
|
"varMag" : {
|
||||||
"type" : "number",
|
"type" : "number",
|
||||||
"format" : "float",
|
"format" : "float",
|
||||||
"description" : "current variable signal magnitude"
|
"description" : "current variable signal magnitude (dB)"
|
||||||
|
},
|
||||||
|
"validRadial" : {
|
||||||
|
"type" : "integer",
|
||||||
|
"description" : "Radial validity estimation\n * 0 - Radial is invalid\n * 1 - Radial is valid\n"
|
||||||
|
},
|
||||||
|
"validRefMag" : {
|
||||||
|
"type" : "integer",
|
||||||
|
"description" : "Reference signal magnitude validity\n * 0 - Magnitude below threshold\n * 1 - Magnitude above threshold\n"
|
||||||
|
},
|
||||||
|
"validVarMag" : {
|
||||||
|
"type" : "integer",
|
||||||
|
"description" : "Variable signal magnitude validity\n * 0 - Magnitude below threshold\n * 1 - Magnitude above threshold\n"
|
||||||
},
|
},
|
||||||
"morseIdent" : {
|
"morseIdent" : {
|
||||||
"type" : "string",
|
"type" : "string",
|
||||||
@ -9645,6 +9661,14 @@ margin-bottom: 20px;
|
|||||||
"magDecAdjust" : {
|
"magDecAdjust" : {
|
||||||
"type" : "integer",
|
"type" : "integer",
|
||||||
"description" : "Adjust radial lines on map for magnetic declination of VOR"
|
"description" : "Adjust radial lines on map for magnetic declination of VOR"
|
||||||
|
},
|
||||||
|
"rrTime" : {
|
||||||
|
"type" : "integer",
|
||||||
|
"description" : "Round robin turn time in seconds"
|
||||||
|
},
|
||||||
|
"centerShift" : {
|
||||||
|
"type" : "integer",
|
||||||
|
"description" : "Shift of center frequency in Hz"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"description" : "VORLocalizer"
|
"description" : "VORLocalizer"
|
||||||
@ -44850,7 +44874,7 @@ except ApiException as e:
|
|||||||
</div>
|
</div>
|
||||||
<div id="generator">
|
<div id="generator">
|
||||||
<div class="content">
|
<div class="content">
|
||||||
Generated 2020-11-29T21:00:18.945+01:00
|
Generated 2020-12-06T23:43:21.772+01:00
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -55,18 +55,39 @@ VORDemodSCReport:
|
|||||||
volume:
|
volume:
|
||||||
type: number
|
type: number
|
||||||
format: float
|
format: float
|
||||||
|
navId:
|
||||||
|
description: VOR unique identifier when set by VOR localizer feature
|
||||||
|
type: integer
|
||||||
radial:
|
radial:
|
||||||
description: current detected radial
|
description: current detected radial (degrees)
|
||||||
type: number
|
type: number
|
||||||
format: float
|
format: float
|
||||||
refMag:
|
refMag:
|
||||||
description: current reference signal magnitude
|
description: current reference signal magnitude (dB)
|
||||||
type: number
|
type: number
|
||||||
format: float
|
format: float
|
||||||
varMag:
|
varMag:
|
||||||
description: current variable signal magnitude
|
description: current variable signal magnitude (dB)
|
||||||
type: number
|
type: number
|
||||||
format: float
|
format: float
|
||||||
|
validRadial:
|
||||||
|
type: integer
|
||||||
|
description: >
|
||||||
|
Radial validity estimation
|
||||||
|
* 0 - Radial is invalid
|
||||||
|
* 1 - Radial is valid
|
||||||
|
validRefMag:
|
||||||
|
type: integer
|
||||||
|
description: >
|
||||||
|
Reference signal magnitude validity
|
||||||
|
* 0 - Magnitude below threshold
|
||||||
|
* 1 - Magnitude above threshold
|
||||||
|
validVarMag:
|
||||||
|
type: integer
|
||||||
|
description: >
|
||||||
|
Variable signal magnitude validity
|
||||||
|
* 0 - Magnitude below threshold
|
||||||
|
* 1 - Magnitude above threshold
|
||||||
morseIdent:
|
morseIdent:
|
||||||
description: current identification morse code transcript
|
description: current identification morse code transcript
|
||||||
type: string
|
type: string
|
||||||
|
@ -19,3 +19,9 @@ VORLocalizerSettings:
|
|||||||
magDecAdjust:
|
magDecAdjust:
|
||||||
description: Adjust radial lines on map for magnetic declination of VOR
|
description: Adjust radial lines on map for magnetic declination of VOR
|
||||||
type: integer
|
type: integer
|
||||||
|
rrTime:
|
||||||
|
description: Round robin turn time in seconds
|
||||||
|
type: integer
|
||||||
|
centerShift:
|
||||||
|
description: Shift of center frequency in Hz
|
||||||
|
type: integer
|
||||||
|
59
sdrbase/util/average.h
Normal file
59
sdrbase/util/average.h
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
///////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// //
|
||||||
|
// 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 _UTIL_AVERAGE_H_
|
||||||
|
#define _UTIL_AVERAGE_H_
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
template <typename T, typename Total>
|
||||||
|
class AverageUtil
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
AverageUtil()
|
||||||
|
: m_numSamples(0), m_total(0)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
AverageUtil(T sample)
|
||||||
|
: m_numSamples(1), m_total(sample)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
void reset()
|
||||||
|
{
|
||||||
|
m_numSamples = 0;
|
||||||
|
m_total = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator()(T sample)
|
||||||
|
{
|
||||||
|
m_total += sample;
|
||||||
|
m_numSamples++;
|
||||||
|
}
|
||||||
|
|
||||||
|
double asDouble() const { return ((double)m_total) / (m_numSamples == 0 ? 1 : m_numSamples); }
|
||||||
|
float asFloat() const { return ((float)m_total) / (m_numSamples == 0 ? 1 : m_numSamples); }
|
||||||
|
operator T() const { return m_total / (m_numSamples == 0 ? 1 : m_numSamples); }
|
||||||
|
T instantAverage() const { return m_total / (m_numSamples == 0 ? 1 : m_numSamples); }
|
||||||
|
int getNumSamples() const { return m_numSamples; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
int m_numSamples;
|
||||||
|
Total m_total;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* _UTIL_AVERAGE_H_ */
|
@ -344,6 +344,51 @@ bool WebAPIUtils::setSubObjectDouble(QJsonObject &json, const QString &key, doub
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get integer value from within nested JSON object
|
||||||
|
bool WebAPIUtils::getSubObjectInt(const QJsonObject &json, const QString &key, int &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].toInt();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set integer value withing nested JSON object
|
||||||
|
bool WebAPIUtils::setSubObjectInt(QJsonObject &json, const QString &key, int 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
|
// look for value in key=value
|
||||||
bool WebAPIUtils::extractValue(const QJsonObject &json, const QString &key, QJsonValue &value)
|
bool WebAPIUtils::extractValue(const QJsonObject &json, const QString &key, QJsonValue &value)
|
||||||
{
|
{
|
||||||
|
@ -47,6 +47,8 @@ public:
|
|||||||
static bool getObjectObjects(const QJsonObject &json, const QString &key, QList<QJsonObject> &objects);
|
static bool getObjectObjects(const QJsonObject &json, const QString &key, QList<QJsonObject> &objects);
|
||||||
static bool getSubObjectDouble(const QJsonObject &json, const QString &key, double &value);
|
static bool getSubObjectDouble(const QJsonObject &json, const QString &key, double &value);
|
||||||
static bool setSubObjectDouble(QJsonObject &json, const QString &key, double value);
|
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 extractValue(const QJsonObject &json, const QString &key, QJsonValue &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 extractArray(const QJsonObject &json, const QString &key, QJsonArray &value);
|
||||||
static bool extractObject(const QJsonObject &json, const QString &key, QJsonObject &value);
|
static bool extractObject(const QJsonObject &json, const QString &key, QJsonObject &value);
|
||||||
|
@ -55,18 +55,39 @@ VORDemodSCReport:
|
|||||||
volume:
|
volume:
|
||||||
type: number
|
type: number
|
||||||
format: float
|
format: float
|
||||||
|
navId:
|
||||||
|
description: VOR unique identifier when set by VOR localizer feature
|
||||||
|
type: integer
|
||||||
radial:
|
radial:
|
||||||
description: current detected radial
|
description: current detected radial (degrees)
|
||||||
type: number
|
type: number
|
||||||
format: float
|
format: float
|
||||||
refMag:
|
refMag:
|
||||||
description: current reference signal magnitude
|
description: current reference signal magnitude (dB)
|
||||||
type: number
|
type: number
|
||||||
format: float
|
format: float
|
||||||
varMag:
|
varMag:
|
||||||
description: current variable signal magnitude
|
description: current variable signal magnitude (dB)
|
||||||
type: number
|
type: number
|
||||||
format: float
|
format: float
|
||||||
|
validRadial:
|
||||||
|
type: integer
|
||||||
|
description: >
|
||||||
|
Radial validity estimation
|
||||||
|
* 0 - Radial is invalid
|
||||||
|
* 1 - Radial is valid
|
||||||
|
validRefMag:
|
||||||
|
type: integer
|
||||||
|
description: >
|
||||||
|
Reference signal magnitude validity
|
||||||
|
* 0 - Magnitude below threshold
|
||||||
|
* 1 - Magnitude above threshold
|
||||||
|
validVarMag:
|
||||||
|
type: integer
|
||||||
|
description: >
|
||||||
|
Variable signal magnitude validity
|
||||||
|
* 0 - Magnitude below threshold
|
||||||
|
* 1 - Magnitude above threshold
|
||||||
morseIdent:
|
morseIdent:
|
||||||
description: current identification morse code transcript
|
description: current identification morse code transcript
|
||||||
type: string
|
type: string
|
||||||
|
@ -19,3 +19,9 @@ VORLocalizerSettings:
|
|||||||
magDecAdjust:
|
magDecAdjust:
|
||||||
description: Adjust radial lines on map for magnetic declination of VOR
|
description: Adjust radial lines on map for magnetic declination of VOR
|
||||||
type: integer
|
type: integer
|
||||||
|
rrTime:
|
||||||
|
description: Round robin turn time in seconds
|
||||||
|
type: integer
|
||||||
|
centerShift:
|
||||||
|
description: Shift of center frequency in Hz
|
||||||
|
type: integer
|
||||||
|
@ -9484,20 +9484,36 @@ margin-bottom: 20px;
|
|||||||
"type" : "number",
|
"type" : "number",
|
||||||
"format" : "float"
|
"format" : "float"
|
||||||
},
|
},
|
||||||
|
"navId" : {
|
||||||
|
"type" : "integer",
|
||||||
|
"description" : "VOR unique identifier when set by VOR localizer feature"
|
||||||
|
},
|
||||||
"radial" : {
|
"radial" : {
|
||||||
"type" : "number",
|
"type" : "number",
|
||||||
"format" : "float",
|
"format" : "float",
|
||||||
"description" : "current detected radial"
|
"description" : "current detected radial (degrees)"
|
||||||
},
|
},
|
||||||
"refMag" : {
|
"refMag" : {
|
||||||
"type" : "number",
|
"type" : "number",
|
||||||
"format" : "float",
|
"format" : "float",
|
||||||
"description" : "current reference signal magnitude"
|
"description" : "current reference signal magnitude (dB)"
|
||||||
},
|
},
|
||||||
"varMag" : {
|
"varMag" : {
|
||||||
"type" : "number",
|
"type" : "number",
|
||||||
"format" : "float",
|
"format" : "float",
|
||||||
"description" : "current variable signal magnitude"
|
"description" : "current variable signal magnitude (dB)"
|
||||||
|
},
|
||||||
|
"validRadial" : {
|
||||||
|
"type" : "integer",
|
||||||
|
"description" : "Radial validity estimation\n * 0 - Radial is invalid\n * 1 - Radial is valid\n"
|
||||||
|
},
|
||||||
|
"validRefMag" : {
|
||||||
|
"type" : "integer",
|
||||||
|
"description" : "Reference signal magnitude validity\n * 0 - Magnitude below threshold\n * 1 - Magnitude above threshold\n"
|
||||||
|
},
|
||||||
|
"validVarMag" : {
|
||||||
|
"type" : "integer",
|
||||||
|
"description" : "Variable signal magnitude validity\n * 0 - Magnitude below threshold\n * 1 - Magnitude above threshold\n"
|
||||||
},
|
},
|
||||||
"morseIdent" : {
|
"morseIdent" : {
|
||||||
"type" : "string",
|
"type" : "string",
|
||||||
@ -9645,6 +9661,14 @@ margin-bottom: 20px;
|
|||||||
"magDecAdjust" : {
|
"magDecAdjust" : {
|
||||||
"type" : "integer",
|
"type" : "integer",
|
||||||
"description" : "Adjust radial lines on map for magnetic declination of VOR"
|
"description" : "Adjust radial lines on map for magnetic declination of VOR"
|
||||||
|
},
|
||||||
|
"rrTime" : {
|
||||||
|
"type" : "integer",
|
||||||
|
"description" : "Round robin turn time in seconds"
|
||||||
|
},
|
||||||
|
"centerShift" : {
|
||||||
|
"type" : "integer",
|
||||||
|
"description" : "Shift of center frequency in Hz"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"description" : "VORLocalizer"
|
"description" : "VORLocalizer"
|
||||||
@ -44850,7 +44874,7 @@ except ApiException as e:
|
|||||||
</div>
|
</div>
|
||||||
<div id="generator">
|
<div id="generator">
|
||||||
<div class="content">
|
<div class="content">
|
||||||
Generated 2020-11-29T21:00:18.945+01:00
|
Generated 2020-12-06T23:43:21.772+01:00
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -36,12 +36,20 @@ SWGVORDemodSCReport::SWGVORDemodSCReport() {
|
|||||||
m_audio_sample_rate_isSet = false;
|
m_audio_sample_rate_isSet = false;
|
||||||
volume = 0.0f;
|
volume = 0.0f;
|
||||||
m_volume_isSet = false;
|
m_volume_isSet = false;
|
||||||
|
nav_id = 0;
|
||||||
|
m_nav_id_isSet = false;
|
||||||
radial = 0.0f;
|
radial = 0.0f;
|
||||||
m_radial_isSet = false;
|
m_radial_isSet = false;
|
||||||
ref_mag = 0.0f;
|
ref_mag = 0.0f;
|
||||||
m_ref_mag_isSet = false;
|
m_ref_mag_isSet = false;
|
||||||
var_mag = 0.0f;
|
var_mag = 0.0f;
|
||||||
m_var_mag_isSet = false;
|
m_var_mag_isSet = false;
|
||||||
|
valid_radial = 0;
|
||||||
|
m_valid_radial_isSet = false;
|
||||||
|
valid_ref_mag = 0;
|
||||||
|
m_valid_ref_mag_isSet = false;
|
||||||
|
valid_var_mag = 0;
|
||||||
|
m_valid_var_mag_isSet = false;
|
||||||
morse_ident = nullptr;
|
morse_ident = nullptr;
|
||||||
m_morse_ident_isSet = false;
|
m_morse_ident_isSet = false;
|
||||||
}
|
}
|
||||||
@ -60,12 +68,20 @@ SWGVORDemodSCReport::init() {
|
|||||||
m_audio_sample_rate_isSet = false;
|
m_audio_sample_rate_isSet = false;
|
||||||
volume = 0.0f;
|
volume = 0.0f;
|
||||||
m_volume_isSet = false;
|
m_volume_isSet = false;
|
||||||
|
nav_id = 0;
|
||||||
|
m_nav_id_isSet = false;
|
||||||
radial = 0.0f;
|
radial = 0.0f;
|
||||||
m_radial_isSet = false;
|
m_radial_isSet = false;
|
||||||
ref_mag = 0.0f;
|
ref_mag = 0.0f;
|
||||||
m_ref_mag_isSet = false;
|
m_ref_mag_isSet = false;
|
||||||
var_mag = 0.0f;
|
var_mag = 0.0f;
|
||||||
m_var_mag_isSet = false;
|
m_var_mag_isSet = false;
|
||||||
|
valid_radial = 0;
|
||||||
|
m_valid_radial_isSet = false;
|
||||||
|
valid_ref_mag = 0;
|
||||||
|
m_valid_ref_mag_isSet = false;
|
||||||
|
valid_var_mag = 0;
|
||||||
|
m_valid_var_mag_isSet = false;
|
||||||
morse_ident = new QString("");
|
morse_ident = new QString("");
|
||||||
m_morse_ident_isSet = false;
|
m_morse_ident_isSet = false;
|
||||||
}
|
}
|
||||||
@ -79,6 +95,10 @@ SWGVORDemodSCReport::cleanup() {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if(morse_ident != nullptr) {
|
if(morse_ident != nullptr) {
|
||||||
delete morse_ident;
|
delete morse_ident;
|
||||||
}
|
}
|
||||||
@ -103,12 +123,20 @@ SWGVORDemodSCReport::fromJsonObject(QJsonObject &pJson) {
|
|||||||
|
|
||||||
::SWGSDRangel::setValue(&volume, pJson["volume"], "float", "");
|
::SWGSDRangel::setValue(&volume, pJson["volume"], "float", "");
|
||||||
|
|
||||||
|
::SWGSDRangel::setValue(&nav_id, pJson["navId"], "qint32", "");
|
||||||
|
|
||||||
::SWGSDRangel::setValue(&radial, pJson["radial"], "float", "");
|
::SWGSDRangel::setValue(&radial, pJson["radial"], "float", "");
|
||||||
|
|
||||||
::SWGSDRangel::setValue(&ref_mag, pJson["refMag"], "float", "");
|
::SWGSDRangel::setValue(&ref_mag, pJson["refMag"], "float", "");
|
||||||
|
|
||||||
::SWGSDRangel::setValue(&var_mag, pJson["varMag"], "float", "");
|
::SWGSDRangel::setValue(&var_mag, pJson["varMag"], "float", "");
|
||||||
|
|
||||||
|
::SWGSDRangel::setValue(&valid_radial, pJson["validRadial"], "qint32", "");
|
||||||
|
|
||||||
|
::SWGSDRangel::setValue(&valid_ref_mag, pJson["validRefMag"], "qint32", "");
|
||||||
|
|
||||||
|
::SWGSDRangel::setValue(&valid_var_mag, pJson["validVarMag"], "qint32", "");
|
||||||
|
|
||||||
::SWGSDRangel::setValue(&morse_ident, pJson["morseIdent"], "QString", "QString");
|
::SWGSDRangel::setValue(&morse_ident, pJson["morseIdent"], "QString", "QString");
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -139,6 +167,9 @@ SWGVORDemodSCReport::asJsonObject() {
|
|||||||
if(m_volume_isSet){
|
if(m_volume_isSet){
|
||||||
obj->insert("volume", QJsonValue(volume));
|
obj->insert("volume", QJsonValue(volume));
|
||||||
}
|
}
|
||||||
|
if(m_nav_id_isSet){
|
||||||
|
obj->insert("navId", QJsonValue(nav_id));
|
||||||
|
}
|
||||||
if(m_radial_isSet){
|
if(m_radial_isSet){
|
||||||
obj->insert("radial", QJsonValue(radial));
|
obj->insert("radial", QJsonValue(radial));
|
||||||
}
|
}
|
||||||
@ -148,6 +179,15 @@ SWGVORDemodSCReport::asJsonObject() {
|
|||||||
if(m_var_mag_isSet){
|
if(m_var_mag_isSet){
|
||||||
obj->insert("varMag", QJsonValue(var_mag));
|
obj->insert("varMag", QJsonValue(var_mag));
|
||||||
}
|
}
|
||||||
|
if(m_valid_radial_isSet){
|
||||||
|
obj->insert("validRadial", QJsonValue(valid_radial));
|
||||||
|
}
|
||||||
|
if(m_valid_ref_mag_isSet){
|
||||||
|
obj->insert("validRefMag", QJsonValue(valid_ref_mag));
|
||||||
|
}
|
||||||
|
if(m_valid_var_mag_isSet){
|
||||||
|
obj->insert("validVarMag", QJsonValue(valid_var_mag));
|
||||||
|
}
|
||||||
if(morse_ident != nullptr && *morse_ident != QString("")){
|
if(morse_ident != nullptr && *morse_ident != QString("")){
|
||||||
toJsonValue(QString("morseIdent"), morse_ident, obj, QString("QString"));
|
toJsonValue(QString("morseIdent"), morse_ident, obj, QString("QString"));
|
||||||
}
|
}
|
||||||
@ -195,6 +235,16 @@ SWGVORDemodSCReport::setVolume(float volume) {
|
|||||||
this->m_volume_isSet = true;
|
this->m_volume_isSet = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
qint32
|
||||||
|
SWGVORDemodSCReport::getNavId() {
|
||||||
|
return nav_id;
|
||||||
|
}
|
||||||
|
void
|
||||||
|
SWGVORDemodSCReport::setNavId(qint32 nav_id) {
|
||||||
|
this->nav_id = nav_id;
|
||||||
|
this->m_nav_id_isSet = true;
|
||||||
|
}
|
||||||
|
|
||||||
float
|
float
|
||||||
SWGVORDemodSCReport::getRadial() {
|
SWGVORDemodSCReport::getRadial() {
|
||||||
return radial;
|
return radial;
|
||||||
@ -225,6 +275,36 @@ SWGVORDemodSCReport::setVarMag(float var_mag) {
|
|||||||
this->m_var_mag_isSet = true;
|
this->m_var_mag_isSet = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
qint32
|
||||||
|
SWGVORDemodSCReport::getValidRadial() {
|
||||||
|
return valid_radial;
|
||||||
|
}
|
||||||
|
void
|
||||||
|
SWGVORDemodSCReport::setValidRadial(qint32 valid_radial) {
|
||||||
|
this->valid_radial = valid_radial;
|
||||||
|
this->m_valid_radial_isSet = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
qint32
|
||||||
|
SWGVORDemodSCReport::getValidRefMag() {
|
||||||
|
return valid_ref_mag;
|
||||||
|
}
|
||||||
|
void
|
||||||
|
SWGVORDemodSCReport::setValidRefMag(qint32 valid_ref_mag) {
|
||||||
|
this->valid_ref_mag = valid_ref_mag;
|
||||||
|
this->m_valid_ref_mag_isSet = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
qint32
|
||||||
|
SWGVORDemodSCReport::getValidVarMag() {
|
||||||
|
return valid_var_mag;
|
||||||
|
}
|
||||||
|
void
|
||||||
|
SWGVORDemodSCReport::setValidVarMag(qint32 valid_var_mag) {
|
||||||
|
this->valid_var_mag = valid_var_mag;
|
||||||
|
this->m_valid_var_mag_isSet = true;
|
||||||
|
}
|
||||||
|
|
||||||
QString*
|
QString*
|
||||||
SWGVORDemodSCReport::getMorseIdent() {
|
SWGVORDemodSCReport::getMorseIdent() {
|
||||||
return morse_ident;
|
return morse_ident;
|
||||||
@ -252,6 +332,9 @@ SWGVORDemodSCReport::isSet(){
|
|||||||
if(m_volume_isSet){
|
if(m_volume_isSet){
|
||||||
isObjectUpdated = true; break;
|
isObjectUpdated = true; break;
|
||||||
}
|
}
|
||||||
|
if(m_nav_id_isSet){
|
||||||
|
isObjectUpdated = true; break;
|
||||||
|
}
|
||||||
if(m_radial_isSet){
|
if(m_radial_isSet){
|
||||||
isObjectUpdated = true; break;
|
isObjectUpdated = true; break;
|
||||||
}
|
}
|
||||||
@ -261,6 +344,15 @@ SWGVORDemodSCReport::isSet(){
|
|||||||
if(m_var_mag_isSet){
|
if(m_var_mag_isSet){
|
||||||
isObjectUpdated = true; break;
|
isObjectUpdated = true; break;
|
||||||
}
|
}
|
||||||
|
if(m_valid_radial_isSet){
|
||||||
|
isObjectUpdated = true; break;
|
||||||
|
}
|
||||||
|
if(m_valid_ref_mag_isSet){
|
||||||
|
isObjectUpdated = true; break;
|
||||||
|
}
|
||||||
|
if(m_valid_var_mag_isSet){
|
||||||
|
isObjectUpdated = true; break;
|
||||||
|
}
|
||||||
if(morse_ident && *morse_ident != QString("")){
|
if(morse_ident && *morse_ident != QString("")){
|
||||||
isObjectUpdated = true; break;
|
isObjectUpdated = true; break;
|
||||||
}
|
}
|
||||||
|
@ -54,6 +54,9 @@ public:
|
|||||||
float getVolume();
|
float getVolume();
|
||||||
void setVolume(float volume);
|
void setVolume(float volume);
|
||||||
|
|
||||||
|
qint32 getNavId();
|
||||||
|
void setNavId(qint32 nav_id);
|
||||||
|
|
||||||
float getRadial();
|
float getRadial();
|
||||||
void setRadial(float radial);
|
void setRadial(float radial);
|
||||||
|
|
||||||
@ -63,6 +66,15 @@ public:
|
|||||||
float getVarMag();
|
float getVarMag();
|
||||||
void setVarMag(float var_mag);
|
void setVarMag(float var_mag);
|
||||||
|
|
||||||
|
qint32 getValidRadial();
|
||||||
|
void setValidRadial(qint32 valid_radial);
|
||||||
|
|
||||||
|
qint32 getValidRefMag();
|
||||||
|
void setValidRefMag(qint32 valid_ref_mag);
|
||||||
|
|
||||||
|
qint32 getValidVarMag();
|
||||||
|
void setValidVarMag(qint32 valid_var_mag);
|
||||||
|
|
||||||
QString* getMorseIdent();
|
QString* getMorseIdent();
|
||||||
void setMorseIdent(QString* morse_ident);
|
void setMorseIdent(QString* morse_ident);
|
||||||
|
|
||||||
@ -82,6 +94,9 @@ private:
|
|||||||
float volume;
|
float volume;
|
||||||
bool m_volume_isSet;
|
bool m_volume_isSet;
|
||||||
|
|
||||||
|
qint32 nav_id;
|
||||||
|
bool m_nav_id_isSet;
|
||||||
|
|
||||||
float radial;
|
float radial;
|
||||||
bool m_radial_isSet;
|
bool m_radial_isSet;
|
||||||
|
|
||||||
@ -91,6 +106,15 @@ private:
|
|||||||
float var_mag;
|
float var_mag;
|
||||||
bool m_var_mag_isSet;
|
bool m_var_mag_isSet;
|
||||||
|
|
||||||
|
qint32 valid_radial;
|
||||||
|
bool m_valid_radial_isSet;
|
||||||
|
|
||||||
|
qint32 valid_ref_mag;
|
||||||
|
bool m_valid_ref_mag_isSet;
|
||||||
|
|
||||||
|
qint32 valid_var_mag;
|
||||||
|
bool m_valid_var_mag_isSet;
|
||||||
|
|
||||||
QString* morse_ident;
|
QString* morse_ident;
|
||||||
bool m_morse_ident_isSet;
|
bool m_morse_ident_isSet;
|
||||||
|
|
||||||
|
@ -44,6 +44,10 @@ SWGVORLocalizerSettings::SWGVORLocalizerSettings() {
|
|||||||
m_reverse_api_feature_index_isSet = false;
|
m_reverse_api_feature_index_isSet = false;
|
||||||
mag_dec_adjust = 0;
|
mag_dec_adjust = 0;
|
||||||
m_mag_dec_adjust_isSet = false;
|
m_mag_dec_adjust_isSet = false;
|
||||||
|
rr_time = 0;
|
||||||
|
m_rr_time_isSet = false;
|
||||||
|
center_shift = 0;
|
||||||
|
m_center_shift_isSet = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
SWGVORLocalizerSettings::~SWGVORLocalizerSettings() {
|
SWGVORLocalizerSettings::~SWGVORLocalizerSettings() {
|
||||||
@ -68,6 +72,10 @@ SWGVORLocalizerSettings::init() {
|
|||||||
m_reverse_api_feature_index_isSet = false;
|
m_reverse_api_feature_index_isSet = false;
|
||||||
mag_dec_adjust = 0;
|
mag_dec_adjust = 0;
|
||||||
m_mag_dec_adjust_isSet = false;
|
m_mag_dec_adjust_isSet = false;
|
||||||
|
rr_time = 0;
|
||||||
|
m_rr_time_isSet = false;
|
||||||
|
center_shift = 0;
|
||||||
|
m_center_shift_isSet = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -84,6 +92,8 @@ SWGVORLocalizerSettings::cleanup() {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SWGVORLocalizerSettings*
|
SWGVORLocalizerSettings*
|
||||||
@ -113,6 +123,10 @@ SWGVORLocalizerSettings::fromJsonObject(QJsonObject &pJson) {
|
|||||||
|
|
||||||
::SWGSDRangel::setValue(&mag_dec_adjust, pJson["magDecAdjust"], "qint32", "");
|
::SWGSDRangel::setValue(&mag_dec_adjust, pJson["magDecAdjust"], "qint32", "");
|
||||||
|
|
||||||
|
::SWGSDRangel::setValue(&rr_time, pJson["rrTime"], "qint32", "");
|
||||||
|
|
||||||
|
::SWGSDRangel::setValue(¢er_shift, pJson["centerShift"], "qint32", "");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QString
|
QString
|
||||||
@ -153,6 +167,12 @@ SWGVORLocalizerSettings::asJsonObject() {
|
|||||||
if(m_mag_dec_adjust_isSet){
|
if(m_mag_dec_adjust_isSet){
|
||||||
obj->insert("magDecAdjust", QJsonValue(mag_dec_adjust));
|
obj->insert("magDecAdjust", QJsonValue(mag_dec_adjust));
|
||||||
}
|
}
|
||||||
|
if(m_rr_time_isSet){
|
||||||
|
obj->insert("rrTime", QJsonValue(rr_time));
|
||||||
|
}
|
||||||
|
if(m_center_shift_isSet){
|
||||||
|
obj->insert("centerShift", QJsonValue(center_shift));
|
||||||
|
}
|
||||||
|
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
@ -237,6 +257,26 @@ SWGVORLocalizerSettings::setMagDecAdjust(qint32 mag_dec_adjust) {
|
|||||||
this->m_mag_dec_adjust_isSet = true;
|
this->m_mag_dec_adjust_isSet = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
qint32
|
||||||
|
SWGVORLocalizerSettings::getRrTime() {
|
||||||
|
return rr_time;
|
||||||
|
}
|
||||||
|
void
|
||||||
|
SWGVORLocalizerSettings::setRrTime(qint32 rr_time) {
|
||||||
|
this->rr_time = rr_time;
|
||||||
|
this->m_rr_time_isSet = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
qint32
|
||||||
|
SWGVORLocalizerSettings::getCenterShift() {
|
||||||
|
return center_shift;
|
||||||
|
}
|
||||||
|
void
|
||||||
|
SWGVORLocalizerSettings::setCenterShift(qint32 center_shift) {
|
||||||
|
this->center_shift = center_shift;
|
||||||
|
this->m_center_shift_isSet = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
SWGVORLocalizerSettings::isSet(){
|
SWGVORLocalizerSettings::isSet(){
|
||||||
@ -266,6 +306,12 @@ SWGVORLocalizerSettings::isSet(){
|
|||||||
if(m_mag_dec_adjust_isSet){
|
if(m_mag_dec_adjust_isSet){
|
||||||
isObjectUpdated = true; break;
|
isObjectUpdated = true; break;
|
||||||
}
|
}
|
||||||
|
if(m_rr_time_isSet){
|
||||||
|
isObjectUpdated = true; break;
|
||||||
|
}
|
||||||
|
if(m_center_shift_isSet){
|
||||||
|
isObjectUpdated = true; break;
|
||||||
|
}
|
||||||
}while(false);
|
}while(false);
|
||||||
return isObjectUpdated;
|
return isObjectUpdated;
|
||||||
}
|
}
|
||||||
|
@ -66,6 +66,12 @@ public:
|
|||||||
qint32 getMagDecAdjust();
|
qint32 getMagDecAdjust();
|
||||||
void setMagDecAdjust(qint32 mag_dec_adjust);
|
void setMagDecAdjust(qint32 mag_dec_adjust);
|
||||||
|
|
||||||
|
qint32 getRrTime();
|
||||||
|
void setRrTime(qint32 rr_time);
|
||||||
|
|
||||||
|
qint32 getCenterShift();
|
||||||
|
void setCenterShift(qint32 center_shift);
|
||||||
|
|
||||||
|
|
||||||
virtual bool isSet() override;
|
virtual bool isSet() override;
|
||||||
|
|
||||||
@ -94,6 +100,12 @@ private:
|
|||||||
qint32 mag_dec_adjust;
|
qint32 mag_dec_adjust;
|
||||||
bool m_mag_dec_adjust_isSet;
|
bool m_mag_dec_adjust_isSet;
|
||||||
|
|
||||||
|
qint32 rr_time;
|
||||||
|
bool m_rr_time_isSet;
|
||||||
|
|
||||||
|
qint32 center_shift;
|
||||||
|
bool m_center_shift_isSet;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user