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