1 // ----------------------------------------------------------------------------
2 // Copyright (C) 2014
3 //              David Freese, W1HKJ
4 //
5 // This file is part of flrig.
6 //
7 // flrig is free software; you can redistribute it and/or modify
8 // it under the terms of the GNU General Public License as published by
9 // the Free Software Foundation; either version 3 of the License, or
10 // (at your option) any later version.
11 //
12 // flrig is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 // GNU General Public License for more details.
16 //
17 // You should have received a copy of the GNU General Public License
18 // aunsigned long int with this program.  If not, see <http://www.gnu.org/licenses/>.
19 // ----------------------------------------------------------------------------
20 
21 #include "rigbase.h"
22 #include "util.h"
23 #include "debug.h"
24 #include "rig_io.h"
25 #include "support.h"
26 
27 
28 const char *szNORIG = "NONE";
29 const char *szNOMODES[] = {"LSB", "USB", NULL};
30 const char *szNOBWS[] = {"NONE", NULL};
31 const char *szDSPLO[] = {"NONE", NULL};
32 const char *szDSPHI[] = {"NONE", NULL};
33 const char *szdsptooltip = "dsp tooltip";
34 const char *szbtnlabel = " ";
35 const int  ibw_val = -1;
36 
37 static GUI basewidgets[] = { {NULL, 0, 0} };
38 
rigbase()39 rigbase::rigbase()
40 {
41 	IDstr = "";
42 	name_ = szNORIG;
43 	modes_ = szNOMODES;
44 	bandwidths_ = szNOBWS;
45 	dsp_SL = szDSPLO;
46 	SL_tooltip = szdsptooltip;
47 	SL_label = szbtnlabel;
48 	dsp_SH = szDSPHI;
49 	SH_tooltip = szdsptooltip;
50 	SH_label = szbtnlabel;
51 	bw_vals_ = &ibw_val;
52 
53 	widgets = basewidgets;
54 
55 	serloop_timing = 200; // msec, 5x / second
56 
57 	stopbits = 2;
58 
59 	CIV = 0;
60 	defaultCIV = 0;
61 	USBaudio = false;
62 
63 	has_xcvr_auto_on_off =
64 	comm_echo =
65 	has_vfo_adj =
66 	has_rit =
67 	has_xit =
68 	has_bfo =
69 	has_power_control =
70 	has_volume_control =
71 	has_mode_control =
72 	has_bandwidth_control =
73 	has_dsp_controls =
74 	has_micgain_control =
75 	has_mic_line_control =
76 	has_auto_notch =
77 	has_notch_control =
78 	has_noise_control =
79 	has_noise_reduction_control =
80 	has_noise_reduction =
81 	has_attenuator_control =
82 	has_preamp_control =
83 	has_ifshift_control =
84 	has_pbt_controls =
85 	has_FILTER =
86 	has_ptt_control =
87 	has_tune_control =
88 	has_swr_control =
89 	has_alc_control =
90 	has_agc_control =
91 	has_rf_control =
92 	has_sql_control =
93 	has_data_port =
94 	restore_mbw =
95 
96 	has_extras =
97 	has_nb_level =
98 	has_agc_level =
99 	has_cw_wpm =
100 	has_cw_vol =
101 	has_cw_spot =
102 	has_cw_spot_tone =
103 	has_cw_qsk =
104 	has_cw_break_in =
105 	has_cw_delay =
106 	has_cw_weight =
107 	has_cw_keyer =
108 	has_vox_onoff =
109 	has_vox_gain =
110 	has_vox_anti =
111 	has_vox_hang =
112 	has_vox_on_dataport =
113 	has_compression =
114 	has_compON =
115 	use_line_in =
116 	has_bpf_center =
117 	has_special =
118 	has_ext_tuner =
119 	has_smeter =
120 	has_power_out =
121 	has_line_out =
122 //	has_split =
123 	has_split_AB =
124 	has_band_selection =
125 	has_get_info =
126 	has_getvfoAorB =
127 	ICOMrig = false;
128 	ICOMmainsub = false;
129 
130 	has_a2b = false;
131 	has_vfoAB = false;
132 
133 	data_type = BINARY;
134 
135 	A.freq = 14070000L;
136 	A.imode = 1;
137 	A.iBW = 0;
138 	B.freq = 14070000L;
139 	B.imode = 1;
140 	B.iBW = 0;
141 	inuse = onA;
142 	precision = 1;
143 	ndigits = 9;
144 	can_change_alt_vfo = false;
145 
146 	freqA = 14070000L;
147 	modeA = 1;
148 	bwA = 0;
149 	freqB = 14070000L;
150 	modeB = 1;
151 	bwB = 0;
152 
153 	def_freq = 14070000L;
154 	def_mode = 1;
155 	def_bw = 0;
156 	bpf_center = 0;
157 	pbt = 0;
158 
159 	ptt_ = tune_ = 0;
160 
161 	rTONE = tTONE = 8;
162 
163 	max_power = 100;
164 
165 	active_mode = 0; // wbx
166 
167 	if_shift_min = -1500;
168 	if_shift_max = 1500;
169 	if_shift_step = 10;
170 	if_shift_mid = 0;
171 
172 	atten_level = 0;
173 	preamp_level = 0;
174 }
175 
to_bcd_be(unsigned long int freq,int len)176 string rigbase::to_bcd_be(unsigned long int freq, int len)
177 {
178 	unsigned char a;
179 	int numchars = len / 2;
180 	string bcd = "";
181 	if (len & 1) numchars ++;
182 	for (int i = 0; i < numchars; i++) {
183 		a = 0;
184 		a |= freq % 10;
185 		freq /= 10;
186 		a |= (freq % 10)<<4;
187 		freq /= 10;
188 		bcd += a;
189 	}
190 	return bcd;
191 }
192 
to_bcd(unsigned long int freq,int len)193 string rigbase::to_bcd(unsigned long int freq, int len)
194 {
195 	string bcd_be = to_bcd_be(freq, len);
196 	string bcd = "";
197 	int bcdlen = bcd_be.size();
198 	for (int i = bcdlen - 1; i >= 0; i--)
199 		bcd += bcd_be[i];
200 	return bcd;
201 }
202 
fm_bcd(string bcd,int len)203 unsigned long int rigbase::fm_bcd (string bcd, int len)
204 {
205 	int i;
206 	unsigned long int f = 0;
207 	int numchars = len/2;
208 	if (len & 1) numchars ++;
209 	for (i = 0; i < numchars; i++) {
210 		f *=10;
211 		f += (bcd[i] >> 4) & 0x0F;
212 		f *= 10;
213 		f += bcd[i] & 0x0F;
214 	}
215 	return f;
216 }
217 
218 
fm_bcd_be(string bcd,int len)219 unsigned long int rigbase::fm_bcd_be(string bcd, int len)
220 {
221 	char temp;
222 	int numchars = len/2;
223 	if (len & 1) numchars++;
224 	for (int i = 0; i < numchars / 2; i++) {
225 		temp = bcd[i];
226 		bcd[i] = bcd[numchars -1 - i];
227 		bcd[numchars -1 - i] = temp;
228 	}
229 	return fm_bcd(bcd, len);
230 }
231 
to_binary_be(unsigned long int freq,int len)232 string rigbase::to_binary_be(unsigned long int freq, int len)
233 {
234 	static string bin = "";
235 	for (int i = 0; i < len; i++) {
236 		bin += freq & 0xFF;
237 		freq >>= 8;
238 	}
239 	return bin;
240 }
241 
to_binary(unsigned long int freq,int len)242 string rigbase::to_binary(unsigned long int freq, int len)
243 {
244 	static string bin = "";
245 	string bin_be = to_binary_be(freq, len);
246 	int binlen = bin_be.size();
247 	for (int i = binlen - 1; i >= 0; i--)
248 		bin += bin_be[i];
249 	return bin;
250 }
251 
fm_binary(string binary,int len)252 unsigned long int rigbase::fm_binary(string binary, int len)
253 {
254 	int i;
255 	unsigned long int f = 0;
256 	for (i = 0; i < len; i++) {
257 		f *= 256;
258 		f += (unsigned char)binary[i];
259 	}
260 	return f;
261 }
262 
fm_binary_be(string binary_be,int len)263 unsigned long int rigbase::fm_binary_be(string binary_be, int len)
264 {
265 	unsigned char temp;
266 	int numchars = len/2;
267 	if (len & 1) numchars++;
268 	for (int i = 0; i < numchars / 2; i++) {
269 		temp = binary_be[i];
270 		binary_be[i] = binary_be[numchars -1 - i];
271 		binary_be[numchars -1 - i] = temp;
272 	}
273 	return fm_binary(binary_be, len);
274 }
275 
to_decimal_be(unsigned long int d,int len)276 string rigbase::to_decimal_be(unsigned long int d, int len)
277 {
278 	static string sdec_be;
279 	sdec_be.clear();
280 	for (int i = 0; i < len; i++) {
281 		sdec_be += (char)((d % 10) + '0');
282 		d /= 10;
283 	}
284 	return sdec_be;
285 }
286 
to_decimal(unsigned long int d,int len)287 string rigbase::to_decimal(unsigned long int d, int len)
288 {
289 	static string sdec;
290 	sdec.clear();
291 	string sdec_be = to_decimal_be(d, len);
292 	int bcdlen = sdec_be.size();
293 	for (int i = bcdlen - 1; i >= 0; i--)
294 		sdec += sdec_be[i];
295 	return sdec;
296 }
297 
fm_decimal(string decimal,int len)298 unsigned long int rigbase::fm_decimal(string decimal, int len)
299 {
300 	unsigned long int d = 0;
301 	for (int i = 0; i < len; i++) {
302 		d *= 10;
303 		d += decimal[i] - '0';
304 	}
305 	return d;
306 }
307 
fm_decimal_be(string decimal_be,int len)308 unsigned long int rigbase::fm_decimal_be(string decimal_be, int len)
309 {
310 	unsigned char temp;
311 	int numchars = len/2;
312 	if (len & 1) numchars++;
313 	for (int i = 0; i < numchars / 2; i++) {
314 		temp = decimal_be[i];
315 		decimal_be[i] = decimal_be[numchars -1 - i];
316 		decimal_be[numchars -1 - i] = temp;
317 	}
318 	return fm_decimal(decimal_be, len);
319 }
320 
321 //======================================================================
322 // translation 0..255 <==> 0..100
323 // for Icom controls
324 //======================================================================
325 
326 static int set100[] =
327 {  0,  3,  6,  8, 11, 13, 16, 18, 21, 23,
328   26, 29, 31, 34, 36, 39, 41, 44, 46, 49,
329   51, 54, 57, 59, 62, 64, 67, 69, 72, 74,
330   77, 80, 82, 85, 87, 90, 92, 95, 97,100,
331  102,105,108,110,113,115,118,120,123,125,
332  128,131,133,136,138,141,143,146,148,151,
333  153,156,159,161,164,166,169,171,174,176,
334  179,182,184,187,189,192,194,197,199,202,
335  204,207,210,212,215,217,220,222,225,227,
336  230,233,235,238,240,243,245,248,250,253,255};
337 
bcd255(int val)338 string rigbase::bcd255(int val)
339 {
340 	return to_bcd(set100[(int)(val)], 3);
341 }
342 
num100(string bcd)343 int rigbase::num100(string bcd)
344 {
345 	int val = fm_bcd(bcd, 3);
346 	for (int n = 0; n < 101; n++) {
347 		if (set100[n] > val)  return n - 1;
348 		if (set100[n] == val) return n;
349 	}
350 	return 0;
351 }
352 
hexval(int hex)353 int rigbase::hexval(int hex)
354 {
355 	int val = 0;
356 	val += 10 * ((hex >> 4) & 0x0F);
357 	val += hex & 0x0F;
358 	return val;
359 }
360 
hex2val(string hexstr)361 int rigbase::hex2val(string hexstr)
362 {
363 	return 100 * hexval(hexstr[0]) + hexval(hexstr[1]);
364 }
365 
366 
367 //======================================================================
368 
waitN(size_t n,int timeout,const char * sz,int pr)369 int rigbase::waitN(size_t n, int timeout, const char *sz, int pr)
370 {
371 	guard_lock reply_lock(&mutex_replystr);
372 
373 	char sztemp[50];
374 	string returned = "";
375 	string tosend = cmd;
376 	int cnt = 0;
377 	int waited = 0;
378 	size_t num = n + cmd.length();
379 	int delay =  num * 11000.0 / RigSerial->Baud() +
380 			progStatus.use_tcpip ? progStatus.tcpip_ping_delay : 0;
381 
382 	replystr.clear();
383 	RigSerial->FlushBuffer();
384 
385 	if(!progStatus.use_tcpip && !RigSerial->IsOpen()) {
386 		snprintf(sztemp, sizeof(sztemp), "TEST %s", sz);
387 		showresp(WARN, pr, sztemp, tosend, replystr);
388 		return 0;
389 	}
390 
391 	sendCommand(tosend, 0);
392 	MilliSleep(delay);
393 
394 	returned = "";
395 	for ( cnt = 0; cnt < timeout / 10; cnt++) {
396 		readResponse();
397 		returned.append(respstr);
398 		if (returned.length() >= n) {
399 			replystr = returned;
400 			waited = cnt * 10 + delay;
401 			snprintf(sztemp, sizeof(sztemp), "%s OK %d ms", sz, waited);
402 			showresp(WARN, pr, sztemp, cmd, returned);
403 			return replystr.length();
404 		}
405 		MilliSleep(10);
406 		Fl::awake();
407 	}
408 
409 	replystr = returned;
410 	waited = timeout + delay;
411 	snprintf(sztemp, sizeof(sztemp), "%s failed %d ms", sz, waited);
412 	showresp(ERR, pr, sztemp, cmd, returned);
413 	return 0;
414 }
415 
wait_char(int ch,size_t n,int timeout,const char * sz,int pr)416 int rigbase::wait_char(int ch, size_t n, int timeout, const char *sz, int pr)
417 {
418 	guard_lock reply_lock(&mutex_replystr);
419 
420 	char sztemp[50];
421 	string returned = "";
422 	string tosend = cmd;
423 	int cnt = 0;
424 	int waited = 0;
425 	size_t num = n + cmd.length();
426 
427 	int delay =  num * 11000.0 / RigSerial->Baud() +
428 			progStatus.use_tcpip ? progStatus.tcpip_ping_delay : 0;
429 
430 	replystr.clear();
431 	RigSerial->FlushBuffer();
432 
433 	if(!progStatus.use_tcpip && !RigSerial->IsOpen()) {
434 		snprintf(sztemp, sizeof(sztemp), "TEST %s", sz);
435 		showresp(DEBUG, pr, sztemp, tosend, replystr);
436 		return 0;
437 	}
438 
439 	sendCommand(tosend, 0);
440 	MilliSleep(delay);
441 
442 	returned = "";
443 	for ( cnt = 0; cnt < timeout / 10; cnt++) {
444 		readResponse();
445 		returned.append(respstr);
446 		if (returned.find(ch) != string::npos) {
447 			replystr = returned;
448 			waited = cnt * 10 + delay;
449 			snprintf(sztemp, sizeof(sztemp), "%s OK %d ms", sz, waited);
450 			showresp(DEBUG, pr, sztemp, cmd, returned);
451 			return replystr.length();
452 		}
453 		MilliSleep(10);
454 		Fl::awake();
455 	}
456 
457 	replystr = returned;
458 	waited = timeout + delay;
459 	snprintf(sztemp, sizeof(sztemp), "%s failed %d ms", sz, waited);
460 	showresp(ERR, pr, sztemp, cmd, returned);
461 	return 0;
462 }
463 
464 // Yaesu transceiver - wait for response to identifier request
465 // return boolean state of response
466 // ID  - for most
467 // AI  - for FTdx9000
468 // wait - wait nnn milliseconds before declaring transceiver DOA
469 //        default 200 msec
470 // retry - number of retries, default
id_OK(string ID,int wait)471 bool rigbase::id_OK(string ID, int wait)
472 {
473 	guard_lock reply_lock(&mutex_replystr);
474 
475 	string returned;
476 	for (int n = 0; n < progStatus.comm_retries; n++) {
477 		sendCommand(string(ID).append(";", 0));
478 		returned = "";
479 		for (int cnt = 0; cnt < wait / 10; cnt++) {
480 			readResponse();
481 			returned.append(respstr);
482 			if (returned.find(ID)) {
483 				replystr = returned;
484 				return true;
485 			}
486 			MilliSleep(10);
487 			Fl::awake();
488 		}
489 	}
490 	replystr.clear();
491 	return false;
492 }
493 
sendOK(string cmd)494 void rigbase::sendOK(string cmd)
495 {
496 	if (IDstr.empty()) {
497 		sendCommand(cmd,0);
498 		return;
499 	}
500 	if (id_OK(IDstr, 100))
501 		sendCommand(cmd, 0);
502 }
503 
set_split(bool val)504 void rigbase::set_split(bool val)
505 {
506 	split = val;
507 }
508 
get_split()509 int  rigbase::get_split()
510 {
511 	return split;
512 }
513 
514 char bcdval[100] = {
515 '\x00', '\x01', '\x02', '\x03', '\x04', '\x05', '\x06', '\x07', '\x08', '\x09',
516 '\x10', '\x11', '\x12', '\x13', '\x14', '\x15', '\x16', '\x17', '\x18', '\x19',
517 '\x20', '\x21', '\x22', '\x23', '\x24', '\x25', '\x26', '\x27', '\x28', '\x29',
518 '\x30', '\x31', '\x32', '\x33', '\x34', '\x35', '\x36', '\x37', '\x38', '\x39',
519 '\x40', '\x41', '\x42', '\x43', '\x44', '\x45', '\x46', '\x47', '\x48', '\x49',
520 '\x50', '\x51', '\x52', '\x53', '\x54', '\x55', '\x56', '\x57', '\x58', '\x59',
521 '\x60', '\x61', '\x62', '\x63', '\x64', '\x65', '\x66', '\x67', '\x68', '\x69',
522 '\x70', '\x71', '\x72', '\x73', '\x74', '\x75', '\x76', '\x77', '\x78', '\x79',
523 '\x80', '\x81', '\x82', '\x83', '\x84', '\x85', '\x86', '\x87', '\x88', '\x89',
524 '\x90', '\x91', '\x92', '\x93', '\x94', '\x95', '\x96', '\x97', '\x98', '\x99'
525 };
526