1 #include "TransceiverBase.hpp"
2 
3 #include <exception>
4 
5 #include <QString>
6 #include <QTimer>
7 #include <QThread>
8 #include <QDebug>
9 
10 #include "moc_TransceiverBase.cpp"
11 
12 namespace
13 {
14   auto const unexpected = TransceiverBase::tr ("Unexpected rig error");
15 }
16 
start(unsigned sequence_number)17 void TransceiverBase::start (unsigned sequence_number) noexcept
18 {
19   CAT_TRACE ("#: " << sequence_number);
20 
21   QString message;
22   try
23     {
24       last_sequence_number_ = sequence_number;
25       may_update u {this, true};
26       shutdown ();
27       startup ();
28     }
29   catch (std::exception const& e)
30     {
31       CAT_TRACE ("#: " << sequence_number << " what: " << e.what ());
32       message = e.what ();
33     }
34   catch (...)
35     {
36       CAT_TRACE ("#: " << sequence_number);
37       message = unexpected;
38     }
39   if (!message.isEmpty ())
40     {
41       offline (message);
42     }
43 }
44 
set(TransceiverState const & s,unsigned sequence_number)45 void TransceiverBase::set (TransceiverState const& s,
46                            unsigned sequence_number) noexcept
47 {
48   CAT_TRACE ("#: " << s);
49 
50   QString message;
51   try
52     {
53       last_sequence_number_ = sequence_number;
54       may_update u {this, true};
55       bool was_online {requested_.online ()};
56       if (!s.online () && was_online)
57         {
58           shutdown ();
59         }
60       else if (s.online () && !was_online)
61         {
62           shutdown ();
63           startup ();
64         }
65       if (requested_.online ())
66         {
67           bool ptt_on {false};
68           bool ptt_off {false};
69           if (s.ptt () != requested_.ptt ())
70             {
71               ptt_on = s.ptt ();
72               ptt_off = !s.ptt ();
73             }
74           if (ptt_off)
75             {
76               do_ptt (false);
77               do_post_ptt (false);
78               QThread::msleep (100); // some rigs cannot process CAT
79                                      // commands while switching from
80                                      // Tx to Rx
81             }
82           if (s.frequency ()    // ignore bogus zero frequencies
83               && ((s.frequency () != requested_.frequency () // and QSY
84                    || (s.mode () != UNK && s.mode () != requested_.mode ())))) // or mode change
85             {
86               do_frequency (s.frequency (), s.mode (), ptt_off);
87               do_post_frequency (s.frequency (), s.mode ());
88 
89               // record what actually changed
90               requested_.frequency (actual_.frequency ());
91               requested_.mode (actual_.mode ());
92             }
93           if (!s.tx_frequency ()
94               || (s.tx_frequency () > 10000 // ignore bogus startup values
95                   && s.tx_frequency () < std::numeric_limits<Frequency>::max () - 10000))
96             {
97               if ((s.tx_frequency () != requested_.tx_frequency () // and QSY
98                    || (s.mode () != UNK && s.mode () != requested_.mode ())) // or mode change
99                   // || s.split () != requested_.split ())) // or split change
100                   || (s.tx_frequency () && ptt_on)) // or about to tx split
101                 {
102                   do_tx_frequency (s.tx_frequency (), s.mode (), ptt_on);
103                   do_post_tx_frequency (s.tx_frequency (), s.mode ());
104 
105                   // record what actually changed
106                   requested_.tx_frequency (actual_.tx_frequency ());
107                   requested_.split (actual_.split ());
108                 }
109             }
110           if (ptt_on)
111             {
112               do_ptt (true);
113               do_post_ptt (true);
114               QThread::msleep (100); // some rigs cannot process CAT
115                                      // commands while switching from
116                                      // Rx to Tx
117             }
118 
119           // record what actually changed
120           requested_.ptt (actual_.ptt ());
121         }
122     }
123   catch (std::exception const& e)
124     {
125       CAT_TRACE ("#: " << sequence_number << " what: " << e.what ());
126       message = e.what ();
127     }
128   catch (...)
129     {
130       CAT_TRACE ("#: " << sequence_number << " " << sequence_number);
131       message = unexpected;
132     }
133   if (!message.isEmpty ())
134     {
135       offline (message);
136     }
137 }
138 
startup()139 void TransceiverBase::startup ()
140 {
141   CAT_TRACE ("startup");
142   QString message;
143   try
144     {
145       actual_.online (true);
146       requested_.online (true);
147       auto res = do_start ();
148       do_post_start ();
149       Q_EMIT resolution (res);
150     }
151   catch (std::exception const& e)
152     {
153       CAT_TRACE ("startup" << " what: " << e.what ());
154       message = e.what ();
155     }
156   catch (...)
157     {
158       CAT_TRACE ("startup");
159       message = unexpected;
160     }
161   if (!message.isEmpty ())
162     {
163       offline (message);
164     }
165 }
166 
shutdown()167 void TransceiverBase::shutdown ()
168 {
169   CAT_TRACE ("shutdown");
170   may_update u {this};
171   if (requested_.online ())
172     {
173       try
174         {
175           // try and ensure PTT isn't left set
176           do_ptt (false);
177           do_post_ptt (false);
178           if (requested_.split ())
179             {
180               // try and reset split mode
181               do_tx_frequency (0, UNK, true);
182               do_post_tx_frequency (0, UNK);
183             }
184           do_stop ();
185           do_post_stop ();
186         }
187       catch (...)
188         {
189           CAT_TRACE ("shutdown");
190           // don't care about exceptions
191         }
192     }
193   actual_ = TransceiverState {};
194   requested_ = TransceiverState {};
195 }
196 
stop()197 void TransceiverBase::stop () noexcept
198 {
199   CAT_TRACE ("stop");
200   QString message;
201   try
202     {
203       shutdown ();
204     }
205   catch (std::exception const& e)
206     {
207       CAT_TRACE ("stop" << " what: " << e.what ());
208       message = e.what ();
209     }
210   catch (...)
211     {
212       CAT_TRACE ("stop");
213       message = unexpected;
214     }
215   if (!message.isEmpty ())
216     {
217       offline (message);
218     }
219   else
220     {
221       Q_EMIT finished ();
222     }
223 }
224 
update_rx_frequency(Frequency rx)225 void TransceiverBase::update_rx_frequency (Frequency rx)
226 {
227   CAT_TRACE ("frequency: " << rx);
228   if (rx)
229     {
230       actual_.frequency (rx);
231       requested_.frequency (rx);    // track rig changes
232     }
233 }
234 
update_other_frequency(Frequency tx)235 void TransceiverBase::update_other_frequency (Frequency tx)
236 {
237   CAT_TRACE ("frequency: " << tx);
238   actual_.tx_frequency (tx);
239 }
240 
update_split(bool state)241 void TransceiverBase::update_split (bool state)
242 {
243   CAT_TRACE ("state: " << state);
244   actual_.split (state);
245 }
246 
update_mode(MODE m)247 void TransceiverBase::update_mode (MODE m)
248 {
249   CAT_TRACE ("mode: " << m);
250   actual_.mode (m);
251   requested_.mode (m);    // track rig changes
252 }
253 
update_PTT(bool state)254 void TransceiverBase::update_PTT (bool state)
255 {
256   CAT_TRACE ("state: " << state);
257   actual_.ptt (state);
258 }
259 
update_complete(bool force_signal)260 void TransceiverBase::update_complete (bool force_signal)
261 {
262   CAT_TRACE ("force signal: " << force_signal);
263   if ((do_pre_update ()
264        && actual_ != last_)
265       || force_signal)
266     {
267       Q_EMIT update (actual_, last_sequence_number_);
268       last_ = actual_;
269     }
270 }
271 
offline(QString const & reason)272 void TransceiverBase::offline (QString const& reason)
273 {
274   CAT_TRACE ("reason: " << reason);
275   Q_EMIT failure (reason);
276   try
277     {
278       shutdown ();
279     }
280   catch (...)
281     {
282       CAT_TRACE ("reason: " << reason);
283       // don't care
284     }
285 }
286