1 // ----------------------------------------------------------------------------
2 // Copyright (C) 2014
3 // David Freese, W1HKJ
4 //
5 // This file is part of flrig.
6 //
7 // flrig is free software; you can redistribute it and/or modify
8 // it under the terms of the GNU General Public License as published by
9 // the Free Software Foundation; either version 3 of the License, or
10 // (at your option) any later version.
11 //
12 // flrig is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 // GNU General Public License for more details.
16 //
17 // You should have received a copy of the GNU General Public License
18 // aunsigned long int with this program. If not, see <http://www.gnu.org/licenses/>.
19 // ----------------------------------------------------------------------------
20
21 /*
22 * Note for anyone wishing to expand on the command set.
23 *
24 * The Argo V always sends a response and ends the response with a "G\r" to
25 * indicate that the command was accepted. A rejected command is responded to by a
26 * two character sequence "Z\r". You should always expect a maximum response equal
27 * to the number of data bytes plus two.
28 *
29 * For example:
30 * A request for the present receiver filter bandwidth is the the string:
31 * "?W\r" which is 3 bytes in length
32 * The response from the Argonaut V will be:
33 * "Wn\rG\r" which is 5 bytes in length, where n is an unsigned char (byte)
34 * If the transceiver failed to receive the command correctly it will respond:
35 * "Z\r" ----> you need to check for that condition
36 *
37 */
38
39 #include "TT516.h"
40 #include "support.h"
41
42 static const char TT516name_[] = "TT-516";
43
44 static const char *TT516modes_[] = {
45 "AM", "USB", "LSB", "CW", "FM", NULL};
46
47 static int TT516_def_bw[] = { 26, 36, 36, 12, 36 };
48 static const char TT516mode_chr[] = { '0', '1', '2', '3', '4' };
49 static const char TT516mode_type[] = { 'U', 'U', 'L', 'U', 'U' };
50
51 static const char *TT516_widths[] = {
52 "200", "250", "300", "350", "400", "450", "500", "550", "600", "650",
53 "700", "750", "800", "850", "900", "950", "1000", "1100", "1200", "1300",
54 "1400", "1500", "1600", "1700", "1800", "1900", "2000", "2100", "2200", "2300",
55 "2400", "2500", "2600", "2700", "2800", "2900", "3000", NULL};
56 static int TT516_WIDTH_bw_vals[] = {
57 1, 2, 3, 4, 5, 6, 7, 8, 9,10,
58 11,12,13,14,15,16,17,18,19,20,
59 21,22,23,24,25,26,27,28,29,30,
60 31,32,33,34,35,36,37, WVALS_LIMIT};
61
62 static const char *TT516_AM_widths[] = {
63 "400", "500", "600", "700", "800", "900", "1000", "1100", "1200", "1350",
64 "1400", "1500", "1600", "1700", "1800", "1900", "2000", "2200", "2400", "2600",
65 "2800", "3000", "3200", "3400", "3600", "3800", "4000", "4200", "4400", "4600",
66 "4800", "5000", "5200", "5400", "5600", "5800", "6000", NULL};
67 static int TT516_AM_bw_vals[] = {
68 1, 2, 3, 4, 5, 6, 7, 8, 9,10,
69 11,12,13,14,15,16,17,18,19,20,
70 21,22,23,24,25,26,27,28,29,30,
71 31,32,33,34,35,36,37, WVALS_LIMIT};
72
73 static char TT516setBW[] = "*Wx\r";
74 static char TT516setPBT[] = "*Pxx\r";
75 static char TT516setMODE[] = "*Mnn\r";
76 static char TT516setFREQA[] = "*Annnn\r";
77 static char TT516setFREQB[] = "*Bnnnn\r";
78 static char TT516setNB[] = "*Kn\r";
79 static char TT516setXMT[] = "#1\r";
80 static char TT516setRCV[] = "#0\r";
81 static char TT516setSPLIT[] = "*On\r";
82 static char TT516setATT[] = "*Jn\r";
83 static char TT516getFREQA[] = "?A\r";
84 static char TT516getFREQB[] = "?B\r";
85 static char TT516getFWDPWR[] = "?F\r";
86 static char TT516getATT[] = "?J\r";
87 static char TT516getMODE[] = "?M\r";
88 //static char TT516getPBT[] = "?P\r";
89 static char TT516getREFPWR[] = "?R\r";
90 static char TT516getSMETER[] = "?S\r";
91 static char TT516getBW[] = "?W\r";
92 static char TT516setVfo[] = "*EVx\r";
93
94 static GUI rig_widgets[]= {
95 { (Fl_Widget *)btnIFsh, 214, 105, 50 },
96 { (Fl_Widget *)sldrIFSHIFT, 266, 105, 156 },
97 { (Fl_Widget *)NULL, 0, 0, 0 }
98 };
99
RIG_TT516()100 RIG_TT516::RIG_TT516() {
101 // base class values
102 name_ = TT516name_;
103 modes_ = TT516modes_;
104 bandwidths_ = TT516_widths;
105 bw_vals_ = TT516_WIDTH_bw_vals;
106
107 widgets = rig_widgets;
108
109 comm_baudrate = BR1200;
110 stopbits = 1;
111 comm_retries = 2;
112 comm_wait = 20;
113 comm_timeout = 50;
114 comm_rtscts = false;
115 comm_rtsplus = false;
116 comm_dtrplus = false;
117 comm_catptt = true;
118 comm_rtsptt = false;
119 comm_dtrptt = false;
120 serloop_timing = 200;
121
122 def_mode = modeB = modeA = B.imode = A.imode = 1;
123 def_bw = bwB = bwA = B.iBW = A.iBW = 34;
124 def_freq = freqB = freqA = B.freq = A.freq = 14070000;
125
126 max_power = 25;
127 can_change_alt_vfo = true;
128
129 has_power_control =
130 has_volume_control =
131 has_micgain_control =
132 has_notch_control =
133 has_preamp_control =
134 has_tune_control =
135 has_swr_control = false;
136
137 has_smeter =
138 has_power_out =
139 has_swr_control =
140 has_split =
141 has_noise_control =
142 has_attenuator_control =
143 has_ifshift_control =
144 has_ptt_control =
145 has_bandwidth_control =
146 has_mode_control = true;
147
148 precision = 10;
149 ndigits = 7;
150
151 }
152
initialize()153 void RIG_TT516::initialize()
154 {
155 rig_widgets[0].W = btnIFsh;
156 rig_widgets[1].W = sldrIFSHIFT;
157 }
158
check()159 bool RIG_TT516::check ()
160 {
161 cmd = TT516getFREQA;
162 int ret = waitN(8, 150, "check", HEX);
163 if (ret != 8) return false;
164 return true;
165 }
166
get_vfoA()167 unsigned long int RIG_TT516::get_vfoA ()
168 {
169 cmd = TT516getFREQA;
170 int ret = waitN(8, 150, "get vfo A", HEX);
171 if (ret != 8) return A.freq;
172 if (replystr[0] != 'A') return A.freq;
173 if (replystr[6] != 'G') return A.freq;
174 int f = 0;
175 for (size_t n = 1; n < 5; n++) {
176 f = f*256 + ((unsigned char)replystr[n] & 0xFF) ;
177 A.freq = f;
178 }
179 return A.freq;
180 }
181
set_vfoA(unsigned long int freq)182 void RIG_TT516::set_vfoA (unsigned long int freq)
183 {
184 A.freq = freq;
185 cmd = TT516setFREQA;
186 cmd[5] = freq & 0xff; freq = freq >> 8;
187 cmd[4] = freq & 0xff; freq = freq >> 8;
188 cmd[3] = freq & 0xff; freq = freq >> 8;
189 cmd[2] = freq & 0xff;
190 LOG_INFO(" %c%c %02X %02X %02X %02X %02X", cmd[0], cmd[1],
191 cmd[2] & 0xFF, cmd[3] & 0xFF, cmd[4] & 0xFF, cmd[5] & 0xFF, cmd[6]);
192 sendCommand(cmd);
193 return;
194 }
195
get_vfoB()196 unsigned long int RIG_TT516::get_vfoB ()
197 {
198 cmd = TT516getFREQB;
199 int ret = waitN(8, 150, "get vfo B", HEX);
200 if (ret != 8) return B.freq;
201 if (replystr[0] != 'B') return B.freq;
202 if (replystr[6] != 'G') return B.freq;
203
204 int f = 0;
205 for (size_t n = 1; n < 5; n++) {
206 f = f*256 + ((unsigned char)replystr[n] & 0xFF) ;
207 B.freq = f;
208 }
209
210 return B.freq;
211 }
212
set_vfoB(unsigned long int freq)213 void RIG_TT516::set_vfoB (unsigned long int freq)
214 {
215 B.freq = freq;
216 cmd = TT516setFREQB;
217 cmd[5] = freq & 0xff; freq = freq >> 8;
218 cmd[4] = freq & 0xff; freq = freq >> 8;
219 cmd[3] = freq & 0xff; freq = freq >> 8;
220 cmd[2] = freq & 0xff;
221 LOG_INFO(" %c%c %02X %02X %02X %02X %02X", cmd[0], cmd[1],
222 cmd[2] & 0xFF, cmd[3] & 0xFF, cmd[4] & 0xFF, cmd[5] & 0xFF, cmd[6]);
223 sendCommand(cmd);
224 return;
225 }
226
selectA()227 void RIG_TT516::selectA()
228 {
229 cmd = TT516setVfo;
230 cmd[3] = 'A';
231 sendCommand(cmd);
232 inuse = onA;
233 set_bwA(A.iBW);
234 return;
235 }
236
selectB()237 void RIG_TT516::selectB()
238 {
239 cmd = TT516setVfo;
240 cmd[3] = 'B';
241 sendCommand(cmd);
242 inuse = onB;
243 set_bwB(B.iBW);
244 return;
245 }
246
set_split(bool val)247 void RIG_TT516::set_split(bool val)
248 {
249 cmd = TT516setSPLIT;
250 cmd[2] = val ? '\x01' : '\x00';
251 sendCommand(cmd);
252 return;
253 }
254
255 // Tranceiver PTT on/off
set_PTT_control(int val)256 void RIG_TT516::set_PTT_control(int val)
257 {
258 if (val) sendCommand(TT516setXMT);
259 else sendCommand(TT516setRCV);
260 }
261
get_modetype(int n)262 int RIG_TT516::get_modetype(int n)
263 {
264 return TT516mode_type[n];
265 }
266
bwtable(int m)267 const char **RIG_TT516::bwtable(int m)
268 {
269 if (m == 0) {
270 bandwidths_ = TT516_AM_widths;
271 bw_vals_ = TT516_AM_bw_vals;
272 return TT516_AM_widths;
273 }
274 bandwidths_ = TT516_widths;
275 bw_vals_ = TT516_WIDTH_bw_vals;
276 return TT516_widths;
277 }
278
def_bandwidth(int m)279 int RIG_TT516::def_bandwidth(int m)
280 {
281 return TT516_def_bw[m];
282 }
283
adjust_bandwidth(int m)284 int RIG_TT516::adjust_bandwidth(int m)
285 {
286 bwtable(m);
287 return def_bandwidth(m);
288 }
289
set_modeA(int val)290 void RIG_TT516::set_modeA(int val)
291 {
292 A.imode = val;
293 cmd = TT516setMODE;
294 cmd[2] = TT516mode_chr[A.imode];
295 cmd[3] = TT516mode_chr[B.imode];
296 sendCommand(cmd);
297 }
298
get_modeA()299 int RIG_TT516::get_modeA()
300 {
301 cmd = TT516getMODE;
302 int ret = waitN(6, 150, "get mode A", HEX);
303 if (ret < 6) return A.imode;
304 if (replystr[ret - 2] != 'G') return A.imode;
305 size_t p = replystr.rfind("M");
306 if (p == string::npos) return A.imode;
307
308 A.imode = replystr[p+1] - '0';
309
310 return A.imode;
311 }
312
set_modeB(int val)313 void RIG_TT516::set_modeB(int val)
314 {
315 B.imode = val;
316 cmd = TT516setMODE;
317 cmd[2] = TT516mode_chr[A.imode];
318 cmd[3] = TT516mode_chr[B.imode];
319 sendCommand(cmd);
320 }
321
get_modeB()322 int RIG_TT516::get_modeB()
323 {
324 cmd = TT516getMODE;
325 int ret = waitN(6, 150, "get mode B", HEX);
326 if (ret < 6) return B.imode;
327 if (replystr[ret - 2] != 'G') return B.imode;
328 size_t p = replystr.rfind("M");
329 if (p == string::npos) return B.imode;
330
331 B.imode = replystr[p+2] - '0';
332
333 return B.imode;
334 }
335
get_bwA()336 int RIG_TT516::get_bwA()
337 {
338 if (inuse == onA) {
339 cmd = TT516getBW;
340 int ret = waitN(5, 150, "get bw A", HEX);
341 if (ret < 5) return A.iBW;
342 if (replystr[ret - 2] != 'G') return A.iBW;
343 size_t p = replystr.rfind("W");
344 if (p == string::npos) return A.iBW;
345 A.iBW = (unsigned char)replystr[p+1];
346 }
347 return A.iBW;
348 }
349
set_bwA(int val)350 void RIG_TT516::set_bwA(int val)
351 {
352 A.iBW = val;
353 if (inuse == onA) {
354 cmd = TT516setBW;
355 cmd[2] = val;
356 sendCommand(cmd);
357 }
358 }
359
get_bwB()360 int RIG_TT516::get_bwB()
361 {
362 if (inuse == onB) {
363 cmd = TT516getBW;
364 int ret = waitN(5, 150, "get bw B", HEX);
365 if (ret < 5) return B.iBW;
366 if (replystr[ret - 2] != 'G') return B.iBW;
367 size_t p = replystr.rfind("W");
368 if (p == string::npos) return B.iBW;
369 B.iBW = (unsigned char)replystr[p+1];
370 }
371 return B.iBW;
372 }
373
set_bwB(int val)374 void RIG_TT516::set_bwB(int val)
375 {
376 B.iBW = val;
377 if (inuse == onB) {
378 cmd = TT516setBW;
379 cmd[2] = val;
380 sendCommand(cmd);
381 }
382 }
383
set_if_shift(int val)384 void RIG_TT516::set_if_shift(int val)
385 {
386 cmd = TT516setPBT;
387 short int si = val;
388 cmd[2] = (si & 0xff00) >> 8;
389 cmd[3] = (si & 0xff);
390 sendCommand(cmd);
391 }
392
get_if_shift(int & val)393 bool RIG_TT516::get_if_shift(int &val)
394 {
395 val = 0;
396 return false;
397 }
398
get_if_min_max_step(int & min,int & max,int & step)399 void RIG_TT516::get_if_min_max_step(int &min, int &max, int &step)
400 {
401 min = -2900;
402 max = 2900;
403 step = 100;
404 }
405
set_attenuator(int val)406 void RIG_TT516::set_attenuator(int val)
407 {
408 cmd = TT516setATT;
409 if (val) cmd[2] = '1';
410 else cmd[2] = '0';
411 sendCommand(cmd);
412 }
413
414
get_attenuator()415 int RIG_TT516::get_attenuator()
416 {
417 cmd = TT516getATT;
418 int ret = sendCommand(cmd);
419 if (ret < 5) return 0;
420 size_t p = replystr.rfind("J");
421 if (p == string::npos) return 0;
422 if (replystr[p+1] == '1')
423 return 1;
424 return 0;
425 }
426
set_noise(bool b)427 void RIG_TT516::set_noise(bool b)
428 {
429 cmd = TT516setNB;
430 if (b)
431 cmd[2] = '4';
432 else
433 cmd[2] = '0';
434 sendCommand(cmd);
435 }
436
get_smeter()437 int RIG_TT516::get_smeter()
438 {
439 double sig = 0.0;
440 cmd = TT516getSMETER;
441 int ret = sendCommand(cmd);
442 if (ret < 6) return 0;
443 size_t p = replystr.rfind("S");
444 if (p == string::npos) return 0;
445
446 sig = (50.0 / 9.0) * ((unsigned char)replystr[p+1] + (unsigned char)replystr[p+2] / 256.0);
447
448 return (int)sig;
449 }
450
get_swr()451 int RIG_TT516::get_swr()
452 {
453 double swr = (fwdv + refv) / (fwdv - refv + .0001);
454 swr -= 1.0;
455 swr *= 25.0;
456 if (swr < 0) swr = 0;
457 if (swr > 100) swr = 100;
458 return (int)swr;
459 }
460
get_power_out()461 int RIG_TT516::get_power_out()
462 {
463 fwdpwr = refpwr = fwdv = refv = 0;
464 cmd = TT516getFWDPWR;
465 int ret = sendCommand(cmd);
466 if (ret < 5) return fwdpwr;
467 size_t p = replystr.rfind("F");
468 if (p == string::npos) return fwdpwr;
469
470 fwdv = 1.0 * (unsigned char)replystr[p+1];
471 cmd = TT516getREFPWR;
472 ret = sendCommand(cmd);
473 if (ret < 5) return fwdpwr;
474 p = replystr.rfind("R");
475 if (p == string::npos) return fwdpwr;
476
477 refv = 1.0 * (unsigned char)replystr[p+1];
478
479 fwdpwr = 30.0 * (fwdv * fwdv) / (256 * 256);
480 refpwr = 30.0 * (refv * refv) / (256 * 256);
481
482 return fwdpwr;
483 }
484