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 "IC746.h"
22 
23 //=============================================================================
24 // IC-746, IC746PRO
25 //=============================================================================
26 
27 const char IC746name_[] = "IC-746";
28 
29 const char *IC746modes_[] = {
30 		"LSB", "USB", "AM", "CW", "RTTY", "FM", "CW-R", "RTTY-R", NULL};
31 // mode values are 0, 1, 2, 3, 4, 5, 7, 8
32 const char IC746_mode_type[] =
33 	{ 'L', 'U', 'U', 'U', 'L', 'U', 'L', 'U'};
34 
35 const char *IC746_widths[] = { "NORM", "NARR", NULL};
36 static int IC746_bw_vals[] = { 1, 2, WVALS_LIMIT};
37 
38 static GUI IC746_widgetsdgets[]= {
39 	{ (Fl_Widget *)btnVol,        2, 125,  50 },	//0
40 	{ (Fl_Widget *)sldrVOLUME,   54, 125, 156 },	//1
41 	{ (Fl_Widget *)btnAGC,        2, 145,  50 },	//2
42 	{ (Fl_Widget *)sldrRFGAIN,   54, 145, 156 },	//3
43 	{ (Fl_Widget *)sldrSQUELCH,  54, 165, 156 },	//4
44 	{ (Fl_Widget *)btnNR,         2, 185,  50 },	//5
45 	{ (Fl_Widget *)sldrNR,       54, 185, 156 },	//6
46 	{ (Fl_Widget *)btnLOCK,     214, 105,  50 },	//7
47 	{ (Fl_Widget *)sldrINNER,   266, 105, 156 },	//8
48 	{ (Fl_Widget *)btnCLRPBT,   214, 125,  50 },	//9
49 	{ (Fl_Widget *)sldrOUTER,   266, 125, 156 },	//10
50 	{ (Fl_Widget *)btnNotch,    214, 145,  50 },	//11
51 	{ (Fl_Widget *)sldrNOTCH,   266, 145, 156 },	//12
52 	{ (Fl_Widget *)sldrMICGAIN, 266, 165, 156 },	//13
53 	{ (Fl_Widget *)sldrPOWER,   266, 185, 156 },	//14
54 	{ (Fl_Widget *)NULL, 0, 0, 0 }
55 };
56 
initialize()57 void RIG_IC746::initialize()
58 {
59 	IC746_widgetsdgets[0].W = btnVol;
60 	IC746_widgetsdgets[1].W = sldrVOLUME;
61 	IC746_widgetsdgets[2].W = btnAGC;
62 	IC746_widgetsdgets[3].W = sldrRFGAIN;
63 	IC746_widgetsdgets[4].W = sldrSQUELCH;
64 	IC746_widgetsdgets[5].W = btnNR;
65 	IC746_widgetsdgets[6].W = sldrNR;
66 	IC746_widgetsdgets[7].W = btnLOCK;
67 	IC746_widgetsdgets[8].W = sldrINNER;
68 	IC746_widgetsdgets[9].W = btnCLRPBT;
69 	IC746_widgetsdgets[10].W = sldrOUTER;
70 	IC746_widgetsdgets[11].W = btnNotch;
71 	IC746_widgetsdgets[12].W = sldrNOTCH;
72 	IC746_widgetsdgets[13].W = sldrMICGAIN;
73 	IC746_widgetsdgets[14].W = sldrPOWER;
74 }
75 
RIG_IC746()76 RIG_IC746::RIG_IC746() {
77 	defaultCIV = 0x56;
78 	name_ = IC746name_;
79 	modes_ = IC746modes_;
80 	bandwidths_ = IC746_widths;
81 	bw_vals_ = IC746_bw_vals;
82 	_mode_type = IC746_mode_type;
83 
84 	widgets = IC746_widgetsdgets;
85 
86 	comm_baudrate = BR9600;
87 	stopbits = 1;
88 	comm_retries = 2;
89 	comm_wait = 5;
90 	comm_timeout = 50;
91 	comm_echo = true;
92 	comm_rtscts = false;
93 	comm_rtsplus = true;
94 	comm_dtrplus = true;
95 	comm_catptt = true;
96 	comm_rtsptt = false;
97 	comm_dtrptt = false;
98 
99 	def_freq = freqB = freqA = B.freq = A.freq = 14070000L;
100 	def_mode = modeB = modeA = B.imode = A.imode = 1;
101 	def_bw = bwB = bwA = B.iBW = A.iBW = 0;
102 	filter_nbr = 0;
103 
104 	ICvol = 0;
105 
106 	has_bandwidth_control =
107 	has_smeter =
108 	has_power_control =
109 	has_volume_control =
110 	has_mode_control =
111 	has_micgain_control =
112 	has_notch_control =
113 	has_attenuator_control =
114 	has_preamp_control =
115 	has_pbt_controls = true;
116 
117 	has_ptt_control =
118 	has_tune_control =
119 	has_noise_control =
120 	has_noise_reduction =
121 	has_noise_reduction_control =
122 	has_rf_control =
123 	has_sql_control =
124 	has_split =
125 	restore_mbw = true;
126 
127 	has_extras = true;
128 
129 	precision = 1;
130 	ndigits = 9;
131 
132 };
133 
selectA()134 void RIG_IC746::selectA()
135 {
136 	cmd = pre_to;
137 	cmd += '\x07';
138 	cmd += '\x00';
139 	cmd.append(post);
140 	waitFB("sel A");
141 }
142 
selectB()143 void RIG_IC746::selectB()
144 {
145 	cmd = pre_to;
146 	cmd += '\x07';
147 	cmd += '\x01';
148 	cmd.append(post);
149 	waitFB("sel B");
150 }
151 
check()152 bool RIG_IC746::check ()
153 {
154 	string resp = pre_fm;
155 	resp += '\x03';
156 	cmd = pre_to;
157 	cmd += '\x03';
158 	cmd.append( post );
159 	bool ok = waitFOR(11, "check vfo");
160 	rig_trace(2, "check()", str2hex(replystr.c_str(), replystr.length()));
161 	return ok;
162 }
163 
get_vfoA()164 unsigned long int RIG_IC746::get_vfoA ()
165 {
166 	if (useB) return A.freq;
167 	string cstr = "\x03";
168 	string resp = pre_fm;
169 	resp.append(cstr);
170 	cmd = pre_to;
171 	cmd.append(cstr);
172 	cmd.append(post);
173 	if (waitFOR(11, "get vfo A")) {
174 		size_t p = replystr.rfind(resp);
175 		if (p != string::npos) {
176 			if (replystr[p+5] == -1)
177 				A.freq = 0;
178 			else
179 				A.freq = fm_bcd_be(replystr.substr(p+5), 10);
180 		}
181 	}
182 	return A.freq;
183 }
184 
set_vfoA(unsigned long int freq)185 void RIG_IC746::set_vfoA (unsigned long int freq)
186 {
187 	A.freq = freq;
188 	cmd = pre_to;
189 	cmd += '\x05';
190 	cmd.append( to_bcd_be( freq, 10 ) );
191 	cmd.append( post );
192 	waitFB("set vfo A");
193 }
194 
get_vfoB()195 unsigned long int RIG_IC746::get_vfoB ()
196 {
197 	if (!useB) return B.freq;
198 	string cstr = "\x03";
199 	string resp = pre_fm;
200 	resp.append(cstr);
201 	cmd = pre_to;
202 	cmd.append(cstr);
203 	cmd.append(post);
204 	if (waitFOR(11, "get vfo B")) {
205 		size_t p = replystr.rfind(resp);
206 		if (p != string::npos) {
207 			if (replystr[p+5] == -1)
208 				A.freq = 0;
209 			else
210 				B.freq = fm_bcd_be(replystr.substr(p+5), 10);
211 		}
212 	}
213 	return B.freq;
214 }
215 
set_vfoB(unsigned long int freq)216 void RIG_IC746::set_vfoB (unsigned long int freq)
217 {
218 	B.freq = freq;
219 	cmd = pre_to;
220 	cmd += '\x05';
221 	cmd.append( to_bcd_be( freq, 10 ) );
222 	cmd.append( post );
223 	waitFB("set vfo B");
224 }
225 
get_smeter()226 int RIG_IC746::get_smeter()
227 {
228 	string cstr = "\x15\x02";
229 	string resp = pre_fm;
230 	resp.append(cstr);
231 	cmd = pre_to;
232 	cmd.append(cstr);
233 	cmd.append(post);
234 	if (waitFOR(9, "get smeter")) {
235 		size_t p = replystr.rfind(resp);
236 		if (p != string::npos)
237 			return (int)ceil(fm_bcd(replystr.substr(p+6), 3) / 2.55);
238 	}
239 	return 0;
240 }
241 
242 // Volume control val 0 ... 100
243 
set_volume_control(int val)244 void RIG_IC746::set_volume_control(int val)
245 {
246 	ICvol = (int)(val);
247 	cmd = pre_to;
248 	cmd.append("\x14\x01");
249 	cmd.append(to_bcd(ICvol, 3));
250 	cmd.append( post );
251 	waitFB("set vol");
252 }
253 
get_volume_control()254 int RIG_IC746::get_volume_control()
255 {
256 	string cstr = "\x14\x01";
257 	string resp = pre_fm;
258 	resp.append(cstr);
259 	cmd = pre_to;
260 	cmd.append(cstr);
261 	cmd.append(post);
262 	if (waitFOR(9, "get vol")) {
263 		size_t p = replystr.rfind(resp);
264 		if (p != string::npos)
265 			return (int)ceil(fm_bcd(replystr.substr(p+6),3));
266 	}
267 	return 0;
268 }
269 
get_vol_min_max_step(int & min,int & max,int & step)270 void RIG_IC746::get_vol_min_max_step(int &min, int &max, int &step)
271 {
272 	min = 0; max = 255; step = 1;
273 }
274 
275 // Tranceiver PTT on/off
set_PTT_control(int val)276 void RIG_IC746::set_PTT_control(int val)
277 {
278 	cmd = pre_to;
279 	cmd += '\x1c';
280 	cmd += '\x00';
281 	cmd += (unsigned char) val;
282 	cmd.append( post );
283 	waitFB("set ptt");
284 	ptt_ = val;
285 }
286 
get_PTT()287 int RIG_IC746::get_PTT()
288 {
289 	cmd = pre_to;
290 	cmd += '\x1c'; cmd += '\x00';
291 	string resp = pre_fm;
292 	resp += '\x1c'; resp += '\x00';
293 	cmd.append(post);
294 	if (waitFOR(8, "get PTT")) {
295 		size_t p = replystr.rfind(resp);
296 		if (p != string::npos)
297 			ptt_ = replystr[p + 6];
298 	}
299 	return ptt_;
300 }
301 
set_attenuator(int val)302 void RIG_IC746::set_attenuator(int val)
303 {
304 	cmd = pre_to;
305 	cmd += '\x11';
306 	cmd += val ? 0x20 : 0x00;
307 	cmd.append( post );
308 	waitFB("set att");
309 	if (!val) {
310 		preamp_level--;
311 		if (preamp_level < 0) preamp_level = 2;
312 		set_preamp(1);
313 	}
314 }
315 
get_attenuator()316 int RIG_IC746::get_attenuator()
317 {
318 	string cstr = "\x11";
319 	string resp = pre_fm;
320 	resp.append(cstr);
321 	cmd = pre_to;
322 	cmd.append(cstr);
323 	cmd.append(post);
324 	if (waitFOR(7, "get att")) {
325 		size_t p = replystr.rfind(resp);
326 		if (p != string::npos)
327 			return (replystr[p+5] ? 1 : 0);
328 	}
329 	return 0;
330 }
331 
next_preamp()332 int  RIG_IC746::next_preamp()
333 {
334 	switch(preamp_level) {
335 		case 0: return 1;
336 		case 1: return 2;
337 		case 2: return 0;
338 	}
339 	return 0;
340 }
341 
set_preamp(int val)342 void RIG_IC746::set_preamp(int val)
343 {
344 	preamp_level = val;
345 	if (preamp_level == 1)
346 		preamp_label("Pre 1", true);
347 	else if (preamp_level == 2)
348 		preamp_label("Pre 2", true);
349 	else if (preamp_level == 0)
350 		preamp_label("Pre", false);
351 
352 	cmd = pre_to;
353 	cmd += '\x16';
354 	cmd += '\x02';
355 	cmd += (unsigned char) preamp_level;
356 	cmd.append( post );
357 	waitFB("set preamp");
358 }
359 
get_preamp()360 int RIG_IC746::get_preamp()
361 {
362 	string cstr = "\x16\x02";
363 	string resp = pre_fm;
364 	resp.append(cstr);
365 	cmd = pre_to;
366 	cmd.append(cstr);
367 	cmd.append(post);
368 	if (waitFOR(8, "get preamp")) {
369 		size_t p = replystr.rfind(resp);
370 		if (p != string::npos) {
371 			if (replystr[p+6] == 0x01) {
372 				preamp_label("Pre 1", true);
373 				preamp_level = 1;
374 			} else if (replystr[p+6] == 0x02) {
375 				preamp_label("Pre 2", true);
376 				preamp_level = 2;
377 			} else {
378 				preamp_label("Pre", false);
379 				preamp_level = 0;
380 			}
381 		}
382 	}
383 	return preamp_level;
384 }
385 
386 // changed noise blanker to noise reduction
set_noise(bool val)387 void RIG_IC746::set_noise(bool val)
388 {
389 	cmd = pre_to;
390 	cmd.append("\x16\x22");
391 	cmd += val ? 1 : 0;
392 	cmd.append(post);
393 	waitFB("set noise");
394 }
395 
get_noise()396 int RIG_IC746::get_noise()
397 {
398 	string cstr = "\x16\x22";
399 	string resp = pre_fm;
400 	resp.append(cstr);
401 	cmd = pre_to;
402 	cmd.append(cstr);
403 	cmd.append(post);
404 	if (waitFOR(8, "get noise")) {
405 		size_t p = replystr.rfind(resp);
406 		if (p != string::npos)
407 			return (replystr[p+6] ? 1 : 0);
408 	}
409 	return 0;
410 }
411 
set_noise_reduction(int val)412 void RIG_IC746::set_noise_reduction(int val)
413 {
414 	cmd = pre_to;
415 	cmd.append("\x16\x40");
416 	cmd += val ? 1 : 0;
417 	cmd.append(post);
418 	waitFB("set NR");
419 }
420 
get_noise_reduction()421 int RIG_IC746::get_noise_reduction()
422 {
423 	string cstr = "\x16\x40";
424 	string resp = pre_fm;
425 	resp.append(cstr);
426 	cmd = pre_to;
427 	cmd.append(cstr);
428 	cmd.append(post);
429 	if (waitFOR(8, "get NR")) {
430 		size_t p = replystr.rfind(resp);
431 		if (p != string::npos)
432 			return (replystr[p+6] ? 1 : 0);
433 	}
434 	return 0;
435 }
436 
437 // 0 < val < 100
set_noise_reduction_val(int val)438 void RIG_IC746::set_noise_reduction_val(int val)
439 {
440 	cmd = pre_to;
441 	cmd.append("\x14\x06");
442 	cmd.append(to_bcd(val * 255 / 100, 3));
443 	cmd.append(post);
444 	waitFB("set NR val");
445 }
446 
get_noise_reduction_val()447 int RIG_IC746::get_noise_reduction_val()
448 {
449 	string cstr = "\x14\x06";
450 	string resp = pre_fm;
451 	resp.append(cstr);
452 	cmd = pre_to;
453 	cmd.append(cstr);
454 	cmd.append(post);
455 	if (waitFOR(9, "get NR val")) {
456 		size_t p = replystr.rfind(resp);
457 		if (p != string::npos)
458 			return (int)ceil(fm_bcd(replystr.substr(p+6),3) / 2.55);
459 	}
460 	return 0;
461 }
462 
set_modeA(int val)463 void RIG_IC746::set_modeA(int val)
464 {
465 	A.imode = val;
466 	cmd = pre_to;
467 	cmd += '\x06';
468 	cmd += val > 5 ? val + 1 : val;
469 	cmd += filter_nbr + 1; // filter #
470 	cmd.append( post );
471 	waitFB("set mode A");
472 }
473 
get_modeA()474 int RIG_IC746::get_modeA()
475 {
476 	string cstr = "\x04";
477 	string resp = pre_fm;
478 	resp.append(cstr);
479 	cmd = pre_to;
480 	cmd.append(cstr);
481 	cmd.append(post);
482 	if (waitFOR(8, "get mode A")) {
483 		size_t p = replystr.rfind(resp);
484 		if (p != string::npos) {
485 			if (replystr[p+5] == -1) { A.imode = filter_nbr = 0; }
486 			else {
487 				A.imode = replystr[p+5];
488 				if (A.imode > 6) A.imode--;
489 				filter_nbr = replystr[p+6] - 1;
490 			}
491 		}
492 	}
493 	return A.imode;
494 }
495 
set_bwA(int val)496 void RIG_IC746::set_bwA(int val)
497 {
498 	filter_nbr = val;
499 	set_modeA(A.imode);
500 }
501 
get_bwA()502 int RIG_IC746::get_bwA()
503 {
504 	return filter_nbr;
505 }
506 
set_modeB(int val)507 void RIG_IC746::set_modeB(int val)
508 {
509 	B.imode = val;
510 	cmd = pre_to;
511 	cmd += '\x06';
512 	cmd += val > 5 ? val + 1 : val;
513 	cmd += filter_nbr + 1; // filter
514 	cmd.append( post );
515 	waitFB("set mode B");
516 }
517 
get_modeB()518 int RIG_IC746::get_modeB()
519 {
520 	string cstr = "\x04";
521 	string resp = pre_fm;
522 	resp.append(cstr);
523 	cmd = pre_to;
524 	cmd.append(cstr);
525 	cmd.append(post);
526 	if (waitFOR(8, "get mode B")) {
527 		size_t p = replystr.rfind(resp);
528 		if (p != string::npos) {
529 			if (replystr[p+5] == -1) { B.imode = filter_nbr = 0; }
530 			else {
531 				B.imode = replystr[p+5];
532 				if (B.imode > 6) B.imode--;
533 				filter_nbr = replystr[p+6] - 1;
534 			}
535 		}
536 	}
537 	return B.imode;
538 }
539 
set_bwB(int val)540 void RIG_IC746::set_bwB(int val)
541 {
542 	filter_nbr = val;
543 	set_modeB(B.imode);
544 }
545 
get_bwB()546 int RIG_IC746::get_bwB()
547 {
548 	return filter_nbr;
549 }
550 
get_modetype(int n)551 int RIG_IC746::get_modetype(int n)
552 {
553 	return _mode_type[n];
554 }
555 
set_mic_gain(int val)556 void RIG_IC746::set_mic_gain(int val)
557 {
558 	val = (int)(val * 255 / 100);
559 	cmd = pre_to;
560 	cmd.append("\x14\x0B");
561 	cmd.append(to_bcd(val,3));
562 	cmd.append(post);
563 	waitFB("set mic");
564 }
565 
get_mic_gain_min_max_step(int & min,int & max,int & step)566 void RIG_IC746::get_mic_gain_min_max_step(int &min, int &max, int &step)
567 {
568 	min = 0;
569 	max = 100;
570 	step = 1;
571 }
572 
set_if_shift(int val)573 void RIG_IC746::set_if_shift(int val)
574 {
575 	int shift;
576 	sh_ = val;
577 	if (val == 0) sh_on_ = false;
578 	else sh_on_ = true;
579 
580 	shift = 128 + val * 128 / 50;
581 	if (shift < 0) shift = 0;
582 	if (shift > 255) shift = 255;
583 
584 	cmd = pre_to;
585 	cmd.append("\x14\x07");
586 	cmd.append(to_bcd(shift, 3));
587 	cmd.append(post);
588 	waitFB("set IF on/off");
589 
590 	cmd = pre_to;
591 	cmd.append("\x14\x08");
592 	cmd.append(to_bcd(shift, 3));
593 	cmd.append(post);
594 	waitFB("set IF val");
595 }
596 
get_if_min_max_step(int & min,int & max,int & step)597 void RIG_IC746::get_if_min_max_step(int &min, int &max, int &step)
598 {
599 	min = -50;
600 	max = +50;
601 	step = 1;
602 }
603 
set_pbt_inner(int val)604 void RIG_IC746::set_pbt_inner(int val)
605 {
606 	int shift = 128 + val * 128 / 50;
607 	if (shift < 0) shift = 0;
608 	if (shift > 255) shift = 255;
609 
610 	cmd = pre_to;
611 	cmd.append("\x14\x07");
612 	cmd.append(to_bcd(shift, 3));
613 	cmd.append(post);
614 	waitFB("set PBT inner");
615 }
616 
set_pbt_outer(int val)617 void RIG_IC746::set_pbt_outer(int val)
618 {
619 	int shift = 128 + val * 128 / 50;
620 	if (shift < 0) shift = 0;
621 	if (shift > 255) shift = 255;
622 
623 	cmd = pre_to;
624 	cmd.append("\x14\x08");
625 	cmd.append(to_bcd(shift, 3));
626 	cmd.append(post);
627 	waitFB("set PBT outer");
628 }
629 
get_pbt_inner()630 int RIG_IC746::get_pbt_inner()
631 {
632 	int val = 0;
633 	string cstr = "\x14\x07";
634 	string resp = pre_fm;
635 	resp.append(cstr);
636 	cmd = pre_to;
637 	cmd.append(cstr);
638 	cmd.append( post );
639 	if (waitFOR(9, "get pbt inner")) {
640 		size_t p = replystr.rfind(resp);
641 		if (p != string::npos) {
642 			val = num100(replystr.substr(p+6));
643 			val -= 50;
644 		}
645 	}
646 	rig_trace(2, "get_pbt_inner()", str2hex(replystr.c_str(), replystr.length()));
647 	return val;
648 }
649 
get_pbt_outer()650 int RIG_IC746::get_pbt_outer()
651 {
652 	int val = 0;
653 	string cstr = "\x14\x08";
654 	string resp = pre_fm;
655 	resp.append(cstr);
656 	cmd = pre_to;
657 	cmd.append(cstr);
658 	cmd.append( post );
659 	if (waitFOR(9, "get pbt outer")) {
660 		size_t p = replystr.rfind(resp);
661 		if (p != string::npos) {
662 			val = num100(replystr.substr(p+6));
663 			val -= 50;
664 		}
665 	}
666 	rig_trace(2, "get_pbt_outer()", str2hex(replystr.c_str(), replystr.length()));
667 	return val;
668 }
669 
670 int ICsql = 0;
set_squelch(int val)671 void RIG_IC746::set_squelch(int val)
672 {
673 	ICsql = (int)(val * 255 / 100);
674 	cmd = pre_to;
675 	cmd.append("\x14\x03");
676 	cmd.append(to_bcd(ICsql, 3));
677 	cmd.append( post );
678 	waitFB("set sql");
679 }
680 
681 int ICrfg = 0;
set_rf_gain(int val)682 void RIG_IC746::set_rf_gain(int val)
683 {
684 	ICrfg = (int)(val * 255 / 100);
685 	cmd = pre_to;
686 	cmd.append("\x14\x02");
687 	cmd.append(to_bcd(ICrfg, 3));
688 	cmd.append( post );
689 	waitFB("set rf gain");
690 }
691 
set_power_control(double val)692 void RIG_IC746::set_power_control(double val)
693 {
694 	cmd = pre_to;
695 	cmd.append("\x14\x0A");
696 	cmd.append(to_bcd((int)(val * 255 / 100), 3));
697 	cmd.append( post );
698 	waitFB("set power");
699 }
700 
set_split(bool val)701 void RIG_IC746::set_split(bool val)
702 {
703 	split = val;
704 	cmd = pre_to;
705 	cmd += 0x0F;
706 	cmd += val ? 0x10 : 0x00;
707 	cmd.append(post);
708 	waitFB("set split");
709 }
710 
get_split()711 int RIG_IC746::get_split()
712 {
713 	return split;
714 }
715 
716 //=============================================================================
717 // 746PRO
718 const char IC746PROname_[] = "IC-746PRO";
719 
720 const char *IC746PROmodes_[] = {
721 		"LSB", "USB", "AM", "CW", "RTTY", "FM", "CW-R", "RTTY-R",
722 		"D-LSB", "D-USB", "D-FM", NULL};
723 
724 const char IC746PRO_mode_type[] =
725 	{ 'L', 'U', 'U', 'U', 'L', 'U', 'L', 'U',
726 	  'L', 'U', 'U' };
727 
728 const char *IC746PRO_SSBwidths[] = {
729   "50",  "100",  "150",  "200",  "250",  "300",  "350",  "400",  "450",  "500",
730 "600",   "700",  "800",  "900", "1000", "1100", "1200", "1300", "1400", "1500",
731 "1600", "1700", "1800", "1900", "2000", "2100", "2200", "2300", "2400", "2500",
732 "2600", "2700", "2800", "2900", "3000", "3100", "3200", "3300", "3400", "3500",
733 "3600",
734 NULL};
735 static int IC746PRO_bw_vals_SSB[] = {
736  1, 2, 3, 4, 5, 6, 7, 8, 9,10,
737 11,12,13,14,15,16,17,18,19,20,
738 21,22,23,24,25,26,27,28,29,30,
739 31,32,33,34,35,36,37,38,39,40,
740 41, WVALS_LIMIT};
741 
742 const char *IC746PRO_RTTYwidths[] = {
743   "50",  "100",  "150",  "200",  "250",  "300",  "350",  "400",  "450",  "500",
744  "600",  "700",  "800",  "900", "1000", "1100", "1200", "1300", "1400", "1500",
745 "1600", "1700", "1800", "1900", "2000", "2100", "2200", "2300", "2400", "2500",
746 "2600", "2700",
747 NULL};
748 static int IC746PRO_bw_vals_RTTY[] = {
749  1, 2, 3, 4, 5, 6, 7, 8, 9,10,
750 11,12,13,14,15,16,17,18,19,20,
751 21,22,23,24,25,26,27,28,29,30,
752 31,32, WVALS_LIMIT};
753 
754 const char *IC746PRO_AMFMwidths[] = { "FILT-1", "FILT-2", "FILT-3", NULL };
755 static int IC746PRO_bw_vals_AMFM[] = {
756 1,2,3,WVALS_LIMIT};
757 
initialize()758 void RIG_IC746PRO::initialize()
759 {
760 	IC746_widgetsdgets[0].W = btnVol;
761 	IC746_widgetsdgets[1].W = sldrVOLUME;
762 	IC746_widgetsdgets[2].W = btnAGC;
763 	IC746_widgetsdgets[3].W = sldrRFGAIN;
764 	IC746_widgetsdgets[4].W = sldrSQUELCH;
765 	IC746_widgetsdgets[5].W = btnNR;
766 	IC746_widgetsdgets[6].W = sldrNR;
767 	IC746_widgetsdgets[7].W = btnLOCK;
768 	IC746_widgetsdgets[8].W = sldrINNER;
769 	IC746_widgetsdgets[9].W = btnCLRPBT;
770 	IC746_widgetsdgets[10].W = sldrOUTER;
771 	IC746_widgetsdgets[11].W = btnNotch;
772 	IC746_widgetsdgets[12].W = sldrNOTCH;
773 	IC746_widgetsdgets[13].W = sldrMICGAIN;
774 	IC746_widgetsdgets[14].W = sldrPOWER;
775 
776 	btn_icom_select_11->activate();
777 	btn_icom_select_12->deactivate();
778 	btn_icom_select_13->deactivate();
779 
780 	choice_rTONE->activate();
781 	choice_tTONE->activate();
782 }
783 
RIG_IC746PRO()784 RIG_IC746PRO::RIG_IC746PRO() {
785 	defaultCIV = 0x66;
786 	name_ = IC746PROname_;
787 	modes_ = IC746PROmodes_;
788 	bandwidths_ = IC746PRO_SSBwidths;
789 	bw_vals_ = IC746PRO_bw_vals_SSB;
790 
791 	_mode_type = IC746PRO_mode_type;
792 	atten_level = 1;
793 	preamp_level = 2;
794 
795 	def_mode = modeB = modeA = B.imode = A.imode = 1;
796 	def_bw = bwB = bwA = B.iBW = A.iBW = 34;
797 	def_freq = freqB = freqA = B.freq = A.freq = 14070000L;
798 
799 	has_smeter =
800 	has_power_control =
801 	has_volume_control =
802 	has_mode_control =
803 	has_bandwidth_control =
804 	has_micgain_control =
805 	has_notch_control =
806 	has_attenuator_control =
807 	has_preamp_control =
808 	has_pbt_controls = true;
809 
810 	has_ptt_control =
811 	has_tune_control =
812 	has_noise_control =
813 	has_noise_reduction =
814 	has_noise_reduction_control =
815 	has_rf_control =
816 	has_sql_control =
817 	has_split =
818 	restore_mbw = true;
819 
820 	has_swr_control =
821 	has_alc_control =
822 	has_power_out = true;
823 
824 	has_extras = true;
825 	has_band_selection = true;
826 
827 	adjustCIV(defaultCIV);
828 };
829 
set_modeA(int val)830 void RIG_IC746PRO::set_modeA(int val)
831 {
832 	A.imode = val;
833 	bool datamode = false;
834 	switch (val) {
835 		case 10 : val = 5; datamode = true; break;
836 		case 9  : val = 1; datamode = true; break;
837 		case 8  : val = 0; datamode = true; break;
838 		case 7  : val = 8; break;
839 		case 6  : val = 7; break;
840 		default: break;
841 	}
842 	cmd = pre_to;
843 	cmd += '\x06';
844 	cmd += val;
845 	cmd += filter_nbr + 1; // filter 1 ... 3
846 	cmd.append( post );
847 	waitFB("set mode A");
848 	if (datamode) { // LSB / USB ==> use DATA mode
849 		cmd = pre_to;
850 		cmd.append("\x1A\x06\x01");
851 		cmd.append(post);
852 		waitFB("data mode");
853 	}
854 }
855 
get_modeA()856 int RIG_IC746PRO::get_modeA()
857 {
858 	int md;
859 	string cstr = "\x04";
860 	string resp = pre_fm;
861 	resp.append(cstr);
862 	cmd = pre_to;
863 	cmd.append(cstr);
864 	cmd.append(post);
865 	if (waitFOR(8, "get mode A")) {
866 		size_t p = replystr.rfind(resp);
867 		if (p != string::npos) {
868 			md = replystr[p+5];
869 			if (md > 6) md--;
870 			filter_nbr = replystr[p+6] - 1;
871 			cstr = "\x1A\x06";
872 			resp = pre_fm;
873 			resp.append(cstr);
874 			cmd = pre_to;
875 			cmd.append(cstr);
876 			cmd.append(post);
877 			if (waitFOR(8, "data ?")) {
878 				p = replystr.rfind(resp);
879 				if (p != string::npos) {
880 					if (replystr[p+6]) {
881 						switch (md) {
882 							case 0 : md = 8; break;
883 							case 1 : md = 9; break;
884 							case 5 : md = 10; break;
885 							default : break;
886 						}
887 					}
888 				}
889 			}
890 			A.imode = md;
891 		}
892 	}
893 	return A.imode;
894 }
895 
set_modeB(int val)896 void RIG_IC746PRO::set_modeB(int val)
897 {
898 	B.imode = val;
899 	bool datamode = false;
900 	switch (val) {
901 		case 10 : val = 5; datamode = true; break;
902 		case 9  : val = 1; datamode = true; break;
903 		case 8  : val = 0; datamode = true; break;
904 		case 7  : val = 8; break;
905 		case 6  : val = 7; break;
906 		default: break;
907 	}
908 	cmd = pre_to;
909 	cmd += '\x06';
910 	cmd += val;
911 	cmd += filter_nbr + 1;
912 	cmd.append( post );
913 	waitFB("set mode B");
914 	if (datamode) { // LSB / USB ==> use DATA mode
915 		cmd = pre_to;
916 		cmd.append("\x1A\x06\x01");
917 		cmd.append(post);
918 		waitFB("data mode");
919 	}
920 }
921 
get_modeB()922 int RIG_IC746PRO::get_modeB()
923 {
924 	int md;
925 	string cstr = "\x04";
926 	string resp = pre_fm;
927 	resp.append(cstr);
928 	cmd = pre_to;
929 	cmd.append(cstr);
930 	cmd.append(post);
931 	if (waitFOR(8, "get mode B")) {
932 		size_t p = replystr.rfind(resp);
933 		if (p != string::npos) {
934 			md = replystr[p+5];
935 			if (md > 6) md--;
936 			filter_nbr = replystr[p+6] - 1; // this is the filter #; not the bandwidth
937 			cstr = "\x1A\x06";
938 			resp = pre_fm;
939 			resp.append(cstr);
940 			cmd = pre_to;
941 			cmd.append(cstr);
942 			cmd.append(post);
943 			if (waitFOR(8, "data ?")) {
944 				p = replystr.rfind(resp);
945 				if (p != string::npos) {
946 					if (replystr[p+6]) {
947 						switch (md) {
948 							case 0 : md = 8; break;
949 							case 1 : md = 9; break;
950 							case 5 : md = 10; break;
951 							default : break;
952 						}
953 					}
954 				}
955 			}
956 			B.imode = md;
957 		}
958 	}
959 	return B.imode;
960 }
961 
adjust_bandwidth(int m)962 int RIG_IC746PRO::adjust_bandwidth(int m)
963 {
964 	if (m == 0 || m == 1 || m == 8 || m == 9) { //SSB
965 		bandwidths_ = IC746PRO_SSBwidths;
966 		bw_vals_ = IC746PRO_bw_vals_SSB;
967 		return (32);
968 	}
969 	if (m == 3 || m == 6) { //CW
970 		bandwidths_ = IC746PRO_SSBwidths;
971 		bw_vals_ = IC746PRO_bw_vals_SSB;
972 		return (14);
973 	}
974 	if (m == 4 || m == 7) { //RTTY
975 		bandwidths_ = IC746PRO_RTTYwidths;
976 		bw_vals_ = IC746PRO_bw_vals_RTTY;
977 		return (28);
978 	}
979 	bandwidths_ = IC746PRO_AMFMwidths;
980 	bw_vals_ = IC746PRO_bw_vals_AMFM;
981 	return (0);
982 }
983 
def_bandwidth(int m)984 int RIG_IC746PRO::def_bandwidth(int m)
985 {
986 	if (m == 0 || m == 1 || m == 8 || m == 9) { //SSB
987 		return (32);
988 	}
989 	if (m == 3 || m == 6) { //CW
990 		return (14);
991 	}
992 	if (m == 4 || m == 7) { //RTTY
993 		return (28);
994 	}
995 	bandwidths_ = IC746PRO_AMFMwidths;
996 	return (0);
997 }
998 
bwtable(int m)999 const char **RIG_IC746PRO::bwtable(int m)
1000 {
1001 	if (m == 0 || m == 1 || m == 8 || m == 9) //SSB
1002 		return IC746PRO_SSBwidths;
1003 	if (m == 3 || m == 6) //CW
1004 		return IC746PRO_SSBwidths;
1005 	if (m == 4 || m == 7) //RTTY
1006 		return IC746PRO_RTTYwidths;
1007 	return IC746PRO_AMFMwidths;
1008 }
1009 
get_swr()1010 int RIG_IC746PRO::get_swr()
1011 {
1012 	string cstr = "\x15\x12";
1013 	string resp = pre_fm;
1014 	resp.append(cstr);
1015 	cmd = pre_to;
1016 	cmd.append(cstr);
1017 	cmd.append( post );
1018 	if (waitFOR(9, "get swr")) {
1019 		size_t p = replystr.rfind(resp);
1020 		if (p != string::npos)
1021 		return (int)ceil(fm_bcd(replystr.substr(p + 6),3) / 2.55 );
1022 	}
1023 	return -1;
1024 }
1025 
get_alc()1026 int RIG_IC746PRO::get_alc()
1027 {
1028 	string cstr = "\x15\x13";
1029 	string resp = pre_fm;
1030 	resp.append(cstr);
1031 	cmd = pre_to;
1032 	cmd.append(cstr);
1033 	cmd.append( post );
1034 	if (waitFOR(9, "get alc")) {
1035 		size_t p = replystr.rfind(resp);
1036 		if (p != string::npos)
1037 		return (int)ceil(fm_bcd(replystr.substr(p + 6),3) / 2.55 );
1038 	}
1039 	return -1;
1040 }
1041 
1042 // Transceiver power level return power in watts
get_power_out()1043 int RIG_IC746PRO::get_power_out()
1044 {
1045 	string cstr = "\x15\x11";
1046 	string resp = pre_fm;
1047 	resp.append(cstr);
1048 	cmd = pre_to;
1049 	cmd.append(cstr);
1050 	cmd.append( post );
1051 	if (waitFOR(9, "get power")) {
1052 		size_t p = replystr.rfind(resp);
1053 		if (p != string::npos)
1054 		return (int)ceil(fm_bcd(replystr.substr(p + 6),3) / 2.55 );
1055 	}
1056 	return -1;
1057 }
1058 
set_bwA(int val)1059 void RIG_IC746PRO::set_bwA(int val)
1060 {
1061 //	if (bandwidths_ == IC746PRO_AMFMwidths) {
1062 //		filter_nbr = val;
1063 //		set_modeA(A.imode);
1064 //		return;
1065 //	}
1066 
1067 	A.iBW = val;
1068 	cmd = pre_to;
1069 	cmd.append("\x1A\x03");
1070 	cmd.append(to_bcd(A.iBW,2));
1071 	cmd.append( post );
1072 	waitFB("set bw A");
1073 }
1074 
get_bwA()1075 int  RIG_IC746PRO::get_bwA()
1076 {
1077 	string cstr = "\x1A\x03";
1078 	string resp = pre_fm;
1079 	resp.append(cstr);
1080 	cmd = pre_to;
1081 	cmd.append(cstr);
1082 	cmd.append( post );
1083 	if (waitFOR(8, "get bw A")) {
1084 		size_t p = replystr.rfind(resp);
1085 		if (p != string::npos)
1086 			A.iBW = (int)ceil(fm_bcd(replystr.substr(p + 6), 2));
1087 	}
1088 	return A.iBW;
1089 }
1090 
set_bwB(int val)1091 void RIG_IC746PRO::set_bwB(int val)
1092 {
1093 //	if (bandwidths_ == IC746PRO_AMFMwidths) {
1094 //		filter_nbr = val;
1095 //		set_modeA(A.imode);
1096 //		return;
1097 //	}
1098 
1099 	B.iBW = val;
1100 	cmd = pre_to;
1101 	cmd.append("\x1A\x03");
1102 	cmd.append(to_bcd(B.iBW,2));
1103 	cmd.append( post );
1104 	waitFB("set bw B");
1105 }
1106 
get_bwB()1107 int  RIG_IC746PRO::get_bwB()
1108 {
1109 	string cstr = "\x1A\x03";
1110 	string resp = pre_fm;
1111 	resp.append(cstr);
1112 	cmd = pre_to;
1113 	cmd.append(cstr);
1114 	cmd.append( post );
1115 	if (waitFOR(8, "get bw B")) {
1116 		size_t p = replystr.rfind(resp);
1117 		if (p != string::npos)
1118 			B.iBW = (int)(fm_bcd(replystr.substr(p + 6), 2));
1119 	}
1120 	return B.iBW;
1121 }
1122 
get_attenuator()1123 int RIG_IC746PRO::get_attenuator()
1124 {
1125 	string cstr = "\x11";
1126 	string resp = pre_fm;
1127 	resp.append(cstr);
1128 	cmd = pre_to;
1129 	cmd.append(cstr);
1130 	cmd.append( post );
1131 	if (waitFOR(7, "get att")) {
1132 		size_t p = replystr.rfind(resp);
1133 		if (p != string::npos)
1134 			return (replystr[p+5] ? 1 : 0);
1135 	}
1136 	return 0;
1137 }
1138 
set_attenuator(int val)1139 void RIG_IC746PRO::set_attenuator(int val)
1140 {
1141 	int cmdval = val ? 0x20 : 0x00;
1142 	cmd = pre_to;
1143 	cmd += '\x11';
1144 	cmd += cmdval;
1145 	cmd.append( post );
1146 	waitFB("set att");
1147 }
1148 
1149 bool IC_notchon = false;
set_notch(bool on,int val)1150 void RIG_IC746PRO::set_notch(bool on, int val)
1151 {
1152 	int notch = (int)(val/20.0 + 128);
1153 	if (notch > 256) notch = 255;
1154 	if (on != IC_notchon) {
1155 		cmd = pre_to;
1156 		cmd.append("\x16\x48");
1157 		cmd += on ? '\x01' : '\x00';
1158 		cmd.append(post);
1159 		waitFB("set notch");
1160 		IC_notchon = on;
1161 	}
1162 
1163 	if (on) {
1164 		cmd = pre_to;
1165 		cmd.append("\x14\x0D");
1166 		cmd.append(to_bcd(notch,3));
1167 		cmd.append(post);
1168 		waitFB("set notch val");
1169 	}
1170 }
1171 
get_notch(int & val)1172 bool RIG_IC746PRO::get_notch(int &val)
1173 {
1174 	bool on = false;
1175 	val = 0;
1176 
1177 	string cstr = "\x16\x48";
1178 	string resp = pre_fm;
1179 	resp.append(cstr);
1180 	cmd = pre_to;
1181 	cmd.append(cstr);
1182 	cmd.append( post );
1183 	if (waitFOR(8, "get notch")) {
1184 		size_t p = replystr.rfind(resp);
1185 		if (p != string::npos)
1186 			on = replystr[p + 6] ? 1 : 0;
1187 		cmd = pre_to;
1188 		resp = pre_fm;
1189 		cstr = "\x14\x0D";
1190 		cmd.append(cstr);
1191 		resp.append(cstr);
1192 		cmd.append(post);
1193 		if (waitFOR(9, "get notch val")) {
1194 			size_t p = replystr.rfind(resp);
1195 			if (p != string::npos)
1196 				val = 20*ceil(fm_bcd(replystr.substr(p + 6),3) - 128);
1197 		}
1198 	}
1199 	return on;
1200 }
1201 
get_notch_min_max_step(int & min,int & max,int & step)1202 void RIG_IC746PRO::get_notch_min_max_step(int &min, int &max, int &step)
1203 {
1204 	min = -1280;
1205 	max = 1280;
1206 	step = 20;
1207 }
1208 
set_rf_gain(int val)1209 void RIG_IC746PRO::set_rf_gain(int val)
1210 {
1211 	int ICrfg = val * 255 / 100;
1212 	cmd = pre_to;
1213 	cmd.append("\x14\x02");
1214 	cmd.append(to_bcd(ICrfg, 3));
1215 	cmd.append( post );
1216 	waitFB("set rf gain");
1217 }
1218 
get_rf_gain()1219 int RIG_IC746PRO::get_rf_gain()
1220 {
1221 	string cstr = "\x14\x02";
1222 	string resp = pre_fm;
1223 	cmd = pre_to;
1224 	cmd.append(cstr).append(post);
1225 	resp.append(cstr);
1226 	if (waitFOR(9, "get rfgain")) {
1227 		size_t p = replystr.rfind(resp);
1228 		if (p != string::npos)
1229 			return (int)ceil(fm_bcd(replystr.substr(p + 6),3) / 2.55);
1230 	}
1231 	return progStatus.rfgain;
1232 }
1233 
set_squelch(int val)1234 void RIG_IC746PRO::set_squelch(int val)
1235 {
1236 	int IC746PROsql = val * 255 / 100;
1237 	cmd = pre_to;
1238 	cmd.append("\x14\x03");
1239 	cmd.append(to_bcd(IC746PROsql, 3));
1240 	cmd.append( post );
1241 	waitFB("set sql");
1242 }
1243 
get_squelch()1244 int  RIG_IC746PRO::get_squelch()
1245 {
1246 	string cstr = "\x14\x03";
1247 	string resp = pre_fm;
1248 	resp.append(cstr);
1249 	cmd = pre_to;
1250 	cmd.append(cstr);
1251 	cmd.append(post);
1252 	if (waitFOR(9, "get sql")) {
1253 		size_t p = replystr.rfind(resp);
1254 		if (p != string::npos)
1255 			return (int)ceil(fm_bcd(replystr.substr(p+6), 3) / 2.55);
1256 	}
1257 	return progStatus.squelch;
1258 }
1259 
set_power_control(double val)1260 void RIG_IC746PRO::set_power_control(double val)
1261 {
1262 	cmd = pre_to;
1263 	cmd.append("\x14\x0A");
1264 	cmd.append(to_bcd((int)(val * 2.55), 3));
1265 	cmd.append( post );
1266 	waitFB("set power");
1267 }
1268 
get_power_control()1269 int RIG_IC746PRO::get_power_control()
1270 {
1271 	string cstr = "\x14\x0A";
1272 	string resp = pre_fm;
1273 	resp.append(cstr);
1274 	cmd = pre_to;
1275 	cmd.append(cstr).append(post);
1276 	if (waitFOR(9, "get power")) {
1277 		size_t p = replystr.rfind(resp);
1278 		if (p != string::npos)
1279 			return (int)ceil(fm_bcd(replystr.substr(p + 6),3) / 2.55);
1280 	}
1281 	return progStatus.power_level;
1282 }
1283 
set_preamp(int val)1284 void RIG_IC746PRO::set_preamp(int val)
1285 {
1286 	if (preamp_level == 0) {
1287 		preamp_level = 1;
1288 		preamp_label("Pre 1", true);
1289 	} else if (preamp_level == 1) {
1290 		preamp_level = 2;
1291 		preamp_label("Pre 2", true);
1292 	} else if (preamp_level == 2) {
1293 		preamp_level = 0;
1294 		preamp_label("Pre", false);
1295 	}
1296 	cmd = pre_to;
1297 	cmd += '\x16';
1298 	cmd += '\x02';
1299 	cmd += (unsigned char) preamp_level;
1300 	cmd.append( post );
1301 	waitFB("set preamp");
1302 }
1303 
get_preamp()1304 int RIG_IC746PRO::get_preamp()
1305 {
1306 	string cstr = "\x16\x02";
1307 	string resp = pre_fm;
1308 	resp.append(cstr);
1309 	cmd = pre_to;
1310 	cmd.append(cstr);
1311 	cmd.append( post );
1312 	if (waitFOR(8, "get preamp")) {
1313 		size_t p = replystr.rfind(resp);
1314 		if (p != string::npos) {
1315 			if (replystr[p+6] == 0x01) {
1316 				preamp_label("Pre 1", true);
1317 				preamp_level = 1;
1318 			} else if (replystr[p+6] == 0x02) {
1319 				preamp_label("Pre 2", true);
1320 				preamp_level = 2;
1321 			} else {
1322 				preamp_label("Pre", false);
1323 				preamp_level = 0;
1324 			}
1325 		}
1326 	}
1327 	return preamp_level;
1328 }
1329 
get_mic_gain()1330 int RIG_IC746PRO::get_mic_gain()
1331 {
1332 	string cstr = "\x14\x0B";
1333 	string resp = pre_fm;
1334 	resp.append(cstr);
1335 	cmd = pre_to;
1336 	cmd.append(cstr);
1337 	cmd.append(post);
1338 	if (waitFOR(9, "get mic")) {
1339 		size_t p = replystr.rfind(resp);
1340 		if (p != string::npos)
1341 			return (int)ceil(fm_bcd(replystr.substr(p+6),3) / 2.55);
1342 	}
1343 	return 0;
1344 }
1345 
set_mic_gain(int val)1346 void RIG_IC746PRO::set_mic_gain(int val)
1347 {
1348 	val = (int)(val * 2.55);
1349 	cmd = pre_to;
1350 	cmd.append("\x14\x0B");
1351 	cmd.append(to_bcd(val,3));
1352 	cmd.append(post);
1353 	waitFB("set mic");
1354 }
1355 
get_mic_gain_min_max_step(int & min,int & max,int & step)1356 void RIG_IC746PRO::get_mic_gain_min_max_step(int &min, int &max, int &step)
1357 {
1358 	min = 0;
1359 	max = 100;
1360 	step = 1;
1361 }
1362 
set_if_shift(int val)1363 void RIG_IC746PRO::set_if_shift(int val)
1364 {
1365 	int shift;
1366 	sh_ = val;
1367 	if (val == 0) sh_on_ = false;
1368 	else sh_on_ = true;
1369 
1370 	shift = 128 + val * 128 / 50;
1371 	if (shift < 0) shift = 0;
1372 	if (shift > 255) shift = 255;
1373 
1374 	cmd = pre_to;
1375 	cmd.append("\x14\x07");
1376 	cmd.append(to_bcd(shift, 3));
1377 	cmd.append(post);
1378 	waitFB("set IF on/off");
1379 
1380 	cmd = pre_to;
1381 	cmd.append("\x14\x08");
1382 	cmd.append(to_bcd(shift, 3));
1383 	cmd.append(post);
1384 	waitFB("set IF val");
1385 }
1386 
get_if_min_max_step(int & min,int & max,int & step)1387 void RIG_IC746PRO::get_if_min_max_step(int &min, int &max, int &step)
1388 {
1389 	min = -50;
1390 	max = +50;
1391 	step = 1;
1392 }
1393 
set_pbt_inner(int val)1394 void RIG_IC746PRO::set_pbt_inner(int val)
1395 {
1396 	int shift = 128 + val * 128 / 50;
1397 	if (shift < 0) shift = 0;
1398 	if (shift > 255) shift = 255;
1399 
1400 	cmd = pre_to;
1401 	cmd.append("\x14\x07");
1402 	cmd.append(to_bcd(shift, 3));
1403 	cmd.append(post);
1404 	waitFB("set PBT inner");
1405 }
1406 
set_pbt_outer(int val)1407 void RIG_IC746PRO::set_pbt_outer(int val)
1408 {
1409 	int shift = 128 + val * 128 / 50;
1410 	if (shift < 0) shift = 0;
1411 	if (shift > 255) shift = 255;
1412 
1413 	cmd = pre_to;
1414 	cmd.append("\x14\x08");
1415 	cmd.append(to_bcd(shift, 3));
1416 	cmd.append(post);
1417 	waitFB("set PBT outer");
1418 }
1419 
get_pbt_inner()1420 int RIG_IC746PRO::get_pbt_inner()
1421 {
1422 	int val = 0;
1423 	string cstr = "\x14\x07";
1424 	string resp = pre_fm;
1425 	resp.append(cstr);
1426 	cmd = pre_to;
1427 	cmd.append(cstr);
1428 	cmd.append( post );
1429 	if (waitFOR(9, "get pbt inner")) {
1430 		size_t p = replystr.rfind(resp);
1431 		if (p != string::npos) {
1432 			val = num100(replystr.substr(p+6));
1433 			val -= 50;
1434 		}
1435 	}
1436 	rig_trace(2, "get_pbt_inner()", str2hex(replystr.c_str(), replystr.length()));
1437 	return val;
1438 }
1439 
get_pbt_outer()1440 int RIG_IC746PRO::get_pbt_outer()
1441 {
1442 	int val = 0;
1443 	string cstr = "\x14\x08";
1444 	string resp = pre_fm;
1445 	resp.append(cstr);
1446 	cmd = pre_to;
1447 	cmd.append(cstr);
1448 	cmd.append( post );
1449 	if (waitFOR(9, "get pbt outer")) {
1450 		size_t p = replystr.rfind(resp);
1451 		if (p != string::npos) {
1452 			val = num100(replystr.substr(p+6));
1453 			val -= 50;
1454 		}
1455 	}
1456 	rig_trace(2, "get_pbt_outer()", str2hex(replystr.c_str(), replystr.length()));
1457 	return val;
1458 }
1459 
set_split(bool val)1460 void RIG_IC746PRO::set_split(bool val)
1461 {
1462 	split = val;
1463 	cmd = pre_to;
1464 	cmd += 0x0F;
1465 	cmd += val ? 0x01 : 0x00;
1466 	cmd.append(post);
1467 	waitFB(val ? "set split ON" : "set split OFF");
1468 }
1469 
get_split()1470 int  RIG_IC746PRO::get_split()
1471 {
1472 	return split;
1473 }
1474 
1475 // Read/Write band stack registers
1476 //
1477 // Read 23 bytes
1478 //
1479 //  0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22
1480 // FE FE nn E0 1A 01 bd rn f5 f4 f3 f2 f1 mo fi fg t1 t2 t3 r1 r2 r3 FD
1481 // Write 23 bytes
1482 //
1483 // FE FE E0 nn 1A 01 bd rn f5 f4 f3 f2 f1 mo fi fg t1 t2 t3 r1 r2 r3 FD
1484 //
1485 // nn - CI-V address
1486 // bd - band selection 1/2/3
1487 // rn - register number 1/2/3
1488 // f5..f1 - frequency BCD reverse
1489 // mo - mode
1490 // fi - filter #
1491 // fg flags: x01 use Tx tone, x02 use Rx tone, x10 data mode
1492 // t1..t3 - tx tone BCD fwd
1493 // r1..r3 - rx tone BCD fwd
1494 //
1495 // FE FE E0 94 1A 01 06 01 70 99 08 18 00 01 03 10 00 08 85 00 08 85 FD
1496 //
1497 // band 6; freq 0018,089,970; USB; data mode; t 88.5; r 88.5
1498 
get_band_selection(int v)1499 void RIG_IC746PRO::get_band_selection(int v)
1500 {
1501 	cmd.assign(pre_to);
1502 	cmd.append("\x1A\x01");
1503 	cmd += to_bcd_be( v, 2 );
1504 	cmd += '\x01';
1505 	cmd.append( post );
1506 
1507 	if (waitFOR(23, "get band stack")) {
1508 		set_trace(2, "get band stack", str2hex(replystr.c_str(), replystr.length()));
1509 		size_t p = replystr.rfind(pre_fm);
1510 		if (p != string::npos) {
1511 			unsigned long int bandfreq = fm_bcd_be(replystr.substr(p+8, 5), 10);
1512 			int bandmode = replystr[p+13];
1513 			int bandfilter = replystr[p+14];
1514 			int banddata = replystr[p+15] & 0x10;
1515 			if ((bandmode == 0 || bandmode == 1) && banddata) bandmode += 7;
1516 			int tone = fm_bcd(replystr.substr(p+16, 3), 6);
1517 			size_t index = 0;
1518 			for (index = 0; index < sizeof(PL_tones) / sizeof(*PL_tones); index++)
1519 				if (tone == PL_tones[index]) break;
1520 			tTONE = index;
1521 			tone = fm_bcd(replystr.substr(p+19, 3), 6);
1522 			for (index = 0; index < sizeof(PL_tones) / sizeof(*PL_tones); index++)
1523 				if (tone == PL_tones[index]) break;
1524 			rTONE = index;
1525 			if (useB) {
1526 				set_vfoB(bandfreq);
1527 				set_modeB(bandmode);
1528 				set_FILT(bandfilter);
1529 			} else {
1530 				set_vfoA(bandfreq);
1531 				set_modeA(bandmode);
1532 				set_FILT(bandfilter);
1533 			}
1534 		}
1535 	} else
1536 		set_trace(2, "get band stack", str2hex(replystr.c_str(), replystr.length()));
1537 }
1538 
set_band_selection(int v)1539 void RIG_IC746PRO::set_band_selection(int v)
1540 {
1541 	unsigned long int freq = (useB ? B.freq : A.freq);
1542 	int fil = (useB ? filB : filA);
1543 	int mode = (useB ? B.imode : A.imode);
1544 
1545 	cmd.assign(pre_to);
1546 	cmd.append("\x1A\x01");
1547 	cmd += to_bcd_be( v, 2 );
1548 	cmd += '\x01';
1549 	cmd.append( to_bcd_be( freq, 10 ) );
1550 	cmd += mode;
1551 	cmd += fil;
1552 	if (mode >= 7)
1553 		cmd += '\x10';
1554 	else
1555 		cmd += '\x00';
1556 	cmd.append(to_bcd(PL_tones[tTONE], 6));
1557 	cmd.append(to_bcd(PL_tones[rTONE], 6));
1558 	cmd.append(post);
1559 	waitFB("set_band_selection");
1560 	set_trace(2, "set_band_selection()", str2hex(replystr.c_str(), replystr.length()));
1561 
1562 	cmd.assign(pre_to);
1563 	cmd.append("\x1A\x01");
1564 	cmd += to_bcd_be( v, 2 );
1565 	cmd += '\x01';
1566 	cmd.append( post );
1567 
1568 	waitFOR(23, "get band stack");
1569 }
1570 
1571