| 
									
										
										
										
											2020-11-30 01:30:18 +01:00
										 |  |  | ///////////////////////////////////////////////////////////////////////////////////
 | 
					
						
							|  |  |  | // Copyright (C) 2020 Edouard Griffiths, F4EXB                                   //
 | 
					
						
							|  |  |  | //                                                                               //
 | 
					
						
							|  |  |  | // This program is free software; you can redistribute it and/or modify          //
 | 
					
						
							|  |  |  | // it under the terms of the GNU General Public License as published by          //
 | 
					
						
							|  |  |  | // the Free Software Foundation as version 3 of the License, or                  //
 | 
					
						
							|  |  |  | // (at your option) any later version.                                           //
 | 
					
						
							|  |  |  | //                                                                               //
 | 
					
						
							|  |  |  | // This program is distributed in the hope that it will be useful,               //
 | 
					
						
							|  |  |  | // but WITHOUT ANY WARRANTY; without even the implied warranty of                //
 | 
					
						
							|  |  |  | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the                  //
 | 
					
						
							|  |  |  | // GNU General Public License V3 for more details.                               //
 | 
					
						
							|  |  |  | //                                                                               //
 | 
					
						
							|  |  |  | // You should have received a copy of the GNU General Public License             //
 | 
					
						
							|  |  |  | // along with this program. If not, see <http://www.gnu.org/licenses/>.          //
 | 
					
						
							|  |  |  | ///////////////////////////////////////////////////////////////////////////////////
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <QDebug>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "SWGDeviceState.h"
 | 
					
						
							| 
									
										
										
										
											2020-12-07 19:32:43 +01:00
										 |  |  | #include "SWGDeviceSettings.h"
 | 
					
						
							|  |  |  | #include "SWGChannelSettings.h"
 | 
					
						
							| 
									
										
										
										
											2020-11-30 01:30:18 +01:00
										 |  |  | #include "SWGSuccessResponse.h"
 | 
					
						
							|  |  |  | #include "SWGErrorResponse.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "device/deviceset.h"
 | 
					
						
							|  |  |  | #include "channel/channelapi.h"
 | 
					
						
							| 
									
										
										
										
											2020-12-07 19:32:43 +01:00
										 |  |  | #include "webapi/webapiadapterinterface.h"
 | 
					
						
							|  |  |  | #include "webapi/webapiutils.h"
 | 
					
						
							| 
									
										
										
										
											2020-11-30 01:30:18 +01:00
										 |  |  | #include "maincore.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "vorlocalizerreport.h"
 | 
					
						
							|  |  |  | #include "vorlocalizerworker.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | MESSAGE_CLASS_DEFINITION(VorLocalizerWorker::MsgConfigureVORLocalizerWorker, Message) | 
					
						
							|  |  |  | MESSAGE_CLASS_DEFINITION(VorLocalizerWorker::MsgRefreshChannels, Message) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class DSPDeviceSourceEngine; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | VorLocalizerWorker::VorLocalizerWorker(WebAPIAdapterInterface *webAPIAdapterInterface) : | 
					
						
							|  |  |  |     m_webAPIAdapterInterface(webAPIAdapterInterface), | 
					
						
							| 
									
										
										
										
											2020-12-07 19:32:43 +01:00
										 |  |  |     m_msgQueueToFeature(nullptr), | 
					
						
							|  |  |  |     m_availableChannels(nullptr), | 
					
						
							| 
									
										
										
										
											2020-11-30 01:30:18 +01:00
										 |  |  |     m_running(false), | 
					
						
							|  |  |  |     m_mutex(QMutex::Recursive) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     qDebug("VorLocalizerWorker::VorLocalizerWorker"); | 
					
						
							|  |  |  | 	connect(&m_updateTimer, SIGNAL(timeout()), this, SLOT(updateHardware())); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | VorLocalizerWorker::~VorLocalizerWorker() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     m_inputMessageQueue.clear(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void VorLocalizerWorker::reset() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QMutexLocker mutexLocker(&m_mutex); | 
					
						
							|  |  |  |     m_inputMessageQueue.clear(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool VorLocalizerWorker::startWork() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QMutexLocker mutexLocker(&m_mutex); | 
					
						
							|  |  |  |     connect(&m_inputMessageQueue, SIGNAL(messageEnqueued()), this, SLOT(handleInputMessages())); | 
					
						
							| 
									
										
										
										
											2020-12-07 19:32:43 +01:00
										 |  |  |     connect(&m_rrTimer, SIGNAL(timeout()), this, SLOT(rrNextTurn())); | 
					
						
							|  |  |  |     m_rrTimer.start(m_settings.m_rrTime * 1000); | 
					
						
							| 
									
										
										
										
											2020-11-30 01:30:18 +01:00
										 |  |  |     m_running = true; | 
					
						
							|  |  |  |     return m_running; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void VorLocalizerWorker::stopWork() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QMutexLocker mutexLocker(&m_mutex); | 
					
						
							| 
									
										
										
										
											2020-12-07 19:32:43 +01:00
										 |  |  |     m_rrTimer.stop(); | 
					
						
							|  |  |  |     disconnect(&m_rrTimer, SIGNAL(timeout()), this, SLOT(rrNextTurn())); | 
					
						
							| 
									
										
										
										
											2020-11-30 01:30:18 +01:00
										 |  |  |     disconnect(&m_inputMessageQueue, SIGNAL(messageEnqueued()), this, SLOT(handleInputMessages())); | 
					
						
							|  |  |  |     m_running = false; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void VorLocalizerWorker::handleInputMessages() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	Message* message; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	while ((message = m_inputMessageQueue.pop()) != nullptr) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		if (handleMessage(*message)) { | 
					
						
							|  |  |  | 			delete message; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool VorLocalizerWorker::handleMessage(const Message& cmd) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (MsgConfigureVORLocalizerWorker::match(cmd)) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         QMutexLocker mutexLocker(&m_mutex); | 
					
						
							|  |  |  |         MsgConfigureVORLocalizerWorker& cfg = (MsgConfigureVORLocalizerWorker&) cmd; | 
					
						
							|  |  |  |         qDebug() << "VorLocalizerWorker::handleMessage: MsgConfigureVORLocalizerWorker"; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         applySettings(cfg.getSettings(), cfg.getForce()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return true; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else if (MsgRefreshChannels::match(cmd)) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         qDebug() << "VorLocalizerWorker::handleMessage: MsgRefreshChannels"; | 
					
						
							|  |  |  |         updateChannels(); | 
					
						
							| 
									
										
										
										
											2020-12-07 19:32:43 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-30 01:30:18 +01:00
										 |  |  |         return true; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void VorLocalizerWorker::applySettings(const VORLocalizerSettings& settings, bool force) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     qDebug() << "VorLocalizerWorker::applySettings:" | 
					
						
							|  |  |  |             << " m_title: " << settings.m_title | 
					
						
							|  |  |  |             << " m_rgbColor: " << settings.m_rgbColor | 
					
						
							|  |  |  |             << " force: " << force; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Remove sub-channels no longer needed
 | 
					
						
							|  |  |  |     for (int i = 0; i < m_vorChannels.size(); i++) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         if (!settings.m_subChannelSettings.contains(m_vorChannels[i].m_subChannelId)) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             qDebug() << "VorLocalizerWorker::applySettings: Removing sink " << m_vorChannels[i].m_subChannelId; | 
					
						
							|  |  |  |             removeVORChannel(m_vorChannels[i].m_subChannelId); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Add new sub channels
 | 
					
						
							| 
									
										
										
										
											2020-12-07 19:32:43 +01:00
										 |  |  |     QHash<int, VORLocalizerSubChannelSettings>::const_iterator itr = settings.m_subChannelSettings.begin(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-30 01:30:18 +01:00
										 |  |  |     while (itr != settings.m_subChannelSettings.end()) | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2020-12-07 19:32:43 +01:00
										 |  |  |         const VORLocalizerSubChannelSettings& subChannelSettings = itr.value(); | 
					
						
							|  |  |  |         qDebug() << "VorLocalizerWorker::applySettings: subchannel " << subChannelSettings.m_id; | 
					
						
							| 
									
										
										
										
											2020-11-30 01:30:18 +01:00
										 |  |  |         int j = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         for (; j < m_vorChannels.size(); j++) | 
					
						
							|  |  |  |         { | 
					
						
							| 
									
										
										
										
											2020-12-07 19:32:43 +01:00
										 |  |  |             if (subChannelSettings.m_id == m_vorChannels[j].m_subChannelId) | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 qDebug() << "VorLocalizerWorker::applySettings: subchannel " | 
					
						
							|  |  |  |                     << subChannelSettings.m_id | 
					
						
							|  |  |  |                     << "already present"; | 
					
						
							| 
									
										
										
										
											2020-11-30 01:30:18 +01:00
										 |  |  |                 break; | 
					
						
							| 
									
										
										
										
											2020-12-07 19:32:43 +01:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2020-11-30 01:30:18 +01:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (j == m_vorChannels.size()) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             // Add a sub-channel sink
 | 
					
						
							| 
									
										
										
										
											2020-12-07 19:32:43 +01:00
										 |  |  |             qDebug() << "VorLocalizerWorker::applySettings: Adding subchannel " << subChannelSettings.m_id; | 
					
						
							| 
									
										
										
										
											2020-11-30 01:30:18 +01:00
										 |  |  |             addVORChannel(subChannelSettings); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         ++itr; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-07 19:32:43 +01:00
										 |  |  |     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); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-30 01:30:18 +01:00
										 |  |  |     m_settings = settings; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void VorLocalizerWorker::updateHardware() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     SWGSDRangel::SWGSuccessResponse response; | 
					
						
							|  |  |  |     SWGSDRangel::SWGErrorResponse error; | 
					
						
							|  |  |  |     m_updateTimer.stop(); | 
					
						
							|  |  |  |     m_mutex.unlock(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void VorLocalizerWorker::removeVORChannel(int navId) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2020-12-07 19:32:43 +01:00
										 |  |  |     qDebug("VorLocalizerWorker::removeVORChannel: %d", navId); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-30 01:30:18 +01:00
										 |  |  |     for (int i = 0; i < m_vorChannels.size(); i++) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         if (m_vorChannels[i].m_subChannelId == navId) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             m_vorChannels.removeAt(i); | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2020-12-07 19:32:43 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     updateChannels(); | 
					
						
							| 
									
										
										
										
											2020-11-30 01:30:18 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-07 19:32:43 +01:00
										 |  |  | void VorLocalizerWorker::addVORChannel(const VORLocalizerSubChannelSettings& subChannelSettings) | 
					
						
							| 
									
										
										
										
											2020-11-30 01:30:18 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2020-12-07 19:32:43 +01:00
										 |  |  |     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 | 
					
						
							|  |  |  |         }; | 
					
						
							| 
									
										
										
										
											2020-11-30 01:30:18 +01:00
										 |  |  |     m_vorChannels.push_back(vorChannel); | 
					
						
							| 
									
										
										
										
											2020-12-07 19:32:43 +01:00
										 |  |  |     updateChannels(); | 
					
						
							| 
									
										
										
										
											2020-11-30 01:30:18 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void VorLocalizerWorker::updateChannels() | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2020-12-07 19:32:43 +01:00
										 |  |  |     qDebug() << "VorLocalizerWorker::updateChannels: " | 
					
						
							|  |  |  |         << "#VORs:" << m_vorChannels.size() | 
					
						
							|  |  |  |         << "#Chans:" << m_availableChannels->size(); | 
					
						
							| 
									
										
										
										
											2020-11-30 01:30:18 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-07 19:32:43 +01:00
										 |  |  |     if ((m_vorChannels.size() == 0) || (m_availableChannels->size() == 0)) { | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2020-11-30 01:30:18 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-07 19:32:43 +01:00
										 |  |  |     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) | 
					
						
							| 
									
										
										
										
											2020-11-30 01:30:18 +01:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2020-12-07 19:32:43 +01:00
										 |  |  |         unsigned int nbChannels = unallocatedVORs.size() < (int) deviceChannel.m_channels.size() ? | 
					
						
							|  |  |  |             unallocatedVORs.size() : | 
					
						
							|  |  |  |             deviceChannel.m_channels.size(); | 
					
						
							|  |  |  |         std::vector<VORRange> vorRanges; | 
					
						
							| 
									
										
										
										
											2020-11-30 01:30:18 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-07 19:32:43 +01:00
										 |  |  |         while (nbChannels != 0) | 
					
						
							| 
									
										
										
										
											2020-11-30 01:30:18 +01:00
										 |  |  |         { | 
					
						
							| 
									
										
										
										
											2020-12-07 19:32:43 +01:00
										 |  |  |             getVORRanges(unallocatedVORs, nbChannels, vorRanges); | 
					
						
							|  |  |  |             filterVORRanges(vorRanges, deviceChannel.m_bandwidth); | 
					
						
							| 
									
										
										
										
											2020-11-30 01:30:18 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-07 19:32:43 +01:00
										 |  |  |             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()) | 
					
						
							| 
									
										
										
										
											2020-11-30 01:30:18 +01:00
										 |  |  |                 { | 
					
						
							| 
									
										
										
										
											2020-12-07 19:32:43 +01:00
										 |  |  |                     if (it->m_subChannelId == vorChannel.m_subChannelId) { | 
					
						
							|  |  |  |                         it = unallocatedVORs.erase(it); | 
					
						
							|  |  |  |                     } else { | 
					
						
							|  |  |  |                         ++it; | 
					
						
							|  |  |  |                     } | 
					
						
							| 
									
										
										
										
											2020-11-30 01:30:18 +01:00
										 |  |  |                 } | 
					
						
							| 
									
										
										
										
											2020-12-07 19:32:43 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |                 iCh++; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             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])); | 
					
						
							| 
									
										
										
										
											2020-11-30 01:30:18 +01:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2020-12-07 19:32:43 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |             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); | 
					
						
							| 
									
										
										
										
											2020-11-30 01:30:18 +01:00
										 |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-07 19:32:43 +01:00
										 |  |  |     for (auto rrPlans : m_rrPlans) | 
					
						
							| 
									
										
										
										
											2020-11-30 01:30:18 +01:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2020-12-07 19:32:43 +01:00
										 |  |  |         qDebug() << "VorLocalizerWorker::updateChannels: RR plans for one device"; | 
					
						
							| 
									
										
										
										
											2020-11-30 01:30:18 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-07 19:32:43 +01:00
										 |  |  |         for (auto rrPlan : rrPlans) | 
					
						
							| 
									
										
										
										
											2020-11-30 01:30:18 +01:00
										 |  |  |         { | 
					
						
							| 
									
										
										
										
											2020-12-07 19:32:43 +01:00
										 |  |  |             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; | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2020-11-30 01:30:18 +01:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2020-12-07 19:32:43 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     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++; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2020-11-30 01:30:18 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-07 19:32:43 +01:00
										 |  |  |     if (m_msgQueueToFeature) { | 
					
						
							|  |  |  |         m_msgQueueToFeature->push(msg); | 
					
						
							| 
									
										
										
										
											2020-11-30 01:30:18 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | } |