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