1 #include "OmniRigTransceiver.hpp"
2
3 #include <QDebug>
4 #include <objbase.h>
5 #include <QThread>
6 #include <QEventLoop>
7
8 #include "qt_helpers.hpp"
9
10 #include "moc_OmniRigTransceiver.cpp"
11
12 namespace
13 {
14 auto constexpr OmniRig_transceiver_one_name = "OmniRig Rig 1";
15 auto constexpr OmniRig_transceiver_two_name = "OmniRig Rig 2";
16 }
17
map_mode(OmniRig::RigParamX param)18 auto OmniRigTransceiver::map_mode (OmniRig::RigParamX param) -> MODE
19 {
20 if (param & OmniRig::PM_CW_U)
21 {
22 return CW_R;
23 }
24 else if (param & OmniRig::PM_CW_L)
25 {
26 return CW;
27 }
28 else if (param & OmniRig::PM_SSB_U)
29 {
30 return USB;
31 }
32 else if (param & OmniRig::PM_SSB_L)
33 {
34 return LSB;
35 }
36 else if (param & OmniRig::PM_DIG_U)
37 {
38 return DIG_U;
39 }
40 else if (param & OmniRig::PM_DIG_L)
41 {
42 return DIG_L;
43 }
44 else if (param & OmniRig::PM_AM)
45 {
46 return AM;
47 }
48 else if (param & OmniRig::PM_FM)
49 {
50 return FM;
51 }
52 CAT_ERROR ("unrecognized mode");
53 throw_qstring (tr ("OmniRig: unrecognized mode"));
54 return UNK;
55 }
56
map_mode(MODE mode)57 OmniRig::RigParamX OmniRigTransceiver::map_mode (MODE mode)
58 {
59 switch (mode)
60 {
61 case AM: return OmniRig::PM_AM;
62 case CW: return OmniRig::PM_CW_L;
63 case CW_R: return OmniRig::PM_CW_U;
64 case USB: return OmniRig::PM_SSB_U;
65 case LSB: return OmniRig::PM_SSB_L;
66 case FSK: return OmniRig::PM_DIG_L;
67 case FSK_R: return OmniRig::PM_DIG_U;
68 case DIG_L: return OmniRig::PM_DIG_L;
69 case DIG_U: return OmniRig::PM_DIG_U;
70 case FM: return OmniRig::PM_FM;
71 case DIG_FM: return OmniRig::PM_FM;
72 default: break;
73 }
74 return OmniRig::PM_SSB_U; // quieten compiler grumble
75 }
76
register_transceivers(logger_type *,TransceiverFactory::Transceivers * registry,unsigned id1,unsigned id2)77 void OmniRigTransceiver::register_transceivers (logger_type *,
78 TransceiverFactory::Transceivers * registry,
79 unsigned id1, unsigned id2)
80 {
81 (*registry)[OmniRig_transceiver_one_name] = TransceiverFactory::Capabilities {
82 id1
83 , TransceiverFactory::Capabilities::none // COM isn't serial or network
84 , true // does PTT
85 , false // doesn't select mic/data (use OmniRig config file)
86 , true // can remote control RTS nd DTR
87 , true // asynchronous interface
88 };
89 (*registry)[OmniRig_transceiver_two_name] = TransceiverFactory::Capabilities {
90 id2
91 , TransceiverFactory::Capabilities::none // COM isn't serial or network
92 , true // does PTT
93 , false // doesn't select mic/data (use OmniRig config file)
94 , true // can remote control RTS nd DTR
95 , true // asynchronous interface
96 };
97 }
98
OmniRigTransceiver(logger_type * the_logger,std::unique_ptr<TransceiverBase> wrapped,RigNumber n,TransceiverFactory::PTTMethod ptt_type,QString const & ptt_port,QObject * parent)99 OmniRigTransceiver::OmniRigTransceiver (logger_type * the_logger,
100 std::unique_ptr<TransceiverBase> wrapped,
101 RigNumber n, TransceiverFactory::PTTMethod ptt_type,
102 QString const& ptt_port, QObject * parent)
103 : TransceiverBase {the_logger, parent}
104 , wrapped_ {std::move (wrapped)}
105 , use_for_ptt_ {TransceiverFactory::PTT_method_CAT == ptt_type || ("CAT" == ptt_port && (TransceiverFactory::PTT_method_RTS == ptt_type || TransceiverFactory::PTT_method_DTR == ptt_type))}
106 , ptt_type_ {ptt_type}
107 , rig_number_ {n}
108 , readable_params_ {0}
109 , writable_params_ {0}
110 , send_update_signal_ {false}
111 , reversed_ {false}
112 {
113 CoInitializeEx (nullptr, 0 /*COINIT_APARTMENTTHREADED*/); // required because Qt only does this for GUI thread
114 CAT_TRACE ("constructed");
115 }
116
~OmniRigTransceiver()117 OmniRigTransceiver::~OmniRigTransceiver ()
118 {
119 CAT_TRACE ("destroying");
120 CoUninitialize ();
121 }
122
do_start()123 int OmniRigTransceiver::do_start ()
124 {
125 CAT_TRACE ("starting");
126 try
127 {
128 if (wrapped_) wrapped_->start (0);
129
130 omni_rig_.reset (new OmniRig::OmniRigX {this});
131 if (omni_rig_->isNull ())
132 {
133 CAT_ERROR ("failed to start COM server");
134 throw_qstring (tr ("Failed to start OmniRig COM server"));
135 }
136
137 // COM/OLE exceptions get signaled
138 connect (&*omni_rig_, SIGNAL (exception (int, QString, QString, QString)), this, SLOT (handle_COM_exception (int, QString, QString, QString)));
139
140 // IOmniRigXEvent interface signals
141 connect (&*omni_rig_, SIGNAL (VisibleChange ()), this, SLOT (handle_visible_change ()));
142 connect (&*omni_rig_, SIGNAL (RigTypeChange (int)), this, SLOT (handle_rig_type_change (int)));
143 connect (&*omni_rig_, SIGNAL (StatusChange (int)), this, SLOT (handle_status_change (int)));
144 connect (&*omni_rig_, SIGNAL (ParamsChange (int, int)), this, SLOT (handle_params_change (int, int)));
145 connect (&*omni_rig_
146 , SIGNAL (CustomReply (int, QVariant const&, QVariant const&))
147 , this, SLOT (handle_custom_reply (int, QVariant const&, QVariant const&)));
148
149 CAT_INFO ("OmniRig s/w version: " << static_cast<quint16> (omni_rig_->SoftwareVersion () >> 16)
150 << '.' << static_cast<quint16> (omni_rig_->SoftwareVersion () & 0xffff)
151 << " i/f version: " << static_cast<int> (omni_rig_->InterfaceVersion () >> 8 & 0xff)
152 << '.' << static_cast<int> (omni_rig_->InterfaceVersion () && 0xff));
153
154 // fetch the interface of the RigX CoClass and instantiate a proxy object
155 switch (rig_number_)
156 {
157 case One: rig_.reset (new OmniRig::RigX (omni_rig_->Rig1 ())); break;
158 case Two: rig_.reset (new OmniRig::RigX (omni_rig_->Rig2 ())); break;
159 }
160
161 Q_ASSERT (rig_);
162 Q_ASSERT (!rig_->isNull ());
163
164 // COM/OLE exceptions get signaled
165 connect (&*rig_, SIGNAL (exception (int, QString, QString, QString)), this, SLOT (handle_COM_exception (int, QString, QString, QString)));
166
167 offline_timer_.reset (new QTimer); // instantiate here as constructor runs in wrong thread
168 offline_timer_->setSingleShot (true);
169 connect (offline_timer_.data (), &QTimer::timeout, [this] () {offline ("Rig went offline");});
170
171 for (int i = 0; i < 5; ++i)
172 {
173 // leave some time for Omni-Rig to do its first poll
174 QThread::msleep (250);
175 if (OmniRig::ST_ONLINE == rig_->Status ())
176 {
177 break;
178 }
179 }
180
181 if (OmniRig::ST_ONLINE != rig_->Status ())
182 {
183 CAT_ERROR ("rig not online");
184 throw_qstring ("OmniRig: " + rig_->StatusStr ());
185 }
186
187 if (use_for_ptt_ && (TransceiverFactory::PTT_method_DTR == ptt_type_ || TransceiverFactory::PTT_method_RTS == ptt_type_))
188 {
189 // fetch the interface for the serial port if we need it for PTT
190 port_.reset (new OmniRig::PortBits (rig_->PortBits ()));
191
192 Q_ASSERT (port_);
193 Q_ASSERT (!port_->isNull ());
194
195 // COM/OLE exceptions get signaled
196 connect (&*port_, SIGNAL (exception (int, QString, QString, QString)), this, SLOT (handle_COM_exception (int, QString, QString, QString)));
197
198 CAT_TRACE ("OmniRig RTS state: " << port_->Rts ());
199
200 // remove locking because it doesn't seem to work properly
201 // if (!port_->Lock ()) // try to take exclusive use of the OmniRig serial port for PTT
202 // {
203 // CAT_WARNING ("Failed to get exclusive use of serial port for PTT from OmniRig");
204 // }
205
206 // start off so we don't accidentally key the radio
207 if (TransceiverFactory::PTT_method_DTR == ptt_type_)
208 {
209 port_->SetDtr (false);
210 }
211 else // RTS
212 {
213 port_->SetRts (false);
214 }
215 }
216
217 rig_type_ = rig_->RigType ();
218 readable_params_ = rig_->ReadableParams ();
219 writable_params_ = rig_->WriteableParams ();
220
221 CAT_INFO (QString {"OmniRig initial rig type: %1 readable params=0x%2 writable params=0x%3 for rig %4"}
222 .arg (rig_type_)
223 .arg (readable_params_, 8, 16, QChar ('0'))
224 .arg (writable_params_, 8, 16, QChar ('0'))
225 .arg (rig_number_));
226 update_rx_frequency (rig_->GetRxFrequency ());
227 int resolution {0};
228 if (OmniRig::PM_UNKNOWN == rig_->Vfo ()
229 && (writable_params_ & (OmniRig::PM_VFOA | OmniRig::PM_VFOB))
230 == (OmniRig::PM_VFOA | OmniRig::PM_VFOB))
231 {
232 // start with VFO A (probably MAIN) on rigs that we
233 // can't query VFO but can set explicitly
234 rig_->SetVfo (OmniRig::PM_VFOA);
235 }
236 auto f = state ().frequency ();
237 if (f % 10) return resolution; // 1Hz resolution
238 auto test_frequency = f - f % 100 + 55;
239 if (OmniRig::PM_FREQ & writable_params_)
240 {
241 rig_->SetFreq (test_frequency);
242 }
243 else if (reversed_ && (OmniRig::PM_FREQB & writable_params_))
244 {
245 rig_->SetFreqB (test_frequency);
246 }
247 else if (!reversed_ && (OmniRig::PM_FREQA & writable_params_))
248 {
249 rig_->SetFreqA (test_frequency);
250 }
251 else
252 {
253 throw_qstring (tr ("OmniRig: don't know how to set rig frequency"));
254 }
255 switch (rig_->GetRxFrequency () - test_frequency)
256 {
257 case -5: resolution = -1; break; // 10Hz truncated
258 case 5: resolution = 1; break; // 10Hz rounded
259 case -15: resolution = -2; break; // 20Hz truncated
260 case -55: resolution = -2; break; // 100Hz truncated
261 case 45: resolution = 2; break; // 100Hz rounded
262 }
263 if (1 == resolution) // may be 20Hz rounded
264 {
265 test_frequency = f - f % 100 + 51;
266 if (OmniRig::PM_FREQ & writable_params_)
267 {
268 rig_->SetFreq (test_frequency);
269 }
270 else if (reversed_ && (OmniRig::PM_FREQB & writable_params_))
271 {
272 rig_->SetFreqB (test_frequency);
273 }
274 else if (!reversed_ && (OmniRig::PM_FREQA & writable_params_))
275 {
276 rig_->SetFreqA (test_frequency);
277 }
278 if (9 == rig_->GetRxFrequency () - test_frequency)
279 {
280 resolution = 2; // 20Hz rounded
281 }
282 }
283 if (OmniRig::PM_FREQ & writable_params_)
284 {
285 rig_->SetFreq (f);
286 }
287 else if (reversed_ && (OmniRig::PM_FREQB & writable_params_))
288 {
289 rig_->SetFreqB (f);
290 }
291 else if (!reversed_ && (OmniRig::PM_FREQA & writable_params_))
292 {
293 rig_->SetFreqA (f);
294 }
295 update_rx_frequency (f);
296 CAT_TRACE ("started");
297
298 return resolution;
299 }
300 catch (...)
301 {
302 CAT_TRACE ("start threw exception");
303 throw;
304 }
305 }
306
do_stop()307 void OmniRigTransceiver::do_stop ()
308 {
309 CAT_TRACE ("stopping");
310 QThread::msleep (200); // leave some time for pending
311 // commands at the server end
312
313 offline_timer_.reset (); // destroy here rather than in
314 // destructor as destructor runs in
315 // wrong thread
316
317 if (port_ && !port_->isNull ())
318 {
319 // port_->Unlock (); // release serial port
320 port_->clear ();
321 port_.reset ();
322 }
323 if (omni_rig_ && !omni_rig_->isNull ())
324 {
325 if (rig_ && !rig_->isNull ())
326 {
327 rig_->clear ();
328 rig_.reset ();
329 CAT_TRACE ("rig_ reset");
330 }
331 omni_rig_->clear ();
332 omni_rig_.reset ();
333 }
334
335 if (wrapped_) wrapped_->stop ();
336
337 CAT_TRACE ("stopped");
338 }
339
handle_COM_exception(int code,QString source,QString desc,QString help)340 void OmniRigTransceiver::handle_COM_exception (int code, QString source, QString desc, QString help)
341 {
342 CAT_ERROR ((QString::number (code) + " at " + source + ": " + desc + " (" + help + ')'));
343 throw_qstring (tr ("OmniRig COM/OLE error: %1 at %2: %3 (%4)").arg (QString::number (code)).arg (source). arg (desc). arg (help));
344 }
345
handle_visible_change()346 void OmniRigTransceiver::handle_visible_change ()
347 {
348 if (!omni_rig_ || omni_rig_->isNull ()) return;
349 CAT_TRACE ("visibility change: visibility =" << omni_rig_->DialogVisible ());
350 }
351
handle_rig_type_change(int rig_number)352 void OmniRigTransceiver::handle_rig_type_change (int rig_number)
353 {
354 CAT_TRACE ("rig type change: rig =" << rig_number);
355 if (rig_number_ == rig_number)
356 {
357 if (!rig_ || rig_->isNull ()) return;
358 readable_params_ = rig_->ReadableParams ();
359 writable_params_ = rig_->WriteableParams ();
360 CAT_INFO (QString {"rig type change to: %1 readable params = 0x%2 writable params = 0x%3 for rig %4"}
361 .arg (rig_->RigType ())
362 .arg (readable_params_, 8, 16, QChar ('0'))
363 .arg (writable_params_, 8, 16, QChar ('0'))
364 .arg (rig_number));
365 }
366 }
367
handle_status_change(int rig_number)368 void OmniRigTransceiver::handle_status_change (int rig_number)
369 {
370 CAT_TRACE (QString {"status change for rig %1"}.arg (rig_number));
371 if (rig_number_ == rig_number)
372 {
373 if (!rig_ || rig_->isNull ()) return;
374 auto const& status = rig_->StatusStr ();
375 CAT_TRACE ("OmniRig status change: new status = " << status);
376 if (OmniRig::ST_ONLINE != rig_->Status ())
377 {
378 if (!offline_timer_->isActive ())
379 {
380 // Omni-Rig is prone to reporting the rig offline and
381 // then recovering autonomously, so we will give it a
382 // few seconds to make its mind up
383 offline_timer_->start (10000);
384 }
385 }
386 else
387 {
388 offline_timer_->stop (); // good to go again
389 }
390 // else
391 // {
392 // update_rx_frequency (rig_->GetRxFrequency ());
393 // update_complete ();
394 // CAT_TRACE ("frequency:" << state ().frequency ());
395 // }
396 }
397 }
398
handle_params_change(int rig_number,int params)399 void OmniRigTransceiver::handle_params_change (int rig_number, int params)
400 {
401 CAT_TRACE (QString {"params change: params=0x%1 for rig %2"}
402 .arg (params, 8, 16, QChar ('0'))
403 .arg (rig_number)
404 << "state before:" << state ());
405 if (rig_number_ == rig_number)
406 {
407 if (!rig_ || rig_->isNull ()) return;
408 // starting_ = false;
409 TransceiverState old_state {state ()};
410 auto need_frequency = false;
411
412 if (params & OmniRig::PM_VFOAA)
413 {
414 CAT_TRACE ("VFOAA");
415 update_split (false);
416 reversed_ = false;
417 update_rx_frequency (rig_->FreqA ());
418 update_other_frequency (rig_->FreqB ());
419 }
420 if (params & OmniRig::PM_VFOAB)
421 {
422 CAT_TRACE ("VFOAB");
423 update_split (true);
424 reversed_ = false;
425 update_rx_frequency (rig_->FreqA ());
426 update_other_frequency (rig_->FreqB ());
427 }
428 if (params & OmniRig::PM_VFOBA)
429 {
430 CAT_TRACE ("VFOBA");
431 update_split (true);
432 reversed_ = true;
433 update_other_frequency (rig_->FreqA ());
434 update_rx_frequency (rig_->FreqB ());
435 }
436 if (params & OmniRig::PM_VFOBB)
437 {
438 CAT_TRACE ("VFOBB");
439 update_split (false);
440 reversed_ = true;
441 update_other_frequency (rig_->FreqA ());
442 update_rx_frequency (rig_->FreqB ());
443 }
444 if (params & OmniRig::PM_VFOA)
445 {
446 CAT_TRACE ("VFOA");
447 reversed_ = false;
448 need_frequency = true;
449 }
450 if (params & OmniRig::PM_VFOB)
451 {
452 CAT_TRACE ("VFOB");
453 reversed_ = true;
454 need_frequency = true;
455 }
456
457 if (params & OmniRig::PM_FREQ)
458 {
459 need_frequency = true;
460 }
461 if (params & OmniRig::PM_FREQA)
462 {
463 auto f = rig_->FreqA ();
464 CAT_TRACE ("FREQA = " << f);
465 if (reversed_)
466 {
467 update_other_frequency (f);
468 }
469 else
470 {
471 update_rx_frequency (f);
472 }
473 }
474 if (params & OmniRig::PM_FREQB)
475 {
476 auto f = rig_->FreqB ();
477 CAT_TRACE ("FREQB = " << f);
478 if (reversed_)
479 {
480 update_rx_frequency (f);
481 }
482 else
483 {
484 update_other_frequency (f);
485 }
486 }
487 if (need_frequency)
488 {
489 if (readable_params_ & OmniRig::PM_FREQA)
490 {
491 auto f = rig_->FreqA ();
492 if (f)
493 {
494 CAT_TRACE ("FREQA = " << f);
495 if (reversed_)
496 {
497 update_other_frequency (f);
498 }
499 else
500 {
501 update_rx_frequency (f);
502 }
503 }
504 }
505 if (readable_params_ & OmniRig::PM_FREQB)
506 {
507 auto f = rig_->FreqB ();
508 if (f)
509 {
510 CAT_TRACE ("FREQB = " << f);
511 if (reversed_)
512 {
513 update_rx_frequency (f);
514 }
515 else
516 {
517 update_other_frequency (f);
518 }
519 }
520 }
521 if (readable_params_ & OmniRig::PM_FREQ && !state ().ptt ())
522 {
523 auto f = rig_->Freq ();
524 if (f)
525 {
526 CAT_TRACE ("FREQ = " << f);
527 update_rx_frequency (f);
528 }
529 }
530 }
531 if (params & OmniRig::PM_PITCH)
532 {
533 CAT_TRACE ("PITCH");
534 }
535 if (params & OmniRig::PM_RITOFFSET)
536 {
537 CAT_TRACE ("RITOFFSET");
538 }
539 if (params & OmniRig::PM_RIT0)
540 {
541 CAT_TRACE ("RIT0");
542 }
543 if (params & OmniRig::PM_VFOEQUAL)
544 {
545 auto f = readable_params_ & OmniRig::PM_FREQA ? rig_->FreqA () : rig_->Freq ();
546 auto m = map_mode (rig_->Mode ());
547 CAT_TRACE (QString {"VFOEQUAL f=%1 m=%2"}.arg (f).arg (m));
548 update_rx_frequency (f);
549 update_other_frequency (f);
550 update_mode (m);
551 }
552 if (params & OmniRig::PM_VFOSWAP)
553 {
554 CAT_TRACE ("VFOSWAP");
555 auto f = state ().tx_frequency ();
556 update_other_frequency (state ().frequency ());
557 update_rx_frequency (f);
558 update_mode (map_mode (rig_->Mode ()));
559 }
560 if (params & OmniRig::PM_SPLITON)
561 {
562 CAT_TRACE ("SPLITON");
563 update_split (true);
564 }
565 if (params & OmniRig::PM_SPLITOFF)
566 {
567 CAT_TRACE ("SPLITOFF");
568 update_split (false);
569 }
570 if (params & OmniRig::PM_RITON)
571 {
572 CAT_TRACE ("RITON");
573 }
574 if (params & OmniRig::PM_RITOFF)
575 {
576 CAT_TRACE ("RITOFF");
577 }
578 if (params & OmniRig::PM_XITON)
579 {
580 CAT_TRACE ("XITON");
581 }
582 if (params & OmniRig::PM_XITOFF)
583 {
584 CAT_TRACE ("XITOFF");
585 }
586 if (params & OmniRig::PM_RX)
587 {
588 CAT_TRACE ("RX");
589 update_PTT (false);
590 }
591 if (params & OmniRig::PM_TX)
592 {
593 CAT_TRACE ("TX");
594 update_PTT ();
595 }
596 if (params & OmniRig::PM_CW_U)
597 {
598 CAT_TRACE ("CW-R");
599 update_mode (CW_R);
600 }
601 if (params & OmniRig::PM_CW_L)
602 {
603 CAT_TRACE ("CW");
604 update_mode (CW);
605 }
606 if (params & OmniRig::PM_SSB_U)
607 {
608 CAT_TRACE ("USB");
609 update_mode (USB);
610 }
611 if (params & OmniRig::PM_SSB_L)
612 {
613 CAT_TRACE ("LSB");
614 update_mode (LSB);
615 }
616 if (params & OmniRig::PM_DIG_U)
617 {
618 CAT_TRACE ("DATA-U");
619 update_mode (DIG_U);
620 }
621 if (params & OmniRig::PM_DIG_L)
622 {
623 CAT_TRACE ("DATA-L");
624 update_mode (DIG_L);
625 }
626 if (params & OmniRig::PM_AM)
627 {
628 CAT_TRACE ("AM");
629 update_mode (AM);
630 }
631 if (params & OmniRig::PM_FM)
632 {
633 CAT_TRACE ("FM");
634 update_mode (FM);
635 }
636
637 if (old_state != state () || send_update_signal_)
638 {
639 update_complete ();
640 send_update_signal_ = false;
641 }
642 CAT_TRACE ("OmniRig params change: state after:" << state ());
643 }
644 }
645
handle_custom_reply(int rig_number,QVariant const & command,QVariant const & reply)646 void OmniRigTransceiver::handle_custom_reply (int rig_number, QVariant const& command, QVariant const& reply)
647 {
648 (void)command;
649 (void)reply;
650
651 if (rig_number_ == rig_number)
652 {
653 if (!rig_ || rig_->isNull ()) return;
654 CAT_TRACE ("custom command" << command.toString ()
655 << "with reply" << reply.toString ()
656 << QString ("for rig %1").arg (rig_number));
657 CAT_TRACE ("rig number:" << rig_number_ << ':' << state ());
658 }
659 }
660
do_ptt(bool on)661 void OmniRigTransceiver::do_ptt (bool on)
662 {
663 CAT_TRACE (on << state ());
664 if (use_for_ptt_ && TransceiverFactory::PTT_method_CAT == ptt_type_)
665 {
666 CAT_TRACE ("set PTT");
667 if (rig_ && !rig_->isNull ())
668 {
669 rig_->SetTx (on ? OmniRig::PM_TX : OmniRig::PM_RX);
670 }
671 }
672 else
673 {
674 if (port_ && !port_->isNull ())
675 {
676 if (TransceiverFactory::PTT_method_RTS == ptt_type_)
677 {
678 CAT_TRACE ("set RTS");
679 port_->SetRts (on);
680 }
681 else // "DTR"
682 {
683 CAT_TRACE ("set DTR");
684 port_->SetDtr (on);
685 }
686 }
687 else if (wrapped_)
688 {
689 CAT_TRACE ("set PTT using basic transceiver");
690 TransceiverState new_state {wrapped_->state ()};
691 new_state.ptt (on);
692 wrapped_->set (new_state, 0);
693 }
694 }
695 update_PTT (on);
696 }
697
do_frequency(Frequency f,MODE m,bool)698 void OmniRigTransceiver::do_frequency (Frequency f, MODE m, bool /*no_ignore*/)
699 {
700 CAT_TRACE (f << ' ' << state ());
701 if (!rig_ || rig_->isNull ()) return;
702 if (UNK != m)
703 {
704 do_mode (m);
705 }
706 if (OmniRig::PM_FREQ & writable_params_)
707 {
708 rig_->SetFreq (f);
709 update_rx_frequency (f);
710 }
711 else if (reversed_ && (OmniRig::PM_FREQB & writable_params_))
712 {
713 rig_->SetFreqB (f);
714 update_rx_frequency (f);
715 }
716 else if (!reversed_ && (OmniRig::PM_FREQA & writable_params_))
717 {
718 rig_->SetFreqA (f);
719 update_rx_frequency (f);
720 }
721 else
722 {
723 throw_qstring (tr ("OmniRig: don't know how to set rig frequency"));
724 }
725 }
726
do_tx_frequency(Frequency tx,MODE m,bool)727 void OmniRigTransceiver::do_tx_frequency (Frequency tx, MODE m, bool /*no_ignore*/)
728 {
729 CAT_TRACE (tx << ' ' << state ());
730 if (!rig_ || rig_->isNull ()) return;
731 bool split {tx != 0};
732 if (split)
733 {
734 if (UNK != m)
735 {
736 do_mode (m);
737 if (OmniRig::PM_UNKNOWN == rig_->Vfo ())
738 {
739 if (writable_params_ & OmniRig::PM_VFOEQUAL)
740 {
741 // nothing to do here because OmniRig will use VFO
742 // equalize to set the mode of the Tx VFO for us
743 }
744 else if ((writable_params_ & (OmniRig::PM_VFOA | OmniRig::PM_VFOB))
745 == (OmniRig::PM_VFOA | OmniRig::PM_VFOB))
746 {
747 rig_->SetVfo (OmniRig::PM_VFOB);
748 do_mode (m);
749 rig_->SetVfo (OmniRig::PM_VFOA);
750 }
751 else if (writable_params_ & OmniRig::PM_VFOSWAP)
752 {
753 rig_->SetVfo (OmniRig::PM_VFOSWAP);
754 do_mode (m);
755 rig_->SetVfo (OmniRig::PM_VFOSWAP);
756 }
757 }
758 }
759 CAT_TRACE ("set SPLIT mode on");
760 rig_->SetSplitMode (state ().frequency (), tx);
761 update_other_frequency (tx);
762 update_split (true);
763 }
764 else
765 {
766 CAT_TRACE ("set SPLIT mode off");
767 rig_->SetSimplexMode (state ().frequency ());
768 update_split (false);
769 }
770 bool notify {false};
771 if (readable_params_ & OmniRig::PM_FREQ || !(readable_params_ & (OmniRig::PM_FREQA | OmniRig::PM_FREQB)))
772 {
773 update_other_frequency (tx); // async updates won't return this
774 // so just store it and hope
775 // operator doesn't change the
776 // "back" VFO on rig
777 notify = true;
778 }
779 if (!((OmniRig::PM_VFOAB | OmniRig::PM_VFOBA | OmniRig::PM_SPLITON) & readable_params_))
780 {
781 CAT_TRACE ("setting SPLIT manually");
782 update_split (split); // we can't read it so just set and
783 // hope op doesn't change it
784 notify = true;
785 }
786 if (notify)
787 {
788 update_complete ();
789 }
790 }
791
do_mode(MODE mode)792 void OmniRigTransceiver::do_mode (MODE mode)
793 {
794 CAT_TRACE (mode << ' ' << state ());
795 if (!rig_ || rig_->isNull ()) return;
796 // TODO: G4WJS OmniRig doesn't seem to have any capability of tracking/setting VFO B mode
797 auto mapped = map_mode (mode);
798 if (mapped & writable_params_)
799 {
800 rig_->SetMode (mapped);
801 update_mode (mode);
802 }
803 else
804 {
805 offline ("OmniRig invalid mode");
806 }
807 }
808