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 "ICF8101.h"
24 #include "support.h"
25 #include "trace.h"
26 
27 //=============================================================================
28 // IC-F8101
29 
30 const char ICF8101name_[] = "IC-F8101";
31 
32 #define NUM_MODES  11
33 
34 enum F81_modes {
35 	F81_LSB, F81_USB, F81_AM, F81_CW, F81_RTTY,
36 	F81_LSBD1, F81_USBD1,
37 	F81_LSBD2, F81_USBD2,
38 	F81_LSBD3, F81_USBD3 };
39 
40 const char *ICF8101modes_[NUM_MODES + 1] = {
41 "LSB", "USB", "AM", "CW", "RTTY", "LSB-D1", "USB-D1", "LSB-D2", "USB-D2", "LSB-D3", "USB-D3", NULL};
42 
43 const char mdval[NUM_MODES] = { 0X00, 0X01, 0X02, 0X03, 0X04, 0x18, 0x19, 0x20, 0x21, 0x22, 0x23};
44 
45 const char ICF8101_mode_type[NUM_MODES] = {
46 'L', 'U', 'U', 'L', 'L', 'L', 'U', 'L', 'U', 'L', 'U' };
47 
48 static int mode_bwA[NUM_MODES] = {-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1};
49 static int mode_bwB[NUM_MODES] = {-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1};
50 
51 static const char *ICF8101_CW_SSB_widths[] = {
52 "100",   "200",  "300",  "400",  "500",  "600",  "700",  "800",  "900", "1000",
53 "1100", "1200", "1300", "1400", "1500", "1600", "1700", "1800", "1900", "2000",
54 "2100", "2200", "2300", "2400", "2500", "2600", "2700", "2800", "2900", "3000",
55 NULL};
56 
57 static const char ICF8101_CW_SSB_width_vals[] = {
58 '\x01', '\x02', '\x03', '\x04', '\x05', '\x06', '\x07', '\x08', '\x09', '\x10',
59 '\x11', '\x12', '\x13', '\x14', '\x15', '\x16', '\x17', '\x18', '\x19', '\x20',
60 '\x21', '\x22', '\x23', '\x24', '\x25', '\x26', '\x27', '\x28', '\x29', '\x30',
61 };
62 #define NUM_CW_SSB_WIDTHS 30
63 
64 static const char *ICF8101_RTTY_widths[] = {
65   "NONE", NULL};
66 
67 static const char *ICF8101_AM_widths[] = {
68   "200",  "400",  "600",  "800", "1000", "1200", "1400", "1600", "1800", "2000",
69  "2200", "2400", "2600", "2800", "3000", "3200", "3400", "3600", "3800", "4000",
70  "4200", "4400", "4600", "4800", "5000", "5200", "5400", "5600", "5800", "5000",
71  "6200", "6400", "6600", "6800", "7000", "7200", "7400", "7600", "7800", "8000",
72  "8200", "8400", "8600", "8800", "9000", "9200", "9400", "9600", "9800", "10000",
73 NULL};
74 
75 static const char ICF8101_bw_vals_AM[] = {
76 '\x01', '\x02', '\x03', '\x04', '\x05', '\x06', '\x07', '\x08', '\x09', '\x10',
77 '\x11', '\x12', '\x13', '\x14', '\x15', '\x16', '\x17', '\x18', '\x19', '\x20',
78 '\x21', '\x22', '\x23', '\x24', '\x25', '\x26', '\x27', '\x28', '\x29', '\x30',
79 '\x31', '\x32', '\x33', '\x34', '\x35', '\x36', '\x37', '\x38', '\x39', '\x40',
80 '\x41', '\x42', '\x43', '\x44', '\x45', '\x46', '\x47', '\x48', '\x49', '\x50',
81 };
82 #define NUM_AM_WIDTHS 50
83 
84 //======================================================================
85 // ICF8101 unique commands
86 //======================================================================
87 
88 static GUI ICF8101_widgets[]= {
89 	{ (Fl_Widget *)btnVol,        2, 125,  50 },	//0
90 	{ (Fl_Widget *)sldrVOLUME,   54, 125, 156 },	//1
91 	{ (Fl_Widget *)btnAGC,      214, 125,  50 },	//2
92 	{ (Fl_Widget *)sldrPOWER,    54, 145, 156 },	//3
93 	{ (Fl_Widget *)sldrMICGAIN, 266, 145, 156 },	//4
94 	{ (Fl_Widget *)NULL, 0, 0, 0 }
95 };
96 /*
97 	{ (Fl_Widget *)sldrRFGAIN,   54, 145, 156 },	//3
98 	{ (Fl_Widget *)sldrSQUELCH,  54, 165, 156 },	//4
99 	{ (Fl_Widget *)btnNR,         2, 185,  50 },	//5
100 	{ (Fl_Widget *)sldrNR,       54, 185, 156 },	//6
101 	{ (Fl_Widget *)btnLOCK,     214, 105,  50 },	//7
102 	{ (Fl_Widget *)sldrINNER,   266, 105, 156 },	//8
103 	{ (Fl_Widget *)btnCLRPBT,   214, 125,  50 },	//9
104 	{ (Fl_Widget *)sldrOUTER,   266, 125, 156 },	//10
105 	{ (Fl_Widget *)btnNotch,    214, 145,  50 },	//11
106 	{ (Fl_Widget *)sldrNOTCH,   266, 145, 156 },	//12
107 };
108 */
109 
initialize()110 void RIG_ICF8101::initialize()
111 {
112 	ICF8101_widgets[0].W = btnVol;
113 	ICF8101_widgets[1].W = sldrVOLUME;
114 	ICF8101_widgets[2].W = btnAGC;
115 	ICF8101_widgets[3].W = sldrPOWER;
116 	ICF8101_widgets[4].W = sldrMICGAIN;
117 /*
118 	ICF8101_widgets[3].W = sldrRFGAIN;
119 	ICF8101_widgets[4].W = sldrSQUELCH;
120 	ICF8101_widgets[5].W = btnNR;
121 	ICF8101_widgets[6].W = sldrNR;
122 	ICF8101_widgets[7].W = btnLOCK;
123 	ICF8101_widgets[8].W = sldrINNER;
124 	ICF8101_widgets[9].W = btnCLRPBT;
125 	ICF8101_widgets[10].W = sldrOUTER;
126 	ICF8101_widgets[11].W = btnNotch;
127 	ICF8101_widgets[12].W = sldrNOTCH;
128 
129 	btn_icom_select_11->deactivate();
130 	btn_icom_select_12->deactivate();
131 	btn_icom_select_13->deactivate();
132 
133 	choice_rTONE->deactivate();
134 	choice_tTONE->deactivate();
135 */
136 }
137 
shutdown()138 void RIG_ICF8101::shutdown()
139 {
140 	cmd = pre_to;
141 	cmd += '\x08';
142 	cmd.append(post);
143 	set_trace(2, "set memory mode", str2hex(cmd.c_str(), cmd.length()));
144 	waitFB("set memory mode");
145 
146 	cmd = pre_to;
147 	cmd.append("\x0E\x01");
148 	cmd.append(post);
149 	set_trace(2, "set scan mode", str2hex(cmd.c_str(), cmd.length()));
150 	waitFB("set scan mode");
151 }
152 
RIG_ICF8101()153 RIG_ICF8101::RIG_ICF8101() {
154 	name_ = ICF8101name_;
155 	modes_ = ICF8101modes_;
156 	_mode_type = ICF8101_mode_type;
157 //	bandwidths_ = ICF8101_CW_SSB_widths;
158 //	bw_vals_ = ICF8101_bw_vals_SSB;
159 	widgets = ICF8101_widgets;
160 
161 	comm_baudrate = BR9600;
162 	stopbits = 1;
163 	comm_retries = 2;
164 	comm_wait = 5;
165 	comm_timeout = 50;
166 	comm_echo = true;
167 	comm_rtscts = false;
168 	comm_rtsplus = true;
169 	comm_dtrplus = true;
170 	comm_catptt = true;
171 	comm_rtsptt = false;
172 	comm_dtrptt = false;
173 
174 	def_freq = A.freq = 14070000;
175 	def_mode = A.imode = 1;
176 //	def_bw = A.iBW = 29;
177 
178 	B.freq = 7070000;
179 	B.imode = 1;
180 //	B.iBW = 29;
181 
182 	has_smeter = true;
183 
184 	has_mode_control = true;
185 	has_volume_control = true;
186 	has_rf_control = true;
187 	has_micgain_control = true;
188 	has_power_control = true;
189 
190 	has_ptt_control = true;
191 	has_tune_control = true;
192 	has_agc_control = true;
193 
194 	has_split_AB = true;
195 
196 	has_noise_control = true;
197 	has_nb_level = true;
198 	has_preamp_control = true;
199 
200 	has_compON = true;
201 	has_compression = true;
202 
203 /*
204 	has_extras = true;
205 	has_power_out = true;
206 	has_swr_control = true;
207 	has_alc_control = true;
208 	has_sql_control = true;
209 	has_attenuator_control = true;
210 	has_noise_reduction = true;
211 	has_noise_reduction_control = true;
212 	has_auto_notch = true;
213 	has_notch_control = true;
214 	has_pbt_controls = true;
215 	has_FILTER = true;
216 	has_vox_onoff = true;
217 	has_vfo_adj = true;
218 	has_a2b = true;
219 
220 	has_band_selection = true;
221 
222 	has_cw_wpm = true;
223 	has_cw_spot_tone = true;
224 	has_cw_qsk = true;
225 	has_cw_break_in = true;
226 */
227 
228 	defaultCIV = 0x8A;
229 	adjustCIV(defaultCIV);
230 
231 	precision = 10;
232 	ndigits = 8;
233 
234 };
235 
minmax(int min,int max,int & val)236 static inline void minmax(int min, int max, int &val)
237 {
238 	if (val > max) val = max;
239 	if (val < min) val = min;
240 }
241 
242 //======================================================================
243 
selectA()244 void RIG_ICF8101::selectA()
245 {
246 	cmd = pre_to;
247 	cmd += '\x07';
248 	cmd += '\x00';
249 	cmd.append(post);
250 	set_trace(2, "selectA()", str2hex(cmd.c_str(), cmd.length()));
251 	waitFB("select A");
252 	inuse = onA;
253 }
254 
selectB()255 void RIG_ICF8101::selectB()
256 {
257 	cmd = pre_to;
258 	cmd += '\x07';
259 	cmd += '\x01';
260 	cmd.append(post);
261 	set_trace(2, "selectB()", str2hex(cmd.c_str(), cmd.length()));
262 	waitFB("select B");
263 	inuse = onB;
264 }
265 
check()266 bool RIG_ICF8101::check ()
267 {
268 	string resp = pre_fm;
269 	resp += '\x03';
270 	cmd = pre_to;
271 	cmd += '\x03';
272 	cmd.append( post );
273 	bool ok = waitFOR(11, "check vfo");
274 	get_trace(2, "check()", str2hex(replystr.c_str(), replystr.length()));
275 	return ok;
276 }
277 
get_vfoA()278 unsigned long int RIG_ICF8101::get_vfoA ()
279 {
280 	if (useB) return A.freq;
281 	string resp = pre_fm;
282 	resp += '\x03';
283 	cmd = pre_to;
284 	cmd += '\x03';
285 	cmd.append( post );
286 	if (waitFOR(11, "get vfo A")) {
287 		size_t p = replystr.rfind(resp);
288 		if (p != string::npos)
289 			A.freq = fm_bcd_be(replystr.substr(p+5), 10);
290 	}
291 	get_trace(2, "get_vfoA()", str2hex(replystr.c_str(), replystr.length()));
292 	return A.freq;
293 }
294 
set_vfoA(unsigned long int freq)295 void RIG_ICF8101::set_vfoA (unsigned long int freq)
296 {
297 	A.freq = freq;
298 	cmd = pre_to;
299 	cmd += '\x1A';
300 	cmd += '\x35';
301 	cmd.append( to_bcd_be( freq, 10 ) );
302 	cmd.append( post );
303 	set_trace(2, "set_vfoA()", str2hex(cmd.c_str(), cmd.length()));
304 	waitFB("set vfo A");
305 }
306 
get_vfoB()307 unsigned long int RIG_ICF8101::get_vfoB ()
308 {
309 	if (!useB) return B.freq;
310 	string resp = pre_fm;
311 	resp += '\x03';
312 	cmd = pre_to;
313 	cmd += '\x03';
314 	cmd.append( post );
315 	if (waitFOR(11, "get vfo B")) {
316 		size_t p = replystr.rfind(resp);
317 		if (p != string::npos)
318 			B.freq = fm_bcd_be(replystr.substr(p+5), 10);
319 	}
320 	get_trace(2, "get_vfoB()", str2hex(replystr.c_str(), replystr.length()));
321 	return B.freq;
322 }
323 
set_vfoB(unsigned long int freq)324 void RIG_ICF8101::set_vfoB (unsigned long int freq)
325 {
326 	B.freq = freq;
327 	cmd = pre_to;
328 	cmd += '\x1A';
329 	cmd += '\x35';
330 	cmd.append( to_bcd_be( freq, 10 ) );
331 	cmd.append( post );
332 	set_trace(2, "set_vfoB()", str2hex(cmd.c_str(), cmd.length()));
333 	waitFB("set vfo B");
334 }
335 
336 // Tranceiver PTT on/off
337 // ON  1A 37 00 02
338 // OFF 1A 37 00 00
set_PTT_control(int val)339 void RIG_ICF8101::set_PTT_control(int val)
340 {
341 	cmd = pre_to;
342 	cmd.append("\x1A\x37");
343 	cmd += '\x00';
344 	cmd += (val ? '\x02' : '\x00');
345 	cmd.append( post );
346 	if (val) {
347 		waitFB("set ptt ON");
348 		set_trace(2, "set_PTT(ON)", str2hex(cmd.c_str(), cmd.length()));
349 	} else {
350 		waitFB("set ptt OFF");
351 		set_trace(2, "set_PTT(OFF)", str2hex(cmd.c_str(), cmd.length()));
352 	}
353 	ptt_ = val;
354 }
355 
get_PTT()356 int RIG_ICF8101::get_PTT()
357 {
358 	cmd = pre_to;
359 	cmd.append("\x1A\x37");
360 	string resp = pre_fm;
361 	resp.append("\x1A\x37");
362 	cmd.append(post);
363 	if (waitFOR(9, "get PTT")) {
364 		size_t p = replystr.rfind(resp);
365 		if (p != string::npos)
366 			ptt_ = (replystr[p + 7] == 0x02);
367 	}
368 	return ptt_;
369 }
370 
371 // Volume control val 0 ... 100
372 struct VOL_TBL {
373 	string catval;
374 	int vol;
375 } vol_tbl[] = {
376 {"\x00\x00", 0},
377 {"\x01\x39", 1},  {"\x01\x43", 2},  {"\x01\x47", 3},  {"\x01\x51", 4},  {"\x01\x55", 5},
378 {"\x01\x59", 6},  {"\x01\x63", 7},  {"\x01\x67", 8},  {"\x01\x71", 9},  {"\x01\x75", 10},
379 {"\x01\x77", 11}, {"\x01\x79", 12}, {"\x01\x81", 13}, {"\x01\x83", 14}, {"\x01\x85", 15},
380 {"\x01\x87", 16}, {"\x01\x89", 17}, {"\x01\x91", 18}, {"\x01\x93", 19}, {"\x01\x95", 20},
381 {"\x01\x97", 21}, {"\x01\x99", 22}, {"\x02\x01", 23}, {"\x02\x03", 24}, {"\x02\x05", 25},
382 {"\x02\x07", 26}, {"\x02\x09", 27}, {"\x02\x11", 28}, {"\x02\x13", 29}, {"\x02\x15", 30},
383 {"\x02\x17", 31}, {"\x02\x19", 32}, {"\x02\x21", 33}, {"\x02\x23", 34}, {"\x02\x25", 35},
384 {"\x02\x27", 36}, {"\x02\x29", 37}, {"\x02\x31", 38}, {"\x02\x33", 39}, {"\x02\x35", 40},
385 {"\x02\x37", 41}, {"\x02\x39", 42}, {"\x02\x41", 43}, {"\x02\x43", 44}, {"\x02\x45", 45},
386 {"\x02\x47", 46}, {"\x02\x49", 47}, {"\x02\x51", 48}, {"\x02\x53", 49}, {"\x02\x55", 50} };
387 
set_volume_control(int val)388 void RIG_ICF8101::set_volume_control(int val)
389 {
390 	if (val < 0) val = 0;
391 	if (val > 50) val = 50;
392 	cmd = pre_to;
393 	cmd.append("\x14\x01");
394 	if (val == 0) {
395 		cmd += '\x00'; cmd += '\x00';
396 	} else
397 		cmd.append(vol_tbl[val].catval);
398 	cmd.append( post );
399 	waitFB("set vol");
400 	set_trace(2, "set_volume_control()", str2hex(cmd.c_str(), cmd.length()));
401 }
402 
get_volume_control()403 int RIG_ICF8101::get_volume_control()
404 {
405 	int val = progStatus.volume;
406 	string cstr = "\x14\x01";
407 	string resp = pre_fm;
408 	resp.append(cstr);
409 	cmd = pre_to;
410 	cmd.append(cstr);
411 	cmd.append( post );
412 	if (waitFOR(9, "get vol")) {
413 		size_t p = replystr.rfind(resp);
414 		if (p != string::npos) {
415 			resp = resp.substr(6, 2);
416 			if (resp[0] == '\x00' && resp[1] == '\x00') {
417 				val = 0;
418 			} else {
419 				for (int i = 1; i <= 50; i++) {
420 					if (resp == vol_tbl[i].catval) {
421 						val = vol_tbl[i].vol;
422 						break;
423 					}
424 				}
425 			}
426 		}
427 	}
428 	get_trace(2, "get_volume_control()", str2hex(replystr.c_str(), replystr.length()));
429 	return val;
430 }
431 
get_vol_min_max_step(int & min,int & max,int & step)432 void RIG_ICF8101::get_vol_min_max_step(int &min, int &max, int &step)
433 {
434 	min = 0; max = 50; step = 1;
435 }
436 
437 struct smtr_map {float meter; int sig[3];}; // sig[PRE/OFF/ATT]
438 
439 static smtr_map sm_map[] = {
440 {  0.0, { 56,  12,   0}}, // S0
441 { 11.0, { 60,  25,   0}}, // S2
442 { 17.0, { 62,  37,   0}}, // S3
443 { 22.0, { 72,  49,  15}}, // S4
444 { 28.0, { 83,  61,  25}}, // S5
445 { 33.0, { 95,  73,  40}}, // S6
446 { 39.0, {108,  85,  55}}, // S7
447 { 45.0, {115,  97,  71}}, // S8
448 { 50.0, {166, 110,  85}}, // S9
449 { 58.0, {231, 167, 107}}, // +10
450 { 67.0, {273, 223, 141}}, // +20
451 { 74.0, {315, 268, 212}}, // +30
452 { 84.0, {356, 310, 256}}, // +40
453 {100.0, {400, 356, 300}}  // +60
454 };
455 
get_smeter()456 int RIG_ICF8101::get_smeter()
457 {
458 	string cstr = "\x1A\x08";
459 	string resp = pre_fm;
460 	resp.append(cstr);
461 	cmd = pre_to;
462 	cmd.append(cstr);
463 	cmd.append( post );
464 	int mtr = 0;
465 	int n = preamp_level;
466 	if (n == 0) n = 1;
467 	else if (n == 1) n = 0;
468 	if (waitFOR(9, "get smeter")) {
469 		size_t p = replystr.rfind(resp);
470 		if (p != string::npos) {
471 			int val = fm_bcd(replystr.substr(p+6), 3);
472 			if (val <= sm_map[0].sig[n]) mtr = 0;
473 			else {
474 				int i = 0;
475 				int i_max = sizeof(sm_map) / sizeof(smtr_map) - 1;
476 				if (val > sm_map[i_max].sig[n]) val = sm_map[i_max].sig[n];
477 				for (i = 0; i < i_max; i++)
478 					if (val >= sm_map[i].sig[n] && val < sm_map[i+1].sig[n])
479 						break;
480 				mtr = (int)ceil(sm_map[i].meter +
481 					(sm_map[i+1].meter - sm_map[i].meter)*(val - sm_map[i].sig[n]) /
482 					(sm_map[i+1].sig[n] - sm_map[i].sig[n]) );
483 			}
484 		}
485 	}
486 	return mtr;
487 }
488 
489 struct mtr_map {int mtr; float pwr;};
490 
491 static mtr_map pwr_map[] = {
492 {0, 0.0},
493 {51, 10.0},
494 {102, 20.0},
495 {153, 30.0},
496 {204, 40.0},
497 {255, 50.0}
498 };
499 
get_power_out(void)500 int RIG_ICF8101::get_power_out(void)
501 {
502 	string cstr = "\x15\x11";
503 	string resp = pre_fm;
504 	resp.append(cstr);
505 	cmd = pre_to;
506 	cmd.append(cstr);
507 	cmd.append( post );
508 	int mtr = 0;
509 	if (waitFOR(9, "get power out")) {
510 		size_t p = replystr.rfind(resp);
511 		if (p != string::npos) {
512 			int val = fm_bcd(replystr.substr(p+6), 3);
513 			size_t i = 0;
514 			if (val < 0) val = 0;
515 			if (val > 255) val = 255;
516 			for (i = 0; i < sizeof(pwr_map) / sizeof(mtr_map) - 1; i++)
517 				if (val >= pwr_map[i].mtr && val < pwr_map[i+1].mtr)
518 					break;
519 			mtr = (int)ceil(pwr_map[i].pwr +
520 				(pwr_map[i+1].pwr - pwr_map[i].pwr)*(val - pwr_map[i].mtr)/(pwr_map[i+1].mtr - pwr_map[i].mtr));
521 		}
522 	}
523 	return mtr;
524 }
525 
526 static int agcval = 0;
get_agc()527 int  RIG_ICF8101::get_agc()
528 {
529 	cmd = pre_to;
530 	cmd.append("\x1A\x05\x03\x06");
531 	cmd.append(post);
532 	if (waitFOR(11, "get AGC")) {
533 		size_t p = replystr.find(pre_fm);
534 		if (p == string::npos) return agcval;
535 		return (agcval = replystr[p+9]); // 0 = off, 1 = FAST, 2 = SLOW, 3 = AUTO
536 	}
537 	return agcval;
538 }
539 
incr_agc()540 int RIG_ICF8101::incr_agc()
541 {
542 	agcval++;
543 	if (agcval == 4) agcval = 0;
544 	cmd = pre_to;
545 	cmd.append("\x1A\x05\x03\x06");
546 	cmd += '\x00';
547 	cmd += agcval;
548 	cmd.append(post);
549 	waitFB("set AGC");
550 	return agcval;
551 }
552 
553 
554 static const char *agcstrs[] = {"AGC", "FST", "SLO", "AUT"};
agc_label()555 const char *RIG_ICF8101::agc_label()
556 {
557 	return agcstrs[agcval];
558 }
559 
agc_val()560 int  RIG_ICF8101::agc_val()
561 {
562 	return (agcval);
563 }
564 
565 
566 // FE FE 8A E0 1A 05 03 07 00 00/01/02 FD (00=LOW, 01=MID, 02=HIGH)
567 
set_power_control(double val)568 void RIG_ICF8101::set_power_control(double val)
569 {
570 	cmd = pre_to;
571 	cmd.append("\x1A\x05\x03\x07");
572 	cmd += '\x00';
573 	cmd += val;
574 	cmd.append( post );
575 	waitFB("set power");
576 	set_trace(2, "set_power()", str2hex(cmd.c_str(), cmd.length()));
577 }
578 
579 // reply FE FE E0 8A 1A 05 03 07 00 XX FD
580 
get_power_control()581 int RIG_ICF8101::get_power_control()
582 {
583 	string cstr = "\x1A\x05\x03\x07";
584 	string resp = pre_fm;
585 	cmd = pre_to;
586 	cmd.append(cstr).append(post);
587 	resp.append(cstr);
588 	int val = progStatus.power_level;
589 	if (waitFOR(11, "get power")) {
590 		size_t p = replystr.rfind(resp);
591 		if (p != string::npos)
592 			val = replystr[p+9];
593 	}
594 	return (progStatus.power_level = val);
595 }
596 
get_mic_gain()597 int RIG_ICF8101::get_mic_gain()
598 {
599 	string cstr = "\x1A\x05\x03\x11";
600 	string resp = pre_fm;
601 	resp.append(cstr);
602 	cmd = pre_to;
603 	cmd.append(cstr);
604 	cmd.append(post);
605 	int val = progStatus.mic_gain;
606 	if (waitFOR(11, "get mic")) {
607 		size_t p = replystr.rfind(resp);
608 		if (p != string::npos) {
609 			val = replystr[p+9];
610 			if (val == '\x0A') val = 10;
611 		}
612 	}
613 	return val;
614 }
615 
set_mic_gain(int val)616 void RIG_ICF8101::set_mic_gain(int val)
617 {
618 	cmd = pre_to;
619 	cmd.append("\x1A\x05\x03\x11");
620 	cmd += '\x00';
621 	if (val < 10) cmd += val;
622 	else cmd += '\x10';
623 	cmd.append(post);
624 	waitFB("set mic");
625 	set_trace(2, "set_mic_gain()", str2hex(cmd.c_str(), cmd.length()));
626 }
627 
get_modeA()628 int RIG_ICF8101::get_modeA()
629 {
630 	int md = A.imode;
631 	int val = 0;
632 
633 	string resp = pre_fm;
634 	resp.append("\x1A\x34");
635 	cmd = pre_to;
636 	cmd.append("\x1A\x34");
637 	cmd.append(post);
638 
639 	if (waitFOR(9, "get mode A")) {
640 		size_t p = replystr.rfind(resp);
641 		if (p != string::npos) {
642 			val = replystr[p + 7];
643 			for (int i = 0; i < NUM_MODES; i++)
644 				if (val == mdval[i]) {
645 					md = i;
646 					break;
647 				}
648 		}
649 	}
650 	get_trace(2, "get_modeA()", str2hex(replystr.c_str(), replystr.length()));
651 	return (A.imode = md);
652 }
653 
set_modeA(int val)654 void RIG_ICF8101::set_modeA(int val)
655 {
656 	A.imode = val;
657 
658 	cmd = pre_to;
659 	cmd.append("\x1A\x36");
660 	cmd += '\x00';
661 	cmd += mdval[A.imode];
662 	cmd.append( post );
663 	waitFB("set mode A");
664 	set_trace(2, "set_modeA()", str2hex(cmd.c_str(), cmd.length()));
665 }
666 
get_modeB()667 int RIG_ICF8101::get_modeB()
668 {
669 	int md = B.imode;
670 	int val = 0;
671 
672 	string resp = pre_fm;
673 	resp.append("\x1A\x34");
674 	cmd = pre_to;
675 	cmd.append("\x1A\x34");
676 	cmd.append(post);
677 
678 	if (waitFOR(9, "get mode B")) {
679 		size_t p = replystr.rfind(resp);
680 		if (p != string::npos) {
681 			val = replystr[p + 7];
682 			for (int i = 0; i < NUM_MODES; i++)
683 				if (val == mdval[i]) {
684 					md = i;
685 					break;
686 				}
687 		}
688 	}
689 	get_trace(2, "get_modeB()", str2hex(replystr.c_str(), replystr.length()));
690 	return (B.imode = md);
691 }
692 
set_modeB(int val)693 void RIG_ICF8101::set_modeB(int val)
694 {
695 	B.imode = val;
696 
697 	cmd = pre_to;
698 	cmd.append("\x1A\x36");
699 	cmd += '\x00';
700 	cmd += mdval[B.imode];
701 	cmd.append( post );
702 	waitFB("set mode B");
703 	set_trace(2, "set_modeB()", str2hex(cmd.c_str(), cmd.length()));
704 }
705 
get_modetype(int n)706 int RIG_ICF8101::get_modetype(int n)
707 {
708 	return _mode_type[n];
709 }
710 
can_split()711 bool RIG_ICF8101::can_split()
712 {
713 	return true;
714 }
715 
716 // 1A 05 03 17 00 [01|00]
set_split(bool val)717 void RIG_ICF8101::set_split(bool val)
718 {
719 	split = val;
720 	cmd = pre_to;
721 	cmd.append("\x1A\x05\x03\x17");
722 	cmd += '\x00';
723 	cmd += val ? 0x01 : 0x00;
724 	cmd.append(post);
725 	waitFB(val ? "set split ON" : "set split OFF");
726 	set_trace(2, (val ? "set split ON" : "set split OFF"), str2hex(cmd.c_str(), cmd.length()));
727 }
728 
729 // F8101 does not respond to get split CAT command
get_split()730 int RIG_ICF8101::get_split()
731 {
732 	string cstr = "\x1A\x05\x03\x17";
733 	cstr += '\x00';
734 	string resp = pre_fm;
735 	resp.append(cstr);
736 
737 	cmd = pre_to;
738 	cmd.append(cstr);
739 	cmd.append( post );
740 
741 	int mtr= -1;
742 	if (waitFOR(11, "get split")) {
743 		size_t p = replystr.rfind(resp);
744 		if (p != string::npos) {
745 			mtr = replystr[p+9];
746 			if (mtr == 0x01) split = 1;
747 		}
748 	}
749 	get_trace(2, "get_split()", str2hex(replystr.c_str(), replystr.length()));
750 	return split;
751 }
752 
set_noise(bool val)753 void RIG_ICF8101::set_noise(bool val)
754 {
755 	cmd = pre_to;
756 	cmd.append("\x1A\x05\x03\x01");
757 	cmd += '\x00';
758 	cmd += val ? '\x01' : '\x00';
759 	cmd.append(post);
760 	waitFB("set noise blanker");
761 	set_trace(2, "set_noise_blanker() ", str2hex(replystr.c_str(), replystr.length()));
762 }
763 
get_noise()764 int RIG_ICF8101::get_noise()
765 {
766 	int val = progStatus.noise;
767 	string cstr = "\x1A\x05\x03\x01";
768 	string resp = pre_fm;
769 	resp.append(cstr);
770 	cmd = pre_to;
771 	cmd.append(cstr);
772 	cmd.append(post);
773 	if (waitFOR(11, "get noise blanker")) {
774 		size_t p = replystr.rfind(resp);
775 		if (p != string::npos) {
776 			val = replystr[p+9];
777 		}
778 	}
779 	get_trace(2, "get_noise_blanker()", str2hex(replystr.c_str(), replystr.length()));
780 	return val;
781 }
782 
set_nb_level(int val)783 void RIG_ICF8101::set_nb_level(int val)
784 {
785 	cmd = pre_to;
786 	cmd.append("\x1A\x05\x03\x02");
787 	cmd += '\x00';
788 	cmd += bcdval[val];
789 	cmd.append(post);
790 	waitFB("set NB level");
791 	set_trace(2, "set_nb_level() ", str2hex(replystr.c_str(), replystr.length()));
792 }
793 
get_nb_level()794 int  RIG_ICF8101::get_nb_level()
795 {
796 	int val = progStatus.nb_level;
797 	string cstr = "\x1A\x05\x03\x02";
798 	string resp = pre_fm;
799 	resp.append(cstr);
800 	cmd = pre_to;
801 	cmd.append(cstr);
802 	cmd.append(post);
803 	if (waitFOR(11, "get NB level")) {
804 		size_t p = replystr.rfind(resp);
805 		if (p != string::npos) {
806 			for (int i = 0; i < 16; i++) {
807 				if (replystr[p+9] == bcdval[i]) {
808 					val = i;
809 					break;
810 				}
811 			}
812 		}
813 	}
814 	progStatus.nb_level = val;
815 	get_trace(2, "get_nb_level()", str2hex(replystr.c_str(), replystr.length()));
816 	return val;
817 }
818 
next_preamp()819 int RIG_ICF8101::next_preamp()
820 {
821 	preamp_level++;
822 	if (preamp_level == 3) preamp_level = 0;
823 	return preamp_level;
824 }
825 
set_preamp(int val)826 void RIG_ICF8101::set_preamp(int val)
827 {
828 	preamp_level = val;
829 	cmd = pre_to;
830 	cmd.append("\x1A\x05\x03\x05");
831 	cmd += '\x00';
832 	switch (val) {
833 		case 0:
834 			preamp_label("OFF", false);
835 			cmd += '\x01';
836 			break;
837 		case 1:
838 			preamp_label("PRE", true);
839 			cmd += '\x00';
840 			break;
841 		case 2:
842 			preamp_label("ATT", true);
843 			cmd += '\x02';
844 	}
845 	cmd.append( post );
846 	waitFB("set Pre/Att");
847 	set_trace(2, "set_preamp_att() ", str2hex(replystr.c_str(), replystr.length()));
848 }
849 
get_preamp()850 int RIG_ICF8101::get_preamp()
851 {
852 	string cstr = "\x1A\x05\x03\x05";
853 	string resp = pre_fm;
854 	resp.append(cstr);
855 	cmd = pre_to;
856 	cmd.append(cstr);
857 	cmd.append( post );
858 	if (waitFOR(11, "get Pre")) {
859 		size_t p = replystr.rfind(resp);
860 		if (p != string::npos) {
861 			switch (replystr[p+9]) {
862 			case 0:
863 				preamp_label("PRE", false);
864 				preamp_level = 1;
865 				break;
866 			case 1:
867 				preamp_label("OFF", true);
868 				preamp_level = 0;
869 				break;
870 			case 2:
871 				preamp_label("ATT", true);
872 				preamp_level = 2;
873 			}
874 		}
875 	}
876 	get_trace(2, "get_preamp_attenuator()", str2hex(replystr.c_str(), replystr.length()));
877 	return preamp_level;
878 }
879 
set_compression(int on,int val)880 void RIG_ICF8101::set_compression(int on, int val)
881 {
882 	std::string onoff = "\x1A\x05\x03\x09";
883 	std::string level = "\x1A\x05\x03\x10";
884 	cmd = pre_to;
885 	cmd.append(onoff);
886 	cmd += '\x00';
887 	if (on) cmd += '\x01';
888 	else cmd += '\x00';
889 	cmd.append(post);
890 	waitFB("set Comp ON/OFF");
891 	set_trace(2, "set_speech_proc() ", str2hex(replystr.c_str(), replystr.length()));
892 
893 	if (val < 0) val = 0;
894 	if (val > 10) val = 10;
895 
896 	cmd.assign(pre_to).append(level);
897 	cmd += '\x00';
898 	cmd += bcdval[val];
899 	cmd.append(post);
900 	waitFB("set comp");
901 	set_trace(2, "set_speech_proc_level() ", str2hex(replystr.c_str(), replystr.length()));
902 }
903 
get_compression(int & on,int & val)904 void RIG_ICF8101::get_compression(int &on, int &val)
905 {
906 	std::string onoff = "\x1A\x05\x03\x09";
907 	std::string level = "\x1A\x05\x03\x10";
908 	std::string resp = pre_fm;
909 	resp.append(onoff);
910 	cmd.assign(pre_to).append(onoff);
911 	cmd.append(post);
912 	if (waitFOR(11, "get comp on/off")) {
913 		size_t p = replystr.find(resp);
914 		if (p != string::npos)
915 			on = (replystr[p+9] == 0x01);
916 	}
917 	get_trace(2, "get_speech_comp_on_off()", str2hex(replystr.c_str(), replystr.length()));
918 
919 	cmd.assign(pre_to).append(level).append(post);
920 	resp.assign(pre_fm).append(level);
921 
922 	if (waitFOR(11, "get compression level")) {
923 		size_t p = replystr.find(resp);
924 		if (p != string::npos) {
925 			for (int i = 0; i < 11; i++) {
926 				if (replystr[p+9] == bcdval[i]) {
927 					val = i;
928 					break;
929 				}
930 			}
931 			get_trace(2, "get_comp_level()", str2hex(replystr.c_str(), replystr.length()));
932 		}
933 	}
934 }
935 
936 // LSB:
937 //  offset: 1A 05 07 01 [00 00]...[15 00]
938 //  width:  1A 05 07 02 [00 01]...[00 30], 100 TO 3000 Hz in 100 Hz steps
939 // USB:
940 //  offset: 1A 05 08 01 [00 00]...[15 00]
941 //  width:  1A 05 08 02 [00 01]...[00 30], 100 TO 3000 Hz in 100 Hz steps
942 // CW:
943 //  offset: 1A 05 09 01 [00 00]...[08 00]
944 //  width:  1A 05 09 02 [00 01]...[00 30], 100 TO 3000 Hz in 100 Hz steps
945 // AM:
946 //  offset: 1A 05 10 01 [00 00]...[00 00]
947 //  width:  1A 05 10 02 [00 01]...[00 50], 200 TO 10000 Hz in 200 Hz steps
948 // RTTY:
949 //  offset: 1A 05 11 01 [00 00] = 1200.0 Hz (mark frequency)
950 //                      [00 01] = 1275.0 Hz
951 //                      [00 02] = 1487.5 Hz
952 //                      [00 03] = 1615.0 Hz
953 //                      [00 04] = 1700.0 Hz
954 //                      [00 05] = 2100.0 Hz
955 //                      [00 05] = 2125.0 Hz
956 //  shift:  1A 05 11 02 [00 00] = 170 Hz
957 //                      [00 01] = 200 Hz
958 //                      [00 01] = 425 Hz
959 //                      [00 01] = 850 Hz
960 //  polarity: 1A 05 11 02 [00 00] = NORMAL
961 //                        [00 01] = REVERSE
962 // LSBD1
963 //  offset: 1A 05 12 01 [00 00] = 1500 Hz
964 //                      [00 01] = 1650 Hz
965 //                      [00 02] = 1800 Hz
966 //  width:  1A 05 12 02 [00 01]...[00 30], 100 TO 3000 Hz in 100 Hz steps
967 // USBD1
968 //  offset: 1A 05 13 01 [00 00] = 1500 Hz
969 //                      [00 01] = 1650 Hz
970 //                      [00 02] = 1800 Hz
971 //  width:  1A 05 13 02 [00 01]...[00 30], 100 TO 3000 Hz in 100 Hz steps
972 // LSBD2
973 //  offset: 1A 05 14 01 [00 00] = 1500 Hz
974 //                      [00 01] = 1650 Hz
975 //                      [00 02] = 1800 Hz
976 //  width:  1A 05 14 02 [00 01]...[00 30], 100 TO 3000 Hz in 100 Hz steps
977 // USBD2
978 //  offset: 1A 05 15 01 [00 00] = 1500 Hz
979 //                      [00 01] = 1650 Hz
980 //                      [00 02] = 1800 Hz
981 //  width:  1A 05 15 02 [00 01]...[00 30], 100 TO 3000 Hz in 100 Hz steps
982 // LSBD3
983 //  offset: 1A 05 16 01 [00 00] = 1500 Hz
984 //                      [00 01] = 1650 Hz
985 //                      [00 02] = 1800 Hz
986 //  width:  1A 05 16 02 [00 01]...[00 30], 100 TO 3000 Hz in 100 Hz steps
987 // USBD3
988 //  offset: 1A 05 17 01 [00 00] = 1500 Hz
989 //                      [00 01] = 1650 Hz
990 //                      [00 02] = 1800 Hz
991 //  width:  1A 05 17 02 [00 01]...[00 30], 100 TO 3000 Hz in 100 Hz steps
992 
get_BANDWIDTHS()993 std::string RIG_ICF8101::get_BANDWIDTHS()
994 {
995 	stringstream s;
996 	for (int i = 0; i < NUM_MODES; i++)
997 		s << mode_bwA[i] << " ";
998 	for (int i = 0; i < NUM_MODES; i++)
999 		s << mode_bwB[i] << " ";
1000 	return s.str();
1001 }
1002 
set_BANDWIDTHS(std::string s)1003 void RIG_ICF8101::set_BANDWIDTHS(std::string s)
1004 {
1005 	stringstream strm;
1006 	strm << s;
1007 	for (int i = 0; i < NUM_MODES; i++)
1008 		strm >> mode_bwA[i];
1009 	for (int i = 0; i < NUM_MODES; i++)
1010 		strm >> mode_bwB[i];
1011 }
1012 
adjust_bandwidth(int m)1013 int RIG_ICF8101::adjust_bandwidth(int m)
1014 {
1015 	int iBW;
1016 	switch (m) {
1017 		case F81_AM:
1018 			bandwidths_ = ICF8101_AM_widths;
1019 			iBW = 29;
1020 			break;
1021 		case F81_CW:
1022 			bandwidths_ = ICF8101_CW_SSB_widths;
1023 			iBW = 9;
1024 			break;
1025 		case F81_RTTY:
1026 			bandwidths_ = ICF8101_RTTY_widths;
1027 			iBW = 0;
1028 			break;
1029 		case F81_LSB: case F81_USB:
1030 		case F81_LSBD1: case F81_USBD1:
1031 		case F81_LSBD2: case F81_USBD2:
1032 		case F81_LSBD3: case F81_USBD3:
1033 		default:
1034 			bandwidths_ = ICF8101_CW_SSB_widths;
1035 			iBW = 29;
1036 	}
1037 	return iBW;
1038 }
1039 
def_bandwidth(int m)1040 int RIG_ICF8101::def_bandwidth(int m)
1041 {
1042 	int bw = adjust_bandwidth(m);
1043 	if (useB) {
1044 		if (mode_bwB[m] == -1)
1045 			mode_bwB[m] = bw;
1046 		return mode_bwB[m];
1047 	}
1048 	if (mode_bwA[m] == -1)
1049 		mode_bwA[m] = bw;
1050 	return mode_bwA[m];
1051 }
1052 
bwtable(int m)1053 const char ** RIG_ICF8101::bwtable(int m)
1054 {
1055 	switch (m) {
1056 		case F81_AM:
1057 			return ICF8101_AM_widths;
1058 			break;
1059 		case F81_RTTY:
1060 			return ICF8101_RTTY_widths;
1061 			break;
1062 		case F81_CW:
1063 		case F81_LSB: case F81_USB:
1064 		case F81_LSBD1: case F81_USBD1:
1065 		case F81_LSBD2: case F81_USBD2:
1066 		case F81_LSBD3: case F81_USBD3:
1067 		default:
1068 			return ICF8101_CW_SSB_widths;
1069 	}
1070 	return ICF8101_CW_SSB_widths;
1071 }
1072 
set_BW(int m)1073 void RIG_ICF8101::set_BW(int m)
1074 {
1075 	cmd = pre_to;
1076 	switch (m) {
1077 		case F81_AM:
1078 			cmd.append("\x1A\x05\x10\x02");
1079 			cmd += '\x00';
1080 			cmd += ICF8101_bw_vals_AM[m];
1081 			break;
1082 		case F81_RTTY:
1083 			return;
1084 			break;
1085 		case F81_CW:
1086 			cmd.append("\x1A\x05\x09\x02");
1087 			cmd += '\x00';
1088 			cmd += ICF8101_CW_SSB_width_vals[m];
1089 			break;
1090 		case F81_LSB:
1091 			cmd.append("\x1A\x05\x07\x02");
1092 			cmd += '\x00';
1093 			cmd += ICF8101_CW_SSB_width_vals[m];
1094 			break;
1095 		case F81_USB:
1096 			cmd.append("\x1A\x05\x08\x02");
1097 			cmd += '\x00';
1098 			cmd += ICF8101_CW_SSB_width_vals[m];
1099 			break;
1100 		case F81_LSBD1:
1101 			cmd.append("\x1A\x05\x12\x02");
1102 			cmd += '\x00';
1103 			cmd += ICF8101_CW_SSB_width_vals[m];
1104 			break;
1105 		case F81_USBD1:
1106 			cmd.append("\x1A\x05\x13\x02");
1107 			cmd += '\x00';
1108 			cmd += ICF8101_CW_SSB_width_vals[m];
1109 			break;
1110 		case F81_LSBD2:
1111 			cmd.append("\x1A\x05\x14\x02");
1112 			cmd += '\x00';
1113 			cmd += ICF8101_CW_SSB_width_vals[m];
1114 			break;
1115 		case F81_USBD2:
1116 			cmd.append("\x1A\x05\x15\x02");
1117 			cmd += '\x00';
1118 			cmd += ICF8101_CW_SSB_width_vals[m];
1119 			break;
1120 		case F81_LSBD3:
1121 			cmd.append("\x1A\x05\x15\x02");
1122 			cmd += '\x00';
1123 			cmd += ICF8101_CW_SSB_width_vals[m];
1124 			break;
1125 		case F81_USBD3:
1126 			cmd.append("\x1A\x05\x16\x02");
1127 			cmd += '\x00';
1128 			cmd += ICF8101_CW_SSB_width_vals[m];
1129 			break;
1130 		default:
1131 			cmd.append("\x1A\x05\x08\x02");
1132 			cmd += '\x00';
1133 			cmd += ICF8101_CW_SSB_width_vals[m];
1134 			break;
1135 	}
1136 	cmd.append( post );
1137 }
1138 
set_bwA(int val)1139 void RIG_ICF8101::set_bwA(int val)
1140 {
1141 	A.iBW = val;
1142 	set_BW(val);
1143 	waitFB("set BW A");
1144 	mode_bwA[A.imode] = val;
1145 	set_trace(4, "set_bwA() ", bwtable(A.imode)[val], ": ", str2hex(replystr.c_str(), replystr.length()));
1146 }
1147 
set_bwB(int val)1148 void RIG_ICF8101::set_bwB(int val)
1149 {
1150 	B.iBW = val;
1151 	set_BW(val);
1152 	waitFB("set BW B");
1153 	mode_bwB[B.imode] = val;
1154 	set_trace(4, "set_bwB() ", bwtable(B.imode)[val], ": ", str2hex(replystr.c_str(), replystr.length()));
1155 }
1156 
get_BW(int m)1157 int  RIG_ICF8101::get_BW(int m)
1158 {
1159 	cmd = pre_to;
1160 	string resp = pre_fm;
1161 	switch (m) {
1162 		case F81_AM:
1163 			cmd.append("\x1A\x05\x10\x02");
1164 			resp.append("\x1A\x05\x10\x02");
1165 			break;
1166 		case F81_RTTY:
1167 			return 0;
1168 		case F81_CW:
1169 			cmd.append("\x1A\x05\x09\x02");
1170 			resp.append("\x1A\x05\x09\x02");
1171 			break;
1172 		case F81_LSB:
1173 			cmd.append("\x1A\x05\x07\x02");
1174 			resp.append("\x1A\x05\x07\x02");
1175 			break;
1176 		case F81_USB:
1177 			cmd.append("\x1A\x05\x08\x02");
1178 			resp.append("\x1A\x05\x08\x02");
1179 			break;
1180 		case F81_LSBD1:
1181 			cmd.append("\x1A\x05\x12\x02");
1182 			resp.append("\x1A\x05\x12\x02");
1183 			break;
1184 		case F81_USBD1:
1185 			cmd.append("\x1A\x05\x13\x02");
1186 			resp.append("\x1A\x05\x13\x02");
1187 			break;
1188 		case F81_LSBD2:
1189 			cmd.append("\x1A\x05\x14\x02");
1190 			resp.append("\x1A\x05\x14\x02");
1191 			break;
1192 		case F81_USBD2:
1193 			cmd.append("\x1A\x05\x15\x02");
1194 			resp.append("\x1A\x05\x15\x02");
1195 			break;
1196 		case F81_LSBD3:
1197 			cmd.append("\x1A\x05\x15\x02");
1198 			resp.append("\x1A\x05\x15\x02");
1199 			break;
1200 		case F81_USBD3:
1201 			cmd.append("\x1A\x05\x16\x02");
1202 			resp.append("\x1A\x05\x16\x02");
1203 			break;
1204 		default:
1205 			cmd.append("\x1A\x05\x08\x02");
1206 			resp.append("\x1A\x05\x08\x02");
1207 	}
1208 	int bwval = 0;
1209 	if (waitFOR(11, "get BW")) {
1210 		get_trace(2, "get_bwA()", str2hex(replystr.c_str(), replystr.length()));
1211 		size_t p = replystr.rfind(resp);
1212 		if (p != string::npos) {
1213 			bwval = replystr[p+9];
1214 			const char *vals = ICF8101_CW_SSB_width_vals;
1215 			int n = NUM_CW_SSB_WIDTHS;
1216 			if (m == F81_AM) {
1217 				vals = ICF8101_bw_vals_AM;
1218 				n = NUM_AM_WIDTHS;
1219 			}
1220 			for (int i = 0; i < n; n++) {
1221 				if (bwval == vals[i]) {
1222 					return i;
1223 				}
1224 			}
1225 		}
1226 	}
1227 	get_trace(2, "get_bwA()", str2hex(replystr.c_str(), replystr.length()));
1228 	return 0;
1229 }
1230 
get_bwA()1231 int  RIG_ICF8101::get_bwA()
1232 {
1233 	int bw = get_BW(A.imode);
1234 	if (bw) {
1235 		A.iBW = bw;
1236 		mode_bwA[A.imode] = A.iBW;
1237 	}
1238 	return A.iBW;
1239 }
1240 
get_bwB()1241 int  RIG_ICF8101::get_bwB()
1242 {
1243 	int bw = get_BW(B.imode);
1244 	if (bw) {
1245 		B.iBW = bw;
1246 		mode_bwB[B.imode] = B.iBW;
1247 	}
1248 	return B.iBW;
1249 }
1250