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 #include "TS480HX.h"
22 #include "support.h"
23
24 static const char TS480HXname_[] = "TS-480HX";
25
26 static const char *TS480HXmodes_[] = {
27 "LSB", "USB", "CW", "FM", "AM", "FSK", "CW-R", "FSK-R", NULL};
28 static const char TS480HX_mode_chr[] = { '1', '2', '3', '4', '5', '6', '7', '9' };
29 static const char TS480HX_mode_type[] = { 'L', 'U', 'U', 'U', 'U', 'L', 'L', 'U' };
30
31 static const char *TS480HX_empty[] = { "N/A", NULL };
32 static int TS480HX_bw_vals[] = {1, WVALS_LIMIT};
33
34 // SL command is lo cut when menu 045 OFF
35 static const char *TS480HX_SL[] = {
36 "0", "50", "100", "200", "300",
37 "400", "500", "600", "700", "800",
38 "900", "1000", NULL };
39 static const char *TS480HX_SL_tooltip = "lo cut";
40 static const char *TS480HX_btn_SL_label = "L";
41
42 // SH command is hi cut when menu 045 OFF
43 static const char *TS480HX_SH[] = {
44 "1000", "1200", "1400", "1600", "1800",
45 "2000", "2200", "2400", "2600", "2800",
46 "3000", "3400", "4000", "5000", NULL };
47 static int TS480HX_HI_bw_vals[] = { 1,2,3,4,5,6,7,8,9,10,11,12,13,14,WVALS_LIMIT};
48
49 static const char *TS480HX_SH_tooltip = "hi cut";
50 static const char *TS480HX_btn_SH_label = "H";
51
52 // SL command is width when menu 045 ON
53 static const char *TS480HX_dataW[] = {
54 "50", "100", "250", "500", "1000", "1500", "2400", NULL };
55 static int TS480HX_data_bw_vals[] = {1,2,3,4,5,6,7, WVALS_LIMIT};
56
57 static const char *TS480HX_dataW_tooltip = "width";
58 static const char *TS480HX_dataW_label = "W";
59
60 // SH command is center when menu 045 ON
61 static const char *TS480HX_dataC[] = {
62 "1000", "1500", "2210", NULL };
63 static const char *TS480HX_dataC_tooltip = "center";
64 static const char *TS480HX_dataC_label = "C";
65
66 static const char *TS480HX_AM_SL[] = {
67 "10", "100", "200", "500",
68 NULL };
69
70 static const char *TS480HX_AM_SH[] = {
71 "2500", "3000", "4000", "5000",
72 NULL };
73 //static int TS480HX_AM_bw_vals[] = {1,2,3,4,WVALS_LIMIT};
74
75 static const char *TS480HX_CWwidths[] = {
76 "50", "80", "100", "150", "200",
77 "300", "400", "500", "600", "1000",
78 "2000", NULL};
79 static int TS480HX_CW_bw_vals[] = {1,2,3,4,5,6,7,8,9,10,11,WVALS_LIMIT};
80
81 static const char *TS480HX_CWbw[] = {
82 "FW0050;", "FW0080;", "FW0100;", "FW0150;", "FW0200;",
83 "FW0300;", "FW0400;", "FW0500;", "FW0600;", "FW1000;",
84 "FW2000;" };
85
86 static const char *TS480HX_FSKwidths[] = {
87 "250", "500", "1000", "1500", NULL};
88 static int TS480HX_FSK_bw_vals[] = { 1,2,3,4,WVALS_LIMIT};
89
90 static const char *TS480HX_FSKbw[] = {
91 "FW0250;", "FW0500;", "FW1000;", "FW1500;" };
92
93 static int agcval = 1;
94 static bool fm_mode = false;
95
96 static GUI rig_widgets[]= {
97 { (Fl_Widget *)btnVol, 2, 125, 50 }, // 0
98 { (Fl_Widget *)sldrVOLUME, 54, 125, 156 }, // 1
99 { (Fl_Widget *)sldrRFGAIN, 54, 145, 156 }, // 2
100 { (Fl_Widget *)btnIFsh, 214, 105, 50 }, // 3
101 { (Fl_Widget *)sldrIFSHIFT, 266, 105, 156 }, // 4
102 { (Fl_Widget *)btnDataPort, 214, 125, 50 }, // 5
103 { (Fl_Widget *)sldrSQUELCH, 266, 125, 156 }, // 6
104 { (Fl_Widget *)sldrMICGAIN, 266, 145, 156 }, // 7
105 { (Fl_Widget *)sldrPOWER, 54, 165, 368 }, // 8
106 { (Fl_Widget *)NULL, 0, 0, 0 }
107 };
108
109 static string menu012 = "EX01200004";
110
initialize()111 void RIG_TS480HX::initialize()
112 {
113 rig_widgets[0].W = btnVol;
114 rig_widgets[1].W = sldrVOLUME;
115 rig_widgets[2].W = sldrRFGAIN;
116 rig_widgets[3].W = btnIFsh;
117 rig_widgets[4].W = sldrIFSHIFT;
118 rig_widgets[5].W = btnDataPort;
119 rig_widgets[6].W = sldrSQUELCH;
120 rig_widgets[7].W = sldrMICGAIN;
121 rig_widgets[8].W = sldrPOWER;
122
123 check_menu_45();
124
125 menu012.clear();
126 cmd = "EX0120000;"; // read menu 012 state
127 //might return something like EX01200004;
128
129 if (wait_char(';', 11, 100, "read ex 012", ASC) == 11)
130 menu012 = replystr;
131
132 cmd = "EX01200000;";
133 sendCommand(cmd);
134 }
135
RIG_TS480HX()136 RIG_TS480HX::RIG_TS480HX() {
137 // base class values
138 name_ = TS480HXname_;
139 modes_ = TS480HXmodes_;
140 _mode_type = TS480HX_mode_type;
141 bandwidths_ = TS480HX_empty;
142 bw_vals_ = TS480HX_bw_vals;
143
144 dsp_SL = TS480HX_SL;
145 SL_tooltip = TS480HX_SL_tooltip;
146 SL_label = TS480HX_btn_SL_label;
147
148 dsp_SH = TS480HX_SH;
149 SH_tooltip = TS480HX_SH_tooltip;
150 SH_label = TS480HX_btn_SH_label;
151
152 widgets = rig_widgets;
153
154 comm_baudrate = BR57600;
155 stopbits = 1;
156 comm_retries = 2;
157 comm_wait = 5;
158 comm_timeout = 50;
159 comm_rtscts = true;
160 comm_rtsplus = false;
161 comm_dtrplus = false;
162 comm_catptt = true;
163 comm_rtsptt = false;
164 comm_dtrptt = false;
165 B.imode = A.imode = 1;
166 B.iBW = A.iBW = 0x8A03;
167 B.freq = A.freq = 14070000;
168
169 can_change_alt_vfo = true;
170
171 has_extras = true;
172
173 has_noise_reduction =
174 has_noise_reduction_control =
175 has_auto_notch =
176 has_noise_control =
177 has_sql_control =
178
179 has_split = true;
180 has_split_AB = true;
181 has_data_port = true;
182 has_micgain_control = true;
183 has_ifshift_control = true;
184 has_rf_control = true;
185 has_agc_control = true;
186 has_swr_control = true;
187 has_alc_control = true;
188 has_power_out = true;
189 has_dsp_controls = true;
190 has_smeter = true;
191 has_attenuator_control = true;
192 has_preamp_control = true;
193 has_mode_control = true;
194 has_bandwidth_control = true;
195 has_volume_control = true;
196 has_power_control = true;
197 has_tune_control = true;
198 has_ptt_control = true;
199
200 precision = 1;
201 ndigits = 8;
202
203 _noise_reduction_level = 0;
204 _nrval1 = 2;
205 _nrval2 = 4;
206 }
207
get_bwname_(int n,int md)208 const char * RIG_TS480HX::get_bwname_(int n, int md)
209 {
210 static char bwname[20];
211 if (n > 256) {
212 int hi = (n >> 8) & 0x7F;
213 int lo = n & 0xFF;
214 snprintf(bwname, sizeof(bwname), "%s/%s",
215 (md == 0 || md == 1 || md == 3) ? dsp_SL[lo] : TS480HX_AM_SL[lo],
216 (md == 0 || md == 1 || md == 3) ? dsp_SH[hi] : TS480HX_AM_SH[hi] );
217 } else {
218 snprintf(bwname, sizeof(bwname), "%s",
219 (md == 2 || md == 6) ? TS480HX_CWwidths[n] : TS480HX_FSKwidths[n]);
220 }
221 return bwname;
222 }
223
check_menu_45()224 void RIG_TS480HX::check_menu_45()
225 {
226 // read current switch 45 setting
227 menu_45 = false;
228 cmd = "EX0450000;";
229 if (wait_char(';', 11, 100, "Check menu item 45", ASC) >= 11) {
230 size_t p = replystr.rfind("EX045");
231 if (p != string::npos)
232 menu_45 = (replystr[p+9] == '1');
233 }
234
235 if (menu_45) {
236 dsp_SL = TS480HX_dataW;
237 SL_tooltip = TS480HX_dataW_tooltip;
238 SL_label = TS480HX_dataW_label;
239 dsp_SH = TS480HX_dataC;
240 SH_tooltip = TS480HX_dataC_tooltip;
241 SH_label = TS480HX_dataC_label;
242 B.iBW = A.iBW = 0x8106;
243 } else {
244 dsp_SL = TS480HX_SL;
245 SL_tooltip = TS480HX_SL_tooltip;
246 SL_label = TS480HX_btn_SL_label;
247 dsp_SH = TS480HX_SH;
248 SH_tooltip = TS480HX_SH_tooltip;
249 SH_label = TS480HX_btn_SH_label;
250 B.iBW = A.iBW = 0x8A03;
251 }
252 }
253
shutdown()254 void RIG_TS480HX::shutdown()
255 {
256 // restore state of xcvr beeps
257 if (menu012.empty()) return;
258 cmd = menu012;
259 sendCommand(cmd);
260 }
261
262 // SM cmd 0 ... 100 (rig values 0 ... 15)
get_smeter()263 int RIG_TS480HX::get_smeter()
264 {
265 int mtr = 0;
266 cmd = "SM0;";
267 if (wait_char(';', 8, 100, "get Smeter", ASC) < 8) return 0;
268
269 size_t p = replystr.rfind("SM");
270 if (p != string::npos)
271 mtr = 5 * atoi(&replystr[p + 3]);
272 return mtr;
273 }
274
275 struct pwrpair {int mtr; float pwr;};
276
277 static pwrpair pwrtbl[] = {
278 {0, 0.0},
279 {2, 5.0},
280 {4, 10.0},
281 {7, 25.0},
282 {11, 50.0},
283 {16, 100.0},
284 {20, 200.0} };
285
get_power_out()286 int RIG_TS480HX::get_power_out()
287 {
288 int mtr = 0;
289 cmd = "SM0;";
290 if (wait_char(';', 8, 100, "get power", ASC) < 8) return mtr;
291
292 size_t p = replystr.rfind("SM");
293 if (p != string::npos) {
294 mtr = atoi(&replystr[p + 3]);
295
296 size_t i = 0;
297 for (i = 0; i < sizeof(pwrtbl) / sizeof(pwrpair) - 1; i++)
298 if (mtr >= pwrtbl[i].mtr && mtr < pwrtbl[i+1].mtr)
299 break;
300 if (mtr < 0) mtr = 0;
301 if (mtr > 20) mtr = 20;
302 mtr = (int)ceil(pwrtbl[i].pwr +
303 (pwrtbl[i+1].pwr - pwrtbl[i].pwr)*(mtr - pwrtbl[i].mtr)/(pwrtbl[i+1].mtr - pwrtbl[i].mtr));
304 if (mtr > 200) mtr = 200;
305 }
306 return mtr;
307 }
308
309 // RM cmd 0 ... 100 (rig values 0 ... 8)
310 // User report of RM; command using Send Cmd tab
311 // RM10000;RM20000;RM30000;
312 // RM1nnnn; => SWR
313 // RM2nnnn; => COMP
314 // RM3nnnn; => ALC
315
get_swr()316 int RIG_TS480HX::get_swr()
317 {
318 int mtr = 0;
319 cmd = "RM;";
320 if (wait_char(';', 8, 100, "get SWR/ALC", ASC) < 8) return (int)mtr;
321
322 size_t p = replystr.rfind("RM1");
323 if (p != string::npos)
324 mtr = 66 * atoi(&replystr[p + 3]) / 10;
325 p = replystr.rfind("RM3");
326 if (p != string::npos)
327 alc = 66 * atoi(&replystr[p+3]) / 10;
328 else
329 alc = 0;
330 swralc_polled = true;
331 return mtr;
332 }
333
get_alc(void)334 int RIG_TS480HX::get_alc(void)
335 {
336 if (!swralc_polled) get_swr();
337 swralc_polled = false;
338 return alc;
339 }
340
set_widths(int val)341 int RIG_TS480HX::set_widths(int val)
342 {
343 int bw;
344 if (val == 0 || val == 1 || val == 3) {
345 if (menu_45) {
346 bw = 0x8106; // 1500 Hz 2400 wide
347 dsp_SL = TS480HX_dataW;
348 SL_tooltip = TS480HX_dataW_tooltip;
349 SL_label = TS480HX_dataW_label;
350 dsp_SH = TS480HX_dataC;
351 SH_tooltip = TS480HX_dataC_tooltip;
352 SH_label = TS480HX_dataC_label;
353 bandwidths_ = TS480HX_dataW;
354 bw_vals_ = TS480HX_data_bw_vals;
355 } else {
356 bw = 0x8A03; // 200 ... 3000 Hz
357 dsp_SL = TS480HX_SL;
358 SL_tooltip = TS480HX_SL_tooltip;
359 SL_label = TS480HX_btn_SL_label;
360 dsp_SH = TS480HX_SH;
361 SH_tooltip = TS480HX_SH_tooltip;
362 SH_label = TS480HX_btn_SH_label;
363 bandwidths_ = TS480HX_SH;
364 bw_vals_ = TS480HX_HI_bw_vals;
365 }
366 } else if (val == 2 || val == 6) {
367 bandwidths_ = TS480HX_CWwidths;
368 bw_vals_ = TS480HX_CW_bw_vals;
369 dsp_SL = TS480HX_empty;
370 dsp_SH = TS480HX_empty;
371 bw = 7;
372 } else if (val == 5 || val == 7) {
373 bandwidths_ = TS480HX_FSKwidths;
374 bw_vals_ = TS480HX_FSK_bw_vals;
375 dsp_SL = TS480HX_empty;
376 dsp_SH = TS480HX_empty;
377 bw = 1;
378 } else { // val == 4 ==> AM
379 bandwidths_ = TS480HX_empty;
380 bw_vals_ = TS480HX_bw_vals;
381 dsp_SL = TS480HX_AM_SL;
382 dsp_SH = TS480HX_AM_SH;
383 bw = 0x8201;
384 }
385 return bw;
386 }
387
bwtable(int m)388 const char **RIG_TS480HX::bwtable(int m)
389 {
390 if (m == 0 || m == 1 || m == 3)
391 return TS480HX_empty;
392 else if (m == 2 || m == 6)
393 return TS480HX_CWwidths;
394 else if (m == 5 || m == 7)
395 return TS480HX_FSKwidths;
396 //else AM m == 4
397 return TS480HX_empty;
398 }
399
lotable(int m)400 const char **RIG_TS480HX::lotable(int m)
401 {
402 if (m == 0 || m == 1 || m == 3)
403 return TS480HX_SL;
404 else if (m == 2 || m == 6)
405 return NULL;
406 else if (m == 5 || m == 7)
407 return NULL;
408 return TS480HX_AM_SL;
409 }
410
hitable(int m)411 const char **RIG_TS480HX::hitable(int m)
412 {
413 if (m == 0 || m == 1 || m == 3)
414 return TS480HX_SH;
415 else if (m == 2 || m == 6)
416 return NULL;
417 else if (m == 5 || m == 7)
418 return NULL;
419 return TS480HX_AM_SH;
420 }
421
set_modeA(int val)422 void RIG_TS480HX::set_modeA(int val)
423 {
424 if (val == 3) fm_mode = true;
425 else fm_mode = false;
426 A.imode = val;
427 cmd = "MD";
428 cmd += TS480HX_mode_chr[val];
429 cmd += ';';
430 sendCommand(cmd);
431 showresp(WARN, ASC, "set mode", cmd, "");
432 A.iBW = set_widths(val);
433 }
434
get_modeA()435 int RIG_TS480HX::get_modeA()
436 {
437 cmd = "MD;";
438 if (wait_char(';', 4, 100, "get modeA", ASC) < 4) return A.imode;
439
440 size_t p = replystr.rfind("MD");
441 if (p != string::npos && (p + 2 < replystr.length())) {
442 int md = replystr[p+2];
443 md = md - '1';
444 if (md == 8) md = 7;
445 A.imode = md;
446 A.iBW = set_widths(A.imode);
447 }
448 if (A.imode == 3) fm_mode = true;
449 else fm_mode = false;
450 return A.imode;
451 }
452
set_modeB(int val)453 void RIG_TS480HX::set_modeB(int val)
454 {
455 if (val == 3) fm_mode = true;
456 else fm_mode = false;
457 B.imode = val;
458 cmd = "MD";
459 cmd += TS480HX_mode_chr[val];
460 cmd += ';';
461 sendCommand(cmd);
462 showresp(WARN, ASC, "set mode B", cmd, "");
463 B.iBW = set_widths(val);
464 }
465
get_modeB()466 int RIG_TS480HX::get_modeB()
467 {
468 cmd = "MD;";
469 if (wait_char(';', 4, 100, "get modeB", ASC) < 4) return B.imode;
470
471 size_t p = replystr.rfind("MD");
472 if (p != string::npos && (p + 2 < replystr.length())) {
473 int md = replystr[p+2];
474 md = md - '1';
475 if (md == 8) md = 7;
476 B.imode = md;
477 B.iBW = set_widths(B.imode);
478 }
479 if (B.imode == 3) fm_mode = true;
480 else fm_mode = false;
481 return B.imode;
482 }
483
get_modetype(int n)484 int RIG_TS480HX::get_modetype(int n)
485 {
486 return _mode_type[n];
487 }
488
set_bwA(int val)489 void RIG_TS480HX::set_bwA(int val)
490 {
491 if (A.imode == 0 || A.imode == 1 || A.imode == 3 || A.imode == 4) {
492 if (val < 256) return;
493 A.iBW = val;
494 cmd = "SL";
495 cmd.append(to_decimal(A.iBW & 0xFF, 2)).append(";");
496 sendCommand(cmd);
497 showresp(WARN, ASC, SL_tooltip, cmd, "");
498 cmd = "SH";
499 cmd.append(to_decimal(((A.iBW >> 8) & 0x7F), 2)).append(";");
500 sendCommand(cmd);
501 showresp(WARN, ASC, SH_tooltip, cmd, "");
502 }
503 if (val > 256) return;
504 else if (A.imode == 2 || A.imode == 6) {
505 A.iBW = val;
506 cmd = TS480HX_CWbw[A.iBW];
507 sendCommand(cmd);
508 showresp(WARN, ASC, "set CW bw", cmd, "");
509 }else if (A.imode == 5 || A.imode == 7) {
510 A.iBW = val;
511 cmd = TS480HX_FSKbw[A.iBW];
512 sendCommand(cmd);
513 showresp(WARN, ASC, "set FSK bw", cmd, "");
514 }
515 }
516
get_bwA()517 int RIG_TS480HX::get_bwA()
518 {
519 int i = 0;
520 size_t p;
521
522 bool menu45 = menu_45;
523
524 check_menu_45();
525 if (menu45 != menu_45)
526 Fl::awake(updateBandwidthControl);
527
528 if (A.imode == 0 || A.imode == 1 || A.imode == 3 || A.imode == 4) {
529 int lo = A.iBW & 0xFF, hi = (A.iBW >> 8) & 0x7F;
530 cmd = "SL;";
531 if (wait_char(';', 5, 100, "get SL", ASC) == 5) {
532 p = replystr.rfind("SL");
533 if (p != string::npos)
534 lo = fm_decimal(replystr.substr(p+2), 2);
535 }
536 cmd = "SH;";
537 if (wait_char(';', 5, 100, "get SH", ASC) == 5) {
538 p = replystr.rfind("SH");
539 if (p != string::npos)
540 hi = fm_decimal(replystr.substr(p+2), 2);
541 A.iBW = ((hi << 8) | (lo & 0xFF)) | 0x8000;
542 }
543 } else if (A.imode == 2 || A.imode == 6) {
544 cmd = "FW;";
545 if (wait_char(';', 7, 100, "get FW", ASC) == 7) {
546 p = replystr.rfind("FW");
547 if (p != string::npos) {
548 for (i = 0; i < 11; i++)
549 if (replystr.find(TS480HX_CWbw[i]) == p)
550 break;
551 if (i == 11) i = 10;
552 A.iBW = i;
553 }
554 }
555 } else if (A.imode == 5 || A.imode == 7) {
556 cmd = "FW;";
557 if (wait_char(';', 7, 100, "get FW", ASC) == 7) {
558 p = replystr.rfind("FW");
559 if (p != string::npos) {
560 for (i = 0; i < 4; i++)
561 if (replystr.find(TS480HX_FSKbw[i]) == p)
562 break;
563 if (i == 4) i = 3;
564 A.iBW = i;
565 }
566 }
567 }
568 return A.iBW;
569 }
570
set_bwB(int val)571 void RIG_TS480HX::set_bwB(int val)
572 {
573 if (B.imode == 0 || B.imode == 1 || B.imode == 3 || B.imode == 4) {
574 if (val < 256) return;
575 B.iBW = val;
576 cmd = "SL";
577 cmd.append(to_decimal(B.iBW & 0xFF, 2)).append(";");
578 sendCommand(cmd);
579 showresp(WARN, ASC, SL_tooltip, cmd, "");
580 cmd = "SH";
581 cmd.append(to_decimal(((B.iBW >> 8) & 0x7F), 2)).append(";");
582 sendCommand(cmd);
583 showresp(WARN, ASC, SH_tooltip, cmd, "");
584 }
585 if (val > 256) return;
586 else if (B.imode == 2 || B.imode == 6) { // CW
587 B.iBW = val;
588 cmd = TS480HX_CWbw[B.iBW];
589 sendCommand(cmd);
590 showresp(WARN, ASC, "set CW bw", cmd, "");
591 }else if (B.imode == 5 || B.imode == 7) {
592 B.iBW = val;
593 cmd = TS480HX_FSKbw[B.iBW];
594 sendCommand(cmd);
595 showresp(WARN, ASC, "set FSK bw", cmd, "");
596 }
597 }
598
get_bwB()599 int RIG_TS480HX::get_bwB()
600 {
601 int i = 0;
602 size_t p;
603 bool menu45 = menu_45;
604
605 check_menu_45();
606 if (menu45 != menu_45)
607 Fl::awake(updateBandwidthControl);
608
609 if (B.imode == 0 || B.imode == 1 || B.imode == 3 || B.imode == 4) {
610 int lo = B.iBW & 0xFF, hi = (B.iBW >> 8) & 0x7F;
611 cmd = "SL;";
612 if (wait_char(';', 5, 100, "get SL", ASC) == 5) {
613 p = replystr.rfind("SL");
614 if (p != string::npos)
615 lo = fm_decimal(replystr.substr(p+2), 2);
616 }
617 cmd = "SH;";
618 if (wait_char(';', 5, 100, "get SH", ASC) == 5) {
619 p = replystr.rfind("SH");
620 if (p != string::npos)
621 hi = fm_decimal(replystr.substr(p+2), 2);
622 B.iBW = ((hi << 8) | (lo & 0xFF)) | 0x8000;
623 }
624 } else if (B.imode == 2 || B.imode == 6) {
625 cmd = "FW;";
626 if (wait_char(';', 7, 100, "get FW", ASC) == 7) {
627 p = replystr.rfind("FW");
628 if (p != string::npos) {
629 for (i = 0; i < 11; i++)
630 if (replystr.find(TS480HX_CWbw[i]) == p)
631 break;
632 if (i == 11) i = 10;
633 B.iBW = i;
634 }
635 }
636 } else if (B.imode == 5 || B.imode == 7) {
637 cmd = "FW;";
638 if (wait_char(';', 7, 100, "get FW", ASC) == 7) {
639 p = replystr.rfind("FW");
640 if (p != string::npos) {
641 for (i = 0; i < 4; i++)
642 if (replystr.find(TS480HX_FSKbw[i]) == p)
643 break;
644 if (i == 4) i = 3;
645 B.iBW = i;
646 }
647 }
648 }
649 return B.iBW;
650 }
651
adjust_bandwidth(int val)652 int RIG_TS480HX::adjust_bandwidth(int val)
653 {
654 int bw = 0;
655 if (val == 0 || val == 1 || val == 3)
656 bw = 0x8A03;
657 else if (val == 4)
658 bw = 0x8201;
659 else if (val == 2 || val == 6)
660 bw = 7;
661 else if (val == 5 || val == 7)
662 bw = 1;
663 return bw;
664 }
665
def_bandwidth(int val)666 int RIG_TS480HX::def_bandwidth(int val)
667 {
668 return adjust_bandwidth(val);
669 }
670
671
set_power_control(double val)672 void RIG_TS480HX::set_power_control(double val)
673 {
674 cmd = "PC";
675 char szval[4];
676 if (modeA == 4 && val > 50) val = 50; // AM mode limitation
677 snprintf(szval, sizeof(szval), "%03d", (int)val);
678 cmd += szval;
679 cmd += ';';
680 LOG_WARN("%s", cmd.c_str());
681 sendCommand(cmd);
682 }
683
get_power_control()684 int RIG_TS480HX::get_power_control()
685 {
686 int val = progStatus.power_level;
687 cmd = "PC;";
688 if (wait_char(';', 6, 100, "get Power control", ASC) < 6) return val;
689
690 size_t p = replystr.rfind("PC");
691 if (p == string::npos) return val;
692
693 val = atoi(&replystr[p + 2]);
694
695 return val;
696 }
697
set_attenuator(int val)698 void RIG_TS480HX::set_attenuator(int val)
699 {
700 if (val) cmd = "RA01;";
701 else cmd = "RA00;";
702 LOG_WARN("%s", cmd.c_str());
703 sendCommand(cmd);
704 }
705
get_attenuator()706 int RIG_TS480HX::get_attenuator()
707 {
708 cmd = "RA;";
709 if (wait_char(';', 7, 100, "get attenuator", ASC) < 7) return progStatus.attenuator;
710
711 size_t p = replystr.rfind("RA");
712 if (p == string::npos) return progStatus.attenuator;
713 if (replystr[p+3] == '1') return 1;
714 return 0;
715 }
716
set_preamp(int val)717 void RIG_TS480HX::set_preamp(int val)
718 {
719 if (val) cmd = "PA1;";
720 else cmd = "PA0;";
721 LOG_WARN("%s", cmd.c_str());
722 sendCommand(cmd);
723 }
724
get_preamp()725 int RIG_TS480HX::get_preamp()
726 {
727 cmd = "PA;";
728 if (wait_char(';', 5, 100, "get preamp", ASC) < 5) return progStatus.preamp;
729
730 size_t p = replystr.rfind("PA");
731 if (p == string::npos) return progStatus.preamp;
732 if (replystr[p+2] == '1') return 1;
733 return 0;
734 }
735
set_if_shift(int val)736 void RIG_TS480HX::set_if_shift(int val)
737 {
738 cmd = "IS+";
739 if (val < 0) cmd[2] = '-';
740 cmd.append(to_decimal(abs(val),4)).append(";");
741 sendCommand(cmd);
742 showresp(WARN, ASC, "set IF shift", cmd, "");
743 }
744
get_if_shift(int & val)745 bool RIG_TS480HX::get_if_shift(int &val)
746 {
747 cmd = "IS;";
748 if (wait_char(';', 8, 100, "get IF shift", ASC) == 8) {
749 size_t p = replystr.rfind("IS");
750 if (p != string::npos) {
751 val = fm_decimal(replystr.substr(p+3), 4);
752 if (replystr[p+2] == '-') val *= -1;
753 return (val != 0);
754 }
755 }
756 val = progStatus.shift_val;
757 return progStatus.shift;
758 }
759
get_if_min_max_step(int & min,int & max,int & step)760 void RIG_TS480HX::get_if_min_max_step(int &min, int &max, int &step)
761 {
762 if_shift_min = min = -1100;
763 if_shift_max = max = 1100;
764 if_shift_step = step = 10;
765 if_shift_mid = 0;
766 }
767
768 // Noise Reduction (TS2000.cxx) NR1 only works; no NR2 and don' no why
set_noise_reduction(int val)769 void RIG_TS480HX::set_noise_reduction(int val)
770 {
771 if (val == -1) {
772 return;
773 }
774 _noise_reduction_level = val;
775 if (_noise_reduction_level == 0) {
776 nr_label("NR", false);
777 } else if (_noise_reduction_level == 1) {
778 nr_label("NR1", true);
779 } else if (_noise_reduction_level == 2) {
780 nr_label("NR2", true);
781 }
782 cmd.assign("NR");
783 cmd += '0' + _noise_reduction_level;
784 cmd += ';';
785 sendCommand (cmd);
786 showresp(WARN, ASC, "SET noise reduction", cmd, "");
787 }
788
get_noise_reduction()789 int RIG_TS480HX::get_noise_reduction()
790 {
791 cmd = rsp = "NR";
792 cmd.append(";");
793 if (wait_char(';', 4, 100, "GET noise reduction", ASC) == 4) {
794 size_t p = replystr.rfind(rsp);
795 if (p == string::npos) return _noise_reduction_level;
796 _noise_reduction_level = replystr[p+2] - '0';
797 }
798
799 if (_noise_reduction_level == 1) {
800 nr_label("NR1", true);
801 } else if (_noise_reduction_level == 2) {
802 nr_label("NR2", true);
803 } else {
804 nr_label("NR", false);
805 }
806
807 return _noise_reduction_level;
808 }
809
set_noise_reduction_val(int val)810 void RIG_TS480HX::set_noise_reduction_val(int val)
811 {
812 if (_noise_reduction_level == 0) return;
813 if (_noise_reduction_level == 1) _nrval1 = val;
814 else _nrval2 = val;
815
816 cmd.assign("RL").append(to_decimal(val, 2)).append(";");
817 sendCommand(cmd);
818 showresp(WARN, ASC, "SET_noise_reduction_val", cmd, "");
819 }
820
get_noise_reduction_val()821 int RIG_TS480HX::get_noise_reduction_val()
822 {
823 int nrval = 0;
824 if (_noise_reduction_level == 0) return 0;
825 int val = progStatus.noise_reduction_val;
826 cmd = rsp = "RL";
827 cmd.append(";");
828 if (wait_char(';', 5, 100, "GET noise reduction val", ASC) == 5) {
829 size_t p = replystr.rfind(rsp);
830 if (p == string::npos) {
831 nrval = (_noise_reduction_level == 1 ? _nrval1 : _nrval2);
832 return nrval;
833 }
834 val = atoi(&replystr[p+2]);
835 }
836
837 if (_noise_reduction_level == 1) _nrval1 = val;
838 else _nrval2 = val;
839
840 return val;
841 }
842
get_agc()843 int RIG_TS480HX::get_agc()
844 {
845 cmd = "GT;";
846 wait_char(';', 6, 100, "GET agc val", ASC);
847 size_t p = replystr.rfind("GT");
848 if (p == string::npos) return agcval;
849 if (replystr[4] == ' ') return 0;
850 agcval = replystr[4] - '0' + 1; // '0' == off, '1' = fast, '2' = slow
851 return agcval;
852 }
853
incr_agc()854 int RIG_TS480HX::incr_agc()
855 {
856 if (fm_mode) return 0;
857 agcval++;
858 if (agcval == 4) agcval = 1;
859 cmd.assign("GT00");
860 cmd += (agcval + '0' - 1);
861 cmd += ";";
862 sendCommand(cmd);
863 showresp(WARN, ASC, "SET agc", cmd, replystr);
864 return agcval;
865 }
866
867
868 static const char *agcstrs[] = {"FM", "AGC", "FST", "SLO"};
agc_label()869 const char *RIG_TS480HX::agc_label()
870 {
871 if (fm_mode) return agcstrs[0];
872 return agcstrs[agcval];
873 }
874
agc_val()875 int RIG_TS480HX::agc_val()
876 {
877 if (fm_mode) return 0;
878 return agcval;
879 }
880
881 // Auto Notch, beat canceller (TS2000.cxx) BC1 only, not BC2
set_auto_notch(int v)882 void RIG_TS480HX::set_auto_notch(int v)
883 {
884 cmd = v ? "BC1;" : "BC0;";
885 sendCommand(cmd);
886 showresp(WARN, ASC, "set auto notch", cmd, "");
887
888 }
889
get_auto_notch()890 int RIG_TS480HX::get_auto_notch()
891 {
892 cmd = "BC;";
893 if (wait_char(';', 4, 100, "get auto notch", ASC) == 4) {
894 int anotch = 0;
895 size_t p = replystr.rfind("BC");
896 if (p != string::npos) {
897 anotch = (replystr[p+2] == '1');
898 return anotch;
899 }
900 }
901 return 0;
902 }
903
904 // Noise Blanker (TS2000.cxx)
set_noise(bool b)905 void RIG_TS480HX::set_noise(bool b)
906 {
907 if (b)
908 cmd = "NB1;";
909 else
910 cmd = "NB0;";
911 sendCommand(cmd);
912 showresp(WARN, ASC, "set NB", cmd, "");
913 }
914
get_noise()915 int RIG_TS480HX::get_noise()
916 {
917 cmd = "NB;";
918 if (wait_char(';', 4, 100, "get Noise Blanker", ASC) == 4) {
919 size_t p = replystr.rfind("NB");
920 if (p == string::npos) return 0;
921 if (replystr[p+2] == '0') return 0;
922 }
923 return 1;
924 }
925
926 // Tranceiver PTT on/off
set_PTT_control(int val)927 void RIG_TS480HX::set_PTT_control(int val)
928 {
929 if (val) {
930 if (progStatus.data_port) cmd = "TX1;"; // DTS transmission using ANI input
931 else cmd = "TX0;"; // mic input
932 } else cmd = "RX;";
933 sendCommand(cmd);
934 showresp(WARN, ASC, "set PTT", cmd, "");
935 }
936
get_PTT()937 int RIG_TS480HX::get_PTT()
938 {
939 cmd = "IF;";
940 int ret = wait_char(';', 38, 100, "get VFO", ASC);
941 if (ret < 38) return ptt_;
942 ptt_ = (replybuff[28] == '1');
943 return ptt_;
944 }
945
set_rf_gain(int val)946 void RIG_TS480HX::set_rf_gain(int val)
947 {
948 cmd = "RG";
949 cmd.append(to_decimal(val,3)).append(";");
950 sendCommand(cmd);
951 showresp(WARN, ASC, "set rf gain", cmd, "");
952 }
953
get_rf_gain()954 int RIG_TS480HX::get_rf_gain()
955 {
956 int val = progStatus.rfgain;
957 cmd = "RG;";
958 if (wait_char(';', 6, 100, "get rf gain", ASC) < 6) return val;
959
960 size_t p = replystr.rfind("RG");
961 if (p != string::npos)
962 val = fm_decimal(replystr.substr(p+2), 3);
963 return val;
964 }
965
get_rf_min_max_step(int & min,int & max,int & step)966 void RIG_TS480HX::get_rf_min_max_step(int &min, int &max, int &step)
967 {
968 min = 0; max = 100; step = 1;
969 }
970
971 /*
972 void RIG_TS480HX::selectA()
973 {
974 cmd = "FR0;FT0;";
975 sendCommand(cmd);
976 showresp(WARN, ASC, "Rx on A, Tx on A", cmd, "");
977 }
978
979 void RIG_TS480HX::selectB()
980 {
981 cmd = "FR1;FT1;";
982 sendCommand(cmd);
983 showresp(WARN, ASC, "Rx on B, Tx on B", cmd, "");
984 }
985
986 void RIG_TS480HX::set_split(bool val)
987 {
988 split = val;
989 if (useB) {
990 if (val) {
991 cmd = "FR1;FT0;";
992 sendCommand(cmd);
993 showresp(WARN, ASC, "Rx on B, Tx on A", cmd, "");
994 } else {
995 cmd = "FR1;FT1;";
996 sendCommand(cmd);
997 showresp(WARN, ASC, "Rx on B, Tx on B", cmd, "");
998 }
999 } else {
1000 if (val) {
1001 cmd = "FR0;FT1;";
1002 sendCommand(cmd);
1003 showresp(WARN, ASC, "Rx on A, Tx on B", cmd, "");
1004 } else {
1005 cmd = "FR0;FT0;";
1006 sendCommand(cmd);
1007 showresp(WARN, ASC, "Rx on A, Tx on A", cmd, "");
1008 }
1009 }
1010 }
1011
1012 bool RIG_TS480HX::can_split()
1013 {
1014 return true;
1015 }
1016
1017 int RIG_TS480HX::get_split()
1018 {
1019 size_t p;
1020 int split = 0;
1021 char rx = 0, tx = 0;
1022 // tx vfo
1023 cmd = rsp = "FT";
1024 cmd.append(";");
1025 if (wait_char(';', 4, 100, "get split tx vfo", ASC) == 4) {
1026 p = replystr.rfind(rsp);
1027 if (p == string::npos) return split;
1028 tx = replystr[p+2];
1029 }
1030 // rx vfo
1031 cmd = rsp = "FR";
1032 cmd.append(";");
1033 if (wait_char(';', 4, 100, "get split rx vfo", ASC) == 4) {
1034 p = replystr.rfind(rsp);
1035 if (p == string::npos) return split;
1036 rx = replystr[p+2];
1037 // split test
1038 split = (tx == '1' ? 2 : 0) + (rx == '1' ? 1 : 0);
1039 }
1040
1041 return split;
1042 }
1043
1044 unsigned long int RIG_TS480HX::get_vfoA ()
1045 {
1046 cmd = "FA;";
1047 if (wait_char(';', 14, 100, "get vfo A", ASC) < 14) return A.freq;
1048
1049 size_t p = replystr.rfind("FA");
1050 if (p != string::npos && (p + 12 < replystr.length())) {
1051 int f = 0;
1052 for (size_t n = 2; n < 13; n++)
1053 f = f*10 + replystr[p+n] - '0';
1054 A.freq = f;
1055 }
1056 return A.freq;
1057 }
1058
1059 void RIG_TS480HX::set_vfoA (unsigned long int freq)
1060 {
1061 A.freq = freq;
1062 cmd = "FA00000000000;";
1063 for (int i = 12; i > 1; i--) {
1064 cmd[i] += freq % 10;
1065 freq /= 10;
1066 }
1067 sendCommand(cmd);
1068 showresp(WARN, ASC, "set vfo A", cmd, "");
1069 }
1070
1071 unsigned long int RIG_TS480HX::get_vfoB ()
1072 {
1073 cmd = "FB;";
1074 if (wait_char(';', 14, 100, "get vfo B", ASC) < 14) return B.freq;
1075
1076 size_t p = replystr.rfind("FB");
1077 if (p != string::npos && (p + 12 < replystr.length())) {
1078 int f = 0;
1079 for (size_t n = 2; n < 13; n++)
1080 f = f*10 + replystr[p+n] - '0';
1081 B.freq = f;
1082 }
1083 return B.freq;
1084 }
1085
1086 void RIG_TS480HX::set_vfoB (unsigned long int freq)
1087 {
1088 B.freq = freq;
1089 cmd = "FB00000000000;";
1090 for (int i = 12; i > 1; i--) {
1091 cmd[i] += freq % 10;
1092 freq /= 10;
1093 }
1094 sendCommand(cmd);
1095 showresp(WARN, ASC, "set vfo B", cmd, "");
1096 }
1097
1098 // Squelch (TS990.cxx)
1099 void RIG_TS480HX::set_squelch(int val)
1100 {
1101 cmd = "SQ0";
1102 cmd.append(to_decimal(abs(val),3)).append(";");
1103 sendCommand(cmd);
1104 showresp(INFO, ASC, "set squelch", cmd, "");
1105 }
1106
1107 int RIG_TS480HX::get_squelch()
1108 {
1109 int val = 0;
1110 cmd = "SQ0;";
1111 if (wait_char(';', 7, 20, "get squelch", ASC) >= 7) {
1112 size_t p = replystr.rfind("SQ0");
1113 if (p == string::npos) return val;
1114 replystr[p + 6] = 0;
1115 val = atoi(&replystr[p + 3]);
1116 }
1117 return val;
1118 }
1119
1120 void RIG_TS480HX::get_squelch_min_max_step(int &min, int &max, int &step)
1121 {
1122 min = 0; max = 255; step = 1;
1123 }
1124
1125 void RIG_TS480HX::set_mic_gain(int val)
1126 {
1127 cmd = "MG";
1128 cmd.append(to_decimal(val,3)).append(";");
1129 sendCommand(cmd);
1130 showresp(WARN, ASC, "set mic gain", cmd, "");
1131 }
1132
1133 int RIG_TS480HX::get_mic_gain()
1134 {
1135 int val = progStatus.mic_gain;
1136 cmd = "MG;";
1137 if (wait_char(';', 6, 100, "get mic gain", ASC) < 6) return val;
1138
1139 size_t p = replystr.rfind("MG");
1140 if (p != string::npos)
1141 val = fm_decimal(replystr.substr(p+2), 3);
1142 return val;
1143 }
1144
1145 void RIG_TS480HX::get_mic_min_max_step(int &min, int &max, int &step)
1146 {
1147 min = 0; max = 100; step = 1;
1148 }
1149
1150 void RIG_TS480HX::set_volume_control(int val)
1151 {
1152 cmd = "AG";
1153 char szval[5];
1154 snprintf(szval, sizeof(szval), "%04d", val * 255 / 100);
1155 cmd += szval;
1156 cmd += ';';
1157 LOG_WARN("%s", cmd.c_str());
1158 sendCommand(cmd);
1159 }
1160
1161 int RIG_TS480HX::get_volume_control()
1162 {
1163 int val = progStatus.volume;
1164 cmd = "AG0;";
1165 if (wait_char(';', 7, 100, "get vol", ASC) < 7) return val;
1166
1167 size_t p = replystr.rfind("AG");
1168 if (p == string::npos) return val;
1169 replystr[p + 6] = 0;
1170 val = atoi(&replystr[p + 3]);
1171 val = val * 100 / 255;
1172 return val;
1173 }
1174
1175 void RIG_TS480HX::tune_rig()
1176 {
1177 cmd = "AC111;";
1178 LOG_WARN("%s", cmd.c_str());
1179 sendCommand(cmd);
1180 }
1181
1182 */
1183