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