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 "TS2000.h"
22 #include "support.h"
23 
24 static const char TS2000name_[] = "TS-2000";
25 
26 static const char *TS2000modes_[] = {
27 	"LSB", "USB", "CW", "FM", "AM", "FSK", "CW-R", "FSK-R", NULL};
28 
29 static const char TS2000_mode_chr[] =  { '1', '2', '3', '4', '5', '6', '7', '9' };
30 static const char TS2000_mode_type[] = { 'L', 'U', 'U', 'U', 'U', 'L', 'L', 'U' };
31 
32 static const char *TS2000_empty[] = { "N/A", NULL };
33 //------------------------------------------------------------------------------
34 static const char *TS2000_SL[] = {
35  "0",   "50", "100", "200", "300",
36 "400",  "500", "600", "700", "800",
37 "900", "1000", NULL };
38 static const char *TS2000_CAT_SL[] = {
39 "SL00;", "SL01;", "SL02;", "SL03;", "SL04;",
40 "SL05;", "SL06;", "SL07;", "SL08;", "SL09;",
41 "SL10;", "SL11;" };
42 static const char *TS2000_SL_tooltip = "lo cut";
43 static const char *TS2000_SSB_btn_SL_label = "L";
44 //------------------------------------------------------------------------------
45 static const char *TS2000_SH[] = {
46 "1400", "1600", "1800", "2000", "2200",
47 "2400", "2600", "2800", "3000", "3400",
48 "4000", "5000", NULL };
49 static const char *TS2000_CAT_SH[] = {
50 "SH00;", "SH01;", "SH02;", "SH03;", "SH04;",
51 "SH05;", "SH06;", "SH07;", "SH08;", "SH09;",
52 "SH10;", "SH11;" };
53 static const char *TS2000_SH_tooltip = "hi cut";
54 static const char *TS2000_SSB_btn_SH_label = "H";
55 //------------------------------------------------------------------------------
56 static const char *TS2000_AM_SL[] = {
57 "0", "100", "200", "500", NULL };
58 static const char *TS2000_AM_SH[] = {
59 "2500", "3000", "4000", "5000" };
60 //------------------------------------------------------------------------------
61 static const char *TS2000_CWwidths[] = {
62 "50", "80", "100", "150", "200",
63 "300", "400", "500", "600", "1000",
64 "2000", NULL};
65 static const char *TS2000_CWbw[] = {
66 "FW0050;", "FW0080;", "FW0100;", "FW0150;", "FW0200;",
67 "FW0300;", "FW0400;", "FW0500;", "FW0600;", "FW1000;",
68 "FW2000;" };
69 //------------------------------------------------------------------------------
70 static const char *TS2000_FSKwidths[] = {
71 "250", "500", "1000", "1500", NULL};
72 static const char *TS2000_FSKbw[] = {
73 "FW0250;", "FW0500;", "FW1000;", "FW1500;" };
74 //------------------------------------------------------------------------------
75 
76 static GUI rig_widgets[]= {
77 	{ (Fl_Widget *)btnVol,        2, 125,  50 }, // 0
78 	{ (Fl_Widget *)sldrVOLUME,   54, 125, 156 }, // 1
79 	{ (Fl_Widget *)sldrRFGAIN,   54, 145, 156 }, // 2
80 	{ (Fl_Widget *)btnIFsh,     214, 105,  50 }, // 3
81 	{ (Fl_Widget *)sldrIFSHIFT, 266, 105, 156 }, // 4
82 	{ (Fl_Widget *)btnNotch,    214, 125,  50 }, // 5
83 	{ (Fl_Widget *)sldrNOTCH,   266, 125, 156 }, // 6
84 	{ (Fl_Widget *)sldrSQUELCH, 266, 145, 156 }, // 7
85 	{ (Fl_Widget *)sldrMICGAIN, 266, 165, 156 }, // 8
86 	{ (Fl_Widget *)sldrPOWER,    54, 165, 368 }, // 9
87 	{ (Fl_Widget *)NULL,          0,   0,   0 }
88 };
89 
90 // mid range on loudness
91 static string menu012 = "EX01200004";
92 
initialize()93 void RIG_TS2000::initialize()
94 {
95 	rig_widgets[0].W = btnVol;
96 	rig_widgets[1].W = sldrVOLUME;
97 	rig_widgets[2].W = sldrRFGAIN;
98 	rig_widgets[3].W = btnIFsh;
99 	rig_widgets[4].W = sldrIFSHIFT;
100 	rig_widgets[5].W = btnNotch;
101 	rig_widgets[6].W = sldrNOTCH;
102 	rig_widgets[7].W = sldrSQUELCH;
103 	rig_widgets[8].W = sldrMICGAIN;
104 	rig_widgets[9].W = sldrPOWER;
105 
106 	menu012.clear();
107 	cmd = "EX0120000;"; // read menu 012 state
108 //might return something like EX01200004;
109 
110 	if (wait_char(';', 11, 100, "read ex 012", ASC) == 11)
111 		menu012 = replystr;
112 
113 // disable beeps before resetting front panel display to SWR
114 	cmd = "EX01200000;";
115 	sendCommand(cmd);
116 	sett("No beeps");
117 	select_swr();
118 
119 // restore state of xcvr beeps
120 //	cmd = menu012;
121 //	sendCommand(cmd);
122 
123 // get current noise reduction values for NR1 and NR2
124 	string current_nr;
125 	cmd = "NR;";
126 	if (wait_char(';', 4, 100, "read current NR", ASC) == 4)
127 		current_nr = replystr;
128 	if (current_nr == "?;") return;
129 
130 	cmd = "NR1;";
131 	sendCommand(cmd);
132 	gett("get NR");
133 	cmd = "RL;";
134 	if (wait_char(';', 5, 100, "GET noise reduction val", ASC) == 5) {
135 		size_t p = replystr.rfind("RL");
136 		if (p != string::npos)
137 			_nrval1 = atoi(&replystr[p+2]);
138 	}
139 	cmd = "NR2;";
140 	sendCommand(cmd);
141 	gett("get NR value");
142 
143 	cmd = "RL;";
144 	if (wait_char(';', 5, 100, "GET noise reduction val", ASC) == 5) {
145 		size_t p = replystr.rfind("RL");
146 		if (p != string::npos)
147 			_nrval2 = atoi(&replystr[p+2]);
148 	}
149 
150 // restore xcvr setting for NR
151 	cmd = current_nr;
152 	sendCommand(cmd);
153 }
154 
shutdown()155 void RIG_TS2000::shutdown()
156 {
157 // restore state of xcvr beeps
158 	if (menu012.empty()) return;
159 	cmd = menu012;
160 	sendCommand(cmd);
161 	sett("restore beeps");
162 }
163 
164 static bool is_tuning = false;
165 static int  skip_get = 2;
166 
RIG_TS2000()167 RIG_TS2000::RIG_TS2000() {
168 // base class values
169 	name_ = TS2000name_;
170 	modes_ = TS2000modes_;
171 	bandwidths_ = TS2000_empty;
172 
173 	dsp_SL     = TS2000_SL;
174 	SL_tooltip = TS2000_SL_tooltip;
175 	SL_label   = TS2000_SSB_btn_SL_label;
176 
177 	dsp_SH     = TS2000_SH;
178 	SH_tooltip = TS2000_SH_tooltip;
179 	SH_label   = TS2000_SSB_btn_SH_label;
180 
181 	widgets = rig_widgets;
182 
183 	comm_baudrate = BR4800;
184 	stopbits = 2;
185 	comm_retries = 2;
186 	comm_wait = 5;
187 	comm_timeout = 50;
188 	comm_rtscts = true;
189 	comm_rtsplus = false;
190 	comm_dtrplus = false;
191 	comm_catptt = true;
192 	comm_rtsptt = false;
193 	comm_dtrptt = false;
194 	B.imode = A.imode = 1;
195 	B.iBW = A.iBW = 0x8803;
196 	B.freq = A.freq = 14070000;
197 	can_change_alt_vfo = true;
198 
199 	has_power_out =
200 	has_swr_control =
201 	has_alc_control =
202 	has_split =
203 	has_split_AB =
204 	has_dsp_controls =
205 	has_rf_control =
206 	has_notch_control =
207 	has_auto_notch =
208 	has_ifshift_control =
209 	has_smeter =
210 	has_noise_reduction =
211 	has_noise_reduction_control =
212 	has_noise_control =
213 	has_micgain_control =
214 	has_volume_control =
215 	has_power_control =
216 	has_tune_control =
217 	has_attenuator_control =
218 	has_preamp_control =
219 	has_mode_control =
220 	has_bandwidth_control =
221 	has_sql_control =
222 	has_ptt_control =
223 	has_extras = true;
224 
225 	rxona = true;
226 
227 	precision = 1;
228 	ndigits = 9;
229 
230 	att_level = 0;
231 	preamp_level = 0;
232 	_noise_reduction_level = 0;
233 	_nrval1 = 2;
234 	_nrval2 = 4;
235 
236 	is_tuning = false;
237 }
238 
get_bwname_(int n,int md)239 const char * RIG_TS2000::get_bwname_(int n, int md)
240 {
241 	static char bwname[20];
242 	if (n > 256) {
243 		int hi = (n >> 8) & 0x7F;
244 		int lo = n & 0xFF;
245 		snprintf(bwname, sizeof(bwname), "%s/%s",
246 			(md == LSB || md == USB || md == FM) ? TS2000_SL[lo] : TS2000_AM_SL[lo],
247 			(md == LSB || md == USB || md == FM) ? TS2000_SH[hi] : TS2000_AM_SH[hi] );
248 	} else {
249 		snprintf(bwname, sizeof(bwname), "%s",
250 			(md == CW || md == CWR) ? TS2000_CWwidths[n] : TS2000_FSKwidths[n]);
251 	}
252 	return bwname;
253 }
254 
get_smeter()255 int RIG_TS2000::get_smeter()
256 {
257 	int smtr = 0;
258 	if (rxona)
259 		cmd = "SM0;";
260 	else
261 		cmd = "SM1;";
262 	if (wait_char(';', 8, 100, "get smeter", ASC) == 8) {
263 		size_t p = replystr.rfind("SM");
264 		if (p != string::npos) {
265 			smtr = fm_decimal(replystr.substr(p+3),4);
266 			if (rxona)
267 				smtr = (smtr * 100) / 30;
268 			else
269 				smtr = (smtr * 100) / 15;
270 		}
271 	}
272 	gett("smeter");
273 	return smtr;
274 }
275 
276 // Transceiver power level
set_power_control(double val)277 void RIG_TS2000::set_power_control(double val)
278 {
279 	int ival = (int)val;
280 	cmd = "PC";
281 	cmd.append(to_decimal(ival, 3)).append(";");
282 	sendCommand(cmd);
283 	showresp(WARN, ASC, "set pwr ctrl", cmd, "");
284 	sett("pwr control");
285 }
286 
get_power_out()287 int RIG_TS2000::get_power_out()
288 {
289 	int poutmtr = 0;
290 	cmd = "SM0;";
291 	if (wait_char(';', 8, 100, "get power out", ASC) == 8) {
292 		size_t p = replystr.rfind("SM0");
293 		if (p != string::npos) {
294 			poutmtr = fm_decimal(replystr.substr(p+3),4);
295 			if (poutmtr <= 6) poutmtr = poutmtr * 2;
296 			else if (poutmtr <= 11) poutmtr = 11 + (poutmtr - 6)*(26 - 11)/(11 - 6);
297 			else if (poutmtr <= 18) poutmtr = 26 + (poutmtr - 11)*(50 - 26)/(18 - 11);
298 			else poutmtr = 50 + (poutmtr - 18)*(100 - 50)/(27 - 18);
299 			if (poutmtr > 100) poutmtr = 100;
300 		}
301 	}
302 	gett("power out");
303 	return poutmtr;
304 }
305 
get_power_control()306 int RIG_TS2000::get_power_control()
307 {
308 	int pctrl = 0;
309 	cmd = "PC;";
310 	if (wait_char(';', 6, 100, "get pout", ASC) == 6) {
311 		size_t p = replystr.rfind("PC");
312 		if (p != string::npos) {
313 			pctrl = fm_decimal(replystr.substr(p+2), 3);
314 		}
315 	}
316 	gett("power control");
317 	return pctrl;
318 }
319 
set_attenuator(int val)320 void RIG_TS2000::set_attenuator(int val)
321 {
322 	att_level = val;
323 	if (val) cmd = "RA01;";
324 	else     cmd = "RA00;";
325 	sendCommand(cmd);
326 	showresp(WARN, ASC, "set ATT", cmd, "");
327 	sett("attenuator");
328 }
329 
get_attenuator()330 int RIG_TS2000::get_attenuator()
331 {
332 	cmd = "RA;";
333 	if (wait_char(';', 7, 100, "get ATT", ASC) == 7) {
334 		size_t p = replystr.rfind("RA");
335 		if (p != string::npos && (p+3 < replystr.length())) {
336 			if (replystr[p+2] == '0' && replystr[p+3] == '0')
337 				att_level = 0;
338 			else
339 				att_level = 1;
340 		}
341 	}
342 	gett("attenuator");
343 	return att_level;
344 }
345 
set_preamp(int val)346 void RIG_TS2000::set_preamp(int val)
347 {
348 	preamp_level = val;
349 	if (val) cmd = "PA1;";
350 	else     cmd = "PA0;";
351 	sendCommand(cmd);
352 	showresp(WARN, ASC, "set PRE", cmd, "");
353 	sett("preamp");
354 }
355 
get_preamp()356 int RIG_TS2000::get_preamp()
357 {
358 	cmd = "PA;";
359 	if (wait_char(';', 5, 100, "get PRE", ASC) == 5) {
360 		size_t p = replystr.rfind("PA");
361 		if (p != string::npos && (p+2 < replystr.length())) {
362 			if (replystr[p+2] == '1')
363 				preamp_level = 1;
364 			else
365 				preamp_level = 0;
366 		}
367 	}
368 	gett("preamp");
369 	return preamp_level;
370 }
371 
set_widths(int val)372 int RIG_TS2000::set_widths(int val)
373 {
374 	int bw;
375 	switch (val) {
376 	case LSB: case USB: case FM:
377 		bandwidths_ = TS2000_SH;
378 		dsp_SL = TS2000_SL;
379 		SL_tooltip = TS2000_SL_tooltip;
380 		SL_label   = TS2000_SSB_btn_SL_label;
381 		dsp_SH = TS2000_SH;
382 		SH_tooltip = TS2000_SH_tooltip;
383 		SH_label   = TS2000_SSB_btn_SH_label;
384 		if (val == FM) bw = 0x8A03; // 200 ... 4000 Hz
385 		else bw = 0x8803; // 200 ... 3000 Hz
386 		break;
387 	case CW: case CWR:
388 		bandwidths_ = TS2000_CWwidths;
389 		dsp_SL = TS2000_empty;
390 		dsp_SH = TS2000_empty;
391 		bw = 7;
392 		break;
393 	case FSK: case FSKR:
394 		bandwidths_ = TS2000_FSKwidths;
395 		dsp_SL = TS2000_empty;
396 		dsp_SH = TS2000_empty;
397 		bw = 1;
398 		break;
399 	case AM: default:
400 		bandwidths_ = TS2000_AM_SH;
401 		dsp_SL = TS2000_AM_SL;
402 		dsp_SH = TS2000_AM_SH;
403 		bw = 0x8201;
404 		break;
405 	}
406 	return bw;
407 }
408 
bwtable(int val)409 const char **RIG_TS2000::bwtable(int val)
410 {
411 	if (val == LSB || val == USB || val == FM)
412 		return TS2000_SH;
413 	else if (val == CW || val == CWR)
414 		return TS2000_CWwidths;
415 	else if (val == FSK || val == FSKR)
416 		return TS2000_FSKwidths;
417 //else AM m == 4
418 	return TS2000_AM_SH;
419 }
420 
lotable(int val)421 const char **RIG_TS2000::lotable(int val)
422 {
423 	if (val == LSB || val == USB || val == FM)
424 		return TS2000_SL;
425 	if (val == AM)
426 		return TS2000_AM_SL;
427 	return NULL;
428 }
429 
hitable(int val)430 const char **RIG_TS2000::hitable(int val)
431 {
432 	if (val == LSB || val == USB || val == FM)
433 		return TS2000_SH;
434 	if (val == AM)
435 		return TS2000_AM_SH;
436 	return NULL;
437 }
438 
set_modeA(int val)439 void RIG_TS2000::set_modeA(int val)
440 {
441 	if (val >= (int)(sizeof(TS2000_mode_chr)/sizeof(*TS2000_mode_chr))) return;
442 	_currmode = A.imode = val;
443 	cmd = "MD";
444 	cmd += TS2000_mode_chr[val];
445 	cmd += ';';
446 	sendCommand(cmd);
447 	showresp(WARN, ASC, "set mode", cmd, "");
448 	sett("modeA");
449 	A.iBW = set_widths(val);
450 }
451 
get_modeA()452 int RIG_TS2000::get_modeA()
453 {
454 	if (tuning()) return A.imode;
455 	if (skip_get) {
456 		skip_get--;
457 		return A.imode;
458 	}
459 	cmd = "MD;";
460 	if (wait_char(';', 4, 100, "get mode A", ASC) == 4) {
461 		size_t p = replystr.rfind("MD");
462 		if (p != string::npos) {
463 			int md = replystr[p+2];
464 			md = md - '1';
465 			if (md == 8) md = 7;
466 			A.imode = md;
467 			A.iBW = set_widths(A.imode);
468 		}
469 	}
470 	_currmode = A.imode;
471 	gett("modeA");
472 	return A.imode;
473 }
474 
set_modeB(int val)475 void RIG_TS2000::set_modeB(int val)
476 {
477 	if (val >= (int)(sizeof(TS2000_mode_chr)/sizeof(*TS2000_mode_chr))) return;
478 	_currmode = B.imode = val;
479 	cmd = "MD";
480 	cmd += TS2000_mode_chr[val];
481 	cmd += ';';
482 	sendCommand(cmd);
483 	showresp(WARN, ASC, "set mode B", cmd, "");
484 	sett("modeB");
485 	B.iBW = set_widths(val);
486 }
487 
get_modeB()488 int RIG_TS2000::get_modeB()
489 {
490 	if (tuning()) return B.imode;
491 	if (skip_get) return B.imode;
492 	cmd = "MD;";
493 	if (wait_char(';', 4, 100, "get mode B", ASC) == 4) {
494 		size_t p = replystr.rfind("MD");
495 		if (p != string::npos) {
496 			int md = replystr[p+2];
497 			md = md - '1';
498 			if (md == 8) md = 7;
499 			B.imode = md;
500 			B.iBW = set_widths(B.imode);
501 		}
502 	}
503 	_currmode = B.imode;
504 	gett("modeB");
505 	return B.imode;
506 }
507 
adjust_bandwidth(int val)508 int RIG_TS2000::adjust_bandwidth(int val)
509 {
510 	int bw = 0;
511 	if (val == LSB || val == USB)
512 		bw = 0x8803;
513 	else if (val == FM)
514 		bw = 0x8A03;
515 	else if (val == AM)
516 		bw = 0x8301;
517 	else if (val == CW || val == CWR)
518 		bw = 7;
519 	else if (val == FSK || val == FSKR)
520 		bw = 1;
521 	return bw;
522 }
523 
def_bandwidth(int val)524 int RIG_TS2000::def_bandwidth(int val)
525 {
526 	return adjust_bandwidth(val);
527 }
528 
set_bwA(int val)529 void RIG_TS2000::set_bwA(int val)
530 {
531 	if (A.imode == LSB || A.imode == USB || A.imode == FM || A.imode == AM) {
532 		if (val < 256) return;
533 		A.iBW = val;
534 		cmd = "SL";
535 		int index = A.iBW & 0x7F;
536 		if (index >= (int)(sizeof(TS2000_CAT_SL)/sizeof(*TS2000_CAT_SL))) return;
537 		cmd = TS2000_CAT_SL[index];
538 		sendCommand(cmd);
539 		showresp(WARN, ASC, "set lower", cmd, "");
540 		sett("bwA lower");
541 		cmd = "SH";
542 		index = (A.iBW >> 8) & 0x7F;
543 		if (index >= (int)(sizeof(TS2000_CAT_SH)/sizeof(*TS2000_CAT_SH))) return;
544 		cmd = TS2000_CAT_SH[index];
545 		sendCommand(cmd);
546 		showresp(WARN, ASC, "set upper", cmd, "");
547 		sett("bwA upper");
548 	}
549 	if (val > 256) return;
550 	else if (A.imode == CW || A.imode == CWR) {
551 		A.iBW = val;
552 		int index = A.iBW & 0x7F;
553 		if (index >= (int)(sizeof(TS2000_CWbw)/sizeof(*TS2000_CWbw))) return;
554 		cmd = TS2000_CWbw[index];
555 		sendCommand(cmd);
556 		showresp(WARN, ASC, "set CW bw", cmd, "");
557 		sett("CW bw");
558 	}else if (A.imode == FSK || A.imode == FSKR) {
559 		A.iBW = val;
560 		int index = A.iBW & 0x7F;
561 		if (index >= (int)(sizeof(TS2000_FSKbw)/sizeof(*TS2000_FSKbw))) return;
562 		cmd = TS2000_FSKbw[index];
563 		sendCommand(cmd);
564 		showresp(WARN, ASC, "set FSK bw", cmd, "");
565 		sett("FSK bw");
566 	}
567 }
568 
get_bwA()569 int RIG_TS2000::get_bwA()
570 {
571 	if (tuning()) return A.iBW;
572 	if (skip_get) return A.iBW;
573 	size_t i = 0;
574 	size_t p;
575 	if (A.imode == LSB || A.imode == USB || A.imode == FM || A.imode == AM) {
576 		int lo = A.iBW & 0xFF, hi = (A.iBW >> 8) & 0x7F;
577 		cmd = "SL;";
578 		if (wait_char(';', 5, 100, "get SL", ASC) == 5) {
579 			p = replystr.rfind("SL");
580 			if (p != string::npos)
581 				lo = fm_decimal(replystr.substr(2), 2);
582 		}
583 		gett("bwA lower");
584 		cmd = "SH;";
585 		if (wait_char(';', 5, 100, "get SH", ASC) == 5) {
586 			p = replystr.rfind("SH");
587 			if (p != string::npos)
588 				hi = fm_decimal(replystr.substr(2), 2);
589 			A.iBW = ((hi << 8) | (lo & 0xFF)) | 0x8000;
590 		}
591 		gett("bwA upper");
592 	} else if (A.imode == CW || A.imode == CWR) { // CW
593 		cmd = "FW;";
594 		if (wait_char(';', 7, 100, "get FW", ASC) == 7) {
595 			p = replystr.rfind("FW");
596 			if (p != string::npos) {
597 				for (i = 0; i < sizeof(TS2000_CWbw)/sizeof(*TS2000_CWbw); i++)
598 					if (replystr.find(TS2000_CWbw[i]) == p)
599 						break;
600 				A.iBW = i;
601 			}
602 		}
603 		gett("bwA CW");
604 	} else if (A.imode == FSK || A.imode == FSKR) {
605 		cmd = "FW;";
606 		if (wait_char(';', 7, 100, "get FW", ASC) == 7) {
607 			p = replystr.rfind("FW");
608 			if (p != string::npos) {
609 				for (i = 0; i < sizeof(TS2000_FSKbw)/sizeof(*TS2000_FSKbw); i++)
610 					if (replystr.find(TS2000_FSKbw[i]) == p)
611 						break;
612 				A.iBW = i;
613 			}
614 		}
615 		gett("bwA FSK");
616 	}
617 	return A.iBW;
618 }
619 
set_bwB(int val)620 void RIG_TS2000::set_bwB(int val)
621 {
622 	if (B.imode == LSB || B.imode == USB || B.imode == FM || B.imode == AM) {
623 		if (val < 256) return;
624 		B.iBW = val;
625 		cmd = "SL";
626 		int index = B.iBW & 0x7F;
627 		if (index >= (int)(sizeof(TS2000_CAT_SL)/sizeof(*TS2000_CAT_SL))) return;
628 		cmd = TS2000_CAT_SL[index];
629 		sendCommand(cmd);
630 		showresp(WARN, ASC, "set lower", cmd, "");
631 		sett("bwB lower");
632 		cmd = "SH";
633 		index = (B.iBW >> 8) & 0x7F;
634 		if (index >= (int)(sizeof(TS2000_CAT_SH)/sizeof(*TS2000_CAT_SH))) return;
635 		cmd = TS2000_CAT_SH[index];
636 		sendCommand(cmd);
637 		showresp(WARN, ASC, "set upper", cmd, "");
638 		sett("bwB upper");
639 	}
640 	if (val > 256) return;
641 	else if (B.imode == CW || B.imode == CWR) {
642 		B.iBW = val;
643 		int index = B.iBW & 0x7F;
644 		if (index >= (int)(sizeof(TS2000_CWbw)/sizeof(*TS2000_CWbw))) return;
645 		cmd = TS2000_CWbw[index];
646 		sendCommand(cmd);
647 		showresp(WARN, ASC, "set CW bw", cmd, "");
648 		sett("bwB CW");
649 	}else if (B.imode == FSK || B.imode == FSKR) {
650 		B.iBW = val;
651 		int index = B.iBW & 0x7F;
652 		if (index >= (int)(sizeof(TS2000_FSKbw)/sizeof(*TS2000_FSKbw))) return;
653 		cmd = TS2000_FSKbw[index];
654 		sendCommand(cmd);
655 		showresp(WARN, ASC, "set FSK bw", cmd, "");
656 		sett("bwB FSK");
657 	}
658 }
659 
get_bwB()660 int RIG_TS2000::get_bwB()
661 {
662 	if (tuning()) return B.iBW;
663 	if (skip_get) return B.iBW;
664 	size_t i = 0;
665 	size_t p;
666 	if (B.imode == LSB || B.imode == USB || B.imode == FM || B.imode == AM) {
667 		int lo = B.iBW & 0xFF, hi = (B.iBW >> 8) & 0x7F;
668 		cmd = "SL;";
669 		if (wait_char(';', 5, 100, "get SL", ASC) == 5) {
670 			p = replystr.rfind("SL");
671 			if (p != string::npos)
672 				lo = fm_decimal(replystr.substr(2), 2);
673 		}
674 		gett("bwB lower");
675 		cmd = "SH;";
676 		if (wait_char(';', 5, 100, "get SH", ASC) == 5) {
677 			p = replystr.rfind("SH");
678 			if (p != string::npos)
679 				hi = fm_decimal(replystr.substr(2), 2);
680 			B.iBW = ((hi << 8) | (lo & 0xFF)) | 0x8000;
681 		}
682 		gett("bwB upper");
683 	} else if (B.imode == CW || B.imode == CWR) {
684 		cmd = "FW;";
685 		if (wait_char(';', 7, 100, "get FW", ASC) == 7) {
686 			p = replystr.rfind("FW");
687 			if (p != string::npos) {
688 				for (i = 0; i < sizeof(TS2000_CWbw)/sizeof(*TS2000_CWbw); i++)
689 					if (replystr.find(TS2000_CWbw[i]) == p)
690 						break;
691 				B.iBW = i;
692 			}
693 		}
694 		gett("bwB CW");
695 	} else if (B.imode == FSK || B.imode == FSKR) {
696 		cmd = "FW;";
697 		if (wait_char(';', 7, 100, "get FW", ASC) == 7) {
698 			p = replystr.rfind("FW");
699 			if (p != string::npos) {
700 				for (i = 0; i < sizeof(TS2000_FSKbw)/sizeof(*TS2000_FSKbw); i++)
701 					if (replystr.find(TS2000_FSKbw[i]) == p)
702 						break;
703 				B.iBW = i;
704 			}
705 		}
706 		gett("bwB FSK");
707 	}
708 	return B.iBW;
709 }
710 
get_modetype(int n)711 int RIG_TS2000::get_modetype(int n)
712 {
713 	if (n >= (int)(sizeof(TS2000_mode_type)/sizeof(*TS2000_mode_type))) return 0;
714 	return TS2000_mode_type[n];
715 }
716 
get_if_min_max_step(int & min,int & max,int & step)717 void RIG_TS2000::get_if_min_max_step(int &min, int &max, int &step)
718 {
719 	if_shift_min = min = 400;
720 	if_shift_max = max = 1000;
721 	if_shift_step = step = 50;
722 	if_shift_mid = 700;
723 }
724 
set_notch(bool on,int val)725 void RIG_TS2000::set_notch(bool on, int val)
726 {
727 	if (on) {
728 		cmd = "BC2;"; // set manual notch
729 		sendCommand(cmd);
730 		showresp(WARN, ASC, "set notch on", cmd, "");
731 		sett("notch ON");
732 		cmd = "BP";
733 //		val = round((val - 220) / 50);
734 		val = round((val - 200) / 50);
735 		cmd.append(to_decimal(val, 3)).append(";");
736 		sendCommand(cmd);
737 		showresp(WARN, ASC, "set notch val", cmd, "");
738 		sett("notch val");
739 	} else {
740 		cmd = "BC0;"; // no notch action
741 		sendCommand(cmd);
742 		showresp(WARN, ASC, "set notch off", cmd, "");
743 		sett("notch OFF");
744 	}
745 }
746 
get_notch(int & val)747 bool  RIG_TS2000::get_notch(int &val)
748 {
749 	bool ison = false;
750 	cmd = "BC;";
751 	if (wait_char(';', 4, 100, "get notch on/off", ASC) == 4) {
752 		size_t p = replystr.rfind("BC");
753 		if (p != string::npos) {
754 			if (replystr[p+2] == '2') {
755 				ison = true;
756 				cmd = "BP;";
757 				if (wait_char(';', 6, 100, "get notch val", ASC) == 6) {
758 					gett("notch val");
759 					p = replystr.rfind("BP");
760 					if (p != string::npos)
761 						val = 200 + 50 * fm_decimal(replystr.substr(p+2),3);
762 				}
763 			}
764 		}
765 	}
766 	gett("notch on/off");
767 	return (ison);
768 }
769 
get_notch_min_max_step(int & min,int & max,int & step)770 void RIG_TS2000::get_notch_min_max_step(int &min, int &max, int &step)
771 {
772 	min = 200;
773 	max = 3350;
774 	step = 50;
775 }
776 
set_auto_notch(int v)777 void RIG_TS2000::set_auto_notch(int v)
778 {
779 	cmd = v ? "NT1;" : "NT0;";
780 	sendCommand(cmd);
781 	showresp(WARN, ASC, "set auto notch", cmd, "");
782 	sett("auto notch");
783 }
784 
get_auto_notch()785 int  RIG_TS2000::get_auto_notch()
786 {
787 	int anotch = 0;
788 	cmd = "NT;";
789 	if (wait_char(';', 4, 100, "get auto notch", ASC) == 4) {
790 		size_t p = replystr.rfind("NT");
791 		if (p != string::npos) {
792 			anotch = (replystr[p+2] == '1');
793 		}
794 	}
795 	gett("auto notch");
796 	return anotch;
797 }
798 
set_noise_reduction(int val)799 void RIG_TS2000::set_noise_reduction(int val)
800 {
801 	if (val == -1) {
802 		return;
803 	}
804 	_noise_reduction_level = val;
805 	if (_noise_reduction_level == 0) {
806 		nr_label("NR", false);
807 	} else if (_noise_reduction_level == 1) {
808 		nr_label("NR1", true);
809 	} else if (_noise_reduction_level == 2) {
810 		nr_label("NR2", true);
811 	}
812 	cmd.assign("NR");
813 	cmd += '0' + _noise_reduction_level;
814 	cmd += ';';
815 	sendCommand (cmd);
816 	showresp(WARN, ASC, "SET noise reduction", cmd, "");
817 	sett("noise reduction");
818 }
819 
get_noise_reduction()820 int  RIG_TS2000::get_noise_reduction()
821 {
822 	cmd = rsp = "NR";
823 	cmd.append(";");
824 	if (wait_char(';', 4, 100, "GET noise reduction", ASC) == 4) {
825 		size_t p = replystr.rfind(rsp);
826 		if (p == string::npos) return _noise_reduction_level;
827 		_noise_reduction_level = replystr[p+2] - '0';
828 	}
829 	if (replystr == "?;") {
830 		_noise_reduction_level = 0;
831 		return 0;
832 	}
833 
834 	if (_noise_reduction_level == 1) {
835 		nr_label("NR1", true);
836 	} else if (_noise_reduction_level == 2) {
837 		nr_label("NR2", true);
838 	} else {
839 		nr_label("NR", false);
840 	}
841 	gett("nr level");
842 	return _noise_reduction_level;
843 }
844 
set_noise_reduction_val(int val)845 void RIG_TS2000::set_noise_reduction_val(int val)
846 {
847 	if (_noise_reduction_level == 0) return;
848 	if (_noise_reduction_level == 1) _nrval1 = val;
849 	else _nrval2 = val;
850 
851 	cmd.assign("RL").append(to_decimal(val, 2)).append(";");
852 	sendCommand(cmd);
853 	showresp(WARN, ASC, "SET_noise_reduction_val", cmd, "");
854 	sett("noise reduction val");
855 }
856 
get_noise_reduction_val()857 int  RIG_TS2000::get_noise_reduction_val()
858 {
859 	int nrval = 0;
860 	if (_noise_reduction_level == 0) return 0;
861 	int val = progStatus.noise_reduction_val;
862 	cmd = rsp = "RL";
863 	cmd.append(";");
864 	if (wait_char(';', 5, 100, "GET noise reduction val", ASC) == 5) {
865 		size_t p = replystr.rfind(rsp);
866 		if (p == string::npos) {
867 			nrval = (_noise_reduction_level == 1 ? _nrval1 : _nrval2);
868 			return nrval;
869 		}
870 		val = atoi(&replystr[p+2]);
871 	}
872 	gett("noise reduction val");
873 
874 	if (_noise_reduction_level == 1) _nrval1 = val;
875 	else _nrval2 = val;
876 
877 	return val;
878 }
879