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 #include <iostream>
21 #include <sstream>
22 
23 #include "IC7200.h"
24 #include "support.h"
25 #include "trace.h"
26 
27 //=============================================================================
28 // IC-7200
29 
30 const char IC7200name_[] = "IC-7200";
31 
32 // these are only defined in this file
33 // undef'd at end of file
34 #define NUM_FILTERS 3
35 #define NUM_MODES  9
36 
37 enum {
38 	LSB7200, USB7200, AM7200,
39 	CW7200, RTTY7200,
40 	CWR7200, RTTYR7200,
41 	LSBD7200, USBD7200 };
42 
43 static int mode_filterA[NUM_MODES] = {1,1,1,1,1,1,1,1,1};
44 static int mode_filterB[NUM_MODES] = {1,1,1,1,1,1,1,1,1};
45 
46 static int mode_bwA[NUM_MODES] = {-1,-1,-1,-1,-1,-1,-1,-1,-1,};
47 static int mode_bwB[NUM_MODES] = {-1,-1,-1,-1,-1,-1,-1,-1,-1,};
48 
49 static const char *szfilter[NUM_FILTERS] = {"W", "M", "N"};
50 
51 const char *IC7200modes_[] = {
52 "LSB", "USB", "AM", "CW", "RTTY", "CW-R", "RTTY-R",
53 "LSB-D", "USB-D", NULL};
54 
55 const char mdval[] = { 0, 1, 2, 3, 4, 7, 8, 0, 1};
56 
57 static char IC7200_mode_type[] = {
58 'L', 'U', 'U', 'L', 'L', 'U', 'U',
59 'L', 'U' };
60 
61 const char *IC7200_SSBwidths[] = {
62   "50",  "100",  "150",  "200",  "250",  "300",  "350",  "400",  "450",  "500",
63 "600",   "700",  "800",  "900", "1000", "1100", "1200", "1300", "1400", "1500",
64 "1600", "1700", "1800", "1900", "2000", "2100", "2200", "2300", "2400", "2500",
65 "2600", "2700", "2800", "2900", "3000", "3100", "3200", "3300", "3400", "3500",
66 "3600",
67 NULL};
68 static int IC7200_bw_vals_SSB[] = {
69  1, 2, 3, 4, 5, 6, 7, 8, 9,10,
70 11,12,13,14,15,16,17,18,19,20,
71 21,22,23,24,25,26,27,28,29,30,
72 31,32,33,34,35,36,37,38,39,40,
73 41, WVALS_LIMIT};
74 
75 const char *IC7200_RTTYwidths[] = {
76   "50",  "100",  "150",  "200",  "250",  "300",  "350",  "400",  "450",  "500",
77  "600",  "700",  "800",  "900", "1000", "1100", "1200", "1300", "1400", "1500",
78 "1600", "1700", "1800", "1900", "2000", "2100", "2200", "2300", "2400", "2500",
79 "2600", "2700",
80 NULL};
81 static int IC7200_bw_vals_RTTY[] = {
82  1, 2, 3, 4, 5, 6, 7, 8, 9,10,
83 11,12,13,14,15,16,17,18,19,20,
84 21,22,23,24,25,26,27,28,29,30,
85 31,32, WVALS_LIMIT};
86 
87 const char *IC7200_AMwidths[] = {
88   "200",  "400",  "600",  "800", "1000", "1200", "1400", "1600", "1800", "2000",
89  "2200", "2400", "2600", "2800", "3000", "3200", "3400", "3600", "3800", "4000",
90  "4200", "4400", "4600", "4800", "5000", "5200", "5400", "5600", "5800", "5000",
91  "6200", "6400", "6600", "6800", "7000", "7200", "7400", "7600", "7800", "8000",
92 NULL};
93 static int IC7200_bw_vals_AM[] = {
94  1, 2, 3, 4, 5, 6, 7, 8, 9,10,
95 11,12,13,14,15,16,17,18,19,20,
96 21,22,23,24,25,26,27,28,29,30,
97 31,32,33,34,35,36,37,38,39,40,
98 WVALS_LIMIT};
99 
100 //======================================================================
101 // IC7200 unique commands
102 //======================================================================
103 
104 static GUI IC7200_widgets[]= {
105 	{ (Fl_Widget *)btnVol,        2, 125,  50 },	//0
106 	{ (Fl_Widget *)sldrVOLUME,   54, 125, 156 },	//1
107 	{ (Fl_Widget *)btnAGC,        2, 145,  50 },	//2
108 	{ (Fl_Widget *)sldrRFGAIN,   54, 145, 156 },	//3
109 	{ (Fl_Widget *)sldrSQUELCH,  54, 165, 156 },	//4
110 	{ (Fl_Widget *)btnNR,         2, 185,  50 },	//5
111 	{ (Fl_Widget *)sldrNR,       54, 185, 156 },	//6
112 	{ (Fl_Widget *)btnLOCK,     214, 105,  50 },	//7
113 	{ (Fl_Widget *)sldrINNER,   266, 105, 156 },	//8
114 	{ (Fl_Widget *)btnCLRPBT,   214, 125,  50 },	//9
115 	{ (Fl_Widget *)sldrOUTER,   266, 125, 156 },	//10
116 	{ (Fl_Widget *)btnNotch,    214, 145,  50 },	//11
117 	{ (Fl_Widget *)sldrNOTCH,   266, 145, 156 },	//12
118 	{ (Fl_Widget *)sldrMICGAIN, 266, 165, 156 },	//13
119 	{ (Fl_Widget *)sldrPOWER,   266, 185, 156 },	//14
120 	{ (Fl_Widget *)NULL, 0, 0, 0 }
121 };
122 
initialize()123 void RIG_IC7200::initialize()
124 {
125 	IC7200_widgets[0].W = btnVol;
126 	IC7200_widgets[1].W = sldrVOLUME;
127 	IC7200_widgets[2].W = btnAGC;
128 	IC7200_widgets[3].W = sldrRFGAIN;
129 	IC7200_widgets[4].W = sldrSQUELCH;
130 	IC7200_widgets[5].W = btnNR;
131 	IC7200_widgets[6].W = sldrNR;
132 	IC7200_widgets[7].W = btnLOCK;
133 	IC7200_widgets[8].W = sldrINNER;
134 	IC7200_widgets[9].W = btnCLRPBT;
135 	IC7200_widgets[10].W = sldrOUTER;
136 	IC7200_widgets[11].W = btnNotch;
137 	IC7200_widgets[12].W = sldrNOTCH;
138 	IC7200_widgets[13].W = sldrMICGAIN;
139 	IC7200_widgets[14].W = sldrPOWER;
140 
141 	btn_icom_select_11->deactivate();
142 	btn_icom_select_12->deactivate();
143 	btn_icom_select_13->deactivate();
144 
145 	choice_rTONE->deactivate();
146 	choice_tTONE->deactivate();
147 }
148 
RIG_IC7200()149 RIG_IC7200::RIG_IC7200() {
150 	name_ = IC7200name_;
151 	modes_ = IC7200modes_;
152 	_mode_type = IC7200_mode_type;
153 	bandwidths_ = IC7200_SSBwidths;
154 	bw_vals_ = IC7200_bw_vals_SSB;
155 	widgets = IC7200_widgets;
156 
157 	comm_baudrate = BR9600;
158 	stopbits = 1;
159 	comm_retries = 2;
160 	comm_wait = 5;
161 	comm_timeout = 50;
162 	comm_echo = true;
163 	comm_rtscts = false;
164 	comm_rtsplus = true;
165 	comm_dtrplus = true;
166 	comm_catptt = true;
167 	comm_rtsptt = false;
168 	comm_dtrptt = false;
169 
170 	def_freq = A.freq = 14070000;
171 	def_mode = A.imode = 1;
172 	def_bw = A.iBW = 32;
173 
174 	B.freq = 7070000;
175 	B.imode = 1;
176 	B.iBW = 32;
177 
178 	has_extras = true;
179 	has_smeter = true;
180 	has_power_out = true;
181 	has_swr_control = true;
182 	has_alc_control = true;
183 	has_agc_control = true;
184 	has_sql_control = true;
185 	has_power_control = true;
186 	has_volume_control = true;
187 	has_mode_control = true;
188 	has_bandwidth_control = true;
189 	has_micgain_control = true;
190 	has_attenuator_control = true;
191 	has_preamp_control = true;
192 	has_noise_control = true;
193 	has_nb_level = true;
194 	has_noise_reduction = true;
195 	has_noise_reduction_control = true;
196 	has_auto_notch = true;
197 	has_notch_control = true;
198 	has_pbt_controls = true;
199 	has_FILTER = true;
200 	has_rf_control = true;
201 	has_compON = true;
202 	has_compression = true;
203 	has_vox_onoff = true;
204 	has_ptt_control = true;
205 	has_tune_control = true;
206 	has_split_AB = true;
207 	has_vfo_adj = true;
208 	has_a2b = true;
209 
210 	has_band_selection = true;
211 
212 	has_cw_wpm = true;
213 	has_cw_spot_tone = true;
214 	has_cw_qsk = true;
215 	has_cw_break_in = true;
216 
217 	defaultCIV = 0x76;
218 	adjustCIV(defaultCIV);
219 
220 	precision = 1;
221 	ndigits = 8;
222 
223 	CW_sense = 0; // normal
224 };
225 
minmax(int min,int max,int & val)226 static inline void minmax(int min, int max, int &val)
227 {
228 	if (val > max) val = max;
229 	if (val < min) val = min;
230 }
231 
232 //======================================================================
233 
selectA()234 void RIG_IC7200::selectA()
235 {
236 	cmd = pre_to;
237 	cmd += '\x07';
238 	cmd += '\x00';
239 	cmd.append(post);
240 	set_trace(2, "selectA()", str2hex(cmd.c_str(), cmd.length()));
241 	waitFB("select A");
242 	inuse = onA;
243 }
244 
selectB()245 void RIG_IC7200::selectB()
246 {
247 	cmd = pre_to;
248 	cmd += '\x07';
249 	cmd += '\x01';
250 	cmd.append(post);
251 	set_trace(2, "selectB()", str2hex(cmd.c_str(), cmd.length()));
252 	waitFB("select B");
253 	inuse = onB;
254 }
255 
check()256 bool RIG_IC7200::check ()
257 {
258 	string resp = pre_fm;
259 	resp += '\x03';
260 	cmd = pre_to;
261 	cmd += '\x03';
262 	cmd.append( post );
263 	bool ok = waitFOR(11, "check vfo");
264 	get_trace(2, "check()", str2hex(replystr.c_str(), replystr.length()));
265 	return ok;
266 }
267 
get_vfoA()268 unsigned long int RIG_IC7200::get_vfoA ()
269 {
270 	if (useB) return A.freq;
271 	string resp = pre_fm;
272 	resp += '\x03';
273 	cmd = pre_to;
274 	cmd += '\x03';
275 	cmd.append( post );
276 	if (waitFOR(11, "get vfo A")) {
277 		size_t p = replystr.rfind(resp);
278 		if (p != string::npos) {
279 			if (replystr[p+5] == -1)
280 				A.freq = 0;
281 			else
282 				A.freq = fm_bcd_be(replystr.substr(p+5), 10);
283 		}
284 	}
285 	get_trace(2, "get_vfoA()", str2hex(replystr.c_str(), replystr.length()));
286 	return A.freq;
287 }
288 
set_vfoA(unsigned long int freq)289 void RIG_IC7200::set_vfoA (unsigned long int freq)
290 {
291 	A.freq = freq;
292 	cmd = pre_to;
293 	cmd += '\x05';
294 	cmd.append( to_bcd_be( freq, 10 ) );
295 	cmd.append( post );
296 	set_trace(2, "set_vfoA()", str2hex(cmd.c_str(), cmd.length()));
297 	waitFB("set vfo A");
298 }
299 
get_vfoB()300 unsigned long int RIG_IC7200::get_vfoB ()
301 {
302 	if (!useB) return B.freq;
303 	string resp = pre_fm;
304 	resp += '\x03';
305 	cmd = pre_to;
306 	cmd += '\x03';
307 	cmd.append( post );
308 	if (waitFOR(11, "get vfo B")) {
309 		size_t p = replystr.rfind(resp);
310 		if (p != string::npos) {
311 			if (replystr[p+5] == -1)
312 				A.freq = 0;
313 			else
314 				B.freq = fm_bcd_be(replystr.substr(p+5), 10);
315 		}
316 	}
317 	get_trace(2, "get_vfoB()", str2hex(replystr.c_str(), replystr.length()));
318 	return B.freq;
319 }
320 
set_vfoB(unsigned long int freq)321 void RIG_IC7200::set_vfoB (unsigned long int freq)
322 {
323 	B.freq = freq;
324 	cmd = pre_to;
325 	cmd += '\x05';
326 	cmd.append( to_bcd_be( freq, 10 ) );
327 	cmd.append( post );
328 	set_trace(2, "set_vfoB()", str2hex(cmd.c_str(), cmd.length()));
329 	waitFB("set vfo B");
330 }
331 
can_split()332 bool RIG_IC7200::can_split()
333 {
334 	return true;
335 }
336 
set_split(bool val)337 void RIG_IC7200::set_split(bool val)
338 {
339 	split = val;
340 	cmd = pre_to;
341 	cmd += 0x0F;
342 	cmd += val ? 0x01 : 0x00;
343 	cmd.append(post);
344 	waitFB(val ? "set split ON" : "set split OFF");
345 	set_trace(2, "set_split()", str2hex(cmd.c_str(), cmd.length()));
346 }
347 
348 // 7200 does not respond to get split CAT command
get_split()349 int RIG_IC7200::get_split()
350 {
351 	return split;
352 }
353 
354 // Tranceiver PTT on/off
set_PTT_control(int val)355 void RIG_IC7200::set_PTT_control(int val)
356 {
357 	cmd = pre_to;
358 	cmd += '\x1c';
359 	cmd += '\x00';
360 	cmd += (val ? '\x01' : '\x00');
361 	cmd.append( post );
362 	if (val)
363 		waitFB("set ptt ON");
364 	else
365 		waitFB("set ptt OFF");
366 	ptt_ = val;
367 	set_trace(2, "set_PTT()", str2hex(cmd.c_str(), cmd.length()));
368 }
369 
get_PTT()370 int RIG_IC7200::get_PTT()
371 {
372 	cmd = pre_to;
373 	cmd += '\x1c'; cmd += '\x00';
374 	string resp = pre_fm;
375 	resp += '\x1c'; resp += '\x00';
376 	cmd.append(post);
377 	if (waitFOR(8, "get PTT")) {
378 		size_t p = replystr.rfind(resp);
379 		if (p != string::npos)
380 			ptt_ = replystr[p + 6];
381 	}
382 	get_trace(2, "get_PTT()", str2hex(replystr.c_str(), replystr.length()));
383 	return ptt_;
384 }
385 
386 // Volume control val 0 ... 100
set_volume_control(int val)387 void RIG_IC7200::set_volume_control(int val)
388 {
389 	cmd = pre_to;
390 	cmd.append("\x14\x01");
391 	cmd.append(bcd255(val));
392 	cmd.append( post );
393 	waitFB("set vol");
394 	set_trace(2, "set_volume_control()", str2hex(cmd.c_str(), cmd.length()));
395 }
396 
get_volume_control()397 int RIG_IC7200::get_volume_control()
398 {
399 	int val = progStatus.volume;
400 	string cstr = "\x14\x01";
401 	string resp = pre_fm;
402 	resp.append(cstr);
403 	cmd = pre_to;
404 	cmd.append(cstr);
405 	cmd.append( post );
406 	if (waitFOR(9, "get vol")) {
407 		size_t p = replystr.rfind(resp);
408 		if (p != string::npos)
409 			val = num100(replystr.substr(p+6));
410 	}
411 	get_trace(2, "get_volume_control()", str2hex(replystr.c_str(), replystr.length()));
412 	return val;
413 }
414 
get_vol_min_max_step(int & min,int & max,int & step)415 void RIG_IC7200::get_vol_min_max_step(int &min, int &max, int &step)
416 {
417 	min = 0; max = 100; step = 1;
418 }
419 
get_smeter()420 int RIG_IC7200::get_smeter()
421 {
422 	string cstr = "\x15\x02";
423 	string resp = pre_fm;
424 	resp.append(cstr);
425 	cmd = pre_to;
426 	cmd.append(cstr);
427 	cmd.append( post );
428 	int mtr= -1;
429 	if (waitFOR(9, "get smeter")) {
430 		size_t p = replystr.rfind(resp);
431 		if (p != string::npos) {
432 			mtr = fm_bcd(replystr.substr(p+6), 3);
433 			mtr = (int)ceil(mtr /2.55);
434 			if (mtr > 100) mtr = 100;
435 		}
436 	}
437 	get_trace(2, "get_smeter()", str2hex(replystr.c_str(), replystr.length()));
438 	return mtr;
439 }
440 
441 struct pwrpair {int mtr; float pwr;};
442 
443 static pwrpair pwrtbl[] = {
444 {0, 0.0},
445 {40, 10.0},
446 {76, 20.0},
447 {92, 25.0},
448 {103, 30.0},
449 {124, 40.0},
450 {143, 50.0},
451 {183, 75.0},
452 {213, 100.0},
453 {255, 140.0} };
454 
get_power_out(void)455 int RIG_IC7200::get_power_out(void)
456 {
457 	string cstr = "\x15\x11";
458 	string resp = pre_fm;
459 	resp.append(cstr);
460 	cmd = pre_to;
461 	cmd.append(cstr);
462 	cmd.append( post );
463 	int mtr= 0;
464 	if (waitFOR(9, "get power out")) {
465 		size_t p = replystr.rfind(resp);
466 		if (p != string::npos) {
467 			mtr = fm_bcd(replystr.substr(p+6), 3);
468 			size_t i = 0;
469 			for (i = 0; i < sizeof(pwrtbl) / sizeof(pwrpair) - 1; i++)
470 				if (mtr >= pwrtbl[i].mtr && mtr < pwrtbl[i+1].mtr)
471 					break;
472 			if (mtr < 0) mtr = 0;
473 			if (mtr > 255) mtr = 255;
474 			mtr = (int)ceil(pwrtbl[i].pwr +
475 				(pwrtbl[i+1].pwr - pwrtbl[i].pwr)*(mtr - pwrtbl[i].mtr)/(pwrtbl[i+1].mtr - pwrtbl[i].mtr));
476 
477 			if (mtr > 100) mtr = 100;
478 		}
479 	}
480 	get_trace(2, "get_power_out()", str2hex(replystr.c_str(), replystr.length()));
481 	return mtr;
482 }
483 
get_swr(void)484 int RIG_IC7200::get_swr(void)
485 {
486 	string cstr = "\x15\x12";
487 	string resp = pre_fm;
488 	resp.append(cstr);
489 	cmd = pre_to;
490 	cmd.append(cstr);
491 	cmd.append( post );
492 	int mtr= -1;
493 	if (waitFOR(9, "get swr")) {
494 		size_t p = replystr.rfind(resp);
495 		if (p != string::npos) {
496 			mtr = fm_bcd(replystr.substr(p+6), 3);
497 			mtr = (int)ceil(mtr /2.55);
498 			if (mtr > 100) mtr = 100;
499 		}
500 	}
501 	get_trace(2, "get_swr()", str2hex(replystr.c_str(), replystr.length()));
502 	return mtr;
503 }
504 
get_alc(void)505 int RIG_IC7200::get_alc(void)
506 {
507 	string cstr = "\x15\x13";
508 	string resp = pre_fm;
509 	resp.append(cstr);
510 	cmd = pre_to;
511 	cmd.append(cstr);
512 	cmd.append( post );
513 	int mtr= -1;
514 	if (waitFOR(9, "get alc")) {
515 		size_t p = replystr.rfind(resp);
516 		if (p != string::npos) {
517 			mtr = fm_bcd(replystr.substr(p+6), 3);
518 			mtr = (int)ceil(mtr /2.55);
519 			if (mtr > 100) mtr = 100;
520 		}
521 	}
522 	get_trace(2, "get_alc()", str2hex(replystr.c_str(), replystr.length()));
523 	return mtr;
524 }
525 
set_noise(bool val)526 void RIG_IC7200::set_noise(bool val)
527 {
528 	cmd = pre_to;
529 	cmd.append("\x16\x22");
530 	cmd += val ? 1 : 0;
531 	cmd.append(post);
532 	waitFB("set noise");
533 	set_trace(2, "set_noise()", str2hex(cmd.c_str(), cmd.length()));
534 }
535 
get_noise()536 int RIG_IC7200::get_noise()
537 {
538 	int val = progStatus.noise;
539 	string cstr = "\x16\x22";
540 	string resp = pre_fm;
541 	resp.append(cstr);
542 	cmd = pre_to;
543 	cmd.append(cstr);
544 	cmd.append(post);
545 	if (waitFOR(8, "get noise")) {
546 		size_t p = replystr.rfind(resp);
547 		if (p != string::npos) {
548 			val = replystr[p+6];
549 		}
550 	}
551 	get_trace(2, "get_noise()", str2hex(replystr.c_str(), replystr.length()));
552 	return val;
553 }
554 
set_nb_level(int val)555 void RIG_IC7200::set_nb_level(int val)
556 {
557 	cmd = pre_to;
558 	cmd.append("\x14\x12");
559 	cmd.append(bcd255(val));
560 	cmd.append( post );
561 	waitFB("set NB level");
562 	set_trace(2, "set_nb_level()", str2hex(cmd.c_str(), cmd.length()));
563 }
564 
get_nb_level()565 int  RIG_IC7200::get_nb_level()
566 {
567 	int val = progStatus.nb_level;
568 	string cstr = "\x14\x12";
569 	string resp = pre_fm;
570 	resp.append(cstr);
571 	cmd = pre_to;
572 	cmd.append(cstr);
573 	cmd.append(post);
574 	if (waitFOR(9, "get NB level")) {
575 		size_t p = replystr.rfind(resp);
576 		if (p != string::npos)
577 			val = num100(replystr.substr(p+6));
578 	}
579 	get_trace(2, "get_nb_level()", str2hex(replystr.c_str(), replystr.length()));
580 	return val;
581 }
582 
set_noise_reduction(int val)583 void RIG_IC7200::set_noise_reduction(int val)
584 {
585 	cmd = pre_to;
586 	cmd.append("\x16\x40");
587 	cmd += val ? 1 : 0;
588 	cmd.append(post);
589 	waitFB("set NR");
590 	set_trace(2, "set_noise_reduction()", str2hex(cmd.c_str(), cmd.length()));
591 }
592 
get_noise_reduction()593 int RIG_IC7200::get_noise_reduction()
594 {
595 	string cstr = "\x16\x40";
596 	string resp = pre_fm;
597 	resp.append(cstr);
598 	cmd = pre_to;
599 	cmd.append(cstr);
600 	cmd.append(post);
601 	if (waitFOR(8, "get NR")) {
602 		size_t p = replystr.rfind(resp);
603 		if (p != string::npos)
604 			return (replystr[p+6] ? 1 : 0);
605 	}
606 	get_trace(2, "get_noise_reduction()", str2hex(replystr.c_str(), replystr.length()));
607 	return progStatus.noise_reduction;
608 }
609 
610 // 0 < val < 100
set_noise_reduction_val(int val)611 void RIG_IC7200::set_noise_reduction_val(int val)
612 {
613 	cmd = pre_to;
614 	cmd.append("\x14\x06");
615 	val = val * 16 + 8;
616 	cmd.append(to_bcd(val, 3));
617 	cmd.append(post);
618 	waitFB("set NRval");
619 	set_trace(2, "set_noise_reduction_val()", str2hex(cmd.c_str(), cmd.length()));
620 }
621 
get_noise_reduction_val()622 int RIG_IC7200::get_noise_reduction_val()
623 {
624 	int val = progStatus.noise_reduction_val;
625 	string cstr = "\x14\x06";
626 	string resp = pre_fm;
627 	resp.append(cstr);
628 	cmd = pre_to;
629 	cmd.append(cstr);
630 	cmd.append(post);
631 	if (waitFOR(9, "get NRval")) {
632 		size_t p = replystr.rfind(resp);
633 		if (p != string::npos) {
634 			val = fm_bcd(replystr.substr(p+6), 3);
635 			val = (val - 8) / 16;
636 		}
637 	}
638 	get_trace(2, "get_nr_val()", str2hex(replystr.c_str(), replystr.length()));
639 	return val;
640 }
641 
set_attenuator(int val)642 void RIG_IC7200::set_attenuator(int val)
643 {
644 	if (val) {
645 		atten_label("20 dB", true);
646 		atten_level = 1;
647 		set_preamp(0);
648 	} else {
649 		atten_label("ATT", false);
650 		atten_level = 0;
651 	}
652 
653 	cmd = pre_to;
654 	cmd += '\x11';
655 	cmd += atten_level ? '\x20' : '\x00';
656 	cmd.append( post );
657 	waitFB("set att");
658 	set_trace(2, "set_attenuator()", str2hex(cmd.c_str(), cmd.length()));
659 }
660 
next_attenuator()661 int RIG_IC7200::next_attenuator()
662 {
663 	if (atten_level) return 0;
664 	return 1;
665 }
666 
get_attenuator()667 int RIG_IC7200::get_attenuator()
668 {
669 	cmd = pre_to;
670 	cmd += '\x11';
671 	cmd.append( post );
672 	string resp = pre_fm;
673 	resp += '\x11';
674 	if (waitFOR(7, "get ATT")) {
675 		get_trace(2, "get_ATT()", str2hex(replystr.c_str(), replystr.length()));
676 		size_t p = replystr.rfind(resp);
677 		if (p != string::npos) {
678 			if (!replystr[p+5]) {
679 				atten_label("ATT", false);
680 				atten_level = 0;
681 				return 0;
682 			} else {
683 				atten_label("20 dB", true);
684 				atten_level = 1;
685 				return 1;
686 			}
687 		}
688 	}
689 	return 0;
690 }
691 
next_preamp()692 int RIG_IC7200::next_preamp()
693 {
694 	if (preamp_level)
695 		return 0;
696 	return 1;
697 }
698 
set_preamp(int val)699 void RIG_IC7200::set_preamp(int val)
700 {
701 	if (val) {
702 		preamp_label("Pre ON", true);
703 		preamp_level = 1;
704 		if (atten_level == 1) {
705 			atten_label("ATT", false);
706 			atten_level = 0;
707 		}
708 	} else {
709 		preamp_label("Pre", false);
710 		preamp_level = 0;
711 	}
712 
713 	cmd = pre_to;
714 	cmd += '\x16';
715 	cmd += '\x02';
716 	cmd += preamp_level ? 0x01 : 0x00;
717 	cmd.append( post );
718 	waitFB("set Pre");
719 	set_trace(2, "set_preamp()", str2hex(cmd.c_str(), cmd.length()));
720 }
721 
get_preamp()722 int RIG_IC7200::get_preamp()
723 {
724 	string cstr = "\x16\x02";
725 	string resp = pre_fm;
726 	resp.append(cstr);
727 	cmd = pre_to;
728 	cmd.append(cstr);
729 	cmd.append( post );
730 	if (waitFOR(8, "get Pre")) {
731 		get_trace(2, "get_preamp()", str2hex(replystr.c_str(), replystr.length()));
732 		size_t p = replystr.rfind(resp);
733 		if (p != string::npos) {
734 			if (replystr[p+6] == 0x01) {
735 				preamp_label("Pre ON", true);
736 				preamp_level = 1;
737 //				progStatus.preamp = true;
738 			} else {
739 				preamp_label("Pre", false);
740 				preamp_level = 0;
741 //				progStatus.preamp = false;
742 			}
743 		}
744 	}
745 	return preamp_level; //progStatus.preamp;
746 }
747 
set_rf_gain(int val)748 void RIG_IC7200::set_rf_gain(int val)
749 {
750 	cmd = pre_to;
751 	cmd.append("\x14\x02");
752 	cmd.append(bcd255(val));
753 	cmd.append( post );
754 	waitFB("set RF");
755 	set_trace(2, "set_rf_gain()", str2hex(cmd.c_str(), cmd.length()));
756 }
757 
get_rf_gain()758 int RIG_IC7200::get_rf_gain()
759 {
760 	int val = progStatus.rfgain;
761 	string cstr = "\x14\x02";
762 	string resp = pre_fm;
763 	cmd = pre_to;
764 	cmd.append(cstr).append(post);
765 	resp.append(cstr);
766 	if (waitFOR(9, "get RF")) {
767 		size_t p = replystr.rfind(resp);
768 		if (p != string::npos)
769 			val = num100(replystr.substr(p + 6));
770 	}
771 	get_trace(2, "get_rf_gain()", str2hex(replystr.c_str(), replystr.length()));
772 	return val;
773 }
774 
set_squelch(int val)775 void RIG_IC7200::set_squelch(int val)
776 {
777 	cmd = pre_to;
778 	cmd.append("\x14\x03");
779 	cmd.append(bcd255(val));
780 	cmd.append( post );
781 	waitFB("set Sqlch");
782 	set_trace(2, "set_squelch()", str2hex(cmd.c_str(), cmd.length()));
783 }
784 
get_squelch()785 int  RIG_IC7200::get_squelch()
786 {
787 	int val = progStatus.squelch;
788 	string cstr = "\x14\x03";
789 	string resp = pre_fm;
790 	resp.append(cstr);
791 	cmd = pre_to;
792 	cmd.append(cstr);
793 	cmd.append(post);
794 	if (waitFOR(9, "get squelch")) {
795 		size_t p = replystr.rfind(resp);
796 		if (p != string::npos)
797 			val = num100(replystr.substr(p+6));
798 	}
799 	get_trace(2, "get_squelch()", str2hex(replystr.c_str(), replystr.length()));
800 	return val;
801 }
802 
set_power_control(double val)803 void RIG_IC7200::set_power_control(double val)
804 {
805 	cmd = pre_to;
806 	cmd.append("\x14\x0A");
807 	cmd.append(bcd255(val));
808 	cmd.append( post );
809 	waitFB("set power");
810 	set_trace(2, "set_power_control()", str2hex(cmd.c_str(), cmd.length()));
811 }
812 
get_power_control()813 int RIG_IC7200::get_power_control()
814 {
815 	string cstr = "\x14\x0A";
816 	string resp = pre_fm;
817 	cmd = pre_to;
818 	cmd.append(cstr).append(post);
819 	resp.append(cstr);
820 	int val = progStatus.power_level;
821 	string retstr = "ret str";
822 	if (waitFOR(9, "get power")) {
823 		size_t p = replystr.rfind(resp);
824 		if (p != string::npos) {
825 			val = num100(replystr.substr(p+6));
826 			retstr = str2hex(replystr.substr(p).c_str(), 9);
827 		}
828 	}
829 	get_trace(2, "get_power_control()", str2hex(replystr.c_str(), replystr.length()));
830 	return val;
831 }
832 
get_mic_gain_min_max_step(int & min,int & max,int & step)833 void RIG_IC7200::get_mic_gain_min_max_step(int &min, int &max, int &step)
834 {
835 	min = 0;
836 	max = 100;
837 	step = 1;
838 }
839 
get_mic_gain()840 int RIG_IC7200::get_mic_gain()
841 {
842 	string cstr = "\x14\x0B";
843 	string resp = pre_fm;
844 	resp.append(cstr);
845 	cmd = pre_to;
846 	cmd.append(cstr);
847 	cmd.append(post);
848 	if (waitFOR(9, "get mic")) {
849 		size_t p = replystr.rfind(resp);
850 		if (p != string::npos) {
851 			return num100(replystr.substr(p + 6));
852 		}
853 	}
854 	get_trace(2, "get_mic_gain()", str2hex(replystr.c_str(), replystr.length()));
855 	return 0;
856 }
857 
set_mic_gain(int val)858 void RIG_IC7200::set_mic_gain(int val)
859 {
860 	cmd = pre_to;
861 	cmd.append("\x14\x0B");
862 	cmd.append(bcd255(val));
863 	cmd.append(post);
864 	waitFB("set mic");
865 	set_trace(2, "set_mic_gain()", str2hex(cmd.c_str(), cmd.length()));
866 }
867 
get_modeA()868 int RIG_IC7200::get_modeA()
869 {
870 	int md = A.imode;
871 	size_t p = 0;
872 
873 	string resp = pre_fm;
874 	resp += '\x04';
875 	cmd = pre_to;
876 	cmd += '\x04';
877 	cmd.append(post);
878 
879 	if (waitFOR(8, "get mode A")) {
880 		p = replystr.rfind(resp);
881 		if (p != string::npos) {
882 			if (replystr[p+5] == -1) { md = A.filter = 0; }
883 			else {
884 				md = replystr[p + 5];
885 				if (md > 6) md -= 2;
886 				A.filter = replystr[p+6];
887 			}
888 		}
889 	}
890 	get_trace(2, "get_modeA()", str2hex(replystr.c_str(), replystr.length()));
891 
892 	cmd = pre_to;
893 	cmd += "\x1A\x04";
894 	cmd.append(post);
895 	resp = pre_fm;
896 	resp += "\x1A\x04";
897 	if (waitFOR(9, "data mode?")) {
898 		p = replystr.rfind(resp);
899 		if (p != string::npos) {
900 			if ((replystr[p+6] & 0x01) == 0x01) {
901 				if (md == 0) md = 7;
902 				if (md == 1) md = 8;
903 			}
904 		}
905 	}
906 	if (A.filter > 0 && A.filter < 4)
907 		mode_filterA[A.imode] = A.filter;
908 
909 	get_trace(2, "get_data_modeA()", str2hex(replystr.c_str(), replystr.length()));
910 	get_trace(4, "mode_filterA[", IC7200modes_[md], "] = ", szfilter[A.filter-1]);
911 
912 	if (A.imode == CW7200 || A.imode == CWR7200) {
913 		cmd.assign(pre_to).append("\x1A\x03\x37").append(post);
914 		resp.assign(pre_fm).append("\x1A\x03\x37");
915 		if (waitFOR(9, "get CW sideband")) {
916 			p = replystr.rfind(resp);
917 			CW_sense = replystr[p + 7];
918 			if (CW_sense) IC7200_mode_type[A.imode] = 'U';
919 			else IC7200_mode_type[A.imode] = 'L';
920 		}
921 	}
922 
923 	return (A.imode = md);
924 }
925 
set_modeA(int val)926 void RIG_IC7200::set_modeA(int val)
927 {
928 	A.imode = val;
929 
930 	cmd = pre_to;
931 	cmd += '\x06';
932 	cmd += mdval[A.imode];
933 	cmd += mode_filterA[A.imode];
934 	cmd.append( post );
935 
936 	waitFB("set mode A, default filter");
937 
938 	set_trace(4, "set mode A[", IC7200modes_[A.imode], "] ", str2hex(replystr.c_str(), replystr.length()));
939 
940 	if (val < 7) return;
941 
942 	cmd = pre_to;
943 	cmd += '\x1A'; cmd += '\x04';
944 	cmd += '\x01';
945 	cmd += mode_filterA[A.imode];
946 	cmd.append( post);
947 	waitFB("set data mode A");
948 
949 	set_trace(2, "set_data_modeA()", str2hex(replystr.c_str(), replystr.length()));
950 }
951 
get_modeB()952 int RIG_IC7200::get_modeB()
953 {
954 	int md = B.imode;
955 	size_t p = 0;
956 
957 	cmd = pre_to;
958 	cmd += '\x04';
959 	cmd.append(post);
960 	string resp = pre_fm;
961 	resp += '\x04';
962 	if (waitFOR(8, "get mode B")) {
963 		p = replystr.rfind(resp);
964 		if (p != string::npos) {
965 			if (replystr[p+5] == -1) { md = B.filter = 0; }
966 			else {
967 				md = replystr[p+5];
968 				if (md > 6) md -= 2;
969 				B.filter = replystr[p+6];
970 			}
971 		}
972 	}
973 	get_trace(2, "get_modeB()", str2hex(replystr.c_str(), replystr.length()));
974 
975 	cmd = pre_to;
976 	cmd += "\x1A\x04";
977 	cmd.append(post);
978 	resp = pre_fm;
979 	resp += "\x1A\x04";
980 	if (waitFOR(9, "get data B")) {
981 		p = replystr.rfind(resp);
982 		if (p != string::npos) {
983 			if ((replystr[p+6] & 0x01) == 0x01) {
984 				if (md == 0) md = 7;
985 				if (md == 1) md = 8;
986 			}
987 		}
988 	}
989 	if (B.filter > 0 && B.filter < 4)
990 		mode_filterB[B.imode] = B.filter;
991 
992 	get_trace(2, "get_data_modeB()", str2hex(replystr.c_str(), replystr.length()));
993 	get_trace(4, "mode_filterB[", IC7200modes_[md], "] = ", szfilter[B.filter-1]);
994 
995 	if (B.imode == CW7200 || B.imode == CWR7200) {
996 		cmd.assign(pre_to).append("\x1A\x03\x37").append(post);
997 		resp.assign(pre_fm).append("\x1A\x03\x37");
998 		if (waitFOR(9, "get CW sideband")) {
999 			p = replystr.rfind(resp);
1000 			CW_sense = replystr[p + 7];
1001 			if (CW_sense) IC7200_mode_type[B.imode] = 'U';
1002 			else IC7200_mode_type[B.imode] = 'L';
1003 		}
1004 	}
1005 
1006 	return (B.imode = md);
1007 }
1008 
set_modeB(int val)1009 void RIG_IC7200::set_modeB(int val)
1010 {
1011 	B.imode = val;
1012 
1013 	cmd = pre_to;
1014 	cmd += '\x06';
1015 	cmd += mdval[B.imode];
1016 	cmd += mode_filterB[B.imode];
1017 	cmd.append( post );
1018 	waitFB("set mode B, default filter");
1019 
1020 	set_trace(4, "set mode B[", IC7200modes_[B.imode], "] ", str2hex(replystr.c_str(), replystr.length()));
1021 
1022 	if (val < 7) return;
1023 
1024 	cmd = pre_to;
1025 	cmd += '\x1A'; cmd += '\x04';
1026 	cmd += '\x01';
1027 	cmd += mode_filterB[B.imode];
1028 	cmd.append( post);
1029 	waitFB("set data mode B");
1030 
1031 	set_trace(2, "set data mode B ",  str2hex(replystr.c_str(), replystr.length()));
1032 
1033 }
1034 
get_modetype(int n)1035 int RIG_IC7200::get_modetype(int n)
1036 {
1037 	return _mode_type[n];
1038 }
1039 
get_FILT(int mode)1040 int RIG_IC7200::get_FILT(int mode)
1041 {
1042 	if (useB) return mode_filterB[mode];
1043 	return mode_filterA[mode];
1044 }
1045 
set_FILT(int filter)1046 void RIG_IC7200::set_FILT(int filter)
1047 {
1048 	if (filter < 1 || filter > 3)
1049 		return;
1050 
1051 	if (useB) {
1052 		B.filter = filter;
1053 		mode_filterB[B.imode] = filter;
1054 
1055 		cmd = pre_to;
1056 		cmd += '\x06';
1057 		cmd += mdval[B.imode];
1058 		cmd += filter;
1059 		cmd.append( post );
1060 
1061 		waitFB("set mode/filter B");
1062 	set_trace(2, "set mode/filter B", str2hex(replystr.c_str(), replystr.length()));
1063 
1064 		if (B.imode < 7) return;
1065 
1066 		cmd = pre_to;
1067 		cmd += '\x1A'; cmd += '\x04';
1068 		cmd += '\x01';
1069 		cmd += filter;
1070 		cmd.append( post);
1071 		waitFB("set data mode/filter B");
1072 	set_trace(2, "set data mode/filter B", str2hex(replystr.c_str(), replystr.length()));
1073 
1074 	} else {
1075 		A.filter = filter;
1076 		mode_filterA[A.imode] = filter;
1077 
1078 		cmd = pre_to;
1079 		cmd += '\x06';
1080 		cmd += mdval[A.imode];
1081 		cmd += filter;
1082 		cmd.append( post );
1083 		waitFB("set filter A ");
1084 	set_trace(2, "set filter A", str2hex(replystr.c_str(), replystr.length()));
1085 
1086 		if (A.imode < 7) return;
1087 
1088 		cmd = pre_to;
1089 		cmd += '\x1A'; cmd += '\x04';
1090 		cmd += '\x01';
1091 		cmd += mode_filterA[A.imode];
1092 		cmd.append( post);
1093 		waitFB("set data filter A");
1094 	set_trace(2, "set data filter A", str2hex(replystr.c_str(), replystr.length()));
1095 	}
1096 
1097 }
1098 
FILT(int val)1099 const char *RIG_IC7200::FILT(int val)
1100 {
1101 	if (val < 1) val = 1;
1102 	if (val > 3) val = 3;
1103 	return(szfilter[val - 1]);
1104 }
1105 
nextFILT()1106 const char *RIG_IC7200::nextFILT()
1107 {
1108 	int val = A.filter;
1109 	if (useB) val = B.filter;
1110 	val++;
1111 	if (val > 3) val = 1;
1112 	set_FILT(val);
1113 	return szfilter[val - 1];
1114 }
1115 
set_FILTERS(std::string s)1116 void RIG_IC7200::set_FILTERS(std::string s)
1117 {
1118 	stringstream strm;
1119 	strm << s;
1120 	for (int i = 0; i < NUM_MODES; i++)
1121 		strm >> mode_filterA[i];
1122 	for (int i = 0; i < NUM_MODES; i++)
1123 		strm >> mode_filterB[i];
1124 	for (int i = 0; i < NUM_MODES; i++) {
1125 		if (mode_filterA[i] < 1) mode_filterA[i] = 1;
1126 		if (mode_filterA[i] > 3) mode_filterA[i] = 3;
1127 		if (mode_filterB[i] < 1) mode_filterB[i] = 1;
1128 		if (mode_filterB[i] > 3) mode_filterB[i] = 3;
1129 	}
1130 }
1131 
get_FILTERS()1132 std::string RIG_IC7200::get_FILTERS()
1133 {
1134 	for (int i = 0; i < NUM_MODES; i++) {
1135 		if (mode_filterA[i] < 1) mode_filterA[i] = 1;
1136 		if (mode_filterA[i] > 3) mode_filterA[i] = 3;
1137 		if (mode_filterB[i] < 1) mode_filterB[i] = 1;
1138 		if (mode_filterB[i] > 3) mode_filterB[i] = 3;
1139 	}
1140 	stringstream s;
1141 	for (int i = 0; i < NUM_MODES; i++)
1142 		s << mode_filterA[i] << " ";
1143 	for (int i = 0; i < NUM_MODES; i++)
1144 		s << mode_filterB[i] << " ";
1145 	return s.str();
1146 }
1147 
get_BANDWIDTHS()1148 std::string RIG_IC7200::get_BANDWIDTHS()
1149 {
1150 	stringstream s;
1151 	for (int i = 0; i < NUM_MODES; i++)
1152 		s << mode_bwA[i] << " ";
1153 	for (int i = 0; i < NUM_MODES; i++)
1154 		s << mode_bwB[i] << " ";
1155 	return s.str();
1156 }
1157 
set_BANDWIDTHS(std::string s)1158 void RIG_IC7200::set_BANDWIDTHS(std::string s)
1159 {
1160 	stringstream strm;
1161 	strm << s;
1162 	for (int i = 0; i < NUM_MODES; i++)
1163 		strm >> mode_bwA[i];
1164 	for (int i = 0; i < NUM_MODES; i++)
1165 		strm >> mode_bwB[i];
1166 }
1167 
adjust_bandwidth(int m)1168 int RIG_IC7200::adjust_bandwidth(int m)
1169 {
1170 	switch (m) {
1171 		case 2: // AM
1172 			bandwidths_ = IC7200_AMwidths;
1173 			bw_vals_ = IC7200_bw_vals_AM;
1174 			bwA = 30;
1175 			break;
1176 		case 3:
1177 		case 5: // CW
1178 			bandwidths_ = IC7200_SSBwidths;
1179 			bw_vals_ = IC7200_bw_vals_SSB;
1180 			bwA = 14;
1181 			break;
1182 		case 4:
1183 		case 6: // RTTY
1184 			bandwidths_ = IC7200_RTTYwidths;
1185 			bw_vals_ = IC7200_bw_vals_RTTY;
1186 			bwA = 28;
1187 			break;
1188 		case 0:
1189 		case 1:
1190 		case 7:
1191 		case 8:
1192 		default: // SSB
1193 			bandwidths_ = IC7200_SSBwidths;
1194 			bw_vals_ = IC7200_bw_vals_SSB;
1195 			bwA = 32;
1196 	}
1197 	return bwA;
1198 }
1199 
def_bandwidth(int m)1200 int RIG_IC7200::def_bandwidth(int m)
1201 {
1202 	int bw = adjust_bandwidth(m);
1203 	if (useB) {
1204 		if (mode_bwB[m] == -1)
1205 			mode_bwB[m] = bw;
1206 		return mode_bwB[m];
1207 	}
1208 	if (mode_bwA[m] == -1)
1209 		mode_bwA[m] = bw;
1210 	return mode_bwA[m];
1211 }
1212 
bwtable(int m)1213 const char ** RIG_IC7200::bwtable(int m)
1214 {
1215 	switch (m) {
1216 		case 2: // AM
1217 			return IC7200_AMwidths;
1218 			break;
1219 		case 3:
1220 		case 5: // CW
1221 			return IC7200_SSBwidths;
1222 			break;
1223 		case 4:
1224 		case 6: // RTTY
1225 			return IC7200_RTTYwidths;
1226 			break;
1227 		case 0:
1228 		case 1:
1229 		case 7:
1230 		case 8:
1231 		default: // SSB
1232 			return IC7200_SSBwidths;
1233 	}
1234 	return IC7200_SSBwidths;
1235 }
1236 
set_bwA(int val)1237 void RIG_IC7200::set_bwA(int val)
1238 {
1239 	A.iBW = val;
1240 	cmd = pre_to;
1241 	cmd.append("\x1A\x02");
1242 	cmd.append(to_bcd(val, 2));
1243 	cmd.append( post );
1244 	waitFB("set BW A");
1245 	mode_bwA[A.imode] = val;
1246 	set_trace(4, "set_bwA() ", bwtable(A.imode)[val], ": ", str2hex(replystr.c_str(), replystr.length()));
1247 }
1248 
get_bwA()1249 int  RIG_IC7200::get_bwA()
1250 {
1251 	cmd = pre_to;
1252 	cmd += "\x1A\x02";
1253 	cmd.append( post );
1254 	string resp = pre_fm;
1255 	resp += "\x1A\x02";
1256 	int bwval = A.iBW;
1257 	if (waitFOR(8, "get BW A")) {
1258 		size_t p = replystr.rfind(resp);
1259 		if (p != string::npos)
1260 			bwval = (fm_bcd(replystr.substr(p+6),2));
1261 	}
1262 	if (bwval != A.iBW) {
1263 		A.iBW = bwval;
1264 	}
1265 	get_trace(2, "get_bwA()", str2hex(replystr.c_str(), replystr.length()));
1266 
1267 	mode_bwA[A.imode] = A.iBW;
1268 
1269 	return A.iBW;
1270 }
1271 
set_bwB(int val)1272 void RIG_IC7200::set_bwB(int val)
1273 {
1274 	B.iBW = val;
1275 	cmd = pre_to;
1276 	cmd.append("\x1A\x02");
1277 	cmd.append(to_bcd(val, 2));
1278 	cmd.append( post );
1279 	waitFB("set BW B");
1280 	mode_bwB[B.imode] = val;
1281 	set_trace(4, "set_bwB() ", bwtable(B.imode)[val], ": ", str2hex(replystr.c_str(), replystr.length()));
1282 }
1283 
get_bwB()1284 int  RIG_IC7200::get_bwB()
1285 {
1286 	cmd = pre_to;
1287 	cmd += "\x1A\x02";
1288 	cmd.append( post );
1289 	string resp = pre_fm;
1290 	resp += "\x1A\x02";
1291 	int bwval = B.iBW;
1292 	if (waitFOR(8, "get BW B")) {
1293 		size_t p = replystr.rfind(resp);
1294 		if (p != string::npos)
1295 			bwval = (fm_bcd(replystr.substr(p+6),2));
1296 	}
1297 	if (bwval != B.iBW) {
1298 		B.iBW = bwval;
1299 	}
1300 	get_trace(2, "get_bwB()", str2hex(replystr.c_str(), replystr.length()));
1301 	mode_bwB[B.imode] = B.iBW;
1302 	return B.iBW;
1303 }
1304 
set_auto_notch(int val)1305 void RIG_IC7200::set_auto_notch(int val)
1306 {
1307 	cmd = pre_to;
1308 	cmd += '\x16';
1309 	cmd += '\x41';
1310 	cmd += (unsigned char)val;
1311 	cmd.append( post );
1312 	waitFB("set AN");
1313 	set_trace(2, "set_auto_notch()", str2hex(cmd.c_str(), cmd.length()));
1314 }
1315 
get_auto_notch()1316 int RIG_IC7200::get_auto_notch()
1317 {
1318 	string cstr = "\x16\x41";
1319 	string resp = pre_fm;
1320 	resp.append(cstr);
1321 	cmd = pre_to;
1322 	cmd.append(cstr);
1323 	cmd.append( post );
1324 	if (waitFOR(8, "get AN")) {
1325 		get_trace(2, "get_auto_notch()", str2hex(replystr.c_str(), replystr.length()));
1326 		size_t p = replystr.rfind(resp);
1327 		if (p != string::npos) {
1328 			if (replystr[p+6] == 0x01) {
1329 				auto_notch_label("AN", true);
1330 				return true;
1331 			} else {
1332 				auto_notch_label("AN", false);
1333 				return false;
1334 			}
1335 		}
1336 	}
1337 	return progStatus.auto_notch;
1338 }
1339 
1340 static int comp_level[] = {11,34,58,81,104,128,151,174,197,221,244};
set_compression(int on,int val)1341 void RIG_IC7200::set_compression(int on, int val)
1342 {
1343 	cmd = pre_to;
1344 	cmd.append("\x16\x44");
1345 	if (on) cmd += '\x01';
1346 	else cmd += '\x00';
1347 	cmd.append(post);
1348 	waitFB("set Comp ON/OFF");
1349 	set_trace(2, "set_compression_on_off()", str2hex(cmd.c_str(), cmd.length()));
1350 
1351 	if (val < 0) return;
1352 	if (val > 10) return;
1353 
1354 	cmd.assign(pre_to).append("\x14\x0E");
1355 	cmd.append(to_bcd(comp_level[val], 3));
1356 	cmd.append( post );
1357 	waitFB("set comp");
1358 	set_trace(2, "set_compression_level()", str2hex(cmd.c_str(), cmd.length()));
1359 }
1360 
get_compression(int & on,int & val)1361 void RIG_IC7200::get_compression(int &on, int &val)
1362 {
1363 	std::string resp;
1364 
1365 	cmd.assign(pre_to).append("\x16\x44").append(post);
1366 
1367 	resp.assign(pre_fm).append("\x16\x44");
1368 
1369 	if (waitFOR(8, "get comp on/off")) {
1370 		get_trace(2, "get_comp_on_off()", str2hex(replystr.c_str(), replystr.length()));
1371 		size_t p = replystr.find(resp);
1372 		if (p != string::npos)
1373 			on = (replystr[p+6] == 0x01);
1374 	}
1375 
1376 	cmd.assign(pre_to).append("\x14\x0E").append(post);
1377 	resp.assign(pre_fm).append("\x14\x0E");
1378 
1379 	if (waitFOR(9, "get comp level")) {
1380 		get_trace(2, "get_comp_level()", str2hex(replystr.c_str(), replystr.length()));
1381 		size_t p = replystr.find(resp);
1382 		int level = 0;
1383 		if (p != string::npos) {
1384 			level = fm_bcd(replystr.substr(p+6), 3);
1385 			for (val = 0; val < 11; val++)
1386 				if (level <= comp_level[val]) break;
1387 		}
1388 	}
1389 }
1390 
set_vox_onoff()1391 void RIG_IC7200::set_vox_onoff()
1392 {
1393 	if (progStatus.vox_onoff) {
1394 		cmd = pre_to;
1395 		cmd.append("\x16\x46");
1396 		cmd += '\x01';
1397 		cmd.append(post);
1398 		waitFB("set Vox ON");
1399 	} else {
1400 		cmd = pre_to;
1401 		cmd.append("\x16\x46");
1402 		cmd += '\x00';
1403 		cmd.append(post);
1404 		waitFB("set Vox OFF");
1405 	}
1406 	set_trace(2, "set_vox_on_off()", str2hex(cmd.c_str(), cmd.length()));
1407 }
1408 
set_notch(bool on,int freq)1409 void RIG_IC7200::set_notch(bool on, int freq)
1410 {
1411 	int hexval;
1412 	switch (vfo->imode) {
1413 		default: case USB7200: case USBD7200: case RTTYR7200:
1414 			hexval = freq - 1500;
1415 			break;
1416 		case LSB7200: case LSBD7200: case RTTY7200:
1417 			hexval = 1500 - freq;
1418 			break;
1419 		case CW7200:
1420 			if (CW_sense)
1421 				hexval = freq - progStatus.cw_spot_tone;
1422 			else
1423 				hexval = progStatus.cw_spot_tone - freq;
1424 			break;
1425 		case CWR7200:
1426 			if (CW_sense)
1427 				hexval = progStatus.cw_spot_tone - freq;
1428 			else
1429 				hexval = freq - progStatus.cw_spot_tone;
1430 			break;
1431 	}
1432 
1433 	hexval /= 20;
1434 	hexval += 128;
1435 	if (hexval < 0) hexval = 0;
1436 	if (hexval > 255) hexval = 255;
1437 
1438 	cmd = pre_to;
1439 	cmd.append("\x16\x48");
1440 	cmd += on ? '\x01' : '\x00';
1441 	cmd.append(post);
1442 	waitFB("set notch");
1443 
1444 	cmd = pre_to;
1445 	cmd.append("\x14\x0D");
1446 	cmd.append(to_bcd(hexval,3));
1447 	cmd.append(post);
1448 	waitFB("set notch val");
1449 }
1450 
get_notch(int & val)1451 bool RIG_IC7200::get_notch(int &val)
1452 {
1453 	bool on = false;
1454 	val = 1500;
1455 
1456 	string cstr = "\x16\x48";
1457 	string resp = pre_fm;
1458 	resp.append(cstr);
1459 	cmd = pre_to;
1460 	cmd.append(cstr);
1461 	cmd.append( post );
1462 	if (waitFOR(8, "get notch")) {
1463 		size_t p = replystr.rfind(resp);
1464 		if (p != string::npos)
1465 			on = replystr[p + 6];
1466 		cmd = pre_to;
1467 		resp = pre_fm;
1468 		cstr = "\x14\x0D";
1469 		cmd.append(cstr);
1470 		resp.append(cstr);
1471 		cmd.append(post);
1472 		if (waitFOR(9, "notch val")) {
1473 			size_t p = replystr.rfind(resp);
1474 			if (p != string::npos) {
1475 				val = (int)ceil(fm_bcd(replystr.substr(p+6),3));
1476 				val -= 128;
1477 				val *= 20;
1478 				switch (vfo->imode) {
1479 					default: case USB7200: case USBD7200: case RTTYR7200:
1480 						val = 1500 + val;
1481 						break;
1482 					case LSB: case LSBD7200: case RTTY7200:
1483 						val = 1500 - val;
1484 						break;
1485 					case CW7200:
1486 						if (CW_sense)
1487 							val = progStatus.cw_spot_tone + val;
1488 						else
1489 							val = progStatus.cw_spot_tone - val;
1490 						break;
1491 					case CWR7200:
1492 						if (CW_sense)
1493 							val = progStatus.cw_spot_tone - val;
1494 						else
1495 							val = progStatus.cw_spot_tone + val;
1496 						break;
1497 				}
1498 			}
1499 		}
1500 	}
1501 	return on;
1502 }
1503 
get_notch_min_max_step(int & min,int & max,int & step)1504 void RIG_IC7200::get_notch_min_max_step(int &min, int &max, int &step)
1505 {
1506 	switch (vfo->imode) {
1507 		default:
1508 		case USB7200: case USBD7200: case RTTYR7200:
1509 		case LSB7200: case LSBD7200: case RTTY7200:
1510 			min = 0; max = 3000; step = 20; break;
1511 		case CW7200: case CWR7200:
1512 			min = progStatus.cw_spot_tone - 500;
1513 			max = progStatus.cw_spot_tone + 500;
1514 			step = 20;
1515 			break;
1516 	}
1517 }
1518 
1519 static int agcval = 0;
get_agc()1520 int  RIG_IC7200::get_agc()
1521 {
1522 	cmd = pre_to;
1523 	cmd.append("\x16\x12");
1524 	cmd.append(post);
1525 	if (waitFOR(8, "get AGC")) {
1526 		size_t p = replystr.find(pre_fm);
1527 		if (p == string::npos) return agcval;
1528 		return (agcval = replystr[p+6]); // 1 = off, 2 = FAST, 3 = SLOW
1529 	}
1530 	get_trace(2, "get_agc()", str2hex(replystr.c_str(), replystr.length()));
1531 	return agcval;
1532 }
1533 
incr_agc()1534 int RIG_IC7200::incr_agc()
1535 {
1536 	agcval++;
1537 	if (agcval == 3) agcval = 0;
1538 	cmd = pre_to;
1539 	cmd.append("\x16\x12");
1540 	cmd += agcval;
1541 	cmd.append(post);
1542 	waitFB("set AGC");
1543 	return agcval;
1544 }
1545 
1546 
1547 static const char *agcstrs[] = {"AGC", "FST", "SLO"};
agc_label()1548 const char *RIG_IC7200::agc_label()
1549 {
1550 	return agcstrs[agcval];
1551 }
1552 
agc_val()1553 int  RIG_IC7200::agc_val()
1554 {
1555 	return (agcval);
1556 }
1557 
set_if_shift(int val)1558 void RIG_IC7200::set_if_shift(int val)
1559 {
1560 	int shift;
1561 	sh_ = val;
1562 	if (val == 0) sh_on_ = false;
1563 	else sh_on_ = true;
1564 
1565 	shift = 128 + val * 128 / 50;
1566 	if (shift < 0) shift = 0;
1567 	if (shift > 255) shift = 255;
1568 
1569 	cmd = pre_to;
1570 	cmd.append("\x14\x07");
1571 	cmd.append(to_bcd(shift, 3));
1572 	cmd.append(post);
1573 	waitFB("set IF on/off");
1574 	set_trace(2, "set_if_shift_on_off()", str2hex(cmd.c_str(), cmd.length()));
1575 
1576 	cmd = pre_to;
1577 	cmd.append("\x14\x08");
1578 	cmd.append(to_bcd(shift, 3));
1579 	cmd.append(post);
1580 	waitFB("set IF val");
1581 	set_trace(2, "set_if_shift_val()", str2hex(cmd.c_str(), cmd.length()));
1582 }
1583 
get_if_shift(int & val)1584 bool RIG_IC7200::get_if_shift(int &val) {
1585 	val = sh_;
1586 	return sh_on_;
1587 }
1588 
get_if_min_max_step(int & min,int & max,int & step)1589 void RIG_IC7200::get_if_min_max_step(int &min, int &max, int &step)
1590 {
1591 	min = -50;
1592 	max = +50;
1593 	step = 1;
1594 }
1595 
set_pbt_inner(int val)1596 void RIG_IC7200::set_pbt_inner(int val)
1597 {
1598 	int shift = 128 + val * 128 / 50;
1599 	if (shift < 0) shift = 0;
1600 	if (shift > 255) shift = 255;
1601 
1602 	cmd = pre_to;
1603 	cmd.append("\x14\x07");
1604 	cmd.append(to_bcd(shift, 3));
1605 	cmd.append(post);
1606 	waitFB("set PBT inner");
1607 	set_trace(2, "set_PBT_inner()", str2hex(cmd.c_str(), cmd.length()));
1608 }
1609 
set_pbt_outer(int val)1610 void RIG_IC7200::set_pbt_outer(int val)
1611 {
1612 	int shift = 128 + val * 128 / 50;
1613 	if (shift < 0) shift = 0;
1614 	if (shift > 255) shift = 255;
1615 
1616 	cmd = pre_to;
1617 	cmd.append("\x14\x08");
1618 	cmd.append(to_bcd(shift, 3));
1619 	cmd.append(post);
1620 	waitFB("set PBT outer");
1621 	set_trace(2, "set_PBT_outer()", str2hex(cmd.c_str(), cmd.length()));
1622 }
1623 
get_pbt_inner()1624 int RIG_IC7200::get_pbt_inner()
1625 {
1626 	int val = 0;
1627 	string cstr = "\x14\x07";
1628 	string resp = pre_fm;
1629 	resp.append(cstr);
1630 	cmd = pre_to;
1631 	cmd.append(cstr);
1632 	cmd.append( post );
1633 	if (waitFOR(9, "get pbt inner")) {
1634 		size_t p = replystr.rfind(resp);
1635 		if (p != string::npos) {
1636 			val = num100(replystr.substr(p+6));
1637 			val -= 50;
1638 		}
1639 	}
1640 	get_trace(2, "get_pbt_inner()", str2hex(replystr.c_str(), replystr.length()));
1641 	return val;
1642 }
1643 
get_pbt_outer()1644 int RIG_IC7200::get_pbt_outer()
1645 {
1646 	int val = 0;
1647 	string cstr = "\x14\x08";
1648 	string resp = pre_fm;
1649 	resp.append(cstr);
1650 	cmd = pre_to;
1651 	cmd.append(cstr);
1652 	cmd.append( post );
1653 	if (waitFOR(9, "get pbt outer")) {
1654 		size_t p = replystr.rfind(resp);
1655 		if (p != string::npos) {
1656 			val = num100(replystr.substr(p+6));
1657 			val -= 50;
1658 		}
1659 	}
1660 	get_trace(2, "get_pbt_outer()", str2hex(replystr.c_str(), replystr.length()));
1661 	return val;
1662 }
1663 
1664 // CW methods
1665 
get_cw_wpm_min_max(int & min,int & max)1666 void RIG_IC7200::get_cw_wpm_min_max(int &min, int &max)
1667 {
1668 	min = 6; max = 48;
1669 }
1670 
set_cw_wpm()1671 void RIG_IC7200::set_cw_wpm()
1672 {
1673 	int iwpm = round((progStatus.cw_wpm - 6) * 255 / 42 + 0.5);
1674 	minmax(0, 255, iwpm);
1675 
1676 	cmd.assign(pre_to).append("\x14\x0C");
1677 	cmd.append(to_bcd(iwpm, 3));
1678 	cmd.append( post );
1679 	waitFB("SET cw wpm");
1680 	set_trace(2, "set_cw_wpm()", str2hex(cmd.c_str(), cmd.length()));
1681 }
1682 
set_break_in()1683 void RIG_IC7200::set_break_in()
1684 {
1685 // 16 47 00 break-in off
1686 // 16 47 01 break-in semi
1687 // 16 47 02 break-in full
1688 
1689 	cmd.assign(pre_to).append("\x16\x47");
1690 
1691 	switch (progStatus.break_in) {
1692 		case 2: cmd += '\x02'; break_in_label("FULL"); break;
1693 		case 1: cmd += '\x01'; break_in_label("SEMI");  break;
1694 		case 0:
1695 		default: cmd += '\x00'; break_in_label("BK-IN");
1696 	}
1697 	cmd.append(post);
1698 	waitFB("SET break-in");
1699 	set_trace(2, "set_break_in()", str2hex(cmd.c_str(), cmd.length()));
1700 }
1701 
get_cw_qsk_min_max_step(double & min,double & max,double & step)1702 void RIG_IC7200::get_cw_qsk_min_max_step(double &min, double &max, double &step)
1703 {
1704 	min = 2.0; max = 13.0; step = 0.1;
1705 }
1706 
set_cw_qsk()1707 void RIG_IC7200::set_cw_qsk()
1708 {
1709 	int qsk = round ((progStatus.cw_qsk - 2.0) * 255.0 / 11.0 + 0.5);
1710 	minmax(0, 255, qsk);
1711 
1712 	cmd.assign(pre_to).append("\x14\x0F");
1713 	cmd.append(to_bcd(qsk, 3));
1714 	cmd.append(post);
1715 	waitFB("Set cw qsk delay");
1716 	set_trace(2, "set_cw_qsk()", str2hex(cmd.c_str(), cmd.length()));
1717 }
1718 
get_cw_spot_tone_min_max_step(int & min,int & max,int & step)1719 void RIG_IC7200::get_cw_spot_tone_min_max_step(int &min, int &max, int &step)
1720 {
1721 	min = 300; max = 900; step = 5;
1722 }
1723 
set_cw_spot_tone()1724 void RIG_IC7200::set_cw_spot_tone()
1725 {
1726 	cmd.assign(pre_to).append("\x14\x09"); // values 0=300Hz 255=900Hz
1727 	int n = round((progStatus.cw_spot_tone - 300) * 255.0 / 600.0 + 0.5);
1728 	minmax(0, 255, n);
1729 
1730 	cmd.append(to_bcd(n, 3));
1731 	cmd.append( post );
1732 	waitFB("SET cw spot tone");
1733 	set_trace(2, "set_cw_spot_tone()", str2hex(cmd.c_str(), cmd.length()));
1734 }
1735 
set_cw_vol()1736 void RIG_IC7200::set_cw_vol()
1737 {
1738 	cmd.assign(pre_to);
1739 	cmd.append("\x1A\x03\x06");
1740 	cmd.append(to_bcd((int)(progStatus.cw_vol * 2.55), 3));
1741 	cmd.append( post );
1742 	waitFB("SET cw sidetone volume");
1743 	set_trace(2, "set_cw_vol()", str2hex(cmd.c_str(), cmd.length()));
1744 }
1745 
setVfoAdj(double v)1746 void RIG_IC7200::setVfoAdj(double v)
1747 {
1748 	vfo_ = v;
1749 	cmd.assign(pre_to);
1750 	cmd.append("\x1A\x03\x49");
1751 	cmd.append(bcd255(int(v)));
1752 	cmd.append(post);
1753 	waitFB("SET vfo adjust");
1754 	set_trace(2, "set_vfo_adj()", str2hex(cmd.c_str(), cmd.length()));
1755 }
1756 
getVfoAdj()1757 double RIG_IC7200::getVfoAdj()
1758 {
1759 	cmd.assign(pre_to);
1760 	cmd.append("\x1A\x03\x49");
1761 	cmd.append(post);
1762 
1763 	if (waitFOR(10, "get vfo adj")) {
1764 		size_t p = replystr.find(pre_fm);
1765 		if (p != string::npos) {
1766 			vfo_ = num100(replystr.substr(p+7));
1767 		}
1768 	}
1769 	get_trace(2, "get_vfo_adj()", str2hex(replystr.c_str(), replystr.length()));
1770 	return vfo_;
1771 }
1772 
get_band_selection(int v)1773 void RIG_IC7200::get_band_selection(int v)
1774 {
1775 	cmd.assign(pre_to);
1776 	cmd.append("\x1A\x01");
1777 	cmd += to_bcd_be( v, 2 );
1778 	cmd += '\x01';
1779 	cmd.append( post );
1780 
1781 	if (waitFOR(17, "get band")) {
1782 		std::string ans = replystr;
1783 		size_t p = ans.rfind(pre_fm);
1784 		if (p != string::npos) {
1785 			unsigned long int bandfreq = fm_bcd_be(ans.substr(p+8, 5), 10);
1786 			int bandmode = ans[p+13];
1787 			int bandfilter = ans[p+14];
1788 			int banddata = ans[p+15] & 0x10;
1789 			if ((bandmode == 0 || bandmode == 1) && banddata) bandmode += 7;
1790 			if (useB) {
1791 				set_vfoB(bandfreq);
1792 				set_modeB(bandmode);
1793 				set_FILT(bandfilter);
1794 			} else {
1795 				set_vfoA(bandfreq);
1796 				set_modeA(bandmode);
1797 				set_FILT(bandfilter);
1798 			}
1799 			get_trace(2, "get_band", str2hex(ans.substr(p).c_str(), ans.substr(p).length()));
1800 		}
1801 	}
1802 }
1803 
set_band_selection(int v)1804 void RIG_IC7200::set_band_selection(int v)
1805 {
1806 	unsigned long int freq = (useB ? B.freq : A.freq);
1807 	int mode = (useB ? B.imode : A.imode);
1808 	int fil = (useB ? B.filter : A.filter);
1809 
1810 	cmd.assign(pre_to);
1811 	cmd.append("\x1A\x01");
1812 	cmd += to_bcd_be( v, 2 );
1813 	cmd += '\x01';
1814 	cmd.append( to_bcd_be( freq, 10 ) );
1815 	cmd += mdval[mode];
1816 	cmd += fil;
1817 	if (mode >= 7)
1818 		cmd += '\x10';
1819 	else
1820 		cmd += '\x00';
1821 	cmd.append(post);
1822 	waitFB("set band");
1823 	set_trace(2, "SET", str2hex(cmd.c_str(), cmd.length()));
1824 
1825 	cmd.assign(pre_to);
1826 	cmd.append("\x1A\x01");
1827 	cmd += to_bcd_be( v, 2 );
1828 	cmd += '\x01';
1829 	cmd.append( post );
1830 
1831 	waitFOR(17, "get band stack");
1832 	get_trace(2, "get_band_stack", str2hex(replystr.c_str(), replystr.length()));
1833 }
1834 
1835