1 // ----------------------------------------------------------------------------
2 // Copyright (C) 2014
3 //              David Freese, W1HKJ
4 // Modified: January 2017
5 //              Andy Stewart, KB1OIQ
6 // Updated: June 2018
7 //              Cliff Scott, AE5ZA
8 //
9 // This file is part of flrig.
10 //
11 // flrig is free software; you can redistribute it and/or modify
12 // it under the terms of the GNU General Public License as published by
13 // the Free Software Foundation; either version 3 of the License, or
14 // (at your option) any later version.
15 //
16 // flrig is distributed in the hope that it will be useful,
17 // but WITHOUT ANY WARRANTY; without even the implied warranty of
18 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19 // GNU General Public License for more details.
20 //
21 // You should have received a copy of the GNU General Public License
22 // aunsigned long int with this program.  If not, see <http://www.gnu.org/licenses/>.
23 // ----------------------------------------------------------------------------
24 
25 #include <string>
26 #include <sstream>
27 
28 #include "IC7300.h"
29 #include "support.h"
30 #include "trace.h"
31 
32 //=============================================================================
33 // IC-7300
34 
35 const char IC7300name_[] = "IC-7300";
36 
37 // these are only defined in this file
38 // undef'd at end of file
39 #define NUM_FILTERS 3
40 #define NUM_MODES  12
41 
42 static int mode_filterA[NUM_MODES] = {1,1,1,1,1,1,1,1,1,1,1,1};
43 static int mode_filterB[NUM_MODES] = {1,1,1,1,1,1,1,1,1,1,1,1};
44 
45 static int mode_bwA[NUM_MODES] = {-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1};
46 static int mode_bwB[NUM_MODES] = {-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1};
47 
48 static const char *szfilter[NUM_FILTERS] = {"1", "2", "3"};
49 
50 enum {
51 LSB7300, USB7300, AM7300, FM7300, CW7300, CWR7300, RTTY7300, RTTYR7300,
52 LSBD7300, USBD7300, AMD7300, FMD7300
53 };
54 
55 const char *IC7300modes_[] = {
56 	"LSB", "USB", "AM", "FM",
57 	"CW", "CW-R", "RTTY", "RTTY-R",
58 	"LSB-D", "USB-D", "AM-D", "FM-D", NULL};
59 
60 char IC7300_mode_type[] = {
61 	'L', 'U', 'U', 'U',
62 	'L', 'U', 'L', 'U',
63 	'L', 'U', 'U', 'U' };
64 
65 const char IC7300_mode_nbr[] = {
66 	0x00, 0x01, 0x02, 0x05, 0x03, 0x07, 0x04, 0x08,
67 	0x00, 0x01, 0x02, 0x05 };
68 
69 const char *IC7300_ssb_bws[] = {
70 "50",    "100",  "150",  "200",  "250",  "300",  "350",  "400",  "450",  "500",
71 "600",   "700",  "800",  "900", "1000", "1100", "1200", "1300", "1400", "1500",
72 "1600", "1700", "1800", "1900", "2000", "2100", "2200", "2300", "2400", "2500",
73 "2600", "2700", "2800", "2900", "3000", "3100", "3200", "3300", "3400", "3500",
74 "3600", NULL };
75 static int IC7300_bw_vals_SSB[] = {
76  0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
77 10,11,12,13,14,15,16,17,18,19,
78 20,21,22,23,24,25,26,27,28,29,
79 30,31,32,33,34,35,36,37,38,39,
80 40, WVALS_LIMIT};
81 
82 const char *IC7300_rtty_bws[] = {
83 "50",    "100",  "150",  "200",  "250",  "300",  "350",  "400",  "450",  "500",
84 "600",   "700",  "800",  "900", "1000", "1100", "1200", "1300", "1400", "1500",
85 "1600", "1700", "1800", "1900", "2000", "2100", "2200", "2300", "2400", "2500",
86 "2600", "2700", NULL };
87 static int IC7300_bw_vals_RTTY[] = {
88  0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
89 10,11,12,13,14,15,16,17,18,19,
90 20,21,22,23,24,25,26,27,28,29,
91 30,31, WVALS_LIMIT};
92 
93 const char *IC7300_am_bws[] = {
94 "200",   "400",  "600",  "800", "1000", "1200", "1400", "1600", "1800", "2000",
95 "2200", "2400", "2600", "2800", "3000", "3200", "3400", "3600", "3800", "4000",
96 "4200", "4400", "4600", "4800", "5000", "5200", "5400", "5600", "5800", "6000",
97 "6200", "6400", "6600", "6800", "7000", "7300", "7400", "7300", "7800", "8000",
98 "8200", "8400", "8600", "8800", "9000", "9200", "9400", "9600", "9800", "10000", NULL };
99 static int IC7300_bw_vals_AM[] = {
100  0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
101 10,11,12,13,14,15,16,17,18,19,
102 20,21,22,23,24,25,26,27,28,29,
103 30,31,32,33,34,35,36,37,38,39,
104 40,41,42,43,44,45,46,47,48,49
105 WVALS_LIMIT};
106 
107 const char *IC7300_fm_bws[] = { "FIXED", NULL };
108 static int IC7300_bw_vals_FM[] = { 1, WVALS_LIMIT};
109 
110 static GUI IC7300_widgets[]= {
111 	{ (Fl_Widget *)btnVol,        2, 125,  50 },	//0
112 	{ (Fl_Widget *)sldrVOLUME,   54, 125, 156 },	//1
113 	{ (Fl_Widget *)btnAGC,        2, 145,  50 },	//2
114 	{ (Fl_Widget *)sldrRFGAIN,   54, 145, 156 },	//3
115 	{ (Fl_Widget *)sldrSQUELCH,  54, 165, 156 },	//4
116 	{ (Fl_Widget *)btnNR,         2, 185,  50 },	//5
117 	{ (Fl_Widget *)sldrNR,       54, 185, 156 },	//6
118 	{ (Fl_Widget *)btnLOCK,     214, 105,  50 },	//7
119 	{ (Fl_Widget *)sldrINNER,   266, 105, 156 },	//8
120 	{ (Fl_Widget *)btnCLRPBT,   214, 125,  50 },	//9
121 	{ (Fl_Widget *)sldrOUTER,   266, 125, 156 },	//10
122 	{ (Fl_Widget *)btnNotch,    214, 145,  50 },	//11
123 	{ (Fl_Widget *)sldrNOTCH,   266, 145, 156 },	//12
124 	{ (Fl_Widget *)sldrMICGAIN, 266, 165, 156 },	//13
125 	{ (Fl_Widget *)sldrPOWER,   266, 185, 156 },	//14
126 	{ (Fl_Widget *)NULL, 0, 0, 0 }
127 };
128 
initialize()129 void RIG_IC7300::initialize()
130 {
131 	IC7300_widgets[0].W = btnVol;
132 	IC7300_widgets[1].W = sldrVOLUME;
133 	IC7300_widgets[2].W = btnAGC;
134 	IC7300_widgets[3].W = sldrRFGAIN;
135 	IC7300_widgets[4].W = sldrSQUELCH;
136 	IC7300_widgets[5].W = btnNR;
137 	IC7300_widgets[6].W = sldrNR;
138 	IC7300_widgets[7].W = btnLOCK;
139 	IC7300_widgets[8].W = sldrINNER;
140 	IC7300_widgets[9].W = btnCLRPBT;
141 	IC7300_widgets[10].W = sldrOUTER;
142 	IC7300_widgets[11].W = btnNotch;
143 	IC7300_widgets[12].W = sldrNOTCH;
144 	IC7300_widgets[13].W = sldrMICGAIN;
145 	IC7300_widgets[14].W = sldrPOWER;
146 
147 	btn_icom_select_11->deactivate();
148 	btn_icom_select_12->deactivate();
149 	btn_icom_select_13->deactivate();
150 
151 	choice_rTONE->activate();
152 	choice_tTONE->activate();
153 }
154 
RIG_IC7300()155 RIG_IC7300::RIG_IC7300() {
156 	defaultCIV = 0x94;
157 	adjustCIV(defaultCIV);
158 
159 	name_ = IC7300name_;
160 	modes_ = IC7300modes_;
161 	bandwidths_ = IC7300_ssb_bws;
162 	bw_vals_ = IC7300_bw_vals_SSB;
163 
164 	_mode_type = IC7300_mode_type;
165 
166 	comm_baudrate = BR19200;
167 	stopbits = 1;
168 	comm_retries = 2;
169 	comm_wait = 5;
170 	comm_timeout = 50;
171 	comm_echo = true;
172 	comm_rtscts = false;
173 	comm_rtsplus = true;
174 	comm_dtrplus = true;
175 	comm_catptt = true;
176 	comm_rtsptt = false;
177 	comm_dtrptt = false;
178 
179 	widgets = IC7300_widgets;
180 
181 	def_freq = A.freq = 14070000;
182 	def_mode = A.imode = 9;
183 	def_bw = A.iBW = 34;
184 
185 	B.freq = 7070000;
186 	B.imode = 9;
187 	B.iBW = 34;
188 
189 	has_extras = true;
190 
191 	has_cw_wpm = true;
192 	has_cw_spot_tone = true;
193 	has_cw_qsk = true;
194 	has_cw_break_in = true;
195 
196 	has_vox_onoff = true;
197 	has_vox_gain = true;
198 	has_vox_anti = true;
199 	has_vox_hang = true;
200 
201 	has_compON = true;
202 	has_compression = true;
203 
204 	has_split = true;
205 	has_split_AB = true;
206 
207 	has_micgain_control = true;
208 	has_bandwidth_control = true;
209 
210 	has_smeter = true;
211 
212 	has_power_out = true;
213 	has_swr_control = true;
214 	has_alc_control = true;
215 	has_sql_control = true;
216 	has_agc_control = true;
217 
218 	has_power_control = true;
219 	has_volume_control = true;
220 	has_mode_control = true;
221 
222 	has_attenuator_control = true;
223 	has_preamp_control = true;
224 
225 	has_noise_control = true;
226 	has_nb_level = true;
227 
228 	has_noise_reduction = true;
229 	has_noise_reduction_control = true;
230 
231 	has_auto_notch = true;
232 	has_notch_control = true;
233 
234 	has_pbt_controls = true;
235 	has_FILTER = true;
236 
237 	has_rf_control = true;
238 
239 	has_ptt_control = true;
240 	has_tune_control = true;
241 
242 	has_band_selection = true;
243 
244 	has_xcvr_auto_on_off = true;
245 
246 	precision = 1;
247 	ndigits = 8;
248 
249 	has_vfo_adj = true;
250 
251 	can_change_alt_vfo = true;
252 	has_a2b = true;
253 
254 	CW_sense = 0; // CW is LSB
255 };
256 
minmax(int min,int max,int & val)257 static inline void minmax(int min, int max, int &val)
258 {
259 	if (val > max) val = max;
260 	if (val < min) val = min;
261 }
262 
selectA()263 void RIG_IC7300::selectA()
264 {
265 	cmd.assign(pre_to).append("\x07");
266 	cmd += '\x00';
267 	cmd.append(post);
268 	waitFB("select A");
269 
270 	isett("selectA");
271 }
272 
selectB()273 void RIG_IC7300::selectB()
274 {
275 	cmd.assign(pre_to).append("\x07");
276 	cmd += '\x01';
277 	cmd.append(post);
278 	waitFB("select B");
279 
280 	isett("selectB");
281 }
282 
283 //======================================================================
284 // IC7300 unique commands
285 //======================================================================
286 
swapAB()287 void RIG_IC7300::swapAB()
288 {
289 	cmd = pre_to;
290 	cmd += 0x07; cmd += 0xB0;
291 	cmd.append(post);
292 	waitFB("Exchange vfos");
293 	get_modeA(); // get mode to update the filter A / B usage
294 	get_modeB();
295 }
296 
set_xcvr_auto_on()297 void RIG_IC7300::set_xcvr_auto_on()
298 {
299 	cmd = pre_to;
300 	cmd += '\x19'; cmd += '\x00';
301 	cmd.append(post);
302 	if (waitFOR(8, "get ID", 100) == false) {
303 		cmd.clear();
304 		int fes[] = { 2, 2, 2, 3, 7, 13, 25, 50, 75, 150, 150, 150 };
305 		if (progStatus.comm_baudrate >= 0 && progStatus.comm_baudrate <= 11) {
306 			cmd.append( fes[progStatus.comm_baudrate], '\xFE');
307 		}
308 		cmd.append(pre_to);
309 		cmd += '\x18'; cmd += '\x01';
310 		cmd.append(post);
311 		waitFB("Power ON", 200);
312 		for (int i = 0; i < 5000; i += 100) {
313 			MilliSleep(100);
314 			update_progress(100 * i / 5000);
315 			Fl::awake();
316 		}
317 	}
318 }
319 
set_xcvr_auto_off()320 void RIG_IC7300::set_xcvr_auto_off()
321 {
322 	cmd.clear();
323 	cmd.append(pre_to);
324 	cmd += '\x18'; cmd += '\x00';
325 	cmd.append(post);
326 	waitFB("Power OFF", 200);
327 }
328 
check()329 bool RIG_IC7300::check ()
330 {
331 	string resp = pre_fm;
332 	resp += '\x03';
333 	cmd = pre_to;
334 	cmd += '\x03';
335 	cmd.append( post );
336 	bool ok = waitFOR(11, "check vfo");
337 	isett("check vfo");
338 	return ok;
339 }
340 
get_vfoA()341 unsigned long int RIG_IC7300::get_vfoA ()
342 {
343 	string resp;
344 
345 	cmd.assign(pre_to).append("\x25");
346 	resp.assign(pre_fm).append("\x25");
347 
348 	if (useB) {
349 		cmd  += '\x01';
350 		resp += '\x01';
351 	} else {
352 		cmd  += '\x00';
353 		resp += '\x00';
354 	}
355 
356 	cmd.append(post);
357 	if (waitFOR(12, "get vfo A")) {
358 		size_t p = replystr.rfind(resp);
359 		if (p != string::npos) {
360 			if (replystr[p+6] == -1)
361 				A.freq = 0;
362 			else
363 				A.freq = fm_bcd_be(replystr.substr(p+6), 10);
364 		}
365 	}
366 
367 	igett("get_vfoA");
368 
369 	return A.freq;
370 }
371 
set_vfoA(unsigned long int freq)372 void RIG_IC7300::set_vfoA (unsigned long int freq)
373 {
374 	A.freq = freq;
375 
376 	cmd.assign(pre_to).append("\x25");
377 	if (useB) cmd += '\x01';
378 	else      cmd += '\x00';
379 
380 	cmd.append( to_bcd_be( freq, 10) );
381 	cmd.append( post );
382 	waitFB("set vfo A");
383 
384 	isett("set_vfoA");
385 
386 }
387 
get_vfoB()388 unsigned long int RIG_IC7300::get_vfoB ()
389 {
390 	string resp;
391 
392 	cmd.assign(pre_to).append("\x25");
393 	resp.assign(pre_fm).append("\x25");
394 
395 	if (useB) {
396 		cmd  += '\x00';
397 		resp += '\x00';
398 	} else {
399 		cmd  += '\x01';
400 		resp += '\x01';
401 	}
402 
403 	cmd.append(post);
404 	if (waitFOR(12, "get vfo B")) {
405 		size_t p = replystr.rfind(resp);
406 		if (p != string::npos) {
407 			if (replystr[p+6] == -1)
408 				A.freq = 0;
409 			else
410 				B.freq = fm_bcd_be(replystr.substr(p+6), 10);
411 		}
412 	}
413 
414 	igett("get_vfoB");
415 
416 	return B.freq;
417 }
418 
set_vfoB(unsigned long int freq)419 void RIG_IC7300::set_vfoB (unsigned long int freq)
420 {
421 	B.freq = freq;
422 
423 	cmd.assign(pre_to).append("\x25");
424 	if (useB) cmd += '\x00';
425 	else      cmd += '\x01';
426 
427 	cmd.append( to_bcd_be( freq, 10 ) );
428 	cmd.append( post );
429 	waitFB("set vfo B");
430 
431 	isett("set_vfoB");
432 }
433 
434 // expecting
435 //  0  1  2  3  4  5  6  7  8  9
436 // FE FE E0 94 26 NN NN NN NN FD
437 //                |  |  |  |
438 //                |  |  |  |__filter setting, 01, 02, 03
439 //                |  |  |_____data mode, 00 - off, 01 - on
440 //                |  |________Mode 00 - LSB
441 //                |                01 - USB
442 //                |                02 - AM
443 //                |                03 - CW
444 //                |                04 - RTTY
445 //                |                05 - FM
446 //                |                07 - CW-R
447 //                |                08 - RTTY-R
448 //                |___________selected vfo, 00 - active, 01 - inactive
449 
get_modeA()450 int RIG_IC7300::get_modeA()
451 {
452 	int md = 0;
453 	size_t p;
454 
455 	string resp;
456 	cmd.assign(pre_to).append("\x26");
457 	resp.assign(pre_fm).append("\x26");
458 
459 	if (useB)
460 		cmd += '\x01';
461 	else
462 		cmd += '\x00';
463 
464 	cmd.append(post);
465 
466 	if (waitFOR(10, "get mode A")) {
467 		p = replystr.rfind(resp);
468 		if (p == string::npos)
469 			goto end_wait_modeA;
470 
471 		if (replystr[p+6] == -1) { md = A.imode = 0; }
472 		else {
473 			for (md = 0; md < LSBD7300; md++) {
474 				if (replystr[p+6] == IC7300_mode_nbr[md]) {
475 					A.imode = md;
476 					if (replystr[p+7] == 0x01 && A.imode < 4)
477 						A.imode += 8;
478 					if (A.imode > 11)
479 						A.imode = 1;
480 					break;
481 				}
482 			}
483 			A.filter = replystr[p+8];
484 			if (A.filter > 0 && A.filter < 4)
485 				mode_filterA[A.imode] = A.filter;
486 		}
487 	}
488 
489 end_wait_modeA:
490 
491 	get_trace(4, "get mode A[", IC7300modes_[A.imode], "] ", str2hex(replystr.c_str(), replystr.length()));
492 
493 	if (A.imode == CW7300 || A.imode == CWR7300) {
494 		cmd.assign(pre_to).append("\x1A\x05");
495 		cmd += '\x00'; cmd += '\x53';
496 		cmd.append(post);
497 		resp.assign(pre_fm).append("\x1A\x05");
498 		resp += '\x00'; resp += '\x53';
499 		if (waitFOR(10, "get CW sideband")) {
500 			p = replystr.rfind(resp);
501 			CW_sense = replystr[p+8];
502 			if (CW_sense) IC7300_mode_type[A.imode] = 'U';
503 			else IC7300_mode_type[A.imode] = 'L';
504 		}
505 		get_trace(2, "get CW sideband ", str2hex(replystr.c_str(), replystr.length()));
506 	}
507 
508 	return A.imode;
509 }
510 
511 // LSB  USB  AM   CW  RTTY  FM  CW-R  RTTY-R  LSB-D  USB-D
512 //  0    1    2    3   4     5    6     7      8      9
513 
set_modeA(int val)514 void RIG_IC7300::set_modeA(int val)
515 {
516 	A.imode = val;
517 	cmd.assign(pre_to);
518 	cmd += '\x26';
519 	if (useB)
520 		cmd += '\x01';					// unselected vfo
521 	else
522 		cmd += '\x00';					// selected vfo
523 	cmd += IC7300_mode_nbr[A.imode];	// operating mode
524 	if (A.imode >= LSBD7300)
525 		cmd += '\x01';					// data mode
526 	else
527 		cmd += '\x00';
528 	cmd += mode_filterA[A.imode];		// filter
529 	cmd.append( post );
530 	waitFB("set mode A");
531 
532 	set_trace(4, "set mode A[", IC7300modes_[A.imode], "] ", str2hex(replystr.c_str(), replystr.length()));
533 }
534 
get_modeB()535 int RIG_IC7300::get_modeB()
536 {
537 	int md = 0;
538 	size_t p;
539 
540 	string resp;
541 	cmd.assign(pre_to).append("\x26");
542 	resp.assign(pre_fm).append("\x26");
543 
544 	if (useB)
545 		cmd += '\x00';   // active vfo
546 	else
547 		cmd += '\x01';   // inactive vfo
548 	cmd.append(post);
549 
550 	if (waitFOR(10, "get mode B")) {
551 		p = replystr.rfind(resp);
552 		if (p == string::npos)
553 			goto end_wait_modeB;
554 
555 		if (replystr[p+6] == -1) { md = filA = 0; }
556 		else {
557 			for (md = 0; md < LSBD7300; md++) {
558 				if (replystr[p+6] == IC7300_mode_nbr[md]) {
559 					B.imode = md;
560 					if (replystr[p+7] == 0x01 && B.imode < 4)
561 						B.imode += 8;
562 					if (B.imode > 11)
563 						B.imode = 1;
564 					break;
565 				}
566 			}
567 			B.filter = replystr[p+8];
568 		}
569 	}
570 
571 end_wait_modeB:
572 
573 	get_trace(4, "get mode B[", IC7300modes_[B.imode], "] ", str2hex(replystr.c_str(), replystr.length()));
574 
575 	if (B.filter > 0 && B.filter < 4)
576 		mode_filterB[B.imode] = B.filter;
577 
578 	get_trace(4, "get mode A[", IC7300modes_[B.imode], "] ", str2hex(replystr.c_str(), replystr.length()));
579 	if (B.imode == CW7300 || B.imode == CWR7300) {
580 		cmd.assign(pre_to).append("\x1A\x05");
581 		cmd += '\x00'; cmd += '\x53';
582 		cmd.append(post);
583 		resp.assign(pre_fm).append("\x1A\x05");
584 		resp += '\x00'; resp += '\x53';
585 		if (waitFOR(10, "get CW sideband")) {
586 			p = replystr.rfind(resp);
587 			CW_sense = replystr[p+8];
588 			if (CW_sense) IC7300_mode_type[B.imode] = 'U';
589 			else IC7300_mode_type[B.imode] = 'L';
590 		}
591 		get_trace(2, "get CW sideband ", str2hex(replystr.c_str(), replystr.length()));
592 	}
593 
594 	return B.imode;
595 }
596 
set_modeB(int val)597 void RIG_IC7300::set_modeB(int val)
598 {
599 	B.imode = val;
600 	cmd.assign(pre_to);
601 	cmd += '\x26';
602 	if (useB)
603 		cmd += '\x00';					// selected vfo
604 	else
605 		cmd += '\x01';					// unselected vfo
606 	cmd += IC7300_mode_nbr[B.imode];	// operating mode
607 	if (B.imode >= LSBD7300)
608 		cmd += '\x01';					// data mode
609 	else
610 		cmd += '\x00';
611 	cmd += mode_filterB[B.imode];		// filter
612 	cmd.append( post );
613 	waitFB("set mode B");
614 
615 	set_trace(4, "set mode B[", IC7300modes_[B.imode], "] ", str2hex(replystr.c_str(), replystr.length()));
616 }
617 
get_FILT(int mode)618 int RIG_IC7300::get_FILT(int mode)
619 {
620 	if (useB) return mode_filterB[mode];
621 	return mode_filterA[mode];
622 }
623 
set_FILT(int filter)624 void RIG_IC7300::set_FILT(int filter)
625 {
626 	if (filter < 1 || filter > 3)
627 		return;
628 
629 	if (useB) {
630 		B.filter = filter;
631 		mode_filterB[B.imode] = filter;
632 		cmd.assign(pre_to);
633 		cmd += '\x26';
634 		cmd += '\x00';						// selected vfo
635 		cmd += IC7300_mode_nbr[B.imode];	// operating mode
636 		if (B.imode >= LSBD7300) cmd += '\x01';	// data mode
637 		else cmd += '\x00';
638 		cmd += filter;						// filter
639 		cmd.append( post );
640 		waitFB("set mode/filter B");
641 
642 		set_trace(4, "set mode/filter B[", IC7300modes_[B.imode], "] ", str2hex(replystr.c_str(), replystr.length()));
643 	} else {
644 		A.filter = filter;
645 		mode_filterA[A.imode] = filter;
646 		cmd.assign(pre_to);
647 		cmd += '\x26';
648 		cmd += '\x00';						// selected vfo
649 		cmd += IC7300_mode_nbr[A.imode];	// operating mode
650 		if (A.imode >= LSBD7300) cmd += '\x01';	// data mode
651 		else cmd += '\x00';
652 		cmd += filter;						// filter
653 		cmd.append( post );
654 		waitFB("set mode/filter A");
655 
656 		set_trace(4, "set mode/filter A[", IC7300modes_[A.imode], "] ", str2hex(replystr.c_str(), replystr.length()));
657 	}
658 }
659 
FILT(int val)660 const char *RIG_IC7300::FILT(int val)
661 {
662 	if (val < 1) val = 1;
663 	if (val > 3) val = 3;
664 	return(szfilter[val - 1]);
665 }
666 
nextFILT()667 const char * RIG_IC7300::nextFILT()
668 {
669 	int val = A.filter;
670 	if (useB) val = B.filter;
671 	val++;
672 	if (val > 3) val = 1;
673 	set_FILT(val);
674 	return szfilter[val - 1];
675 }
676 
set_FILTERS(std::string s)677 void RIG_IC7300::set_FILTERS(std::string s)
678 {
679 	stringstream strm;
680 	strm << s;
681 	for (int i = 0; i < NUM_MODES; i++)
682 		strm >> mode_filterA[i];
683 	for (int i = 0; i < NUM_MODES; i++)
684 		strm >> mode_filterB[i];
685 	for (int i = 0; i < NUM_MODES; i++) {
686 		if (mode_filterA[i] < 1) mode_filterA[i] = 1;
687 		if (mode_filterA[i] > 3) mode_filterA[i] = 3;
688 		if (mode_filterB[i] < 1) mode_filterB[i] = 1;
689 		if (mode_filterB[i] > 3) mode_filterB[i] = 3;
690 	}
691 }
692 
get_FILTERS()693 std::string RIG_IC7300::get_FILTERS()
694 {
695 	stringstream s;
696 	for (int i = 0; i < NUM_MODES; i++) {
697 		if (mode_filterA[i] < 1) mode_filterA[i] = 1;
698 		if (mode_filterA[i] > 3) mode_filterA[i] = 3;
699 		if (mode_filterB[i] < 1) mode_filterB[i] = 1;
700 		if (mode_filterB[i] > 3) mode_filterB[i] = 3;
701 	}
702 	for (int i = 0; i < NUM_MODES; i++)
703 		s << mode_filterA[i] << " ";
704 	for (int i = 0; i < NUM_MODES; i++)
705 		s << mode_filterB[i] << " ";
706 	return s.str();
707 }
708 
get_BANDWIDTHS()709 std::string RIG_IC7300::get_BANDWIDTHS()
710 {
711 	stringstream s;
712 	for (int i = 0; i < NUM_MODES; i++)
713 		s << mode_bwA[i] << " ";
714 	for (int i = 0; i < NUM_MODES; i++)
715 		s << mode_bwB[i] << " ";
716 	return s.str();
717 }
718 
set_BANDWIDTHS(std::string s)719 void RIG_IC7300::set_BANDWIDTHS(std::string s)
720 {
721 	stringstream strm;
722 	strm << s;
723 	for (int i = 0; i < NUM_MODES; i++)
724 		strm >> mode_bwA[i];
725 	for (int i = 0; i < NUM_MODES; i++)
726 		strm >> mode_bwB[i];
727 }
728 
can_split()729 bool RIG_IC7300::can_split()
730 {
731 	return true;
732 }
733 
set_split(bool val)734 void RIG_IC7300::set_split(bool val)
735 {
736 	split = val;
737 	cmd = pre_to;
738 	cmd += 0x0F;
739 	cmd += val ? 0x01 : 0x00;
740 	cmd.append(post);
741 	waitFB(val ? "set split ON" : "set split OFF");
742 
743 	isett("set_split");
744 }
745 
get_split()746 int RIG_IC7300::get_split()
747 {
748 	int read_split = 0;
749 	cmd.assign(pre_to);
750 	cmd.append("\x0F");
751 	cmd.append( post );
752 	if (waitFOR(7, "get split")) {
753 		string resp = pre_fm;
754 		resp.append("\x0F");
755 		size_t p = replystr.find(resp);
756 		if (p != string::npos)
757 			read_split = replystr[p+5];
758 		if (read_split != 0xFA) // fail byte
759 			split = read_split;
760 	}
761 
762 	igett("get_split");
763 
764 	return split;
765 }
766 
get_bwA()767 int RIG_IC7300::get_bwA()
768 {
769 	if (A.imode == 3 || A.imode == 11) return 0; // FM, FM-D
770 
771 	if (useB) selectA();
772 
773 	cmd = pre_to;
774 	cmd.append("\x1a\x03");
775 	cmd.append(post);
776 	int bwval = A.iBW;
777 	if (waitFOR(8, "get_bwA")) {
778 		string resp = pre_fm;
779 		resp.append("\x1A\x03");
780 		size_t p = replystr.find(resp);
781 		if (p != string::npos)
782 			bwval = fm_bcd(replystr.substr(p+6), 2);
783 	}
784 	if (bwval != A.iBW) {
785 		A.iBW = bwval;
786 		mode_bwA[A.imode] = bwval;
787 	}
788 
789 	if (useB) selectB();
790 
791 	igett("get_bwA");
792 
793 	return A.iBW;
794 }
795 
set_bwA(int val)796 void RIG_IC7300::set_bwA(int val)
797 {
798 
799 	if (A.imode == 3 || A.imode == 11) return; // FM, FM-D
800 
801 	A.iBW = val;
802 	if (useB) selectA();
803 
804 	cmd = pre_to;
805 	cmd.append("\x1a\x03");
806 	cmd.append(to_bcd(A.iBW, 2));
807 	cmd.append(post);
808 	waitFB("set bwA");
809 
810 	mode_bwA[A.imode] = val;
811 	isett("set_bwA");
812 
813 	if (useB) selectB();
814 }
815 
get_bwB()816 int RIG_IC7300::get_bwB()
817 {
818 	if (B.imode == 3 || B.imode == 11) return 0; // FM, FM-D
819 
820 	if (!useB) selectB();
821 
822 	cmd = pre_to;
823 	cmd.append("\x1a\x03");
824 	cmd.append(post);
825 	int bwval = B.iBW;
826 	if (waitFOR(8, "get_bwB")) {
827 		string resp = pre_fm;
828 		resp.append("\x1A\x03");
829 		size_t p = replystr.find(resp);
830 		if (p != string::npos)
831 			bwval = fm_bcd(replystr.substr(p+6), 2);
832 	}
833 	if (bwval != B.iBW) {
834 		B.iBW = bwval;
835 		mode_bwB[B.imode] = bwval;
836 	}
837 
838 	if (!useB) selectA();
839 
840 	igett("get_bwB");
841 
842 	return B.iBW;
843 }
844 
set_bwB(int val)845 void RIG_IC7300::set_bwB(int val)
846 {
847 	if (B.imode == 3 || B.imode == 11) return; // FM, FM-D
848 	B.iBW = val;
849 
850 	if (!useB) selectB();
851 
852 	cmd = pre_to;
853 	cmd.append("\x1a\x03");
854 	cmd.append(to_bcd(B.iBW, 2));
855 	cmd.append(post);
856 	waitFB("set bwB");
857 
858 	mode_bwB[B.imode] = val;
859 	isett("set_bwB");
860 
861 	if (!useB) selectA();
862 }
863 
864 // LSB  USB  AM   FM   CW  CW-R  RTTY  RTTY-R  LSB-D  USB-D  AM-D  FM-D
865 //  0    1    2    3   4     5    6     7      8      9       10    11
866 
adjust_bandwidth(int m)867 int RIG_IC7300::adjust_bandwidth(int m)
868 {
869 	int bw = 0;
870 	switch (m) {
871 		case 2: case 10: // AM, AM-D
872 			bandwidths_ = IC7300_am_bws;
873 			bw_vals_ = IC7300_bw_vals_AM;
874 			bw = 19;
875 			break;
876 		case 3: case 11: // FM, FM-D
877 			bandwidths_ = IC7300_fm_bws;
878 			bw_vals_ = IC7300_bw_vals_FM;
879 			bw = 0;
880 			break;
881 		case 6: case 7: // RTTY, RTTY-R
882 			bandwidths_ = IC7300_rtty_bws;
883 			bw_vals_ = IC7300_bw_vals_RTTY;
884 			bw = 12;
885 			break;
886 		case 4: case 5: // CW, CW -R
887 			bandwidths_ = IC7300_ssb_bws;
888 			bw_vals_ = IC7300_bw_vals_SSB;
889 			bw = 12;
890 			break;
891 		case 0: case 1: // LSB, USB
892 		case 8: case 9: // LSB-D, USB-D
893 		default:
894 			bandwidths_ = IC7300_ssb_bws;
895 			bw_vals_ = IC7300_bw_vals_SSB;
896 			bw = 34;
897 	}
898 	return bw;
899 }
900 
bwtable(int m)901 const char ** RIG_IC7300::bwtable(int m)
902 {
903 	const char **table;
904 	switch (m) {
905 		case 2: case 10: // AM, AM-D
906 			table = IC7300_am_bws;
907 			break;
908 		case 3: case 11: // FM, FM-D
909 			table = IC7300_fm_bws;
910 			break;
911 		case 6: case 7: // RTTY, RTTY-R
912 			table = IC7300_rtty_bws;
913 			break;
914 		case 4: case 5: // CW, CW -R
915 		case 0: case 1: // LSB, USB
916 		case 8: case 9: // LSB-D, USB-D
917 		default:
918 			table = IC7300_ssb_bws;
919 	}
920 	return table;
921 }
922 
def_bandwidth(int m)923 int RIG_IC7300::def_bandwidth(int m)
924 {
925 	int bw = adjust_bandwidth(m);
926 	if (useB) {
927 		if (mode_bwB[m] == -1)
928 			mode_bwB[m] = bw;
929 		return mode_bwB[m];
930 	}
931 	if (mode_bwA[m] == -1)
932 		mode_bwA[m] = bw;
933 	return mode_bwA[m];
934 }
935 
get_mic_gain()936 int RIG_IC7300::get_mic_gain()
937 {
938 	int val = 0;
939 	string cstr = "\x14\x0B";
940 	string resp = pre_fm;
941 	resp.append(cstr);
942 	cmd = pre_to;
943 	cmd.append(cstr);
944 	cmd.append(post);
945 	if (waitFOR(9, "get mic")) {
946 		size_t p = replystr.rfind(resp);
947 		if (p != string::npos)
948 			val = num100(replystr.substr(p + 6));
949 	}
950 	return val;
951 }
952 
set_mic_gain(int val)953 void RIG_IC7300::set_mic_gain(int val)
954 {
955 	cmd = pre_to;
956 	cmd.append("\x14\x0B");
957 	cmd.append(bcd255(val));
958 	cmd.append( post );
959 	waitFB("set mic gain");
960 }
961 
get_mic_gain_min_max_step(int & min,int & max,int & step)962 void RIG_IC7300::get_mic_gain_min_max_step(int &min, int &max, int &step)
963 {
964 	min = 0;
965 	max = 100;
966 	step = 1;
967 }
968 
969 static int comp_level[] = {11,34,58,81,104,128,151,174,197,221,244};
set_compression(int on,int val)970 void RIG_IC7300::set_compression(int on, int val)
971 {
972 	cmd = pre_to;
973 	cmd.append("\x16\x44");
974 	if (on) cmd += '\x01';
975 	else cmd += '\x00';
976 	cmd.append(post);
977 	waitFB("set Comp ON/OFF");
978 
979 	if (val < 0) return;
980 	if (val > 10) return;
981 
982 	cmd.assign(pre_to).append("\x14\x0E");
983 	cmd.append(to_bcd(comp_level[val], 3));
984 	cmd.append( post );
985 	waitFB("set comp");
986 }
987 
get_compression(int & on,int & val)988 void RIG_IC7300::get_compression(int &on, int &val)
989 {
990 	std::string resp;
991 
992 	cmd.assign(pre_to).append("\x16\x44").append(post);
993 
994 	resp.assign(pre_fm).append("\x16\x44");
995 
996 	if (waitFOR(8, "get comp on/off")) {
997 		size_t p = replystr.find(resp);
998 		if (p != string::npos)
999 			on = (replystr[p+6] == 0x01);
1000 	}
1001 
1002 	cmd.assign(pre_to).append("\x14\x0E").append(post);
1003 	resp.assign(pre_fm).append("\x14\x0E");
1004 
1005 	if (waitFOR(9, "get comp level")) {
1006 		size_t p = replystr.find(resp);
1007 		int level = 0;
1008 		if (p != string::npos) {
1009 			level = fm_bcd(replystr.substr(p+6), 3);
1010 			for (val = 0; val < 11; val++)
1011 				if (level <= comp_level[val]) break;
1012 		}
1013 	}
1014 }
1015 
set_vox_onoff()1016 void RIG_IC7300::set_vox_onoff()
1017 {
1018 	if (progStatus.vox_onoff) {
1019 		cmd.assign(pre_to).append("\x16\x46\x01");
1020 		cmd.append( post );
1021 		waitFB("set vox ON");
1022 	} else {
1023 		cmd.assign(pre_to).append("\x16\x46");
1024 		cmd += '\x00';
1025 		cmd.append( post );
1026 		waitFB("set vox OFF");
1027 	}
1028 }
1029 
1030 // Xcvr values range 0...255 step 1
get_vox_gain_min_max_step(int & min,int & max,int & step)1031 void RIG_IC7300::get_vox_gain_min_max_step(int &min, int &max, int &step)
1032 {
1033 	min = 0; max = 100; step = 1;
1034 }
1035 
set_vox_gain()1036 void RIG_IC7300::set_vox_gain()
1037 {
1038 	int vox_gain = round((progStatus.vox_gain * 255 / 100 + 0.5));
1039 	minmax(0, 255, vox_gain);
1040 	cmd.assign(pre_to).append("\x14\x16");
1041 	cmd.append(to_bcd(vox_gain, 3));
1042 	cmd.append( post );
1043 	waitFB("SET vox gain");
1044 }
1045 
1046 // Xcvr values range 0...255 step 1
get_vox_anti_min_max_step(int & min,int & max,int & step)1047 void RIG_IC7300::get_vox_anti_min_max_step(int &min, int &max, int &step)
1048 {
1049 	min = 0; max = 100; step = 1;
1050 }
1051 
set_vox_anti()1052 void RIG_IC7300::set_vox_anti()
1053 {
1054 	int vox_anti = round((progStatus.vox_anti * 255 / 100 + 0.5));
1055 	minmax(0, 255, vox_anti);
1056 	cmd.assign(pre_to).append("\x14\x17");
1057 	cmd.append(to_bcd(vox_anti, 3));
1058 	cmd.append( post );
1059 	waitFB("SET anti-vox");
1060 }
1061 
1062 // VOX hang 0.0 - 2.0, step 0.1
1063 // Xcvr values 0..20 step 1
get_vox_hang_min_max_step(int & min,int & max,int & step)1064 void RIG_IC7300::get_vox_hang_min_max_step(int &min, int &max, int &step)
1065 {
1066 	min = 0; max = 20; step = 1;
1067 }
1068 
set_vox_hang()1069 void RIG_IC7300::set_vox_hang()
1070 {
1071 	cmd.assign(pre_to).append("\x1A\x05\x01\x91");
1072 	cmd.append(to_bcd(progStatus.vox_hang, 2));
1073 	cmd.append( post );
1074 	waitFB("SET vox hang");
1075 }
1076 
1077 //----------------------------------------------------------------------
1078 // CW controls
1079 
get_cw_wpm_min_max(int & min,int & max)1080 void RIG_IC7300::get_cw_wpm_min_max(int &min, int &max)
1081 {
1082 	min = 6; max = 48;
1083 }
1084 
set_cw_wpm()1085 void RIG_IC7300::set_cw_wpm()
1086 {
1087 	int iwpm = round((progStatus.cw_wpm - 6) * 255 / 42 + 0.5);
1088 	minmax(0, 255, iwpm);
1089 
1090 	cmd.assign(pre_to).append("\x14\x0C");
1091 	cmd.append(to_bcd(iwpm, 3));
1092 	cmd.append( post );
1093 	waitFB("SET cw wpm");
1094 }
1095 
set_break_in()1096 void RIG_IC7300::set_break_in()
1097 {
1098 // 16 47 00 break-in off
1099 // 16 47 01 break-in semi
1100 // 16 47 02 break-in full
1101 
1102 	cmd.assign(pre_to).append("\x16\x47");
1103 
1104 	switch (progStatus.break_in) {
1105 		case 2: cmd += '\x02'; break_in_label("FULL"); break;
1106 		case 1: cmd += '\x01'; break_in_label("SEMI");  break;
1107 		case 0:
1108 		default: cmd += '\x00'; break_in_label("BK-IN");
1109 	}
1110 	cmd.append(post);
1111 	waitFB("SET break-in");
1112 }
1113 
get_break_in()1114 int RIG_IC7300::get_break_in()
1115 {
1116 	cmd.assign(pre_to).append("\x16\x47").append(post);
1117 	std::string resp;
1118 	resp.assign(pre_fm);
1119 	if (waitFOR(8, "get break in")) {
1120 		size_t p = replystr.rfind(resp);
1121 		if (p != string::npos) {
1122 			progStatus.break_in = replystr[p+6];
1123 			if (progStatus.break_in == 0) break_in_label("qsk");
1124 			else  if (progStatus.break_in == 1) break_in_label("SEMI");
1125 			else  break_in_label("FULL");
1126 		}
1127 	}
1128 	get_trace(2, "get_break_in()", hexstr(replystr).c_str());
1129 	return progStatus.break_in;
1130 }
1131 
get_cw_qsk_min_max_step(double & min,double & max,double & step)1132 void RIG_IC7300::get_cw_qsk_min_max_step(double &min, double &max, double &step)
1133 {
1134 	min = 2.0; max = 13.0; step = 0.1;
1135 }
1136 
set_cw_qsk()1137 void RIG_IC7300::set_cw_qsk()
1138 {
1139 	int qsk = round ((progStatus.cw_qsk - 2.0) * 255.0 / 11.0 + 0.5);
1140 	minmax(0, 255, qsk);
1141 
1142 	cmd.assign(pre_to).append("\x14\x0F");
1143 	cmd.append(to_bcd(qsk, 3));
1144 	cmd.append(post);
1145 	waitFB("Set cw qsk delay");
1146 }
1147 
get_cw_spot_tone_min_max_step(int & min,int & max,int & step)1148 void RIG_IC7300::get_cw_spot_tone_min_max_step(int &min, int &max, int &step)
1149 {
1150 	min = 300; max = 900; step = 5;
1151 }
1152 
set_cw_spot_tone()1153 void RIG_IC7300::set_cw_spot_tone()
1154 {
1155 	cmd.assign(pre_to).append("\x14\x09"); // values 0=300Hz 255=900Hz
1156 	int n = round((progStatus.cw_spot_tone - 300) * 255.0 / 600.0 + 0.5);
1157 	minmax(0, 255, n);
1158 
1159 	cmd.append(to_bcd(n, 3));
1160 	cmd.append( post );
1161 	waitFB("SET cw spot tone");
1162 }
1163 
set_cw_vol()1164 void RIG_IC7300::set_cw_vol()
1165 {
1166 	cmd.assign(pre_to);
1167 	cmd.append("\x1A\x05");
1168 	cmd += '\x00';
1169 	cmd += '\x24';
1170 	cmd.append(to_bcd((int)(progStatus.cw_vol * 2.55), 3));
1171 	cmd.append( post );
1172 	waitFB("SET cw sidetone volume");
1173 }
1174 
1175 // Tranceiver PTT on/off
set_PTT_control(int val)1176 void RIG_IC7300::set_PTT_control(int val)
1177 {
1178 	cmd = pre_to;
1179 	cmd += '\x1c';
1180 	cmd += '\x00';
1181 	cmd += (unsigned char) val;
1182 	cmd.append( post );
1183 	waitFB("set ptt");
1184 	ptt_ = val;
1185 }
1186 
get_PTT()1187 int RIG_IC7300::get_PTT()
1188 {
1189 	cmd = pre_to;
1190 	cmd += '\x1c'; cmd += '\x00';
1191 	string resp = pre_fm;
1192 	resp += '\x1c'; resp += '\x00';
1193 	cmd.append(post);
1194 	if (waitFOR(8, "get PTT")) {
1195 		size_t p = replystr.rfind(resp);
1196 		if (p != string::npos)
1197 			ptt_ = replystr[p + 6];
1198 	}
1199 	return ptt_;
1200 }
1201 
1202 // Volume control val 0 ... 100
set_volume_control(int val)1203 void RIG_IC7300::set_volume_control(int val)
1204 {
1205 	cmd = pre_to;
1206 	cmd.append("\x14\x01");
1207 	cmd.append(bcd255(val));
1208 	cmd.append( post );
1209 	waitFB("set vol");
1210 }
1211 
1212 /*
1213 
1214 I:12:20:22: get vol ans in 0 ms, OK
1215 cmd FE FE 7A E0 14 01 FD
1216 ans FE FE 7A E0 14 01 FD
1217 FE FE E0 7A 14 01 00 65 FD
1218  0  1  2  3  4  5  6  7  8
1219 */
get_volume_control()1220 int RIG_IC7300::get_volume_control()
1221 {
1222 	int val = 0;
1223 	string cstr = "\x14\x01";
1224 	string resp = pre_fm;
1225 	resp.append(cstr);
1226 	cmd = pre_to;
1227 	cmd.append(cstr);
1228 	cmd.append( post );
1229 	if (waitFOR(9, "get vol")) {
1230 		size_t p = replystr.rfind(resp);
1231 		if (p != string::npos)
1232 			val = num100(replystr.substr(p + 6));
1233 	}
1234 	return (val);
1235 }
1236 
get_vol_min_max_step(int & min,int & max,int & step)1237 void RIG_IC7300::get_vol_min_max_step(int &min, int &max, int &step)
1238 {
1239 	min = 0; max = 100; step = 1;
1240 }
1241 
set_power_control(double val)1242 void RIG_IC7300::set_power_control(double val)
1243 {
1244 	cmd = pre_to;
1245 	cmd.append("\x14\x0A");
1246 	cmd.append(bcd255(val));
1247 	cmd.append( post );
1248 	waitFB("set power");
1249 	set_trace(2, "set power control ", str2hex(replystr.c_str(), replystr.length()));
1250 
1251 }
1252 
get_power_control()1253 int RIG_IC7300::get_power_control()
1254 {
1255 	int val = progStatus.power_level;
1256 	string cstr = "\x14\x0A";
1257 	string resp = pre_fm;
1258 	cmd = pre_to;
1259 	cmd.append(cstr).append(post);
1260 	resp.append(cstr);
1261 	if (waitFOR(9, "get power")) {
1262 		get_trace(2, "get power control ", str2hex(replystr.c_str(), replystr.length()));
1263 		size_t p = replystr.rfind(resp);
1264 		if (p != string::npos)
1265 			val = num100(replystr.substr(p+6));
1266 	}
1267 	return val;
1268 }
1269 
get_pc_min_max_step(double & min,double & max,double & step)1270 void RIG_IC7300::get_pc_min_max_step(double &min, double &max, double &step)
1271 {
1272 	min = 0; pmax = max = 100; step = 1;
1273 }
1274 
get_smeter()1275 int RIG_IC7300::get_smeter()
1276 {
1277 	string cstr = "\x15\x02";
1278 	string resp = pre_fm;
1279 	resp.append(cstr);
1280 	cmd = pre_to;
1281 	cmd.append(cstr);
1282 	cmd.append( post );
1283 	int mtr= -1;
1284 	if (waitFOR(9, "get smeter")) {
1285 		size_t p = replystr.rfind(resp);
1286 		if (p != string::npos) {
1287 			mtr = fm_bcd(replystr.substr(p+6), 3);
1288 			mtr = (int)ceil(mtr /2.41);
1289 			if (mtr > 100) mtr = 100;
1290 		}
1291 	}
1292 	return mtr;
1293 }
1294 
1295 struct pwrpair {int mtr; float pwr;};
1296 
1297 static pwrpair pwrtbl[] = {
1298 	{0, 0.0},
1299 	{21, 5.0},
1300 	{43,10.0},
1301 	{65, 15.0},
1302 	{83, 20.0},
1303 	{95, 25.0},
1304 	{105, 30.0},
1305 	{114, 35.0},
1306 	{124, 40.0},
1307 	{143, 50.0},
1308 	{183, 75.0},
1309 	{213, 100.0},
1310 	{255, 120.0 } };
1311 
get_power_out(void)1312 int RIG_IC7300::get_power_out(void)
1313 {
1314 	string cstr = "\x15\x11";
1315 	string resp = pre_fm;
1316 	resp.append(cstr);
1317 	cmd = pre_to;
1318 	cmd.append(cstr);
1319 	cmd.append( post );
1320 	int mtr= 0;
1321 	int val = 0;
1322 	if (waitFOR(9, "get power out")) {
1323 		get_trace(2, "get power out ", str2hex(replystr.c_str(), replystr.length()));
1324 		size_t p = replystr.rfind(resp);
1325 		if (p != string::npos) {
1326 			mtr = hex2val(replystr.substr(p+6, 2));
1327 			mtr = max(0, min(mtr, 255));
1328 			size_t i = 0;
1329 			for (i = 0; i < sizeof(pwrtbl) / sizeof(*pwrtbl) - 1; i++)
1330 				if (mtr >= pwrtbl[i].mtr && mtr < pwrtbl[i+1].mtr)
1331 					break;
1332 			val = (int)ceil(pwrtbl[i].pwr +
1333 				(pwrtbl[i+1].pwr - pwrtbl[i].pwr)*(mtr - pwrtbl[i].mtr)/(pwrtbl[i+1].mtr - pwrtbl[i].mtr));
1334 			if (val > 100) val = 100;
1335 		}
1336 	}
1337 	return val;
1338 }
1339 
1340 struct swrpair {int mtr; float swr;};
1341 
1342 // Table entries below correspond to SWR readings of 1.1, 1.5, 2.0, 2.5, 3.0 and infinity.
1343 // Values are also tweaked to fit the display of the SWR meter.
1344 
1345 
1346 static swrpair swrtbl[] = {
1347 	{0, 0.0},
1348 	{48, 10.5},
1349 	{80, 23.0},
1350 	{103, 35.0},
1351 	{120, 48.0},
1352 	{255, 100.0 } };
1353 
1354 
1355 
get_swr(void)1356 int RIG_IC7300::get_swr(void)
1357 {
1358 	string cstr = "\x15\x12";
1359 	string resp = pre_fm;
1360 	resp.append(cstr);
1361 	cmd = pre_to;
1362 	cmd.append(cstr);
1363 	cmd.append( post );
1364 	int mtr= -1;
1365 	if (waitFOR(9, "get swr")) {
1366 		size_t p = replystr.rfind(resp);
1367 		if (p != string::npos) {
1368 			mtr = fm_bcd(replystr.substr(p+6), 3);
1369 			size_t i = 0;
1370 			for (i = 0; i < sizeof(swrtbl) / sizeof(swrpair) - 1; i++)
1371 				if (mtr >= swrtbl[i].mtr && mtr < swrtbl[i+1].mtr)
1372 					break;
1373 			if (mtr < 0) mtr = 0;
1374 			if (mtr > 255) mtr = 255;
1375 			mtr = (int)ceil(swrtbl[i].swr +
1376 				(swrtbl[i+1].swr - swrtbl[i].swr)*(mtr - swrtbl[i].mtr)/(swrtbl[i+1].mtr - swrtbl[i].mtr));
1377 
1378 			if (mtr > 100) mtr = 100;
1379 		}
1380 	}
1381 	return mtr;
1382 }
1383 
get_alc(void)1384 int RIG_IC7300::get_alc(void)
1385 {
1386 	string cstr = "\x15\x13";
1387 	string resp = pre_fm;
1388 	resp.append(cstr);
1389 	cmd = pre_to;
1390 	cmd.append(cstr);
1391 	cmd.append( post );
1392 	int mtr= -1;
1393 	if (waitFOR(9, "get alc")) {
1394 		size_t p = replystr.rfind(resp);
1395 		if (p != string::npos) {
1396 			mtr = fm_bcd(replystr.substr(p+6), 3);
1397 			mtr = (int)ceil(mtr /1.2);
1398 			if (mtr > 100) mtr = 100;
1399 		}
1400 	}
1401 	return mtr;
1402 }
1403 
set_rf_gain(int val)1404 void RIG_IC7300::set_rf_gain(int val)
1405 {
1406 	cmd = pre_to;
1407 	cmd.append("\x14\x02");
1408 	cmd.append(bcd255(val));
1409 	cmd.append( post );
1410 	waitFB("set RF");
1411 }
1412 
get_rf_gain()1413 int RIG_IC7300::get_rf_gain()
1414 {
1415 	int val = progStatus.rfgain;
1416 	string cstr = "\x14\x02";
1417 	string resp = pre_fm;
1418 	cmd = pre_to;
1419 	cmd.append(cstr).append(post);
1420 	resp.append(cstr);
1421 	if (waitFOR(9, "get RF")) {
1422 		size_t p = replystr.rfind(resp);
1423 		if (p != string::npos)
1424 			val = num100(replystr.substr(p + 6));
1425 	}
1426 	return val;
1427 }
1428 
get_rf_min_max_step(double & min,double & max,double & step)1429 void RIG_IC7300::get_rf_min_max_step(double &min, double &max, double &step)
1430 {
1431 	min = 0; max = 100; step = 1;
1432 }
1433 
next_preamp()1434 int RIG_IC7300::next_preamp()
1435 {
1436 	if (atten_level == 1)
1437 		return preamp_level;
1438 	switch (preamp_level) {
1439 		case 0: return 1;
1440 		case 1: return 2;
1441 		case 2: return 0;
1442 	}
1443 	return 0;
1444 }
1445 
set_preamp(int val)1446 void RIG_IC7300::set_preamp(int val)
1447 {
1448 	if (val) {
1449 		atten_level = 0;
1450 		atten_label("ATT", false);
1451 	}
1452 
1453 	cmd = pre_to;
1454 	cmd += '\x16';
1455 	cmd += '\x02';
1456 
1457 	preamp_level = val;
1458 	switch (val) {
1459 		case 1:
1460 			preamp_label("Amp 1", true);
1461 			break;
1462 		case 2:
1463 			preamp_label("Amp 2", true);
1464 			break;
1465 		case 0:
1466 		default:
1467 			preamp_label("PRE", false);
1468 	}
1469 
1470 	cmd += (unsigned char)preamp_level;
1471 	cmd.append( post );
1472 	waitFB(	(preamp_level == 0) ? "set Preamp OFF" :
1473 			(preamp_level == 1) ? "set Preamp Level 1" :
1474 			"set Preamp Level 2");
1475 }
1476 
get_preamp()1477 int RIG_IC7300::get_preamp()
1478 {
1479 	string cstr = "\x16\x02";
1480 	string resp = pre_fm;
1481 	resp.append(cstr);
1482 	cmd = pre_to;
1483 	cmd.append(cstr);
1484 	cmd.append( post );
1485 	if (waitFOR(8, "get Preamp Level")) {
1486 		size_t p = replystr.rfind(resp);
1487 		if (p != string::npos) {
1488 			preamp_level = replystr[p+6];
1489 			if (preamp_level == 1) {
1490 				preamp_label("Amp 1", true);
1491 			} else if (preamp_level == 2) {
1492 				preamp_label("Amp 2", true);
1493 			} else {
1494 				preamp_label("PRE", false);
1495 				preamp_level = 0;
1496 			}
1497 		}
1498 	}
1499 	return preamp_level;
1500 }
1501 
set_attenuator(int val)1502 void RIG_IC7300::set_attenuator(int val)
1503 {
1504 	if (val) {
1505 		atten_label("20 dB", true);
1506 		atten_level = 1;
1507 		preamp_label("PRE", false);
1508 	} else {
1509 		atten_level = 0;
1510 		atten_label("ATT", false);
1511 	}
1512 
1513 	cmd = pre_to;
1514 	cmd += '\x11';
1515 	cmd += atten_level ? '\x20' : '\x00';
1516 	cmd.append( post );
1517 	waitFB("set att");
1518 }
1519 
next_attenuator()1520 int RIG_IC7300::next_attenuator()
1521 {
1522 	if (atten_level) return 0;
1523 	return 1;
1524 }
1525 
get_attenuator()1526 int RIG_IC7300::get_attenuator()
1527 {
1528 	cmd = pre_to;
1529 	cmd += '\x11';
1530 	cmd.append( post );
1531 	string resp = pre_fm;
1532 	resp += '\x11';
1533 	if (waitFOR(7, "get ATT")) {
1534 		size_t p = replystr.rfind(resp);
1535 		if (p != string::npos) {
1536 			if (replystr[p+5] == 0x20) {
1537 				atten_label("20 dB", true);
1538 				atten_level = 1;
1539 				return 1;
1540 			} else {
1541 				atten_label("ATT", false);
1542 				atten_level = 0;
1543 				return 0;
1544 			}
1545 		}
1546 	}
1547 	return 0;
1548 }
1549 
set_noise(bool val)1550 void RIG_IC7300::set_noise(bool val)
1551 {
1552 	cmd = pre_to;
1553 	cmd.append("\x16\x22");
1554 	cmd += val ? 1 : 0;
1555 	cmd.append(post);
1556 	waitFB("set noise");
1557 }
1558 
get_noise()1559 int RIG_IC7300::get_noise()
1560 {
1561 	int val = progStatus.noise;
1562 	string cstr = "\x16\x22";
1563 	string resp = pre_fm;
1564 	resp.append(cstr);
1565 	cmd = pre_to;
1566 	cmd.append(cstr);
1567 	cmd.append(post);
1568 	if (waitFOR(8, "get noise")) {
1569 		size_t p = replystr.rfind(resp);
1570 		if (p != string::npos) {
1571 			val = replystr[p+6];
1572 		}
1573 	}
1574 	return val;
1575 }
1576 
set_nb_level(int val)1577 void RIG_IC7300::set_nb_level(int val)
1578 {
1579 	cmd = pre_to;
1580 	cmd.append("\x14\x12");
1581 	cmd.append(bcd255(val));
1582 	cmd.append( post );
1583 	waitFB("set NB level");
1584 }
1585 
get_nb_level()1586 int  RIG_IC7300::get_nb_level()
1587 {
1588 	int val = progStatus.nb_level;
1589 	string cstr = "\x14\x12";
1590 	string resp = pre_fm;
1591 	resp.append(cstr);
1592 	cmd = pre_to;
1593 	cmd.append(cstr);
1594 	cmd.append(post);
1595 	if (waitFOR(9, "get NB level")) {
1596 		size_t p = replystr.rfind(resp);
1597 		if (p != string::npos)
1598 			val = num100(replystr.substr(p+6));
1599 	}
1600 	return val;
1601 }
1602 
set_noise_reduction(int val)1603 void RIG_IC7300::set_noise_reduction(int val)
1604 {
1605 	cmd = pre_to;
1606 	cmd.append("\x16\x40");
1607 	cmd += val ? 1 : 0;
1608 	cmd.append(post);
1609 	waitFB("set NR");
1610 }
1611 
get_noise_reduction()1612 int RIG_IC7300::get_noise_reduction()
1613 {
1614 	string cstr = "\x16\x40";
1615 	string resp = pre_fm;
1616 	resp.append(cstr);
1617 	cmd = pre_to;
1618 	cmd.append(cstr);
1619 	cmd.append(post);
1620 	if (waitFOR(8, "get NR")) {
1621 		size_t p = replystr.rfind(resp);
1622 		if (p != string::npos)
1623 			return (replystr[p+6] ? 1 : 0);
1624 	}
1625 	return progStatus.noise_reduction;
1626 }
1627 
1628 /*
1629 
1630 I:12:06:50: get NR ans in 0 ms, OK
1631 cmd FE FE 7A E0 16 40 FD
1632 ans FE FE 7A E0 16 40 FD
1633 FE FE E0 7A 16 40 01 FD
1634  0  1  2  3  4  5  6  7
1635 
1636 I:12:06:50: get NRval ans in 0 ms, OK
1637 cmd FE FE 7A E0 14 06 FD
1638 ans FE FE 7A E0 14 06 FD
1639 FE FE E0 7A 14 06 00 24 FD
1640  0  1  2  3  4  5  6  7  8
1641 
1642 */
1643 
set_noise_reduction_val(int val)1644 void RIG_IC7300::set_noise_reduction_val(int val)
1645 {
1646 	cmd = pre_to;
1647 	cmd.append("\x14\x06");
1648 	val *= 16;
1649 	val += 8;
1650 	cmd.append(to_bcd(val, 3));
1651 	cmd.append(post);
1652 	waitFB("set NRval");
1653 }
1654 
get_noise_reduction_val()1655 int RIG_IC7300::get_noise_reduction_val()
1656 {
1657 	int val = progStatus.noise_reduction_val;
1658 	string cstr = "\x14\x06";
1659 	string resp = pre_fm;
1660 	resp.append(cstr);
1661 	cmd = pre_to;
1662 	cmd.append(cstr);
1663 	cmd.append(post);
1664 	if (waitFOR(9, "get NRval")) {
1665 		size_t p = replystr.rfind(resp);
1666 		if (p != string::npos) {
1667 			val = fm_bcd(replystr.substr(p+6),3);
1668 			val -= 8;
1669 			val /= 16;
1670 		}
1671 	}
1672 	return val;
1673 }
1674 
set_squelch(int val)1675 void RIG_IC7300::set_squelch(int val)
1676 {
1677 	cmd = pre_to;
1678 	cmd.append("\x14\x03");
1679 	cmd.append(bcd255(val));
1680 	cmd.append( post );
1681 	waitFB("set Sqlch");
1682 }
1683 
get_squelch()1684 int  RIG_IC7300::get_squelch()
1685 {
1686 	int val = progStatus.squelch;
1687 	string cstr = "\x14\x03";
1688 	string resp = pre_fm;
1689 	resp.append(cstr);
1690 	cmd = pre_to;
1691 	cmd.append(cstr);
1692 	cmd.append(post);
1693 	if (waitFOR(9, "get squelch")) {
1694 		size_t p = replystr.rfind(resp);
1695 		if (p != string::npos)
1696 			val = num100(replystr.substr(p+6));
1697 	}
1698 	return val;
1699 }
1700 
set_auto_notch(int val)1701 void RIG_IC7300::set_auto_notch(int val)
1702 {
1703 	cmd = pre_to;
1704 	cmd += '\x16';
1705 	cmd += '\x41';
1706 	cmd += (unsigned char)val;
1707 	cmd.append( post );
1708 	waitFB("set AN");
1709 }
1710 
get_auto_notch()1711 int RIG_IC7300::get_auto_notch()
1712 {
1713 	string cstr = "\x16\x41";
1714 	string resp = pre_fm;
1715 	resp.append(cstr);
1716 	cmd = pre_to;
1717 	cmd.append(cstr);
1718 	cmd.append( post );
1719 	if (waitFOR(8, "get AN")) {
1720 		size_t p = replystr.rfind(resp);
1721 		if (p != string::npos) {
1722 			if (replystr[p+6] == 0x01) {
1723 				auto_notch_label("AN", true);
1724 				return true;
1725 			} else {
1726 				auto_notch_label("AN", false);
1727 				return false;
1728 			}
1729 		}
1730 	}
1731 	return progStatus.auto_notch;
1732 }
1733 
set_notch(bool on,int freq)1734 void RIG_IC7300::set_notch(bool on, int freq)
1735 {
1736 	int hexval;
1737 	switch (vfo->imode) {
1738 		default: case USB7300: case USBD7300: case RTTYR7300:
1739 			hexval = freq - 1500;
1740 			break;
1741 		case LSB7300: case LSBD7300: case RTTY7300:
1742 			hexval = 1500 - freq;
1743 			break;
1744 		case CW7300:
1745 			if (CW_sense)
1746 				hexval = freq - progStatus.cw_spot_tone;
1747 			else
1748 				hexval = progStatus.cw_spot_tone - freq;
1749 			break;
1750 		case CWR7300:
1751 			if (CW_sense)
1752 				hexval = progStatus.cw_spot_tone - freq;
1753 			else
1754 				hexval = freq - progStatus.cw_spot_tone;
1755 			break;
1756 	}
1757 
1758 	hexval /= 20;
1759 	hexval += 128;
1760 	if (hexval < 0) hexval = 0;
1761 	if (hexval > 255) hexval = 255;
1762 
1763 	cmd = pre_to;
1764 	cmd.append("\x16\x48");
1765 	cmd += on ? '\x01' : '\x00';
1766 	cmd.append(post);
1767 	waitFB("set notch");
1768 	set_trace(2, "set_notch() ", str2hex(cmd.c_str(), cmd.length()));
1769 
1770 	cmd = pre_to;
1771 	cmd.append("\x14\x0D");
1772 	cmd.append(to_bcd(hexval,3));
1773 	cmd.append(post);
1774 	waitFB("set notch val");
1775 	set_trace(2, "set_notch_val() ", str2hex(cmd.c_str(), cmd.length()));
1776 }
1777 
get_notch(int & val)1778 bool RIG_IC7300::get_notch(int &val)
1779 {
1780 	bool on = false;
1781 	val = 1500;
1782 
1783 	string cstr = "\x16\x48";
1784 	string resp = pre_fm;
1785 	resp.append(cstr);
1786 	cmd = pre_to;
1787 	cmd.append(cstr);
1788 	cmd.append( post );
1789 	if (waitFOR(8, "get notch")) {
1790 		get_trace(2, "get_notch()", str2hex(replystr.c_str(), replystr.length()));
1791 		size_t p = replystr.rfind(resp);
1792 		if (p != string::npos)
1793 			on = replystr[p + 6];
1794 		cmd = pre_to;
1795 		resp = pre_fm;
1796 		cstr = "\x14\x0D";
1797 		cmd.append(cstr);
1798 		resp.append(cstr);
1799 		cmd.append(post);
1800 		if (waitFOR(9, "notch val")) {
1801 			size_t p = replystr.rfind(resp);
1802 			if (p != string::npos) {
1803 				val = (int)ceil(fm_bcd(replystr.substr(p+6),3));
1804 				val -= 128;
1805 				val *= 20;
1806 				switch (vfo->imode) {
1807 					default: case USB7300: case USBD7300: case RTTYR7300:
1808 						val = 1500 + val;
1809 						break;
1810 					case LSB: case LSBD7300: case RTTY7300:
1811 						val = 1500 - val;
1812 						break;
1813 					case CW7300:
1814 						if (CW_sense)
1815 							val = progStatus.cw_spot_tone + val;
1816 						else
1817 							val = progStatus.cw_spot_tone - val;
1818 						break;
1819 					case CWR7300:
1820 						if (CW_sense)
1821 							val = progStatus.cw_spot_tone - val;
1822 						else
1823 							val = progStatus.cw_spot_tone + val;
1824 						break;
1825 				}
1826 			}
1827 			get_trace(2, "get_notch_val() ", str2hex(replystr.c_str(), replystr.length()));
1828 		}
1829 	}
1830 	return on;
1831 }
1832 
get_notch_min_max_step(int & min,int & max,int & step)1833 void RIG_IC7300::get_notch_min_max_step(int &min, int &max, int &step)
1834 {
1835 	switch (vfo->imode) {
1836 		default:
1837 		case USB7300: case USBD7300: case RTTYR7300:
1838 		case LSB7300: case LSBD7300: case RTTY7300:
1839 			min = 0; max = 3000; step = 20; break;
1840 		case CW7300: case CWR7300:
1841 			min = progStatus.cw_spot_tone - 500;
1842 			max = progStatus.cw_spot_tone + 500;
1843 			step = 20;
1844 			break;
1845 	}
1846 }
1847 static int agcval = 3;
get_agc()1848 int  RIG_IC7300::get_agc()
1849 {
1850 	cmd = pre_to;
1851 	cmd.append("\x16\x12");
1852 	cmd.append(post);
1853 	if (waitFOR(8, "get AGC")) {
1854 		size_t p = replystr.find(pre_fm);
1855 		if (p != string::npos)
1856 			agcval = replystr[p+6]; // 1 == off, 2 = FAST, 3 = MED, 4 = SLOW
1857 	}
1858 	return agcval;
1859 }
1860 
incr_agc()1861 int RIG_IC7300::incr_agc()
1862 {
1863 	agcval++;
1864 	if (agcval == 4) agcval = 1;
1865 	cmd = pre_to;
1866 	cmd.append("\x16\x12");
1867 	cmd += agcval;
1868 	cmd.append(post);
1869 	waitFB("set AGC");
1870 	return agcval;
1871 }
1872 
1873 
1874 static const char *agcstrs[] = {"AGC", "FST", "MED", "SLO"};
agc_label()1875 const char *RIG_IC7300::agc_label()
1876 {
1877 	return agcstrs[agcval];
1878 }
1879 
agc_val()1880 int  RIG_IC7300::agc_val()
1881 {
1882 	return (agcval);
1883 }
1884 
set_if_shift(int val)1885 void RIG_IC7300::set_if_shift(int val)
1886 {
1887 	int shift;
1888 	sh_ = val;
1889 	if (val == 0) sh_on_ = false;
1890 	else sh_on_ = true;
1891 
1892 	shift = 128 + val * 128 / 50;
1893 	if (shift < 0) shift = 0;
1894 	if (shift > 255) shift = 255;
1895 
1896 	cmd = pre_to;
1897 	cmd.append("\x14\x07");
1898 	cmd.append(to_bcd(shift, 3));
1899 	cmd.append(post);
1900 	waitFB("set IF on/off");
1901 
1902 	cmd = pre_to;
1903 	cmd.append("\x14\x08");
1904 	cmd.append(to_bcd(shift, 3));
1905 	cmd.append(post);
1906 	waitFB("set IF val");
1907 }
1908 
get_if_shift(int & val)1909 bool RIG_IC7300::get_if_shift(int &val) {
1910 	val = sh_;
1911 	return sh_on_;
1912 }
1913 
get_if_min_max_step(int & min,int & max,int & step)1914 void RIG_IC7300::get_if_min_max_step(int &min, int &max, int &step)
1915 {
1916 	min = -50;
1917 	max = +50;
1918 	step = 1;
1919 }
1920 
set_pbt_inner(int val)1921 void RIG_IC7300::set_pbt_inner(int val)
1922 {
1923 	int shift = 128 + val * 128 / 50;
1924 	if (shift < 0) shift = 0;
1925 	if (shift > 255) shift = 255;
1926 
1927 	cmd = pre_to;
1928 	cmd.append("\x14\x07");
1929 	cmd.append(to_bcd(shift, 3));
1930 	cmd.append(post);
1931 	isett("set_pbt_inner()");
1932 	waitFB("set PBT inner");
1933 }
1934 
set_pbt_outer(int val)1935 void RIG_IC7300::set_pbt_outer(int val)
1936 {
1937 	int shift = 128 + val * 128 / 50;
1938 	if (shift < 0) shift = 0;
1939 	if (shift > 255) shift = 255;
1940 
1941 	cmd = pre_to;
1942 	cmd.append("\x14\x08");
1943 	cmd.append(to_bcd(shift, 3));
1944 	cmd.append(post);
1945 	isett("set_pbt_outer()");
1946 	waitFB("set PBT outer");
1947 }
1948 
get_pbt_inner()1949 int RIG_IC7300::get_pbt_inner()
1950 {
1951 	int val = 0;
1952 	string cstr = "\x14\x07";
1953 	string resp = pre_fm;
1954 	resp.append(cstr);
1955 	cmd = pre_to;
1956 	cmd.append(cstr);
1957 	cmd.append( post );
1958 	if (waitFOR(9, "get pbt inner")) {
1959 		size_t p = replystr.rfind(resp);
1960 		if (p != string::npos) {
1961 			val = num100(replystr.substr(p+6));
1962 			val -= 50;
1963 		}
1964 	}
1965 	igett("get_pbt_inner");
1966 	return val;
1967 }
1968 
get_pbt_outer()1969 int RIG_IC7300::get_pbt_outer()
1970 {
1971 	int val = 0;
1972 	string cstr = "\x14\x08";
1973 	string resp = pre_fm;
1974 	resp.append(cstr);
1975 	cmd = pre_to;
1976 	cmd.append(cstr);
1977 	cmd.append( post );
1978 	if (waitFOR(9, "get pbt outer")) {
1979 		size_t p = replystr.rfind(resp);
1980 		if (p != string::npos) {
1981 			val = num100(replystr.substr(p+6));
1982 			val -= 50;
1983 		}
1984 	}
1985 	igett("get_pbt_outer");
1986 	return val;
1987 }
1988 
setVfoAdj(double v)1989 void RIG_IC7300::setVfoAdj(double v)
1990 {
1991 	vfo_ = v;
1992 	cmd.assign(pre_to);
1993 	cmd.append("\x1A\x05");
1994 	cmd += '\x00';
1995 	cmd += '\x58';
1996 	cmd.append(bcd255(int(v)));
1997 	cmd.append(post);
1998 	waitFB("SET vfo adjust");
1999 }
2000 
getVfoAdj()2001 double RIG_IC7300::getVfoAdj()
2002 {
2003 	cmd.assign(pre_to);
2004 	cmd.append("\x1A\x05");
2005 	cmd += '\x00';
2006 	cmd += '\x58';
2007 	cmd.append(post);
2008 
2009 	if (waitFOR(11, "get vfo adj")) {
2010 		size_t p = replystr.find(pre_fm);
2011 		if (p != string::npos) {
2012 			vfo_ = num100(replystr.substr(p+8));
2013 		}
2014 	}
2015 	return vfo_;
2016 }
2017 
2018 // Read/Write band stack registers
2019 //
2020 // Read 23 bytes
2021 //
2022 //  0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22
2023 // FE FE nn E0 1A 01 bd rn f5 f4 f3 f2 f1 mo fi fg t1 t2 t3 r1 r2 r3 FD
2024 // Write 23 bytes
2025 //
2026 // FE FE E0 nn 1A 01 bd rn f5 f4 f3 f2 f1 mo fi fg t1 t2 t3 r1 r2 r3 FD
2027 //
2028 // nn - CI-V address
2029 // bd - band selection 1/2/3
2030 // rn - register number 1/2/3
2031 // f5..f1 - frequency BCD reverse
2032 // mo - mode
2033 // fi - filter #
2034 // fg flags: x01 use Tx tone, x02 use Rx tone, x10 data mode
2035 // t1..t3 - tx tone BCD fwd
2036 // r1..r3 - rx tone BCD fwd
2037 //
2038 // FE FE E0 94 1A 01 06 01 70 99 08 18 00 01 03 10 00 08 85 00 08 85 FD
2039 //
2040 // band 6; freq 0018,089,970; USB; data mode; t 88.5; r 88.5
2041 
get_band_selection(int v)2042 void RIG_IC7300::get_band_selection(int v)
2043 {
2044 	cmd.assign(pre_to);
2045 	cmd.append("\x1A\x01");
2046 	cmd += to_bcd_be( v, 2 );
2047 	cmd += '\x01';
2048 	cmd.append( post );
2049 
2050 	if (waitFOR(23, "get band stack")) {
2051 		igett("get band stack");
2052 		size_t p = replystr.rfind(pre_fm);
2053 		if (p != string::npos) {
2054 			unsigned long int bandfreq = fm_bcd_be(replystr.substr(p+8, 5), 10);
2055 			int bandmode = replystr[p+13];
2056 			int bandfilter = replystr[p+14];
2057 			int banddata = replystr[p+15] & 0x10;
2058 			if ((bandmode < 4) && banddata) bandmode += 8;
2059 			int tone = fm_bcd(replystr.substr(p+16, 3), 6);
2060 			size_t index = 0;
2061 			for (index = 0; index < sizeof(PL_tones) / sizeof(*PL_tones); index++)
2062 				if (tone == PL_tones[index]) break;
2063 			tTONE = index;
2064 			tone = fm_bcd(replystr.substr(p+19, 3), 6);
2065 			for (index = 0; index < sizeof(PL_tones) / sizeof(*PL_tones); index++)
2066 				if (tone == PL_tones[index]) break;
2067 			rTONE = index;
2068 			if (useB) {
2069 				set_vfoB(bandfreq);
2070 				set_modeB(bandmode);
2071 				set_FILT(bandfilter);
2072 			} else {
2073 				set_vfoA(bandfreq);
2074 				set_modeA(bandmode);
2075 				set_FILT(bandfilter);
2076 			}
2077 		}
2078 	} else
2079 		igett("get band stack");
2080 }
2081 
set_band_selection(int v)2082 void RIG_IC7300::set_band_selection(int v)
2083 {
2084 	unsigned long int freq = (useB ? B.freq : A.freq);
2085 	int fil = (useB ? B.filter : A.filter);
2086 	int mode = (useB ? B.imode : A.imode);
2087 
2088 	cmd.assign(pre_to);
2089 	cmd.append("\x1A\x01");
2090 	cmd += to_bcd_be( v, 2 );
2091 	cmd += '\x01';
2092 	cmd.append( to_bcd_be( freq, 10 ) );
2093 	cmd += IC7300_mode_nbr[mode];
2094 	cmd += fil;
2095 	if (mode >= 7)
2096 		cmd += '\x10';
2097 	else
2098 		cmd += '\x00';
2099 	cmd.append(to_bcd(PL_tones[tTONE], 6));
2100 	cmd.append(to_bcd(PL_tones[rTONE], 6));
2101 	cmd.append(post);
2102 	waitFB("set_band_selection");
2103 	isett("set_band_selection");
2104 }
2105 
2106 /*
2107 
2108 rn - register number 1/2/3
2109 f5..f1 - frequency BCD reverse
2110 mo - mode
2111 fi - filter #
2112 fg flags: x01 use Tx tone, x02 use Rx tone, x10 data mode
2113 t1..t3 - tx tone BCD fwd
2114 r1..r3 - rx tone BCD fwd
2115 
2116 FE FE 94 E0 1A 01 05 01 FD
2117 
2118 FE FE E0 94 1A 01
2119 05
2120 01
2121 00 00 07 14 00
2122 01
2123 03
2124 10
2125 00 10 00
2126 00 08 85
2127 FD
2128 
2129 */
2130