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 <stdlib.h>
22 #include <stdio.h>
23 #include <iostream>
24 #include <sstream>
25 
26 #include "FT450D.h"
27 #include "rig.h"
28 
29 #define FL450D_WAIT_TIME 200
30 
31 static const char FT450Dname_[] = "FT-450D";
32 
33 enum mFT450D {
34   mLSB, mUSB, mCW, mFM, mAM, mRTTY_L, mCW_R, mDATA_L, mRTTY_U, mFM_N, mDATA_U };
35 //  0,    1,   2,   3,   4,    5,       6,     7,       8,        9,    10		mode index
36 
37 #undef  NUM_MODES
38 #define NUM_MODES  11
39 
40 static int mode_bwA[NUM_MODES] = {-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1};
41 static int mode_bwB[NUM_MODES] = {-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1};
42 
43 static const char *FT450Dmodes_[] = {
44 		"LSB", "USB", "CW", "FM", "AM", "RTTY-L", "CW-R", "DATA-L", "RTTY-U", "FM-N", "DATA-U", NULL};
45 static const char mode_chr[] =  { '1', '2', '3', '4', '5', '6', '7', '8', '9', 'B', 'C' };
46 static const char mode_type[] = { 'L', 'U', 'U', 'U', 'U', 'L', 'L', 'L', 'U', 'U', 'U' };
47 
48 static const char *FT450D_ssb_widths[]  = {"1800", "2400", "3000", NULL};
49 static int FT450D_wvals_ssb_widths[] = {1, 2, 3, WVALS_LIMIT};
50 
51 static const char *FT450D_cw_widths[]   = {"300", "500", "2400", NULL};
52 static int FT450D_wvals_cw_widths[] = {1, 2, 3, WVALS_LIMIT};
53 
54 static const char *FT450D_data_widths[] = {"300", "2400", "3000", NULL};
55 static int FT450D_wvals_data_widths[] = {1, 2, 3, WVALS_LIMIT};
56 
57 static const char *FT450D_am_widths[]   = {"3000", "6000", "9000", NULL};
58 static int FT450D_wvals_am_widths[] = {1, 2, 3, WVALS_LIMIT};
59 
60 static const char *FT450D_fm_widths[]   = {"2500", "5000", NULL};
61 static int FT450D_wvals_fm_widths[] = {1, 2, WVALS_LIMIT};
62 
63 static const int FT450D_def_bw[] = {
64   2, 2, 0, 1, 1, 0, 0, 1, 0, 1, 1 };
65 
66 /*
67 static const char *FT450D_US_60m[] = {NULL, "126", "127", "128", "130", NULL};
68 // US has 5 60M presets. Using dummy numbers for all.
69 // First NULL means skip 60m sets in get_band_selection().
70 // Maybe someone can do a cat command MC; on all 5 presets and add returned numbers above.
71 // To send cat commands in flrig goto menu Config->Xcvr select->Send Cmd.
72 // US 60M 5-USB, 5-CW
73 
74 static const char **Channels_60m = FT450D_US_60m;
75 */
76 
77 static GUI rig_widgets[]= {
78 	{ (Fl_Widget *)btnVol,        2, 125,  50 },
79 	{ (Fl_Widget *)sldrVOLUME,   54, 125, 156 },
80 	{ (Fl_Widget *)btnAGC,        2, 145,  50 },
81 	{ (Fl_Widget *)sldrRFGAIN,   54, 145, 156 },
82 	{ (Fl_Widget *)btnIFsh,     214, 105,  50 },
83 	{ (Fl_Widget *)sldrIFSHIFT, 266, 105, 156 },
84 	{ (Fl_Widget *)btnNotch,    214, 125,  50 },
85 	{ (Fl_Widget *)sldrNOTCH,   266, 125, 156 },
86 	{ (Fl_Widget *)sldrMICGAIN, 266, 145, 156 },
87 	{ (Fl_Widget *)sldrPOWER,   266, 165, 156 },
88 	{ (Fl_Widget *)btnNR,         2, 165,  50 },
89 	{ (Fl_Widget *)sldrNR,       54, 165, 156 },
90 	{ (Fl_Widget *)NULL,          0,   0,   0 }
91 };
92 
RIG_FT450D()93 RIG_FT450D::RIG_FT450D() {
94 // base class values
95 	IDstr = "ID";
96 	name_ = FT450Dname_;
97 	modes_ = FT450Dmodes_;
98 	bandwidths_ = FT450D_ssb_widths;
99 	bw_vals_ = FT450D_wvals_ssb_widths;
100 
101 	widgets = rig_widgets;
102 
103 	comm_baudrate = BR38400;
104 	stopbits = 1;
105 	comm_retries = 2;
106 	comm_wait = 5;
107 	comm_timeout = 50;
108 	comm_rtscts = true;
109 	comm_rtsplus = false;
110 	comm_dtrplus = false;
111 	comm_catptt = true;
112 	comm_rtsptt = false;
113 	comm_dtrptt = false;
114 	modeA = 1;
115 	bwA = 2;
116 	def_mode = 10;
117 	def_bw = 2;
118 	def_freq = 14070000;
119 
120 	precision = 10;
121 	ndigits = 8;
122 
123 	has_a2b =
124 	can_change_alt_vfo =
125 	has_xcvr_auto_on_off =
126 	has_noise_reduction =
127 	has_noise_reduction_control =
128 	has_band_selection =
129 	has_extras =
130 	has_vox_onoff =
131 	has_vox_gain =
132 	has_vox_hang =
133 
134 	has_cw_wpm =
135 	has_cw_keyer =
136 //	has_cw_vol =
137 	has_cw_spot =
138 	has_cw_spot_tone =
139 	has_cw_qsk =
140 	has_cw_weight =
141 	has_cw_delay =
142 	has_cw_break_in =
143 
144 	has_split =
145 	has_split_AB =
146 	has_getvfoAorB =
147 	has_smeter =
148 	has_swr_control =
149 	has_alc_control =
150 	has_power_out =
151 	has_power_control =
152 	has_volume_control =
153 	has_agc_control =
154 	has_rf_control =
155 	has_mode_control =
156 	has_noise_control =
157 	has_bandwidth_control =
158 	has_micgain_control =
159 	has_notch_control =
160 	has_attenuator_control =
161 	has_preamp_control =
162 	has_ifshift_control =
163 	has_ptt_control =
164 	has_tune_control = true;
165 
166 	has_band_selection = true;
167 
168 // derived specific
169 	notch_on = false;
170 	m_60m_indx = 0;
171 
172 	precision = 1;
173 	ndigits = 8;
174 }
175 
initialize()176 void RIG_FT450D::initialize()
177 {
178 	LOG_INFO("%s", "Initializing FT-450D");
179 
180 	rig_widgets[0].W = btnVol;
181 	rig_widgets[1].W = sldrVOLUME;
182 	rig_widgets[2].W = btnAGC;
183 	rig_widgets[3].W = sldrRFGAIN;
184 	rig_widgets[4].W = btnIFsh;
185 	rig_widgets[5].W = sldrIFSHIFT;
186 	rig_widgets[6].W = btnNotch;
187 	rig_widgets[7].W = sldrNOTCH;
188 	rig_widgets[8].W = sldrMICGAIN;
189 	rig_widgets[9].W = sldrPOWER;
190 	rig_widgets[10].W = btnNR;
191 	rig_widgets[11].W = sldrNR;
192 
193 	op_yaesu_select60->deactivate();
194 
195 // set progStatus defaults
196 	if (progStatus.noise_reduction_val < 1) progStatus.noise_reduction_val = 1;
197 
198 // turn off auto information mode
199 	sendCommand("AI0;");
200 
201 	get_cw_weight();
202 	get_cw_wpm();
203 	get_break_in();
204 	get_qsk();
205 	get_qsk_delay();
206 	get_cw_spot_tone();
207 	get_vox_gain();
208 	get_vox_hang();
209 
210 	preamp_label("IPO", false);
211 
212 	selectA();
213 }
214 
selectA()215 void RIG_FT450D::selectA()
216 {
217 	cmd = "VS0;";
218 	sendCommand(cmd);
219 	showresp(WARN, ASC, "select vfo A", cmd, replystr);
220 	sett("selectA");
221 }
222 
selectB()223 void RIG_FT450D::selectB()
224 {
225 	cmd = "VS1;";
226 	sendCommand(cmd);
227 	showresp(WARN, ASC, "select vfo B", cmd, replystr);
228 	sett("selectB");
229 }
230 
A2B()231 void RIG_FT450D::A2B()
232 {
233 	cmd = "VV;";
234 	sendCommand(cmd);
235 	showresp(WARN, ASC, "vfo A --> B", cmd, replystr);
236 	sett("A2B");
237 }
238 
check()239 bool RIG_FT450D::check()
240 {
241 	cmd = rsp = "FA";
242 	cmd += ';';
243 	int ret = wait_char(';',11, FL450D_WAIT_TIME, "check", ASC);
244 
245 	gett("check");
246 
247 	if (ret >= 11) return true;
248 	return false;
249 }
250 
get_vfoA()251 unsigned long int RIG_FT450D::get_vfoA ()
252 {
253 	cmd = rsp = "FA";
254 	cmd += ';';
255 	wait_char(';',11, FL450D_WAIT_TIME, "get vfo A", ASC);
256 
257 	gett("get_vfoA");
258 
259 	size_t p = replystr.rfind(rsp);
260 	if (p == string::npos) return freqA;
261 	int f = 0;
262 	for (size_t n = 2; n < 10; n++)
263 		f = f*10 + replystr[p+n] - '0';
264 	freqA = f;
265 	return freqA;
266 }
267 
set_vfoA(unsigned long int freq)268 void RIG_FT450D::set_vfoA (unsigned long int freq)
269 {
270 	if (useB) selectA();
271 	freqA = freq;
272 	cmd = "FA00000000;";
273 	for (int i = 9; i > 1; i--) {
274 		cmd[i] += freq % 10;
275 		freq /= 10;
276 	}
277 	sendCommand(cmd);
278 	showresp(WARN, ASC, "SET vfo A", cmd, replystr);
279 	sett("set_vfoA");
280 	if (useB) selectB();
281 }
282 
get_vfoB()283 unsigned long int RIG_FT450D::get_vfoB ()
284 {
285 	cmd = rsp = "FB";
286 	cmd += ';';
287 	wait_char(';',11, FL450D_WAIT_TIME, "get vfo B", ASC);
288 
289 	gett("get_vfoB");
290 
291 	size_t p = replystr.rfind(rsp);
292 	if (p == string::npos) return freqB;
293 	int f = 0;
294 	for (size_t n = 2; n < 10; n++)
295 		f = f*10 + replystr[p+n] - '0';
296 	freqB = f;
297 	return freqB;
298 }
299 
set_vfoB(unsigned long int freq)300 void RIG_FT450D::set_vfoB (unsigned long int freq)
301 {
302 	if (!useB) selectB();
303 	freqB = freq;
304 	cmd = "FB00000000;";
305 	for (int i = 9; i > 1; i--) {
306 		cmd[i] += freq % 10;
307 		freq /= 10;
308 	}
309 	sendCommand(cmd);
310 	showresp(WARN, ASC, "SET vfo B", cmd, replystr);
311 	sett("set_vfoB");
312 	if (!useB) selectA();
313 }
314 
get_vfoAorB()315 int RIG_FT450D::get_vfoAorB()
316 {
317 	size_t p;
318 	cmd = rsp = "VS";
319 	cmd.append(";");
320 	wait_char(';', 4, FL450D_WAIT_TIME, "get vfo A/B", ASC);
321 	gett("get vfo A/B");
322 	p = replystr.rfind(rsp);
323 	return (replystr[p+2] == '1');
324 }
325 
set_split(bool on)326 void RIG_FT450D::set_split(bool on)
327 {
328 	if (useB) {
329 		if (on) cmd = "FT0;";
330 		else cmd = "FT1;";
331 	} else {
332 		if (on) cmd = "FT1;";
333 		else cmd = "FT0;";
334 	}
335 	sendCommand(cmd);
336 	showresp(WARN, ASC, "SET split", cmd, replystr);
337 	sett("set_split");
338 }
339 
get_split()340 int RIG_FT450D::get_split()
341 {
342 	size_t p;
343 	int split = 0;
344 	char tx;
345 // tx vfo
346 	cmd = rsp = "FT";
347 	cmd.append(";");
348 	wait_char(';',4, FL450D_WAIT_TIME, "get split tx vfo", ASC);
349 	gett("get_split");
350 
351 	p = replystr.rfind(rsp);
352 	if (p == string::npos) return false;
353 	tx = replystr[p+2];
354 
355 	if (useB)
356 		split = (tx == '0');
357 	else
358 		split = (tx == '1');
359 
360 	return split;
361 }
362 
363 struct mtrpair {int val; float mtr;};
364 
365 static mtrpair sm_tbl[] = {
366 {0, 0.0},
367 {18, 6.0},
368 {51, 17.0},
369 {85, 28.0},
370 {118, 39.0},
371 {151, 50.0},
372 {255, 100.0} };
373 
get_smeter()374 int RIG_FT450D::get_smeter()
375 {
376 	cmd = rsp = "SM0";
377 	cmd += ';';
378 	wait_char(';',7, FL450D_WAIT_TIME, "get smeter", ASC); // sets replystr via rigbase
379 	gett("get_smeter");
380 
381 	size_t p = replystr.rfind(rsp);
382 	if (p == string::npos) return 0;
383 	if (p + 6 >= replystr.length()) return 0;
384 	int val = atoi(&replystr[p+3]);
385 
386 	size_t i = 0;
387 	if (val < 0) val = 0;
388 	else if (val > 255) val = 255;
389 	else while(val > sm_tbl[i].val) i++;
390 	int mtr = (int)ceil(sm_tbl[i].mtr +
391 				(sm_tbl[i+1].mtr - sm_tbl[i].mtr) *
392 				(val - sm_tbl[i].val)/(sm_tbl[i+1].val - sm_tbl[i].val));
393 
394 	if (mtr > 100) mtr = 100;
395 
396 	return mtr;
397 }
398 
399 // measured by W3NR
400 //  SWR..... mtr ... display
401 //  6:1..... 255 ... 100
402 //  3:1..... 132 ...  50
403 //  2:1..... 066 ...  26
404 //  2.5:1... 099 ...  39
405 //  1.5:1... 033 ...  13
406 //  1.1:1... 008 ...   3
407 
get_swr()408 int RIG_FT450D::get_swr()
409 {
410 	cmd = rsp = "RM6";
411 	cmd += ';';
412 	wait_char(';',7, FL450D_WAIT_TIME, "get swr", ASC);
413 
414 	gett("get_swr");
415 
416 	size_t p = replystr.rfind(rsp);
417 	if (p == string::npos) return 0;
418 	if (p + 6 >= replystr.length()) return 0;
419 	int mtr = atoi(&replystr[p+3]);
420 	return (int)ceil(mtr / 2.56);
421 }
422 
get_alc()423 int RIG_FT450D::get_alc()
424 {
425 	cmd = rsp = "RM4";
426 	cmd += ';';
427 	wait_char(';',7, FL450D_WAIT_TIME, "get alc", ASC);
428 	gett("get_alc");
429 
430 	size_t p = replystr.rfind(rsp);
431 	if (p == string::npos) return 0;
432 	if (p + 6 >= replystr.length()) return 0;
433 	int mtr = atoi(&replystr[p+3]);
434 	return (int)ceil(mtr / 2.56);
435 }
436 
437 
get_power_out()438 int RIG_FT450D::get_power_out()
439 {
440 	cmd = rsp = "RM5";
441 	sendCommand(cmd.append(";"));
442 	wait_char(';',7, FL450D_WAIT_TIME, "get pout", ASC);
443 
444 	gett("get_power_out");
445 
446 	size_t p = replystr.rfind(rsp);
447 	if (p == string::npos) return 0;
448 	if (p + 6 >= replystr.length()) return 0;
449 	double mtr = (double)(atoi(&replystr[p+3]));
450 
451 // following conversion iaw data measured by Terry, KJ4EED
452 	mtr = (.06 * mtr) + (.002 * mtr * mtr);
453 
454 	return (int)ceil(mtr);
455 }
456 
get_power_control()457 int RIG_FT450D::get_power_control()
458 {
459 	cmd = rsp = "PC";
460 	cmd += ';';
461 	wait_char(';',6, FL450D_WAIT_TIME, "get power", ASC);
462 
463 	gett("get_power_control");
464 
465 	size_t p = replystr.rfind(rsp);
466 	if (p == string::npos) return progStatus.power_level;
467 	if (p + 5 >= replystr.length()) return progStatus.power_level;
468 
469 	int mtr = atoi(&replystr[p+2]);
470 	return mtr;
471 }
472 
set_power_control(double val)473 void RIG_FT450D::set_power_control(double val)
474 {
475 	int ival = (int)val;
476 	cmd = "PC000;";
477 	for (int i = 4; i > 1; i--) {
478 		cmd[i] += ival % 10;
479 		ival /= 10;
480 	}
481 	sendCommand(cmd);
482 	showresp(WARN, ASC, "SET power", cmd, replystr);
483 	sett("set_power_control");
484 }
485 
486 // Volume control return 0 ... 100
get_volume_control()487 int RIG_FT450D::get_volume_control()
488 {
489 	cmd = rsp = "AG0";
490 	cmd += ';';
491 	wait_char(';',7, FL450D_WAIT_TIME, "get vol", ASC);
492 
493 	gett("get_volume_control");
494 
495 	size_t p = replystr.rfind(rsp);
496 	if (p == string::npos) return progStatus.volume;
497 	if (p + 6 >= replystr.length()) return progStatus.volume;
498 	int val = round(atoi(&replystr[p+3]) / 2.55);
499 	if (val > 100) val = 100;
500 	return ceil(val);
501 }
502 
set_volume_control(int val)503 void RIG_FT450D::set_volume_control(int val)
504 {
505 	int ivol = (int)(val * 255 / 100);
506 	cmd = "AG0000;";
507 	for (int i = 5; i > 2; i--) {
508 		cmd[i] += ivol % 10;
509 		ivol /= 10;
510 	}
511 	sendCommand(cmd);
512 	showresp(WARN, ASC, "SET vol", cmd, replystr);
513 	sett("set_volume_control");
514 }
515 
get_vol_min_max_step(int & min,int & max,int & step)516 void RIG_FT450D::get_vol_min_max_step(int &min, int &max, int &step)
517 {
518 	min = 0; max = 100; step = 1;
519 }
520 
521 // Tranceiver PTT on/off
set_PTT_control(int val)522 void RIG_FT450D::set_PTT_control(int val)
523 {
524 	cmd = val ? "TX1;" : "TX0;";
525 	sendCommand(cmd);
526 	showresp(WARN, ASC, "SET PTT", cmd, replystr);
527 	sett("set_PTT_control");
528 	ptt_ = val;
529 }
530 
get_PTT()531 int RIG_FT450D::get_PTT()
532 {
533 	cmd = "TX;";
534 	rsp = "TX";
535 	waitN(4, 100, "get PTT", ASC);
536 
537 	gett("get_PTT");
538 
539 	size_t p = replystr.rfind(rsp);
540 	if (p == string::npos) return ptt_;
541 	ptt_ =  (replystr[p+2] != '0' ? 1 : 0);
542 	return ptt_;
543 }
544 
545 
tune_rig(int val)546 void RIG_FT450D::tune_rig(int val)
547 {
548 	switch (val) {
549 		case 0:
550 			cmd = "AC000;";
551 			break;
552 		case 1:
553 			cmd = "AC001;";
554 			break;
555 		case 2:
556 		default:
557 			cmd = "AC002;";
558 			break;
559 	}
560 	sendCommand(cmd);
561 	showresp(WARN, ASC, "tune rig", cmd, replystr);
562 	sett("tune_rig");
563 }
564 
get_tune()565 int RIG_FT450D::get_tune()
566 {
567 	cmd = rsp = "AC";
568 	cmd += ';';
569 	waitN(5, 100, "get tune", ASC);
570 
571 	rig_trace(2, "get_tuner status()", replystr.c_str());
572 
573 	size_t p = replystr.rfind(rsp);
574 	if (p == string::npos) return 0;
575 	int val = replystr[p+4] - '0';
576 	return (val > 0);
577 }
578 
579 static int attval = 0;
580 
set_attenuator(int val)581 void RIG_FT450D::set_attenuator(int val)
582 {
583 	attval = val;
584 	if (val) cmd = "RA01;";
585 	else	 cmd = "RA00;";
586 	sendCommand(cmd);
587 	showresp(WARN, ASC, "get att", cmd, replystr);
588 	sett("set_attenuator");
589 }
590 
get_attenuator()591 int RIG_FT450D::get_attenuator()
592 {
593 	cmd = rsp = "RA0";
594 	cmd += ';';
595 	wait_char(';', 5, FL450D_WAIT_TIME, "get att", ASC);
596 
597 	gett("get_attenuator");
598 
599 	size_t p = replystr.rfind(rsp);
600 	int val = attval;
601 	if (p != string::npos)
602 		val = (replystr[p+3] == '3' ? 1 : 0);
603 	attval = val;
604 	return val;
605 }
606 
607 static int preval = 0;
608 static bool wait_preamp = false;
set_preamp(int val)609 void RIG_FT450D::set_preamp(int val)
610 {
611 	wait_preamp = true;
612 	preval = val;
613 	if (preval) cmd = "PA00;";
614 	else		cmd = "PA01;";
615 	sendCommand(cmd);
616 	showresp(WARN, ASC, "set preamp", cmd, replystr);
617 	sett("set_preamp");
618 	wait_preamp = false;
619 }
620 
get_preamp()621 int RIG_FT450D::get_preamp()
622 {
623 	while (wait_preamp) {
624 		Fl::awake();
625 		MilliSleep(50);
626 	}
627 	cmd = "PA0;";
628 	wait_char(';', 5, FL450D_WAIT_TIME, "get pre", ASC);
629 	gett("get_preamp");
630 	if (replystr.empty()) return preval;
631 
632 	size_t p = replystr.rfind("PA00;");
633 	if (p != string::npos) {
634 		preval = 1;
635 		preamp_label("IPO", true);
636 	} else if (replystr.rfind("PA01;") != string::npos) {
637 		preval = 0;
638 		preamp_label("IPO", false);
639 	}
640 
641 	return preval;
642 }
643 
adjust_bandwidth(int val)644 int RIG_FT450D::adjust_bandwidth(int val)
645 {
646 	switch (val) {
647 		case mCW     :
648 		case mCW_R   :
649 			bandwidths_ = FT450D_cw_widths;
650 			bw_vals_ = FT450D_wvals_cw_widths;
651 			break;
652 		case mFM     :
653 		case mFM_N   :
654 			bandwidths_ = FT450D_fm_widths;
655 			bw_vals_ = FT450D_wvals_fm_widths;
656 			break;
657 		case mAM :
658 			bandwidths_ = FT450D_am_widths;
659 			bw_vals_ = FT450D_wvals_am_widths;
660 			break;
661 		case mRTTY_L :
662 		case mRTTY_U :
663 		case mDATA_L :
664 		case mDATA_U :
665 			bandwidths_ = FT450D_data_widths;
666 			bw_vals_ = FT450D_wvals_data_widths;
667 			break;
668 		default:
669 			bandwidths_ = FT450D_ssb_widths;
670 			bw_vals_ = FT450D_wvals_ssb_widths;
671 			break;
672 	}
673 	return FT450D_def_bw[val];
674 }
675 
def_bandwidth(int m)676 int RIG_FT450D::def_bandwidth(int m)
677 {
678 	int bw = adjust_bandwidth(m);
679 	if (useB) {
680 		if (mode_bwB[m] == -1)
681 			mode_bwB[m] = bw;
682 		return mode_bwB[m];
683 	}
684 	if (mode_bwA[m] == -1)
685 		mode_bwA[m] = bw;
686 	return mode_bwA[m];
687 }
688 
bwtable(int n)689 const char ** RIG_FT450D::bwtable(int n)
690 {
691 	switch (n) {
692 		case mCW     :
693 		case mCW_R   :
694 			return FT450D_cw_widths;
695 		case mFM     :
696 		case mFM_N   :
697 			return FT450D_fm_widths;
698 		case mAM :
699 			return FT450D_am_widths;
700 		case mRTTY_L :
701 		case mRTTY_U :
702 		case mDATA_L :
703 		case mDATA_U :
704 			return FT450D_data_widths;
705 	}
706 	return FT450D_ssb_widths;
707 }
708 
set_modeA(int val)709 void RIG_FT450D::set_modeA(int val)
710 {
711 	modeA = val;
712 	cmd = "MD0";
713 	cmd += mode_chr[val];
714 	cmd += ';';
715 	sendCommand(cmd);
716 	showresp(WARN, ASC, "SET mode A", cmd, replystr);
717 	sett("set_modeA");
718 
719 	adjust_bandwidth(modeA);
720 	if (val == 2 || val == 6) return;
721 	if (progStatus.spot_onoff) {
722 		progStatus.spot_onoff = false;
723 		set_spot_onoff();
724 		cmd = "CS0;";
725 		sendCommand(cmd);
726 		showresp(WARN, ASC, "SET spot off", cmd, replystr);
727 		sett("set_spot_off");
728 		btnSpot->value(0);
729 	}
730 }
731 
get_modeA()732 int RIG_FT450D::get_modeA()
733 {
734 	cmd = rsp = "MD0";
735 	cmd += ';';
736 	wait_char(';', 5, FL450D_WAIT_TIME, "get mode A", ASC);
737 
738 	gett("get_modeA");
739 
740 	size_t p = replystr.rfind(rsp);
741 	if (p == string::npos) return modeA;
742 	int md = replystr[p+3];
743 	if (md <= '9') md = md - '1';
744 	else md = 9 + md - 'B';
745 	modeA = md;
746 	adjust_bandwidth(modeA);
747 	return modeA;
748 }
749 
set_bwA(int val)750 void RIG_FT450D::set_bwA(int val)
751 {
752 	bwA = val;
753 	switch (val) {
754 		case 0 : cmd = "SH000;"; break;
755 		case 1 : cmd = "SH016;"; break;
756 		case 2 : cmd = "SH031;"; break;
757 		default: cmd = "SH016;";
758 	}
759 	sendCommand(cmd);
760 	mode_bwA[modeA] = bwA;
761 	showresp(WARN, ASC, "SET bwA", cmd, replystr);
762 	sett("set_bwA");
763 }
764 
get_bwA()765 int RIG_FT450D::get_bwA()
766 {
767 	cmd = rsp = "SH0";
768 	cmd += ';';
769 	wait_char(';', 6, FL450D_WAIT_TIME, "get bw A", ASC);
770 
771 	gett("get_bwA");
772 
773 	size_t p = replystr.rfind(rsp);
774 	if (p == string::npos) return bwA;
775 	string bws = replystr.substr(p+3,2);
776 	if (bws == "00") bwA = 0;
777 	else if (bws == "16") bwA = 1;
778 	else if (bws == "31") bwA = 2;
779 	mode_bwA[modeA] = bwA;
780 	return bwA;
781 }
782 
set_modeB(int val)783 void RIG_FT450D::set_modeB(int val)
784 {
785 	modeB = val;
786 	cmd = "MD0";
787 	cmd += mode_chr[val];
788 	cmd += ';';
789 	sendCommand(cmd);
790 	showresp(WARN, ASC, "SET mode B", cmd, replystr);
791 	sett("set_modeB");
792 
793 	adjust_bandwidth(modeB);
794 	if (val == 2 || val == 6) return;
795 	if (progStatus.spot_onoff) {
796 		progStatus.spot_onoff = false;
797 		set_spot_onoff();
798 		cmd = "CS0;";
799 		sendCommand(cmd);
800 		showresp(WARN, ASC, "SET spot off", cmd, replystr);
801 		sett("set spot off");
802 		btnSpot->value(0);
803 	}
804 }
805 
get_modeB()806 int RIG_FT450D::get_modeB()
807 {
808 	cmd = rsp = "MD0";
809 	cmd += ';';
810 	wait_char(';', 5, FL450D_WAIT_TIME, "get mode B", ASC);
811 
812 	gett("get_modeB");
813 
814 	size_t p = replystr.rfind(rsp);
815 	if (p == string::npos) return modeB;
816 	int md = replystr[p+3];
817 	if (md <= '9') md = md - '1';
818 	else md = 9 + md - 'B';
819 	modeB = md;
820 	adjust_bandwidth(modeB);
821 	return modeB;
822 }
823 
set_bwB(int val)824 void RIG_FT450D::set_bwB(int val)
825 {
826 	bwB = val;
827 	switch (val) {
828 		case 0 : cmd = "SH000;"; break;
829 		case 1 : cmd = "SH016;"; break;
830 		case 2 : cmd = "SH031;"; break;
831 		default: cmd = "SH031;";
832 	}
833 	sendCommand(cmd);
834 	mode_bwB[modeB] = bwB;
835 	showresp(WARN, ASC, "SET bwB", cmd, replystr);
836 	sett("set_bwB");
837 }
838 
get_bwB()839 int RIG_FT450D::get_bwB()
840 {
841 	cmd = rsp = "SH0";
842 	cmd += ';';
843 	wait_char(';', 6, FL450D_WAIT_TIME, "get bw B", ASC);
844 
845 	gett("get_bwB");
846 
847 	size_t p = replystr.rfind(rsp);
848 	if (p == string::npos) return bwB;
849 	string bws = replystr.substr(p+3,2);
850 	if (bws == "00") bwB = 0;
851 	else if (bws == "16") bwB = 1;
852 	else if (bws == "31") bwB = 2;
853 	mode_bwB[modeB] = bwB;
854 	return bwB;
855 }
856 
get_BANDWIDTHS()857 std::string RIG_FT450D::get_BANDWIDTHS()
858 {
859 	stringstream s;
860 	for (int i = 0; i < NUM_MODES; i++)
861 		s << mode_bwA[i] << " ";
862 	for (int i = 0; i < NUM_MODES; i++)
863 		s << mode_bwB[i] << " ";
864 	return s.str();
865 }
866 
set_BANDWIDTHS(std::string s)867 void RIG_FT450D::set_BANDWIDTHS(std::string s)
868 {
869 	stringstream strm;
870 	strm << s;
871 	for (int i = 0; i < NUM_MODES; i++)
872 		strm >> mode_bwA[i];
873 	for (int i = 0; i < NUM_MODES; i++)
874 		strm >> mode_bwB[i];
875 }
876 
get_modetype(int n)877 int RIG_FT450D::get_modetype(int n)
878 {
879 	return mode_type[n];
880 }
881 
set_if_shift(int val)882 void RIG_FT450D::set_if_shift(int val)
883 {
884 	cmd = "IS0+0000;";
885 	if (val < 0) cmd[3] = '-';
886 	val = abs(val);
887 	for (int i = 4; i > 0; i--) {
888 		cmd[3+i] += val % 10;
889 		val /= 10;
890 	}
891 	sendCommand(cmd);
892 	showresp(WARN, ASC, "SET ifshift", cmd, replystr);
893 	sett("set_if_shift");
894 }
895 
get_if_shift(int & val)896 bool RIG_FT450D::get_if_shift(int &val)
897 {
898 	cmd = rsp = "IS0";
899 	cmd += ';';
900 	wait_char(';', 9, FL450D_WAIT_TIME, "get if shift", ASC);
901 
902 	gett("get_if_shift");
903 
904 	size_t p = replystr.rfind(rsp);
905 	val = progStatus.shift_val;
906 	if (p == string::npos) return progStatus.shift;
907 	val = atoi(&replystr[p+4]);
908 	if (replystr[p+3] == '-') val = -val;
909 	return (val != 0);
910 }
911 
get_if_min_max_step(int & min,int & max,int & step)912 void RIG_FT450D::get_if_min_max_step(int &min, int &max, int &step)
913 {
914 	min = -1000;
915 	max = 1000;
916 	step = 100;
917 }
918 
set_notch(bool on,int val)919 void RIG_FT450D::set_notch(bool on, int val)
920 {
921 	cmd = "BP00000;";
922 	if (!on) {
923 		if (notch_on) {
924 			sendCommand(cmd);
925 			showresp(WARN, ASC, "SET notch off", cmd, replystr);
926 			sett("set notch off");
927 			notch_on = false;
928 		}
929 		return;
930 	}
931 
932 	cmd = "BP00001;";
933 	if (!notch_on) {
934 		sendCommand(cmd);
935 		showresp(WARN, ASC, "SET notch on", cmd, replystr);
936 		sett("set notch on");
937 		notch_on = true;
938 	}
939 
940 	cmd = "BP01nnn;";
941 	val = val / 10;
942 	for (int i = 3; i > 0; i--) {
943 		cmd[3 + i] = val % 10 + '0';
944 		val /=10;
945 	}
946 	sendCommand(cmd);
947 	showresp(WARN, ASC, "SET notch val", cmd, replystr);
948 	sett("set notch val");
949 }
950 
get_notch(int & val)951 bool  RIG_FT450D::get_notch(int &val)
952 {
953 	bool ison = false;
954 	cmd = rsp = "BP00";
955 	cmd += ';';
956 	wait_char(';', 8, FL450D_WAIT_TIME, "get notch on/off", ASC);
957 
958 	gett("get_notch");
959 
960 	size_t p = replystr.rfind(rsp);
961 	val = progStatus.notch_val = 0; // disabled default slider position
962 	if (p == string::npos) return ison;
963 
964 	if (replystr[p+6] == '1') { // manual notch enabled
965 		ison = true;
966 		val = progStatus.notch_val;
967 		cmd = rsp = "BP01";
968 		cmd += ';';
969 		waitN(8, 100, "get notch val", ASC);
970 
971 		gett("get_notch_val");
972 
973 		p = replystr.rfind(rsp);
974 		if (p == string::npos || rsp.length() < 8) return ison;
975 		val = atoi(&replystr[p+4]);
976 		val = val * 10;
977 	}
978 	notch_on = ison;
979 	return ison;
980 }
981 
get_notch_min_max_step(int & min,int & max,int & step)982 void RIG_FT450D::get_notch_min_max_step(int &min, int &max, int &step)
983 {
984 	min = 10;
985 	max = 4000;
986 	step = 10;
987 }
988 
set_noise(bool b)989 void RIG_FT450D::set_noise(bool b)
990 {
991 	if (b)
992 		cmd = "NB01;";
993 	else
994 		cmd = "NB00;";
995 	sendCommand (cmd);
996 	showresp(WARN, ASC, "SET NB", cmd, replystr);
997 	sett("set_noise");
998 }
999 
set_xcvr_auto_on()1000 void RIG_FT450D::set_xcvr_auto_on()
1001 {
1002 // send dummy data request for ID (see pg 12 CAT reference book)
1003 	cmd = "ID;";
1004 	sendCommand(cmd);
1005 // wait 1 to 2 seconds
1006 	MilliSleep(1500);
1007 	cmd = "PS1;";
1008 	sendCommand(cmd);
1009 // wait for power on status
1010 	cmd = "PS;";
1011 	waitN(4, 500, "Xcvr ON?", ASC);
1012 }
1013 
set_xcvr_auto_off()1014 void RIG_FT450D::set_xcvr_auto_off()
1015 {
1016 	cmd = "PS0;";
1017 	sendCommand(cmd);
1018 	sett("set_xcvr_auto_off");
1019 }
1020 
1021 // val 0 .. 100
1022 static int mg = 0;
set_mic_gain(int val)1023 void RIG_FT450D::set_mic_gain(int val)
1024 {
1025 	cmd = "MG000;";
1026 	if (val == 1) cmd = "MG000;";
1027 	else if (val == 2) cmd = "MG128;";
1028 	else cmd = "MG255;";
1029 	mg = val;
1030 	sendCommand(cmd);
1031 	showresp(WARN, ASC, "SET mic", cmd, replystr);
1032 	sett("set_mic_gain");
1033 }
1034 
get_mic_gain()1035 int RIG_FT450D::get_mic_gain()
1036 {
1037 	cmd = rsp = "MG";
1038 	cmd += ';';
1039 	wait_char(';', 6, FL450D_WAIT_TIME, "get mic", ASC);
1040 
1041 	gett("get_mic_gain");
1042 
1043 	size_t p = replystr.rfind(rsp);
1044 	if (p == string::npos) return mg;
1045 	replystr[p+5] = 0;
1046 	int val = atoi(&replystr[p+2]);
1047 	if (val < 86) return 1;
1048 	if (val < 127) return 2;
1049 	return 3;
1050 }
1051 
get_mic_min_max_step(int & min,int & max,int & step)1052 void RIG_FT450D::get_mic_min_max_step(int &min, int &max, int &step)
1053 {
1054 	min = 1;
1055 	max = 3;
1056 	step = 1;
1057 }
1058 
set_special(int v)1059 void RIG_FT450D::set_special(int v)
1060 {
1061 	if (v) cmd = "VR1;";
1062 	else   cmd = "VR0;";
1063 	sendCommand(cmd);
1064 	showresp(WARN, ASC, "Set special", cmd, replystr);
1065 	sett("set_special");
1066 }
1067 
set_vox_onoff()1068 void RIG_FT450D::set_vox_onoff()
1069 {
1070 	cmd = "VX0;";
1071 	if (progStatus.vox_onoff) cmd[2] = '1';
1072 	sendCommand(cmd);
1073 	showresp(WARN, ASC, "SET vox on/off", cmd, replystr);
1074 	sett("set_vox_onoff");
1075 }
1076 
set_vox_gain()1077 void RIG_FT450D::set_vox_gain()
1078 {
1079 	cmd = "VG";
1080 	cmd.append(to_decimal(progStatus.vox_gain, 3)).append(";");
1081 	sendCommand(cmd);
1082 	showresp(WARN, ASC, "SET vox gain", cmd, replystr);
1083 	sett("set_vox_gain");
1084 }
1085 
set_vox_hang()1086 void RIG_FT450D::set_vox_hang()
1087 {
1088 	cmd = "VD";
1089 	cmd.append(to_decimal(progStatus.vox_hang, 4)).append(";");
1090 	sendCommand(cmd);
1091 	showresp(WARN, ASC, "SET vox delay", cmd, replystr);
1092 	sett("set_vox_hang");
1093 }
1094 
set_cw_wpm()1095 void RIG_FT450D::set_cw_wpm()
1096 {
1097 	cmd = "KS";
1098 	if (progStatus.cw_wpm > 60) progStatus.cw_wpm = 60;
1099 	if (progStatus.cw_wpm < 4) progStatus.cw_wpm = 4;
1100 	cmd.append(to_decimal(progStatus.cw_wpm, 3)).append(";");
1101 	sendCommand(cmd);
1102 	showresp(WARN, ASC, "SET cw wpm", cmd, replystr);
1103 	sett("set_cw_wpm");
1104 }
1105 
1106 
enable_keyer()1107 void RIG_FT450D::enable_keyer()
1108 {
1109 	cmd = "KR0;";
1110 	if (progStatus.enable_keyer) cmd[2] = '1';
1111 	sendCommand(cmd);
1112 	showresp(WARN, ASC, "SET keyer on/off", cmd, replystr);
1113 	sett("enable_keyer");
1114 }
1115 
set_cw_spot()1116 bool RIG_FT450D::set_cw_spot()
1117 {
1118 	if (vfo->imode == 2 || vfo->imode == 6) {
1119 		cmd = "CS0;";
1120 		if (progStatus.spot_onoff) cmd[2] = '1';
1121 		sendCommand(cmd);
1122 		showresp(WARN, ASC, "SET spot on/off", cmd, replystr);
1123 		sett("set_cw_spot");
1124 		return true;
1125 	} else
1126 		return false;
1127 }
1128 
set_cw_weight()1129 void RIG_FT450D::set_cw_weight()
1130 {
1131 	int n = round(progStatus.cw_weight * 10);
1132 	cmd.assign("EX024").append(to_decimal(n, 2)).append(";");
1133 	sendCommand(cmd);
1134 	showresp(WARN, ASC, "SET cw weight", cmd, replystr);
1135 	sett("set_cw_weight");
1136 }
1137 
set_break_in()1138 void RIG_FT450D::set_break_in()
1139 {
1140 	if (progStatus.break_in) {
1141 		cmd = "BI1;";
1142 		break_in_label("FULL");
1143 	} else {
1144 		cmd = "BI0;";
1145 		break_in_label("QSK");
1146 	}
1147 	sendCommand(cmd);
1148 	showresp(WARN, ASC, "SET break in on/off", cmd, replystr);
1149 	sett("set_break_in");
1150 }
1151 
get_break_in()1152 int RIG_FT450D::get_break_in()
1153 {
1154 	cmd = "BI;";
1155 	wait_char(';', 4, FL450D_WAIT_TIME, "get break in", ASC);
1156 	progStatus.break_in = (replystr[2] == '1');
1157 	if (progStatus.break_in) {
1158 		break_in_label("FULL");
1159 		progStatus.cw_delay = 0;
1160 	} else {
1161 		break_in_label("QSK");
1162 		get_qsk_delay();
1163 	}
1164 	return progStatus.break_in;
1165 }
1166 
set_cw_delay()1167 void RIG_FT450D::set_cw_delay()
1168 {
1169 	if (progStatus.break_in) return;
1170 
1171 	int n = progStatus.cw_delay;
1172 	cmd.assign("EX016").append(to_decimal(n,4)).append(";");
1173 	sendCommand(cmd);
1174 	showresp(WARN, ASC, "SET cw delay", cmd, replystr);
1175 	sett("set_cw_delay");
1176 }
1177 
set_cw_qsk()1178 void RIG_FT450D::set_cw_qsk()
1179 {
1180 	if (progStatus.cw_qsk == 0) {
1181 		cmd.assign("BI1;");
1182 		sendCommand(cmd);
1183 		showresp(WARN, ASC, "SET break-in ON", cmd, replystr);
1184 		sett("set break in ON");
1185 		return;
1186 	}
1187 	cmd.assign("BI0;");
1188 	sendCommand(cmd);
1189 	sett("SET break-in OFF");
1190 	int n = progStatus.cw_qsk / 5 - 3;
1191 	cmd.assign("EX018").append(to_decimal(n, 1)).append(";");
1192 	sendCommand(cmd);
1193 	showresp(WARN, ASC, "SET cw qsk", cmd, replystr);
1194 	sett("set cw qsk");
1195 }
1196 
set_cw_spot_tone()1197 void RIG_FT450D::set_cw_spot_tone()
1198 {
1199 	int n = (progStatus.cw_spot_tone - 400) / 50 + 1;
1200 	cmd = "EX020";
1201 	cmd.append(to_decimal(n, 2)).append(";");
1202 	sendCommand(cmd);
1203 	showresp(WARN, ASC, "SET cw tone", cmd, replystr);
1204 	sett("set_cw_spot_tone");
1205 }
1206 
1207 // DNR
set_noise_reduction_val(int val)1208 void RIG_FT450D::set_noise_reduction_val(int val)
1209 {
1210 	cmd.assign("RL0").append(to_decimal(val, 2)).append(";");
1211 	sendCommand(cmd);
1212 	showresp(WARN, ASC, "SET_noise_reduction_level", cmd, replystr);
1213 	sett("set_noise_reduction_val");
1214 }
1215 
get_noise_reduction_val()1216 int  RIG_FT450D::get_noise_reduction_val()
1217 {
1218 	int val = 1;
1219 	cmd = rsp = "RL0";
1220 	cmd.append(";");
1221 	waitN(6, 100, "GET noise reduction level", ASC);
1222 
1223 	gett("get_noise_reduction_val");
1224 
1225 	size_t p = replystr.rfind(rsp);
1226 	if (p == string::npos) return val;
1227 	val = atoi(&replystr[p+3]);
1228 	return val;
1229 }
1230 
1231 // DNR
set_noise_reduction(int val)1232 void RIG_FT450D::set_noise_reduction(int val)
1233 {
1234 	cmd.assign("NR0").append(val ? "1" : "0" ).append(";");
1235 	sendCommand(cmd);
1236 	showresp(WARN, ASC, "SET noise reduction", cmd, replystr);
1237 	sett("set_noise_reduction");
1238 }
1239 
get_noise_reduction()1240 int  RIG_FT450D::get_noise_reduction()
1241 {
1242 	int val;
1243 	cmd = rsp = "NR0";
1244 	cmd.append(";");
1245 	wait_char(';', 5, FL450D_WAIT_TIME, "GET noise reduction", ASC);
1246 	gett("get_noise_reduction");
1247 
1248 	size_t p = replystr.rfind(rsp);
1249 	if (p == string::npos) return 0;
1250 	val = replystr[p+3] - '0';
1251 	return val;
1252 }
1253 
set_rf_gain(int val)1254 void RIG_FT450D::set_rf_gain(int val)
1255 {
1256 	cmd = "RG0000;";
1257 	int rfval = (int)((100 - val) * 2.55);
1258 	for (int i = 5; i > 2; i--) {
1259 		cmd[i] = rfval % 10 + '0';
1260 		rfval /= 10;
1261 	}
1262 	sendCommand(cmd);
1263 	showresp(WARN, ASC, "SET rfgain", cmd, replystr);
1264 	sett("set_rf_gain");
1265 }
1266 
get_rf_gain()1267 int  RIG_FT450D::get_rf_gain()
1268 {
1269 	//int rfval = 0;
1270 	cmd = rsp = "RG0";
1271 	cmd += ';';
1272 	wait_char(';', 7, FL450D_WAIT_TIME, "get rfgain", ASC);
1273 
1274 	gett("get_rf_gain");
1275 
1276 	size_t p = replystr.rfind(rsp);
1277 	if (p == string::npos) return progStatus.rfgain;
1278 	//for (int i = 3; i < 6; i++) {
1279 	//	rfval *= 10;  // Shift out one decimal place so we can add the next character
1280 	//	rfval += replystr[p+i] - '0'; // Subtract ASCII 0 so we get a number
1281 	//}
1282 
1283 	// Parse the RF value from the position returned by rfind for the response.
1284 	// Valid values are 0-255.
1285 	int rfval =
1286 		(replystr[p+3] - '0') * 100 +
1287 		(replystr[p+4] - '0') * 10 +
1288 		(replystr[p+5] - '0');
1289 
1290 	// Convert 0-255 to 0-100 for the slider widget.
1291 	rfval = (int)(rfval / 2.55);
1292 	if (rfval > 100) rfval = 100;
1293 	return rfval;
1294 }
1295 
get_rf_min_max_step(int & min,int & max,int & step)1296 void RIG_FT450D::get_rf_min_max_step(int &min, int &max, int &step)
1297 {
1298 	min = 0;
1299 	max = 100;
1300 	step = 1;
1301 }
1302 
1303 //----------------------------------------------------------------------
1304 // these are used during initialization
1305 
get_cw_weight()1306 void RIG_FT450D::get_cw_weight()
1307 {
1308 	cmd = "EX024;";
1309 	wait_char(';', 9, FL450D_WAIT_TIME, "get CW weight", ASC);
1310 	gett("get_cw_weight");
1311 
1312 	size_t p = replystr.rfind("EX024");
1313 	if (p == string::npos) return;
1314 	replystr[p+8] = 0;
1315 	int val = atoi(&replystr[p+5]);
1316 	progStatus.cw_weight = val / 10.0;
1317 }
1318 
get_cw_wpm()1319 void RIG_FT450D::get_cw_wpm()
1320 {
1321 	cmd = rsp = "KS;";
1322 	wait_char(';', 6, FL450D_WAIT_TIME, "get WPM", ASC);
1323 	gett("get_cw_wpm");
1324 
1325 	size_t p = replystr.rfind("KS");
1326 	if (p == string::npos) return;
1327 
1328 	replystr[p+5] = 0;
1329 	int val = atoi(&replystr[p+2]);
1330 	progStatus.cw_wpm = val;
1331 }
1332 
get_qsk()1333 void RIG_FT450D::get_qsk()
1334 {
1335 	cmd = "EX018;";
1336 	wait_char(';', 7, FL450D_WAIT_TIME, "get CW qsk", ASC);
1337 	gett("get_qsk");
1338 
1339 	size_t p = replystr.rfind("EX018");
1340 	if (p == string::npos) return;
1341 
1342 	switch (replystr[p+5]) {
1343 		default :
1344 		case '0' : progStatus.cw_qsk = 15; break;
1345 		case '1' : progStatus.cw_qsk = 20; break;
1346 		case '2' : progStatus.cw_qsk = 25; break;
1347 		case '3' : progStatus.cw_qsk = 30; break;
1348 	}
1349 }
1350 
get_qsk_delay()1351 void RIG_FT450D::get_qsk_delay()
1352 {
1353 	cmd = "EX016;";
1354 	wait_char(';', 10, FL450D_WAIT_TIME, "get CW delay", ASC);
1355 	gett("get_qsk_delay");
1356 
1357 	size_t p = replystr.rfind("EX016");
1358 	if (p == string::npos) return;
1359 	replystr[p+9] = 0;
1360 	progStatus.cw_delay = atoi(&replystr[p+5]);
1361 }
1362 
get_cw_spot_tone()1363 void RIG_FT450D::get_cw_spot_tone()
1364 {
1365 	cmd = "EX020;";
1366 	wait_char(';', 8, FL450D_WAIT_TIME, "get CW spot tone", ASC);
1367 	gett("get_cw_spot_tone");
1368 
1369 	size_t p = replystr.rfind("EX020");
1370 	if (p == string::npos) return;
1371 	replystr[p+7] = 0;
1372 	int n = atoi(&replystr[p+5]);
1373 	switch (n) {
1374 		case 0:
1375 		case 1: case 2: progStatus.cw_spot_tone = 400; break;
1376 		case 3: case 4: progStatus.cw_spot_tone = 500; break;
1377 		case 5: case 6: progStatus.cw_spot_tone = 600; break;
1378 		case 7: case 8: progStatus.cw_spot_tone = 700; break;
1379 		case 9: default: progStatus.cw_spot_tone = 800; break;
1380 	}
1381 }
1382 
get_vox_gain()1383 void RIG_FT450D::get_vox_gain()
1384 {
1385 	cmd = "VG;";
1386 	wait_char(';', 6, FL450D_WAIT_TIME, "get VOX gain", ASC);
1387 	gett("get_vox_gain");
1388 
1389 	size_t p = replystr.rfind("VG");
1390 	if (p == string::npos) return;
1391 	replystr[p+5] = 0;
1392 	progStatus.vox_gain = atoi(&replystr[p+2]);
1393 }
1394 
get_vox_hang()1395 void RIG_FT450D::get_vox_hang()
1396 {
1397 	cmd = "VD;";
1398 	wait_char(';', 7, FL450D_WAIT_TIME, "get VOX delay", ASC);
1399 	gett("get_vox_hang");
1400 
1401 	size_t p = replystr.rfind("VD");
1402 	if (p == string::npos) return;
1403 	replystr[p+6] = 0;
1404 	progStatus.vox_hang = atoi(&replystr[p+2]);
1405 }
1406 
get_band_selection(int v)1407 void RIG_FT450D::get_band_selection(int v)
1408 {
1409 	if (v < 3) v = v - 1;
1410 	cmd.assign("BS").append(to_decimal(v, 2)).append(";");
1411 	sendCommand(cmd);
1412 	showresp(WARN, ASC, "Select Band Stacks", cmd, replystr);
1413 	sett("get band");
1414 }
1415 
1416 static int agcval = 0;
get_agc()1417 int  RIG_FT450D::get_agc()
1418 {
1419     cmd = "GT0;";
1420     wait_char(';', 6, FL450D_WAIT_TIME, "get agc", ASC);
1421     gett("get_agc");
1422     size_t p = replystr.rfind("GT");
1423     if (p == std::string::npos) return agcval;
1424 
1425     switch (replystr[3]) {
1426         default:
1427         case '0': agcval = 0; break;
1428         case '1': agcval = 1; break;
1429         case '2':
1430         case '3': agcval = 2; break;
1431         case '4':
1432         case '6': agcval = 3; break;
1433     }
1434     return agcval;
1435 }
1436 
incr_agc()1437 int RIG_FT450D::incr_agc()
1438 {
1439 static const char ch[] = {'0', '1', '3', '4'};
1440 	agcval++;
1441 	if (agcval > 3) agcval = 0;
1442 	cmd = "GT00;";
1443 	cmd[3] = ch[agcval];
1444 
1445 	sendCommand(cmd);
1446 	showresp(WARN, ASC, "SET agc", cmd, replystr);
1447 	sett("set_agc");
1448 
1449 	return agcval;
1450 }
1451 
1452 
1453 static const char *agcstrs[] = {"AGC", "FST", "SLO", "AUT"};
agc_label()1454 const char *RIG_FT450D::agc_label()
1455 {
1456 	return agcstrs[agcval];
1457 }
1458 
agc_val()1459 int  RIG_FT450D::agc_val()
1460 {
1461 	return (agcval);
1462 }
1463 
1464 /*
1465 void RIG_FT450D::get_band_selection(int v)
1466 {
1467 	int inc_60m = false;
1468 	cmd = "IF;";
1469 	waitN(27, 100, "get band", ASC);
1470 
1471 	sett("get band");
1472 
1473 	size_t p = replystr.rfind("IF");
1474 	if (p == string::npos) return;
1475 	if (replystr[p+21] != '0') {	// vfo 60M memory mode
1476 		inc_60m = true;
1477 	}
1478 
1479 	if (v == 12) {	// 5MHz 60m presets
1480 		if (Channels_60m[0] == NULL) return;	// no 60m Channels so skip
1481 		if (inc_60m) {
1482 			if (Channels_60m[++m_60m_indx] == NULL)
1483 				m_60m_indx = 0;
1484 		}
1485 		cmd.assign("MC").append(Channels_60m[m_60m_indx]).append(";");
1486 	} else {		// v == 1..11 band selection OR return to vfo mode == 0
1487 		if (inc_60m)
1488 			cmd = "VM;";
1489 		else {
1490 			if (v < 3)
1491 				v = v - 1;
1492 			cmd.assign("BS").append(to_decimal(v, 2)).append(";");
1493 		}
1494 	}
1495 
1496 	sendCommand(cmd);
1497 	showresp(WARN, ASC, "Select Band Stacks", cmd, replystr);
1498 }
1499 */
1500 
1501 //----------------------------------------------------------------------
1502