swift
Loading...
Searching...
No Matches
comsystem.cpp
1// SPDX-FileCopyrightText: Copyright (C) 2013 swift Project Community / Contributors
2// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-swift-pilot-client-1
3
5
6#include <QDBusMetaType>
7#include <QtGlobal>
8
10#include "misc/pq/literals.h"
11#include "misc/stringutils.h"
12
13using namespace swift::misc::physical_quantities;
14using namespace swift::misc::math;
15
16namespace swift::misc::aviation
17{
19 {
21 qDBusRegisterMetaType<ChannelSpacing>();
22 qDBusRegisterMetaType<ComUnit>();
23 }
24
25 void CComSystem::setFrequencyActiveMHz(double frequencyMHz)
26 {
27 const CFrequency f(frequencyMHz, CFrequencyUnit::MHz());
28 this->setFrequencyActive(f);
29 }
30
31 void CComSystem::setFrequencyStandbyMHz(double frequencyMHz)
32 {
33 const CFrequency f(frequencyMHz, CFrequencyUnit::MHz());
34 this->setFrequencyStandby(f);
35 }
36
38 {
39 if (frequency == this->getFrequencyActive())
40 {
41 return;
42 } // save all the comparisons / rounding
43 CFrequency fRounded(frequency);
44 roundToChannelSpacing(fRounded, m_channelSpacing);
45 this->CModulator::setFrequencyActive(fRounded);
46 }
47
49 {
50 if (frequency == this->getFrequencyStandby())
51 {
52 return;
53 } // save all the comparisons / rounding
54 CFrequency fRounded(frequency);
55 roundToChannelSpacing(fRounded, m_channelSpacing);
56 this->CModulator::setFrequencyStandby(fRounded);
57 }
58
60 {
61 return isSameFrequency(this->getFrequencyActive(), comFrequency);
62 }
63
69
70 CComSystem CComSystem::getCom1System(double activeFrequencyMHz, double standbyFrequencyMHz)
71 {
72 return { CModulator::NameCom1(),
74 physical_quantities::CFrequency(standbyFrequencyMHz < 0 ? activeFrequencyMHz : standbyFrequencyMHz,
76 }
77
78 CComSystem CComSystem::getCom1System(const CFrequency &activeFrequency, const CFrequency &standbyFrequency)
79 {
80 return { CModulator::NameCom1(), activeFrequency,
81 standbyFrequency.isNull() ? activeFrequency : standbyFrequency };
82 }
83
84 CComSystem CComSystem::getCom2System(double activeFrequencyMHz, double standbyFrequencyMHz)
85 {
86 return { CModulator::NameCom2(),
88 physical_quantities::CFrequency(standbyFrequencyMHz < 0 ? activeFrequencyMHz : standbyFrequencyMHz,
90 }
91
92 CComSystem CComSystem::getCom2System(const CFrequency &activeFrequency, const CFrequency &standbyFrequency)
93 {
94 return { CModulator::NameCom2(), activeFrequency,
95 standbyFrequency.isNull() ? activeFrequency : standbyFrequency };
96 }
97
99 {
100 if (f.isNull()) return false;
101
102 // comparsion in int avoids double compare issues
104 return fr >= 118000 && fr <= 136990;
105 }
106
108 {
109 if (f.isNull()) return false;
111 return fr >= 220000 && fr <= 399950;
112 }
113
115 {
116 if (f.isNull())
117 {
118 return false;
119 }
121 }
122
124 {
125 const int lastDigits = static_cast<int>(fKHz) % 100;
126 return fKHz % 5 == 0 && lastDigits != 20 && lastDigits != 45 && lastDigits != 70 && lastDigits != 95;
127 }
128
130 {
131 if (!isValid8_33kHzChannel(fKHz))
132 {
133 const int diff = static_cast<int>(fKHz) % 5;
134 int lower = fKHz - diff;
135 if (!isValid8_33kHzChannel(lower))
136 {
137 lower -= 5;
138 }
139 Q_ASSERT_X(isValid8_33kHzChannel(lower), Q_FUNC_INFO, "Lower frequency not valid");
140
141 int upper = fKHz + (5 - diff);
142 if (!isValid8_33kHzChannel(upper))
143 {
144 upper += 5;
145 }
146 Q_ASSERT_X(isValid8_33kHzChannel(upper), Q_FUNC_INFO, "Upper frequency not valid");
147
148 const int lowerDiff = abs(fKHz - lower);
149 const int upperDiff = abs(fKHz - upper);
150
151 fKHz = lowerDiff < upperDiff ? lower : upper;
152 fKHz = std::clamp(fKHz, 118000, 136990);
153 }
154 return fKHz;
155 }
156
158 {
159 if (frequency.isNull())
160 {
161 return;
162 }
163 const double channelSpacingKHz = CComSystem::channelSpacingToFrequencyKHz(channelSpacing);
164 const double fKHz = frequency.valueRounded(CFrequencyUnit::kHz(), 0);
165
166 if (channelSpacing == ChannelSpacing8_33KHz)
167 {
168 const int freqKHz = round8_33kHzChannel(fKHz);
169 frequency.switchUnit(CFrequencyUnit::kHz());
170 frequency.setCurrentUnitValue(freqKHz);
171 }
172 else
173 {
174 const int dDown = static_cast<int>(fKHz / channelSpacingKHz);
175 const double fDownKHz = dDown * channelSpacingKHz;
176 const double fUpKHz = (dDown + 1) * channelSpacingKHz;
177 const bool down = qAbs(fKHz - fDownKHz) < qAbs(fUpKHz - fKHz); // which is the closest value
178 const double fMHz(CMathUtils::round((down ? fDownKHz : fUpKHz) / 1000.0, 3));
179 frequency.switchUnit(CFrequencyUnit::MHz());
180 frequency.setCurrentUnitValue(fMHz);
181 }
182 }
183
185 {
186 const int freqKHz = freq.value(CFrequencyUnit::kHz());
187 if (freqKHz < 118000 || freqKHz >= 137000 || !isValid8_33kHzChannel(freqKHz))
188 {
189 return false;
190 }
191 return !isWithin25kHzChannel(freq);
192 }
193
195 {
196 const int end = static_cast<int>(freq.value(CFrequencyUnit::kHz())) % 100;
197 return end == 0 || end == 25 || end == 50 || end == 75;
198 }
199
200 bool CComSystem::isSameFrequency(const CFrequency &freq1, const CFrequency &freq2)
201 {
202 using namespace swift::misc::physical_quantities::Literals;
203 if (freq1.isNull() || freq2.isNull())
204 {
205 return false;
206 }
207
208 // Normalize .x20 => .x25 and .70 => .x75
209 auto normalize = [](CFrequency freq) {
210 const int freq_end = static_cast<int>(freq.value(CFrequencyUnit::kHz())) % 100;
211 if (freq_end == 20 || freq_end == 70)
212 {
213 freq += 5_kHz;
214 }
215 return freq;
216 };
217
218 CFrequency normalized_freq1 = normalize(freq1);
219 CFrequency normalized_freq2 = normalize(freq2);
220
221 if (normalized_freq1 == normalized_freq2)
222 {
223 return true;
224 } // shortcut for many of such comparisons
225
226 // Avoid precision errors in Hz range
227 return normalized_freq1.valueInteger(CFrequencyUnit::kHz()) ==
228 normalized_freq2.valueInteger(CFrequencyUnit::kHz());
229 }
230
232 {
233 if (input.isEmpty())
234 {
235 return CFrequency::null();
236 }
237 CFrequency comFreq;
238 if (isDigitsOnlyString(input))
239 {
240 const double f = input.toDouble();
241 comFreq = CFrequency(f, f > 999 ? CFrequencyUnit::kHz() : CFrequencyUnit::MHz());
242 }
243 else
244 {
245 comFreq.parseFromString(input, sep);
246 if (comFreq.isNull())
247 {
248 bool ok {};
249 const double f = CPqString::parseNumber(input, ok, sep);
250 if (ok)
251 {
252 comFreq = CFrequency(f, f > 999 ? CFrequencyUnit::kHz() : CFrequencyUnit::MHz());
253 }
254 else
255 {
256 comFreq = CFrequency::null();
257 }
258 }
259 }
260
261 if (comFreq.isNull())
262 {
263 return CFrequency::null();
264 }
266 return isValidComFrequency(comFreq) ? comFreq : CFrequency::null();
267 }
268
269 double CComSystem::channelSpacingToFrequencyKHz(ChannelSpacing channelSpacing)
270 {
271 switch (channelSpacing)
272 {
273 case ChannelSpacing50KHz: return 50.0;
274 case ChannelSpacing25KHz: return 25.0;
275 case ChannelSpacing8_33KHz: return 25.0 / 3.0;
276 default: qFatal("Wrong channel spacing"); return 0.0; // return just supressing compiler warning
277 }
278 }
279} // namespace swift::misc::aviation
static CFrequencyUnit MHz()
Megahertz.
Definition units.h:380
static CFrequencyUnit kHz()
Kilohertz.
Definition units.h:371
static bool isValid8_33kHzChannel(int fKHz)
Is passed frequency in kHz a valid 8.33 channel. This does not check if the frequency is within the c...
static void roundToChannelSpacing(physical_quantities::CFrequency &frequency, ChannelSpacing channelSpacing)
Round to channel spacing, set MHz as unit.
static CComSystem getCom1System(double activeFrequencyMHz, double standbyFrequencyMHz=-1)
COM1 unit.
Definition comsystem.cpp:70
void setFrequencyActiveMHz(double frequencyMHz)
Set active frequency.
Definition comsystem.cpp:25
static bool isWithin25kHzChannel(const physical_quantities::CFrequency &freq)
Is frequency within 25 kHz frequency spacing.
void setActiveUnicom()
Set UNICOM frequency as active.
Definition comsystem.cpp:64
static bool isSameFrequency(const physical_quantities::CFrequency &freq1, const physical_quantities::CFrequency &freq2)
Compare frequencies under consideration that on VATSIM frequencies .x20/.x25 and ....
void setFrequencyStandby(const physical_quantities::CFrequency &frequency)
Set active frequency.
Definition comsystem.cpp:48
void setFrequencyStandbyMHz(double frequencyMHz)
Set standby frequency.
Definition comsystem.cpp:31
static physical_quantities::CFrequency parseComFrequency(const QString &input, physical_quantities::CPqString::SeparatorMode sep)
Parses almost any shitty string to a valid COM frequency.
static bool isValidComFrequency(const physical_quantities::CFrequency &f)
Valid COM frequency (either civil or military).
bool isActiveFrequencySameFrequency(const physical_quantities::CFrequency &comFrequency) const
Is active frequency the same frequency.
Definition comsystem.cpp:59
static bool isExclusiveWithin8_33kHzChannel(const physical_quantities::CFrequency &freq)
Is frequency a "new" 8.33 kHz frequency and not within 25 kHz spacing E.g. returns false for 122....
ChannelSpacing
Channel spacing frequency.
Definition comsystem.h:47
CComSystem()=default
Default constructor.
static int round8_33kHzChannel(int fKHz)
Round passed frequency in kHz to 8.33 frequency spacing.
void setFrequencyActive(const physical_quantities::CFrequency &frequency)
Set active frequency.
Definition comsystem.cpp:37
static CComSystem getCom2System(double activeFrequencyMHz, double standbyFrequencyMHz=-1)
COM2 unit.
Definition comsystem.cpp:84
static bool isValidMilitaryFrequency(const physical_quantities::CFrequency &f)
Valid military aviation frequency?
static void registerMetadata()
Register metadata.
Definition comsystem.cpp:18
static bool isValidCivilAviationFrequency(const physical_quantities::CFrequency &f)
Valid civil aviation frequency?
Definition comsystem.cpp:98
swift::misc::physical_quantities::CFrequency getFrequencyStandby() const
static const QString & NameCom1()
COM1.
void setFrequencyStandby(const swift::misc::physical_quantities::CFrequency &frequency)
Set standby frequency.
Definition modulator.cpp:48
swift::misc::physical_quantities::CFrequency getFrequencyActive() const
void setFrequencyActive(const swift::misc::physical_quantities::CFrequency &frequency)
Set active frequency.
Definition modulator.cpp:42
static const QString & NameCom2()
COM2.
static double round(double value, int digits)
Utility round method.
Definition mathutils.cpp:18
static void registerMetadata()
Register metadata.
static CFrequencyUnit MHz()
Megahertz.
Definition units.h:380
static CFrequencyUnit kHz()
Kilohertz.
Definition units.h:371
static const CFrequency & FrequencyUnicom()
Unicom frequency.
Definition constants.h:29
void parseFromString(const QString &value)
Parse value from string.
PQ & switchUnit(const MU &newUnit)
Change unit, and convert value to maintain the same quantity.
double value(MU unit) const
Value in given unit.
void setCurrentUnitValue(double value)
Set value in current unit.
double valueRounded(MU unit, int digits=-1) const
Rounded value in given unit.
SeparatorMode
Number separators / group separators.
Definition pqstring.h:34
static double parseNumber(const QString &number, bool &success, SeparatorMode mode=SeparatorBestGuess)
Locale aware parsing.
Definition pqstring.cpp:118
T::const_iterator end(const LockFreeReader< T > &reader)
Non-member begin() and end() for so LockFree containers can be used in ranged for loops.
Definition lockfree.h:264
bool isDigitsOnlyString(const QString &testString)
String with digits only.