1 // ----------------------------------------------------------------------------
2 // rigio.cxx
3 //
4 // Copyright (C) 2007-2009
5 //		Dave Freese, W1HKJ
6 //
7 // This file is part of fldigi.
8 //
9 // Fldigi is free software: you can redistribute it and/or modify
10 // it under the terms of the GNU General Public License as published by
11 // the Free Software Foundation, either version 3 of the License, or
12 // (at your option) any later version.
13 //
14 // Fldigi is distributed in the hope that it will be useful,
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 // GNU General Public License for more details.
18 //
19 // You should have received a copy of the GNU General Public License
20 // along with fldigi.  If not, see <http://www.gnu.org/licenses/>.
21 // ----------------------------------------------------------------------------
22 
23 #include <config.h>
24 
25 #include <ctime>
26 #include <sys/time.h>
27 #include <iostream>
28 #include <list>
29 #include <vector>
30 #include <queue>
31 #include <string>
32 
33 #ifdef RIGCATTEST
34 	#include "rigCAT.h"
35 #else
36 	#include "fl_digi.h"
37 	#include "misc.h"
38 	#include "configuration.h"
39 #endif
40 
41 #include "rigsupport.h"
42 #include "rigxml.h"
43 #include "trx.h"
44 #include "serial.h"
45 #include "rigio.h"
46 #include "debug.h"
47 #include "qrunner.h"
48 #include "confdialog.h"
49 #include "status.h"
50 
51 LOG_FILE_SOURCE(debug::LOG_RIGCONTROL);
52 
53 using namespace std;
54 
55 Cserial rigio;
56 static pthread_t		rigCAT_thread;
57 pthread_mutex_t	rigCAT_mutex = PTHREAD_MUTEX_INITIALIZER;
58 pthread_mutex_t	cmdque_mutex = PTHREAD_MUTEX_INITIALIZER;
59 
60 static bool			rigCAT_exit = false;
61 static bool			rigCAT_open = false;
62 
63 static string		sRigWidth = "";
64 static string		sRigMode = "";
65 static long long	llFreq = 0;
66 
67 static void *rigCAT_loop(void *args);
68 
69 #define RXBUFFSIZE 2000
70 static unsigned char replybuff[RXBUFFSIZE+1];
71 static unsigned char retbuf[3];
72 
73 struct CMDQUEUE {
74 	string cmd;
75 	string s;
76 	int retnbr;
77 	int waitval;
CMDQUEUECMDQUEUE78 	CMDQUEUE(string _cmd, string _s, int _retnbr, int _waitval) {
79 		cmd = _cmd;
80 		s = _s;
81 		retnbr = _retnbr;
82 		waitval = _waitval;
83 	}
CMDQUEUECMDQUEUE84 	CMDQUEUE() {cmd.clear(); s.clear(); retnbr = 0; waitval = 0;}
~CMDQUEUECMDQUEUE85 	~CMDQUEUE() {};
86 };
87 
88 queue<CMDQUEUE> cmdque;
89 
add_to_cmdque(string cmd,string s,int retnbr,int waitval)90 void add_to_cmdque( string cmd, string s, int retnbr, int waitval)
91 {
92 	guard_lock quelock(&cmdque_mutex);
93 	cmdque.push(CMDQUEUE(cmd, s, retnbr, waitval));
94 }
95 
cmdque_exec()96 void cmdque_exec()
97 {
98 	bool sendcmd = false;
99 	CMDQUEUE cmdq;
100 	{
101 		guard_lock quelock(&cmdque_mutex);
102 		if (!cmdque.empty()) {
103 			cmdq = cmdque.front();
104 			cmdque.pop();
105 			sendcmd = true;
106 		}
107 	}
108 	if (sendcmd) sendCommand(cmdq.cmd, cmdq.s, cmdq.retnbr, cmdq.waitval);
109 }
110 
sendCommand(string cmd,string s,int retnbr,int waitval)111 bool sendCommand (string cmd, string s, int retnbr, int waitval)
112 {
113 	int numwrite = (int)s.length();
114 	int readafter = 0;
115 	int numread = 0;
116 	int retval = 0;
117 
118 	numread = retnbr;
119 
120 	if (progdefaults.RigCatECHO)
121 		numread += numwrite;
122 
123 	readafter =
124 		waitval + (int) ceilf (
125 			numread * (9 + progdefaults.RigCatStopbits) *
126 			1000.0 / rigio.Baud() );
127 	if (xmlrig.debug)
128 		LOG_INFO(
129 			"%s: '%s', Expect: %d after %d msec",
130 			cmd.c_str(),
131 			(xmlrig.ascii ? s.c_str() : str2hex(s.data(), s.length())),
132 			numread,
133 			readafter);
134 
135 	if (xmlrig.noserial) {
136 		memset(replybuff, 0, RXBUFFSIZE + 1);
137 		numread = 0;
138 		return true;
139 	}
140 
141 	retval = rigio.WriteBuffer((unsigned char *)s.c_str(), numwrite);
142 	if (retval <= 0)
143 		LOG_ERROR("Write error %d", retval);
144 
145 	if (retnbr == 0) return true;
146 
147 	memset(replybuff, 0, RXBUFFSIZE + 1);
148 	numread = 0;
149 	while (readafter > 50) {
150 		MilliSleep(50);
151 		Fl::awake();
152 		readafter -= 50;
153 	}
154 	if (readafter) {
155 		MilliSleep(readafter);
156 		Fl::awake();
157 	}
158 
159 	while (numread < RXBUFFSIZE) {
160 		memset(retbuf, 0, 2);
161 		retval = rigio.ReadBuffer(retbuf, 1);
162 		if (retval == 0) break;
163 		replybuff[numread] = retbuf[0];
164 		numread++;
165 	}
166 	if (xmlrig.debug)
167 		LOG_INFO(
168 			"Reply (%d): '%s'",
169 			numread,
170 			(xmlrig.ascii ? reinterpret_cast<const char *>(replybuff) : str2hex(reinterpret_cast<const char *>(replybuff), numread)));
171 
172 	if (numread > retnbr) {
173 		memmove(replybuff, replybuff + numread - retnbr, retnbr);
174 		numread = retnbr;
175 	}
176 
177 	return (numread == retnbr);
178 }
179 
to_bcd_be(long long freq,int len)180 string to_bcd_be(long long freq, int len)
181 {
182 	string bcd = "";
183 	unsigned char a;
184 	int numchars = len / 2;
185 	if (len & 1) numchars ++;
186 	for (int i = 0; i < numchars; i++) {
187 		a = 0;
188 		a |= freq%10;
189 		freq /= 10;
190 		a |= (freq%10)<<4;
191 		freq /= 10;
192 		bcd += a;
193 	}
194 	return bcd;
195 }
196 
to_bcd(long long freq,int len)197 string to_bcd(long long freq, int len)
198 {
199 	string bcd = "";
200 	string bcd_be = to_bcd_be(freq, len);
201 	int bcdlen = bcd_be.size();
202 	for (int i = bcdlen - 1; i >= 0; i--)
203 		bcd += bcd_be[i];
204 	return bcd;
205 }
206 
fm_bcd(size_t p,int len)207 long long fm_bcd (size_t p, int len)
208 {
209 	int i;
210 	long long f = 0;
211 	int numchars = len/2;
212 	if (len & 1) numchars ++;
213 	for (i = 0; i < numchars; i++) {
214 		f *=10;
215 		f += (replybuff[p + i] >> 4) & 0x0F;
216 		f *= 10;
217 		f += replybuff[p + i] & 0x0F;
218 	}
219 	return f;
220 }
221 
222 
fm_bcd_be(size_t p,int len)223 long long fm_bcd_be(size_t p, int len)
224 {
225 	unsigned char temp;
226 	int numchars = len/2;
227 	if (len & 1) numchars++;
228 	for (int i = 0; i < numchars / 2; i++) {
229 		temp = replybuff[p + i];
230 		replybuff[p + i] = replybuff[p + numchars -1 - i];
231 		replybuff[p + numchars -1 - i] = temp;
232 	}
233 	return fm_bcd(p, len);
234 }
235 
to_binary_be(long long freq,int len)236 string to_binary_be(long long freq, int len)
237 {
238 	string bin = "";
239 	for (int i = 0; i < len; i++) {
240 		bin += freq & 0xFF;
241 		freq >>= 8;
242 	}
243 	return bin;
244 }
245 
to_binary(long long freq,int len)246 string to_binary(long long freq, int len)
247 {
248 	string bin = "";
249 	string bin_be = to_binary_be(freq, len);
250 	int binlen = bin_be.size();
251 	for (int i = binlen - 1; i >= 0; i--)
252 		bin += bin_be[i];
253 	return bin;
254 }
255 
fm_binary(size_t p,int len)256 long long fm_binary(size_t p, int len)
257 {
258 	int i;
259 	long long f = 0;
260 	for (i = 0; i < len; i++) {
261 		f *= 256;
262 		f += replybuff[p + i];
263 	}
264 	return f;
265 }
266 
fm_binary_be(size_t p,int len)267 long long fm_binary_be(size_t p, int len)
268 {
269 	unsigned char temp;
270 	int numchars = len/2;
271 	if (len & 1) numchars++;
272 	for (int i = 0; i < numchars / 2; i++) {
273 		temp = replybuff[p + i];
274 		replybuff[p + i] = replybuff[p + numchars -1 - i];
275 		replybuff[p + numchars -1 - i] = temp;
276 	}
277 	return fm_binary(p, len);
278 }
279 
to_decimal_be(long long d,int len)280 string to_decimal_be(long long d, int len)
281 {
282 	string sdec_be = "";
283 	for (int i = 0; i < len; i++) {
284 		sdec_be += (char)((d % 10) + '0');
285 		d /= 10;
286 	}
287 	return sdec_be;
288 }
289 
to_decimal(long long d,int len)290 string to_decimal(long long d, int len)
291 {
292 	string sdec = "";
293 	string sdec_be = to_decimal_be(d, len);
294 	int bcdlen = sdec_be.size();
295 	for (int i = bcdlen - 1; i >= 0; i--)
296 		sdec += sdec_be[i];
297 	return sdec;
298 }
299 
fm_decimal(size_t p,int len)300 long long fm_decimal(size_t p, int len)
301 {
302 	long long d = 0;
303 	for (int i = 0; i < len; i++) {
304 		d *= 10;
305 		d += replybuff[p + i] - '0';
306 	}
307 	return d;
308 }
309 
fm_decimal_be(size_t p,int len)310 long long fm_decimal_be(size_t p, int len)
311 {
312 	unsigned char temp;
313 	int numchars = len/2;
314 	if (len & 1) numchars++;
315 	for (int i = 0; i < numchars / 2; i++) {
316 		temp = replybuff[p + i];
317 		replybuff[p + i] = replybuff[p + numchars -1 - i];
318 		replybuff[p + numchars -1 - i] = temp;
319 	}
320 	return fm_decimal(p, len);
321 }
322 
to_freqdata(DATA d,long long f)323 string to_freqdata(DATA d, long long f)
324 {
325 	int num, den;
326 	num = 100;
327 	den = (int)(d.resolution * 100);
328 	if (d.size == 0) return "";
329 	if (d.dtype == "BCD") {
330 		if (d.reverse == true)
331 			return to_bcd_be((long long int)(f * num / den), d.size);
332 		else
333 			return to_bcd((long long int)(f * num / den), d.size);
334 	} else if (d.dtype == "BINARY") {
335 		if (d.reverse == true)
336 			return to_binary_be((long long int)(f * num / den), d.size);
337 		else
338 			return to_binary((long long int)(f * num / den), d.size);
339 	} else if (d.dtype == "DECIMAL") {
340 		if (d.reverse == true)
341 			return to_decimal_be((long long int)(f * num / den), d.size);
342 		else
343 			return to_decimal((long long int)(f * num / den), d.size);
344 	}
345 	return "";
346 }
347 
fm_freqdata(DATA d,size_t p)348 long long fm_freqdata(DATA d, size_t p)
349 {
350 	int num, den;
351 	num = (int)(d.resolution * 100);
352 	den = 100;
353 	long long fret = 0;
354 	if (d.dtype == "BCD") {
355 		if (d.reverse == true)
356 			fret = (long long int)(fm_bcd_be(p, d.size) * num / den);
357 		else
358 			fret = (long long int)(fm_bcd(p, d.size)  * num / den);
359 	} else if (d.dtype == "BINARY") {
360 		if (d.reverse == true)
361 			fret = (long long int)(fm_binary_be(p, d.size)  * num / den);
362 		else
363 			fret = (long long int)(fm_binary(p, d.size)  * num / den);
364 	} else if (d.dtype == "DECIMAL") {
365 		if (d.reverse == true)
366 			fret = (long long int)(fm_decimal_be(p, d.size)  * num / den);
367 		else
368 			fret = (long long int)(fm_decimal(p, d.size)  * num / den);
369 	}
370 	return fret;
371 }
372 
rigCAT_getfreq(int retries,bool & failed,int waitval)373 long long rigCAT_getfreq(int retries, bool &failed, int waitval)
374 {
375 	const char symbol[] = "GETFREQ";
376 	failed = false;
377 	if (rigCAT_exit || xmlrig.noserial || !xmlrig.xmlok) {
378 		failed = true;
379 		return progStatus.noCATfreq;
380 	}
381 
382 	if (waitval == 0) waitval = progdefaults.RigCatWait;
383 	XMLIOS modeCmd;
384 	list<XMLIOS>::iterator itrCmd;
385 	string strCmd;
386 	size_t p = 0, len1 = 0, len2 = 0, pData = 0;
387 	long long f = 0;
388 
389 	itrCmd = commands.begin();
390 	while (itrCmd != commands.end()) {
391 		if ((*itrCmd).SYMBOL == symbol)
392 			break;
393 		++itrCmd;
394 	}
395 
396 	if (itrCmd == commands.end()) {
397 		failed = true;
398 		if (xmlrig.debug) LOG_INFO("%s not defined", symbol);
399 		return progStatus.noCATfreq; // get_freq command is not defined!
400 	}
401 
402 	modeCmd = *itrCmd;
403 
404 	if ( modeCmd.str1.empty() == false)
405 		strCmd.append(modeCmd.str1);
406 
407 	if (modeCmd.str2.empty() == false)
408 		strCmd.append(modeCmd.str2);
409 
410 	if ( !modeCmd.info.size() ) {
411 		failed = true;
412 		return 0;
413 	}
414 
415 	for (list<XMLIOS>::iterator preply = reply.begin(); preply != reply.end(); ++preply) {
416 		if (preply->SYMBOL != modeCmd.info)
417 			continue;
418 
419 		XMLIOS  rTemp = *preply;
420 		len1 = rTemp.str1.size();
421 		len2 = rTemp.str2.size();
422 
423 		for (int n = 0; n < retries; n++) {
424 			if (n && progdefaults.RigCatTimeout > 0)
425 			{
426 				int timeout = progdefaults.RigCatTimeout;
427 				while (timeout > 50) {
428 					MilliSleep(50);
429 					Fl::awake();
430 					timeout -= 50;
431 				}
432 				if (timeout) {
433 					MilliSleep(timeout);
434 					Fl::awake();
435 				}
436 			}
437 // send the command
438 			int sendok;
439 			{
440 				guard_lock ser_guard(&rigCAT_mutex);
441 				sendok = sendCommand(symbol, strCmd, rTemp.size, waitval);
442 			}
443 			if ( !sendok ) {
444 				if (xmlrig.debug)
445 					LOG_INFO("sendCommand failed");
446 				goto retry_get_freq;
447 			}
448 // check the pre data string
449 			p = 0;
450 			pData = 0;
451 			if (len1) {
452 				for (size_t i = 0; i < len1; i++) {
453 					if ((char)rTemp.str1[i] != (char)replybuff[i]) {
454 						unsigned int ui = i;
455 						LOG_ERROR("failed pre data string test @ %u", ui);
456 						goto retry_get_freq;
457 					}
458 				}
459 				p = len1;
460 			}
461 			if (rTemp.fill1) p += rTemp.fill1;
462 			pData = p;
463 			if (rTemp.data.dtype == "BCD") {
464 				p += rTemp.data.size / 2;
465 				if (rTemp.data.size & 1) p++;
466 			} else
467 				p += rTemp.data.size;
468 // check the post data string
469 			if (rTemp.fill2) p += rTemp.fill2;
470 
471 			if (len2) {
472 				for (size_t i = 0; i < len2; i++)
473 					if ((char)rTemp.str2[i] != (char)replybuff[p + i]) {
474 						LOG_ERROR("failed post data string test @ %d", static_cast<int>(i));
475 						goto retry_get_freq;
476 					}
477 			}
478 // convert the data field
479 			f = fm_freqdata(rTemp.data, pData);
480 			if ( f >= rTemp.data.min && f <= rTemp.data.max)
481 				return f;
482 			LOG_VERBOSE("freq: %d", static_cast<int>(f));
483 retry_get_freq: ;
484 		}
485 	}
486 	if (progdefaults.RigCatVSP == false)
487 		LOG_ERROR("%s failed", symbol);
488 	failed = true;
489 	return 0;
490 }
491 
rigCAT_setfreq(long long f)492 void rigCAT_setfreq(long long f)
493 {
494 	const char symbol[] = "SETFREQ";
495 	if (rigCAT_exit || xmlrig.noserial || !xmlrig.xmlok) {
496 		progStatus.noCATfreq = f;
497 	}
498 	if (rigCAT_exit || !xmlrig.xmlok) return;
499 
500 	XMLIOS modeCmd;
501 	list<XMLIOS>::iterator itrCmd;
502 	string strCmd;
503 
504 	itrCmd = commands.begin();
505 	while (itrCmd != commands.end()) {
506 		if ((*itrCmd).SYMBOL == symbol)
507 			break;
508 		++itrCmd;
509 	}
510 	if (itrCmd == commands.end()) {
511 		if (xmlrig.debug) LOG_INFO("%s not defined", symbol);
512 		return;
513 	}
514 
515 	modeCmd = *itrCmd;
516 
517 	if ( modeCmd.str1.empty() == false)
518 		strCmd.append(modeCmd.str1);
519 
520 	strCmd.append( to_freqdata(modeCmd.data, f) );
521 
522 	if (modeCmd.str2.empty() == false)
523 		strCmd.append(modeCmd.str2);
524 
525 	if (modeCmd.ok.size()) {
526 		list<XMLIOS>::iterator preply = reply.begin();
527 		while (preply != reply.end()) {
528 			if (preply->SYMBOL == modeCmd.ok) {
529 				XMLIOS  rTemp = *preply;
530 // send the command
531 				for (int n = 0; n < progdefaults.RigCatRetries; n++) {
532 					if (rigCAT_exit) return;
533 					guard_lock ser_guard( &rigCAT_mutex );
534 					if (sendCommand(symbol, strCmd, rTemp.size, progdefaults.RigCatWait))
535 						return;
536 					MilliSleep(50);
537 				}
538 				return;
539 			}
540 			preply++;
541 		}
542 	} else {
543 		for (int n = 0; n < progdefaults.RigCatRetries; n++) {
544 			if (rigCAT_exit) return;
545 			guard_lock ser_guard( &rigCAT_mutex );
546 			if (sendCommand(symbol, strCmd, 0, progdefaults.RigCatWait)) return;
547 			MilliSleep(50);
548 		}
549 	}
550 	if (progdefaults.RigCatVSP == false)
551 		LOG_ERROR("%s failed", symbol);
552 }
553 
rigCAT_getmode()554 string rigCAT_getmode()
555 {
556 	const char symbol[] = "GETMODE";
557 
558 	if (rigCAT_exit || xmlrig.noserial || !xmlrig.xmlok)
559 		return progStatus.noCATmode;
560 
561 	XMLIOS modeCmd;
562 	list<XMLIOS>::iterator itrCmd;
563 	list<MODE>::iterator mode;
564 	list<MODE> *pmode;
565 	string strCmd, mData;
566 	size_t len;
567 
568 	itrCmd = commands.begin();
569 	while (itrCmd != commands.end()) {
570 		if ((*itrCmd).SYMBOL == symbol)
571 			break;
572 		++itrCmd;
573 	}
574 	if (itrCmd == commands.end()) {
575 		if (xmlrig.debug) LOG_INFO("%s not defined", symbol);
576 		return progStatus.noCATmode;
577 	}
578 
579 	modeCmd = *itrCmd;
580 
581 	if ( modeCmd.str1.empty() == false)
582 		strCmd.append(modeCmd.str1);
583 
584 	if (modeCmd.str2.empty() == false)
585 		strCmd.append(modeCmd.str2);
586 
587 	if (!modeCmd.info.size()) return "";
588 
589 	for (list<XMLIOS>::iterator preply = reply.begin(); preply != reply.end(); ++preply) {
590 		if (preply->SYMBOL != modeCmd.info)
591 			continue;
592 
593 		XMLIOS  rTemp = *preply;
594 
595 		for (int n = 0; n < progdefaults.RigCatRetries; n++) {
596 			if (progdefaults.RigCatTimeout > 50)
597 			{
598 				int timeout = progdefaults.RigCatTimeout;
599 				while (timeout > 50) {
600 					MilliSleep(50);
601 					Fl::awake();
602 					timeout -= 50;
603 				}
604 				if (timeout) {
605 					MilliSleep(timeout);
606 					Fl::awake();
607 				}
608 			}
609 			size_t p = 0, pData = 0;
610 // send the command
611 			{
612 				guard_lock ser_guard(&rigCAT_mutex);
613 				if (!sendCommand(symbol, strCmd, rTemp.size, progdefaults.RigCatWait)) goto retry_get_mode;
614 			}
615 // check the pre data string
616 			len = rTemp.str1.size();
617 			if (len) {
618 				for (size_t i = 0; i < len; i++)
619 					if ((char)rTemp.str1[i] != (char)replybuff[i]) {
620 						unsigned int ui = i;
621 						LOG_ERROR("failed pre data string test @ %u", ui);
622 						goto retry_get_mode;
623 					}
624 				p = len;
625 			}
626 			if (rTemp.fill1) p += rTemp.fill1;
627 			pData = p;
628 // check the post data string
629 			p += rTemp.data.size;
630 			len = rTemp.str2.size();
631 			if (rTemp.fill2) p += rTemp.fill2;
632 			if (len) {
633 				for (size_t i = 0; i < len; i++)
634 					if ((char)rTemp.str2[i] != (char)replybuff[p + i])
635 						goto retry_get_mode;
636 			}
637 // convert the data field
638 			mData = "";
639 			for (int i = 0; i < rTemp.data.size; i++)
640 				mData += (char)replybuff[pData + i];
641 // for FT100 and the ilk that use bit fields
642 			if (rTemp.data.size == 1) {
643 				unsigned char d = mData[0];
644 				if (rTemp.data.shiftbits)
645 					d >>= rTemp.data.shiftbits;
646 				d &= rTemp.data.andmask;
647 				mData[0] = d;
648 			}
649 			if (lmodes.empty() == false)
650 					pmode = &lmodes;
651 			else if (lmodeREPLY.empty() == false)
652 				pmode = &lmodeREPLY;
653 			else
654 				goto retry_get_mode;
655 			mode = pmode->begin();
656 			while (mode != pmode->end()) {
657 				if ((*mode).BYTES == mData)
658 					break;
659 				mode++;
660 			}
661 			if (mode != pmode->end())
662 				return ((*mode).SYMBOL);
663 retry_get_mode: ;
664 		}
665 	}
666 	if (progdefaults.RigCatVSP == false)
667 		LOG_ERROR("%s failed", symbol);
668 	return "";
669 }
670 
rigCAT_setmode(const string & md)671 void rigCAT_setmode(const string& md)
672 {
673 	const char symbol[] = "SETMODE";
674 
675 
676 	if (rigCAT_exit || xmlrig.noserial || !xmlrig.xmlok)
677 		progStatus.noCATmode = md;
678 
679 	if (rigCAT_exit || !xmlrig.xmlok) return;
680 
681 	XMLIOS modeCmd;
682 	list<XMLIOS>::iterator itrCmd;
683 	string strCmd;
684 
685 	itrCmd = commands.begin();
686 	while (itrCmd != commands.end()) {
687 		if ((*itrCmd).SYMBOL == symbol)
688 			break;
689 		++itrCmd;
690 	}
691 	modeCmd = *itrCmd;
692 
693 	if ( modeCmd.str1.empty() == false)
694 		strCmd.append(modeCmd.str1);
695 
696 	if ( modeCmd.data.size > 0 ) {
697 		list<MODE>::iterator mode;
698 		list<MODE> *pmode;
699 		if (lmodes.empty() == false)
700 			pmode = &lmodes;
701 		else if (lmodeCMD.empty() == false)
702 			pmode = &lmodeCMD;
703 		else
704 			return;
705 		mode = pmode->begin();
706 		while (mode != pmode->end()) {
707 			if ((*mode).SYMBOL == md)
708 				break;
709 			mode++;
710 		}
711 		if (mode != pmode->end())
712 			strCmd.append( (*mode).BYTES );
713 	}
714 	if (modeCmd.str2.empty() == false)
715 		strCmd.append(modeCmd.str2);
716 
717 	if (modeCmd.ok.size()) {
718 		list<XMLIOS>::iterator preply = reply.begin();
719 		while (preply != reply.end()) {
720 			if (preply->SYMBOL == modeCmd.ok) {
721 				XMLIOS  rTemp = *preply;
722 // send the command
723 				for (int n = 0; n < progdefaults.RigCatRetries; n++) {
724 					if (rigCAT_exit) return;
725 					guard_lock ser_guard( &rigCAT_mutex );
726 					if (sendCommand(symbol, strCmd, rTemp.size, progdefaults.RigCatWait)) return;
727 					MilliSleep(50);
728 				}
729 				return;
730 			}
731 			preply++;
732 		}
733 	} else {
734 		for (int n = 0; n < progdefaults.RigCatRetries; n++) {
735 			if (rigCAT_exit) return;
736 			guard_lock ser_guard( &rigCAT_mutex );
737 			if (sendCommand(symbol, strCmd, 0, progdefaults.RigCatWait)) return;
738 			MilliSleep(50);
739 		}
740 	}
741 	if (progdefaults.RigCatVSP == false)
742 		LOG_ERROR("%s failed", symbol);
743 }
744 
rigCAT_getwidth()745 string rigCAT_getwidth()
746 {
747 	const char symbol[] = "GETBW";
748 
749 	if (rigCAT_exit || xmlrig.noserial || !xmlrig.xmlok)
750 		return progStatus.noCATwidth;
751 
752 	XMLIOS widthCmd;
753 	list<XMLIOS>::iterator itrCmd;
754 	list<BW>::iterator bw;
755 	list<BW> *pbw;
756 	string strCmd, mData;
757 	size_t len = 0, p = 0, pData = 0;
758 
759 	itrCmd = commands.begin();
760 	while (itrCmd != commands.end()) {
761 		if ((*itrCmd).SYMBOL == symbol)
762 			break;
763 		++itrCmd;
764 	}
765 	if (itrCmd == commands.end()) {
766 		if (xmlrig.debug) LOG_INFO("%s not defined", symbol);
767 		return "";
768 	}
769 
770 	widthCmd = *itrCmd;
771 
772 	if ( widthCmd.str1.empty() == false)
773 		strCmd.append(widthCmd.str1);
774 
775 	if (widthCmd.str2.empty() == false)
776 		strCmd.append(widthCmd.str2);
777 
778 	if (!widthCmd.info.size()) return "";
779 
780 	for (list<XMLIOS>::iterator preply = reply.begin(); preply != reply.end(); ++preply) {
781 		if (preply->SYMBOL != widthCmd.info)
782 			continue;
783 
784 		XMLIOS  rTemp = *preply;
785 		for (int n = 0; n < progdefaults.RigCatRetries; n++) {
786 			if (progdefaults.RigCatTimeout > 50)
787 			{
788 				int timeout = progdefaults.RigCatTimeout;
789 				while (timeout > 50) {
790 					MilliSleep(50);
791 					Fl::awake();
792 					timeout -= 50;
793 				}
794 				if (timeout) {
795 					MilliSleep(timeout);
796 					Fl::awake();
797 				}
798 			}
799 
800 			p = 0;
801 			pData = 0;
802 
803 // send the command
804 			int sendok;
805 			{
806 				guard_lock ser_guard(&rigCAT_mutex);
807 				sendok = sendCommand(symbol, strCmd, rTemp.size, progdefaults.RigCatWait);
808 			}
809 			if ( !sendok ) {
810 				goto retry_get_width;
811 			}
812 
813 // check the pre data string
814 			len = rTemp.str1.size();
815 			if (len) {
816 				for (size_t i = 0; i < len; i++)
817 					if ((char)rTemp.str1[i] != (char)replybuff[i]) {
818 						unsigned int ui = i;
819 						LOG_ERROR("failed pre data string test @ %u", ui);
820 						goto retry_get_width;
821 					}
822 				p = pData = len;
823 			}
824 			if (rTemp.fill1) p += rTemp.fill1;
825 			pData = p;
826 			p += rTemp.data.size;
827 // check the post data string
828 			if (rTemp.fill2) p += rTemp.fill2;
829 			len = rTemp.str2.size();
830 			if (len) {
831 				for (size_t i = 0; i < len; i++)
832 					if ((char)rTemp.str2[i] != (char)replybuff[p + i]) {
833 						unsigned int ui = i;
834 						LOG_ERROR("failed pre data string test @ %u", ui);
835 						goto retry_get_width;
836 					}
837 			}
838 // convert the data field
839 			mData = "";
840 			for (int i = 0; i < rTemp.data.size; i++)
841 				mData += (char)replybuff[pData + i];
842 
843 // new for FT100 and the ilk that use bit fields
844 			if (rTemp.data.size == 1) {
845 				unsigned char d = mData[0];
846 				if (rTemp.data.shiftbits)
847 					d >>= rTemp.data.shiftbits;
848 				d &= rTemp.data.andmask;
849 				mData[0] = d;
850 			}
851 			if (!lbwREPLY.empty())
852 				pbw = &lbwREPLY;
853 			else if (lbws.empty() == false)
854 				pbw = &lbws;
855 			else
856 				goto retry_get_width;
857 
858 			bw = pbw->begin();
859 			while (bw != pbw->end()) {
860 				if ((*bw).BYTES == mData)
861 					break;
862 				bw++;
863 			}
864 			if (bw != pbw->end())
865 				return ((*bw).SYMBOL);
866 retry_get_width: ;
867 		}
868 	}
869 	if (progdefaults.RigCatVSP == false)
870 		LOG_ERROR("%s failed", symbol);
871 	return "";
872 }
873 
rigCAT_setwidth(const string & w)874 void rigCAT_setwidth(const string& w)
875 {
876 	const char symbol[] = "SETBW";
877 
878 	if (rigCAT_exit || xmlrig.noserial || !xmlrig.xmlok)
879 		progStatus.noCATwidth = w;
880 
881 	if (rigCAT_exit || !xmlrig.xmlok) return;
882 
883 	XMLIOS modeCmd;
884 	list<XMLIOS>::iterator itrCmd;
885 	string strCmd;
886 
887 	itrCmd = commands.begin();
888 	while (itrCmd != commands.end()) {
889 		if ((*itrCmd).SYMBOL == symbol)
890 			break;
891 		++itrCmd;
892 	}
893 	if (itrCmd == commands.end()) {
894 		if (xmlrig.debug) LOG_INFO("%s not defined", symbol);
895 		progStatus.noCATwidth = w;
896 		return;
897 	}
898 	modeCmd = *itrCmd;
899 
900 	if ( modeCmd.str1.empty() == false)
901 		strCmd.append(modeCmd.str1);
902 
903 	if ( modeCmd.data.size > 0 ) {
904 
905 		list<BW>::iterator bw;
906 		list<BW> *pbw;
907 		if (lbws.empty() == false)
908 			pbw = &lbws;
909 		else if (lbwCMD.empty() == false)
910 			pbw = &lbwCMD;
911 		else
912 			return;
913 		bw = pbw->begin();
914 		while (bw != pbw->end()) {
915 			if ((*bw).SYMBOL == w)
916 				break;
917 			bw++;
918 		}
919 		if (bw != pbw->end())
920 			strCmd.append( (*bw).BYTES );
921 	}
922 	if (modeCmd.str2.empty() == false)
923 		strCmd.append(modeCmd.str2);
924 
925 	if (modeCmd.ok.size()) {
926 		list<XMLIOS>::iterator preply = reply.begin();
927 		while (preply != reply.end()) {
928 			if (preply->SYMBOL == modeCmd.ok) {
929 				XMLIOS  rTemp = *preply;
930 // send the command
931 				for (int n = 0; n < progdefaults.RigCatRetries; n++) {
932 					if (rigCAT_exit) return;
933 					guard_lock ser_guard( &rigCAT_mutex );
934 					if (sendCommand(symbol, strCmd, rTemp.size, progdefaults.RigCatWait)) return;
935 					MilliSleep(50);
936 				}
937 			}
938 			preply++;
939 		}
940 	} else {
941 		for (int n = 0; n < progdefaults.RigCatRetries; n++) {
942 			if (rigCAT_exit) return;
943 			guard_lock ser_guard( &rigCAT_mutex );
944 			if (sendCommand(symbol, strCmd, 0, progdefaults.RigCatWait)) return;
945 			MilliSleep(50);
946 		}
947 	}
948 	LOG_ERROR("%s failed", symbol);
949 }
950 
rigCAT_pttON()951 void rigCAT_pttON()
952 {
953 	const char symbol[] = "PTTON";
954 
955 	if (rigCAT_exit) return;
956 
957 	XMLIOS modeCmd;
958 	list<XMLIOS>::iterator itrCmd;
959 	string strCmd;
960 
961 	rigio.SetPTT(1); // always execute the h/w ptt if enabled
962 
963 	itrCmd = commands.begin();
964 	while (itrCmd != commands.end()) {
965 		if ((*itrCmd).SYMBOL == symbol)
966 			break;
967 		++itrCmd;
968 	}
969 	if (itrCmd == commands.end()) {
970 		if (xmlrig.debug) LOG_INFO("%s not defined", symbol);
971 		return;
972 	}
973 
974 	modeCmd = *itrCmd;
975 
976 	if ( modeCmd.str1.empty() == false)
977 		strCmd.append(modeCmd.str1);
978 	if (modeCmd.str2.empty() == false)
979 		strCmd.append(modeCmd.str2);
980 
981 	if (modeCmd.ok.size()) {
982 //		if (xmlrig.debug)
983 //			LOG_INFO("OK string: %s", str2hex(modeCmd.ok.c_str(), modeCmd.ok.size()) );
984 
985 		list<XMLIOS>::iterator preply = reply.begin();
986 		while (preply != reply.end()) {
987 			if (preply->SYMBOL == modeCmd.ok) {
988 				XMLIOS  rTemp = *preply;
989 // send the command
990 				for (int n = 0; n < progdefaults.RigCatRetries; n++) {
991 					if (rigCAT_exit) return;
992 					guard_lock ser_guard( &rigCAT_mutex );
993 					if (sendCommand(symbol, strCmd, rTemp.size, progdefaults.RigCatWait)) return;
994 					MilliSleep(50);
995 				}
996 				return;
997 			}
998 			preply++;
999 		}
1000 	} else {
1001 		for (int n = 0; n < progdefaults.RigCatRetries; n++) {
1002 			if (rigCAT_exit) return;
1003 			guard_lock ser_guard( &rigCAT_mutex );
1004 			if (sendCommand(symbol, strCmd, 0, progdefaults.RigCatWait)) return;
1005 			MilliSleep(50);
1006 		}
1007 	}
1008 	LOG_VERBOSE("%s failed", symbol);
1009 }
1010 
rigCAT_pttOFF()1011 void rigCAT_pttOFF()
1012 {
1013 	const char symbol[] = "PTTOFF";
1014 
1015 	if (rigCAT_exit) return;
1016 
1017 	XMLIOS modeCmd;
1018 	list<XMLIOS>::iterator itrCmd;
1019 	string strCmd;
1020 
1021 	rigio.SetPTT(0); // always execute the h/w ptt if enabled
1022 
1023 	itrCmd = commands.begin();
1024 	while (itrCmd != commands.end()) {
1025 		if ((*itrCmd).SYMBOL == symbol)
1026 			break;
1027 		++itrCmd;
1028 	}
1029 	if (itrCmd == commands.end()) {
1030 		if (xmlrig.debug) LOG_INFO("%s not defined", symbol);
1031 		return;
1032 	}
1033 
1034 	modeCmd = *itrCmd;
1035 
1036 	if ( modeCmd.str1.empty() == false)
1037 		strCmd.append(modeCmd.str1);
1038 	if (modeCmd.str2.empty() == false)
1039 		strCmd.append(modeCmd.str2);
1040 
1041 	if (modeCmd.ok.size()) {
1042 		list<XMLIOS>::iterator preply = reply.begin();
1043 		while (preply != reply.end()) {
1044 			if (preply->SYMBOL == modeCmd.ok) {
1045 				XMLIOS  rTemp = *preply;
1046 // send the command
1047 				for (int n = 0; n < progdefaults.RigCatRetries; n++) {
1048 					if (rigCAT_exit) return;
1049 					guard_lock ser_guard( &rigCAT_mutex );
1050 					if (sendCommand(symbol, strCmd, rTemp.size, progdefaults.RigCatWait)) return;
1051 					MilliSleep(50);
1052 				}
1053 				return;
1054 			}
1055 			preply++;
1056 		}
1057 	} else {
1058 		for (int n = 0; n < progdefaults.RigCatRetries; n++) {
1059 			if (rigCAT_exit) return;
1060 			guard_lock ser_guard( &rigCAT_mutex );
1061 			if (sendCommand(symbol, strCmd, 0, progdefaults.RigCatWait)) return;
1062 			MilliSleep(50);
1063 		}
1064 	}
1065 	LOG_ERROR("%s failed", symbol);
1066 }
1067 
rigCAT_sendINIT(const string & icmd,int multiplier)1068 void rigCAT_sendINIT(const string& icmd, int multiplier)
1069 {
1070 	if (rigCAT_exit) return;
1071 	const char symbol[] = "INIT";
1072 
1073 	XMLIOS modeCmd;
1074 	list<XMLIOS>::iterator itrCmd;
1075 	string strCmd;
1076 
1077 	itrCmd = commands.begin();
1078 	while (itrCmd != commands.end()) {
1079 		if ((*itrCmd).SYMBOL == icmd)
1080 			break;
1081 		++itrCmd;
1082 	}
1083 	if (itrCmd == commands.end())
1084 		return;
1085 	modeCmd = *itrCmd;
1086 
1087 	if ( modeCmd.str1.empty() == false)
1088 		strCmd.append(modeCmd.str1);
1089 	if (modeCmd.str2.empty() == false)
1090 		strCmd.append(modeCmd.str2);
1091 
1092 	if (modeCmd.ok.size()) {
1093 		list<XMLIOS>::iterator preply = reply.begin();
1094 		while (preply != reply.end()) {
1095 			if (preply->SYMBOL == modeCmd.ok) {
1096 				XMLIOS  rTemp = *preply;
1097 // send the command
1098 				for (int n = 0; n < progdefaults.RigCatRetries; n++) {
1099 					if (rigCAT_exit) return;
1100 					guard_lock ser_guard( &rigCAT_mutex );
1101 					if (sendCommand(symbol, strCmd, rTemp.size, progdefaults.RigCatInitDelay)) return;
1102 					MilliSleep(50);
1103 				}
1104 				return;
1105 			}
1106 			preply++;
1107 		}
1108 	} else {
1109 		for (int n = 0; n < progdefaults.RigCatRetries; n++) {
1110 			if (rigCAT_exit) return;
1111 			guard_lock ser_guard( &rigCAT_mutex );
1112 			if (sendCommand(symbol, strCmd, 0, progdefaults.RigCatInitDelay)) return;
1113 			MilliSleep(50);
1114 		}
1115 	}
1116 	LOG_ERROR("INIT failed");
1117 }
1118 
rigCAT_defaults()1119 void rigCAT_defaults()
1120 {
1121 	listbox_xml_rig_baudrate->index(xmlrig.baud);
1122 	valRigCatStopbits->value(xmlrig.stopbits);
1123 	btnRigCatRTSplus->value(xmlrig.rts);
1124 	btnRigCatDTRplus->value(xmlrig.dtr);
1125 	btnRigCatRTSptt->value(xmlrig.rtsptt);
1126 	btnRigCatDTRptt->value(xmlrig.dtrptt);
1127 	chk_restore_tio->value(xmlrig.restore_tio);
1128 	chkRigCatRTSCTSflow->value(xmlrig.rtscts);
1129 	cntRigCatRetries->value(xmlrig.retries);
1130 	cntRigCatTimeout->value(xmlrig.timeout);
1131 	cntRigCatWait->value(xmlrig.write_delay);
1132 	cntRigCatInitDelay->value(xmlrig.init_delay);
1133 //	cntRigCatWaitForDevice->value(xmlrig.wait_for_device);
1134 	btnRigCatEcho->value(xmlrig.echo);
1135 	btnRigCatCMDptt->value(xmlrig.cmdptt);
1136 	chkRigCatVSP->value(xmlrig.vsp);
1137 }
1138 
rigCAT_init_defaults()1139 void rigCAT_init_defaults()
1140 {
1141 	progdefaults.XmlRigDevice = inpXmlRigDevice->value();
1142 	progdefaults.XmlRigBaudrate = listbox_xml_rig_baudrate->index();
1143 	progdefaults.RigCatStopbits = static_cast<int>(valRigCatStopbits->value());
1144 	progdefaults.RigCatRTSplus = btnRigCatRTSplus->value();
1145 	progdefaults.RigCatDTRplus = btnRigCatDTRplus->value();
1146 	progdefaults.RigCatRTSptt = btnRigCatRTSptt->value();
1147 	progdefaults.RigCatDTRptt = btnRigCatDTRptt->value();
1148 	progdefaults.RigCatRestoreTIO = chk_restore_tio->value();
1149 	progdefaults.RigCatRTSCTSflow = chkRigCatRTSCTSflow->value();
1150 	progdefaults.RigCatRetries = static_cast<int>(cntRigCatRetries->value());
1151 	progdefaults.RigCatTimeout = static_cast<int>(cntRigCatTimeout->value());
1152 	progdefaults.RigCatWait = static_cast<int>(cntRigCatWait->value());
1153 	progdefaults.RigCatInitDelay = static_cast<int>(cntRigCatInitDelay->value());
1154 	progdefaults.RigCatECHO = btnRigCatEcho->value();
1155 	progdefaults.RigCatCMDptt = btnRigCatCMDptt->value();
1156 	progdefaults.RigCatVSP = chkRigCatVSP->value();
1157 }
1158 
rigCAT_init()1159 bool rigCAT_init()
1160 {
1161 
1162 	if (rigCAT_open == true) {
1163 		LOG_ERROR("RigCAT already open");
1164 		return false;
1165 	}
1166 
1167 	sRigMode = "";
1168 	sRigWidth = "";
1169 
1170 	rigCAT_init_defaults();
1171 	rigio.Device(progdefaults.XmlRigDevice);
1172 	rigio.Baud(progdefaults.BaudRate(progdefaults.XmlRigBaudrate));
1173 	rigio.RTS(progdefaults.RigCatRTSplus);
1174 	rigio.DTR(progdefaults.RigCatDTRplus);
1175 	rigio.RTSptt(progdefaults.RigCatRTSptt);
1176 	rigio.DTRptt(progdefaults.RigCatDTRptt);
1177 	rigio.RestoreTIO(progdefaults.RigCatRestoreTIO);
1178 	rigio.RTSCTS(progdefaults.RigCatRTSCTSflow);
1179 	rigio.Stopbits(progdefaults.RigCatStopbits);
1180 
1181 	LOG_INFO("\n\
1182 Serial port parameters:\n\
1183 device	 : %s\n\
1184 baudrate   : %d\n\
1185 stopbits   : %d\n\
1186 retries	: %d\n\
1187 timeout	: %d\n\
1188 wait	   : %d\n\
1189 initial rts: %+d\n\
1190 use rts ptt: %c\n\
1191 initial dtr: %+d\n\
1192 use dtr ptt: %c\n\
1193 restore tio: %c\n\
1194 flowcontrol: %c\n\
1195 echo	   : %c\n",
1196 		rigio.Device().c_str(),
1197 		rigio.Baud(),
1198 		rigio.Stopbits(),
1199 		progdefaults.RigCatRetries,
1200 		progdefaults.RigCatTimeout,
1201 		progdefaults.RigCatWait,
1202 			(rigio.RTS() ? +12 : -12), (rigio.RTSptt() ? 'T' : 'F'),
1203 			(rigio.DTR() ? +12 : -12), (rigio.DTRptt() ? 'T' : 'F'),
1204 			(rigio.RestoreTIO() ? 'T' : 'F'),
1205 			(rigio.RTSCTS() ? 'T' : 'F'),
1206 			progdefaults.RigCatECHO ? 'T' : 'F');
1207 
1208 	if (xmlrig.noserial == false && xmlrig.xmlok) {
1209 		if (rigio.OpenPort() == false) {
1210 			LOG_ERROR("Cannot open serial port %s", rigio.Device().c_str());
1211 			xmlrig.xmlok = true;
1212 		}
1213 	}
1214 
1215 	sRigMode = "";
1216 	sRigWidth = "";
1217 
1218 	if (xmlrig.wait_for_device) {
1219 		int delay = xmlrig.wait_for_device / 10;
1220 		while (delay) {
1221 			MilliSleep(10);
1222 			if (delay % 10) Fl::awake();
1223 			delay--;
1224 		}
1225 	}
1226 
1227 	rigCAT_sendINIT("INIT", progdefaults.RigCatInitDelay);
1228 	bool failed = false;
1229 
1230 	if (xmlrig.noserial)
1231 		rigCAT_getfreq(1, failed, 0);
1232 	else if (xmlrig.xmlok) {
1233 		rigCAT_getfreq(3, failed, progdefaults.RigCatInitDelay);
1234 
1235 		if (failed) {
1236 			LOG_ERROR("*****************Failed to read xcvr frequency");
1237 			if (xmlrig.noserial == false)
1238 				rigio.ClosePort();
1239 			xmlrig.xmlok = false;
1240 		} else
1241 			LOG_INFO("Passed serial port test");
1242 	}
1243 
1244 	llFreq = 0;
1245 
1246 	if (pthread_create(&rigCAT_thread, NULL, rigCAT_loop, NULL) < 0) {
1247 		LOG_ERROR("%s", "pthread_create failed");
1248 		if (xmlrig.xmlok && !xmlrig.noserial)
1249 			rigio.ClosePort();
1250 		xmlrig.xmlok = false;
1251 		return false;
1252 	}
1253 
1254 	LOG_INFO("Created rigCAT thread");
1255 
1256 	rigCAT_open = true;
1257 
1258 	init_Xml_RigDialog();
1259 
1260 	return true;
1261 }
1262 
rigCAT_close(void)1263 void rigCAT_close(void)
1264 {
1265 	if ( rigCAT_open == false || rigCAT_exit == true)
1266 		return;
1267 
1268 	rigCAT_sendINIT("CLOSE");
1269 
1270 	{
1271 		guard_lock ser_guard( &rigCAT_mutex );
1272 		rigCAT_exit = true;
1273 	}
1274 
1275 	LOG_INFO("%s", "Waiting for rigCAT_thread");
1276 
1277 	pthread_join(rigCAT_thread, NULL);
1278 
1279 	rigio.ClosePort();
1280 
1281 	rigCAT_exit = false;
1282 	rigCAT_open = false;
1283 	wf->USB(true);
1284 
1285 }
1286 
rigCAT_active(void)1287 bool rigCAT_active(void)
1288 {
1289 	return (rigCAT_open);
1290 }
1291 
rigCAT_set_ptt(int ptt)1292 void rigCAT_set_ptt(int ptt)
1293 {
1294 	if (progdefaults.CATkeying_disable_ptt &&
1295 		( progdefaults.use_ELCTkeying ||
1296 		  progdefaults.use_ICOMkeying ||
1297 		  progdefaults.use_KNWDkeying ||
1298 		  progdefaults.use_YAESUkeying ) &&
1299 		  active_modem->get_mode() == MODE_CW )
1300 		return;
1301 
1302 	if (rigCAT_open == false)
1303 		return;
1304 	if (ptt) {
1305 		rigCAT_pttON();
1306 	} else{
1307 		rigCAT_pttOFF();
1308 	}
1309 }
1310 
1311 #ifndef RIGCATTEST
rigCAT_set_qsy(long long f)1312 void rigCAT_set_qsy(long long f)
1313 {
1314 	if (rigCAT_open == false)
1315 		return;
1316 
1317 	// send new freq to rig
1318 	rigCAT_setfreq(f);
1319 	wf->rfcarrier(f);
1320 	wf->movetocenter();
1321 }
1322 #endif
1323 
ModeIsLSB(string s)1324 bool ModeIsLSB(string s)
1325 {
1326 	if (connected_to_flrig) return !xmlrpc_USB();
1327 #if USE_HAMLIB
1328 	if (hamlib_active()) return !hamlib_USB();
1329 #endif
1330 	list<string>::iterator pM = LSBmodes.begin();
1331 	while (pM != LSBmodes.end() ) {
1332 		if (*pM == s)
1333 			return true;
1334 		pM++;
1335 	}
1336 	return false;
1337 }
1338 
smeter_data(DATA d,size_t p)1339 int smeter_data(DATA d, size_t p)
1340 {
1341 	int val = 0;
1342 
1343 	if (d.dtype == "BCD") {
1344 		if (d.reverse == true)
1345 			val = (int)(fm_bcd_be(p, d.size));
1346 		else
1347 			val = (int)(fm_bcd(p, d.size));
1348 	} else if (d.dtype == "BINARY") {
1349 		if (d.reverse == true)
1350 			val = (int)(fm_binary_be(p, d.size));
1351 		else
1352 			val = (int)(fm_binary(p, d.size));
1353 	} else if (d.dtype == "DECIMAL") {
1354 		if (d.reverse == true)
1355 			val = (int)(fm_decimal_be(p, d.size));
1356 		else
1357 			val = (int)(fm_decimal(p, d.size));
1358 	}
1359 
1360 	size_t n;
1361 	int sm1, sm2, val1, val2;
1362 	for (n = 0; n < xmlrig.smeter.size() - 1; n++) {
1363 		if ((val >= xmlrig.smeter[n].val) && (val < xmlrig.smeter[n+1].val)) break;
1364 	}
1365 	if (n == xmlrig.smeter.size() - 1) return 0;
1366 	sm1 = xmlrig.smeter[n].mtr;
1367 	sm2 = xmlrig.smeter[n+1].mtr;
1368 	val1 = xmlrig.smeter[n].val;
1369 	val2 = xmlrig.smeter[n+1].val;
1370 
1371 	if (val1 == val2) return 0;
1372 	int mtr = sm1 + (val - val1) * (sm2 - sm1) / (val2 - val1);
1373 
1374 	return mtr;
1375 }
1376 
rigcat_set_smeter(void * data)1377 static void rigcat_set_smeter(void *data)
1378 {
1379 	if (pwrlevel_grp->visible()) return;
1380 	if (!smeter && !pwrmeter) return;
1381 
1382 	if (smeter && progStatus.meters) {
1383 		if (!smeter->visible()) {
1384 			pwrmeter->hide();
1385 			smeter->show();
1386 		}
1387 		int val = reinterpret_cast<intptr_t>(data);
1388 		smeter->value(val);
1389 	}
1390 }
1391 
rigCAT_get_smeter()1392 void rigCAT_get_smeter()
1393 {
1394 	const char symbol[] = "GET_SMETER";
1395 
1396 	if (rigCAT_exit || xmlrig.noserial) return;
1397 
1398 	XMLIOS modeCmd;
1399 	list<XMLIOS>::iterator itrCmd;
1400 	string strCmd;
1401 	size_t p = 0, len1 = 0, len2 = 0, pData = 0;
1402 	long mtr = 0;
1403 
1404 	itrCmd = commands.begin();
1405 	while (itrCmd != commands.end()) {
1406 		if ((*itrCmd).SYMBOL == symbol)
1407 			break;
1408 		++itrCmd;
1409 	}
1410 
1411 	if (itrCmd == commands.end()) {
1412 		if (xmlrig.debug) LOG_INFO("%s not defined", symbol);
1413 		return;
1414 	}
1415 
1416 	modeCmd = *itrCmd;
1417 	if ( !modeCmd.str1.empty() ) strCmd.append(modeCmd.str1);
1418 	if ( !modeCmd.str2.empty() ) strCmd.append(modeCmd.str2);
1419 	if ( !modeCmd.info.size() ) return;
1420 
1421 	list<XMLIOS>::iterator preply;
1422 
1423 	for (preply = reply.begin(); preply != reply.end(); ++preply) {
1424 		if (preply->SYMBOL == modeCmd.info)
1425 			break;
1426 	}
1427 	if (preply == reply.end()) return;
1428 
1429 	XMLIOS  rTemp = *preply;
1430 	len1 = rTemp.str1.size();
1431 	len2 = rTemp.str2.size();
1432 
1433 	int timeout = progdefaults.RigCatTimeout;
1434 	while (timeout > 50) {
1435 		MilliSleep(50);
1436 		Fl::awake();
1437 		timeout -= 50;
1438 	}
1439 	if (timeout) {
1440 		MilliSleep(timeout);
1441 		Fl::awake();
1442 	}
1443 
1444 // send the command
1445 	int sendok;
1446 	{
1447 		guard_lock ser_guard(&rigCAT_mutex);
1448 		sendok = sendCommand(symbol, strCmd, rTemp.size, progdefaults.RigCatWait);
1449 	}
1450 	if ( !sendok ) {
1451 		LOG_ERROR("sendCommand failed");
1452 		return;
1453 	}
1454 
1455 // check the pre data string
1456 	p = 0;
1457 	pData = 0;
1458 	if (len1) {
1459 		for (size_t i = 0; i < len1; i++) {
1460 			if ((char)rTemp.str1[i] != (char)replybuff[i]) {
1461 				unsigned int ui = i;
1462 				LOG_ERROR("failed pre data string test @ %u", ui);
1463 				return;
1464 			}
1465 		}
1466 		p = len1;
1467 	}
1468 	if (rTemp.fill1) p += rTemp.fill1;
1469 	pData = p;
1470 	if (rTemp.data.dtype == "BCD") {
1471 		p += rTemp.data.size / 2;
1472 		if (rTemp.data.size & 1) p++;
1473 	} else
1474 		p += rTemp.data.size;
1475 // check the post data string
1476 	if (rTemp.fill2) p += rTemp.fill2;
1477 	if (len2) {
1478 		for (size_t i = 0; i < len2; i++)
1479 			if ((char)rTemp.str2[i] != (char)replybuff[p + i]) {
1480 				LOG_ERROR("failed post data string test @ %d", static_cast<int>(i));
1481 				return;
1482 			}
1483 	}
1484 // convert the data field
1485 	mtr = smeter_data(rTemp.data, pData);
1486 //	if (xmlrig.debug) LOG_INFO("Converted %s value to %d", symbol, (int)mtr);
1487 
1488 	REQ(rigcat_set_smeter, reinterpret_cast<void *>(mtr));
1489 }
1490 
pmeter_data(DATA d,size_t p)1491 int pmeter_data(DATA d, size_t p)
1492 {
1493 	int val = 0;
1494 
1495 	if (d.dtype == "BCD") {
1496 		if (d.reverse == true)
1497 			val = (int)(fm_bcd_be(p, d.size));
1498 		else
1499 			val = (int)(fm_bcd(p, d.size));
1500 	} else if (d.dtype == "BINARY") {
1501 		if (d.reverse == true)
1502 			val = (int)(fm_binary_be(p, d.size));
1503 		else
1504 			val = (int)(fm_binary(p, d.size));
1505 	} else if (d.dtype == "DECIMAL") {
1506 		if (d.reverse == true)
1507 			val = (int)(fm_decimal_be(p, d.size));
1508 		else
1509 			val = (int)(fm_decimal(p, d.size));
1510 	}
1511 
1512 	size_t n;
1513 	int pm1, pm2, val1, val2;
1514 	for (n = 0; n < xmlrig.pmeter.size() - 1; n++) {
1515 		if ((val > xmlrig.pmeter[n].val) && (val <= xmlrig.pmeter[n+1].val)) break;
1516 	}
1517 	if (n == xmlrig.pmeter.size() - 1) return 0;
1518 	pm1 = xmlrig.pmeter[n].mtr;
1519 	pm2 = xmlrig.pmeter[n+1].mtr;
1520 	val1 = xmlrig.pmeter[n].val;
1521 	val2 = xmlrig.pmeter[n+1].val;
1522 
1523 	if (val1 == val2) return 0;
1524 	int mtr = pm1 + (val - val1) * (pm2 - pm1) / (val2 - val1);
1525 
1526 	return mtr;
1527 }
1528 
rigcat_set_pmeter(void * data)1529 static void rigcat_set_pmeter(void *data)
1530 {
1531 	if (pwrlevel_grp->visible()) return;
1532 	if (!smeter && !pwrmeter) return;
1533 
1534 	if (pwrmeter && progStatus.meters) {
1535 		if (!pwrmeter->visible()) {
1536 			smeter->hide();
1537 			pwrmeter->show();
1538 		}
1539 		int val = reinterpret_cast<intptr_t>(data);
1540 		pwrmeter->value(val);
1541 	}
1542 }
1543 
rigCAT_get_pwrmeter()1544 void rigCAT_get_pwrmeter()
1545 {
1546 	const char symbol[] = "GET_PWRMETER";
1547 
1548 	if (rigCAT_exit || xmlrig.noserial) return;
1549 
1550 	XMLIOS modeCmd;
1551 	list<XMLIOS>::iterator itrCmd;
1552 	string strCmd;
1553 	size_t p = 0, len1 = 0, len2 = 0, pData = 0;
1554 	long mtr = 0;
1555 
1556 	itrCmd = commands.begin();
1557 	while (itrCmd != commands.end()) {
1558 		if ((*itrCmd).SYMBOL == symbol)
1559 			break;
1560 		++itrCmd;
1561 	}
1562 
1563 	if (itrCmd == commands.end()) {
1564 		if (xmlrig.debug) LOG_INFO("%s not defined", symbol);
1565 		return;
1566 	}
1567 
1568 	modeCmd = *itrCmd;
1569 	if ( !modeCmd.str1.empty() ) strCmd.append(modeCmd.str1);
1570 	if ( !modeCmd.str2.empty() ) strCmd.append(modeCmd.str2);
1571 	if ( !modeCmd.info.size() ) return;
1572 
1573 	list<XMLIOS>::iterator preply;
1574 
1575 	for (preply = reply.begin(); preply != reply.end(); ++preply) {
1576 		if (preply->SYMBOL == modeCmd.info)
1577 			break;
1578 	}
1579 	if (preply == reply.end()) return;
1580 
1581 	XMLIOS  rTemp = *preply;
1582 	len1 = rTemp.str1.size();
1583 	len2 = rTemp.str2.size();
1584 
1585 	int timeout = progdefaults.RigCatTimeout;
1586 	while (timeout > 50) {
1587 		MilliSleep(50);
1588 		Fl::awake();
1589 		timeout -= 50;
1590 	}
1591 	if (timeout) {
1592 		MilliSleep(timeout);
1593 		Fl::awake();
1594 	}
1595 
1596 // send the command
1597 	int sendok;
1598 	{
1599 		guard_lock ser_guard(&rigCAT_mutex);
1600 		sendok = sendCommand(symbol, strCmd, rTemp.size, progdefaults.RigCatWait);
1601 	}
1602 	if ( !sendok ) {
1603 		LOG_ERROR("sendCommand failed");
1604 		return;
1605 	}
1606 
1607 // check the pre data string
1608 	p = 0;
1609 	pData = 0;
1610 	if (len1) {
1611 		for (size_t i = 0; i < len1; i++) {
1612 			if ((char)rTemp.str1[i] != (char)replybuff[i]) {
1613 				unsigned int ui = i;
1614 				LOG_ERROR("failed pre data string test @ %u", ui);
1615 				return;
1616 			}
1617 		}
1618 		p = len1;
1619 	}
1620 	if (rTemp.fill1) p += rTemp.fill1;
1621 	pData = p;
1622 	if (rTemp.data.dtype == "BCD") {
1623 		p += rTemp.data.size / 2;
1624 		if (rTemp.data.size & 1) p++;
1625 	} else
1626 		p += rTemp.data.size;
1627 // check the post data string
1628 	if (rTemp.fill2) p += rTemp.fill2;
1629 	if (len2) {
1630 		for (size_t i = 0; i < len2; i++)
1631 			if ((char)rTemp.str2[i] != (char)replybuff[p + i]) {
1632 				LOG_ERROR("failed post data string test @ %d", static_cast<int>(i));
1633 				return;
1634 			}
1635 	}
1636 // convert the data field
1637 	mtr = pmeter_data(rTemp.data, pData);
1638 	if (xmlrig.debug) LOG_INFO("Converted %s to %d", symbol, (int)mtr);
1639 
1640 	REQ(rigcat_set_pmeter, reinterpret_cast<void *>(mtr));
1641 
1642 }
1643 
rigcat_notch(void * data)1644 static void rigcat_notch(void *data)
1645 {
1646 	int val = reinterpret_cast<intptr_t>(data);
1647 	notch_frequency = val;
1648 }
1649 
notch_data(DATA d,size_t p)1650 int notch_data(DATA d, size_t p)
1651 {
1652 	int val = 0;
1653 
1654 	if (d.dtype == "BCD") {
1655 		if (d.reverse == true)
1656 			val = (int)(fm_bcd_be(p, d.size));
1657 		else
1658 			val = (int)(fm_bcd(p, d.size));
1659 	} else if (d.dtype == "BINARY") {
1660 		if (d.reverse == true)
1661 			val = (int)(fm_binary_be(p, d.size));
1662 		else
1663 			val = (int)(fm_binary(p, d.size));
1664 	} else if (d.dtype == "DECIMAL") {
1665 		if (d.reverse == true)
1666 			val = (int)(fm_decimal_be(p, d.size));
1667 		else
1668 			val = (int)(fm_decimal(p, d.size));
1669 	}
1670 
1671 	size_t n;
1672 	int ntch1, ntch2, val1, val2;
1673 	for (n = 0; n < xmlrig.notch.size() - 1; n++) {
1674 		if ((val > xmlrig.notch[n].val) && (val <= xmlrig.notch[n+1].val))
1675 			break;
1676 	}
1677 	if (n == xmlrig.notch.size() - 1)
1678 		return 0;
1679 
1680 	val1 = xmlrig.notch[n].val;
1681 	val2 = xmlrig.notch[n+1].val;
1682 	if (val1 == val2)
1683 		return 0;
1684 
1685 	ntch1 = xmlrig.notch[n].mtr;
1686 	ntch2 = xmlrig.notch[n+1].mtr;
1687 
1688 	return ntch1 + (val - val1) * (ntch2 - ntch1) / (val2 - val1);
1689 }
1690 
notch_val(int freq)1691 int notch_val(int freq)
1692 {
1693 	size_t n;
1694 	int val1, val2, freq1, freq2;
1695 	for (n = 0; n < xmlrig.notch.size() - 1; n++) {
1696 		if ((freq > xmlrig.notch[n].mtr) && (freq <= xmlrig.notch[n+1].mtr))
1697 			break;
1698 	}
1699 	if (n == xmlrig.notch.size() - 1)
1700 		return 0;
1701 
1702 	freq1 = xmlrig.notch[n].mtr;
1703 	freq2 = xmlrig.notch[n+1].mtr;
1704 
1705 	if (freq1 == freq2)
1706 		return 0;
1707 
1708 	val1 = xmlrig.notch[n].val;
1709 	val2 = xmlrig.notch[n+1].val;
1710 
1711 	return val1 + (freq - freq1) * (val2 - val1) / (freq2 - freq1);
1712 
1713 }
1714 
rigCAT_notchON()1715 bool rigCAT_notchON()
1716 {
1717 	const char symbol[] = "GET_NOTCH_ON";
1718 
1719 	if (rigCAT_exit) return 0;
1720 
1721 	XMLIOS modeCmd;
1722 	list<XMLIOS>::iterator itrCmd;
1723 	string strCmd;
1724 	size_t len1 = 0;
1725 
1726 	itrCmd = commands.begin();
1727 	while (itrCmd != commands.end()) {
1728 		if ((*itrCmd).SYMBOL == symbol)
1729 			break;
1730 		++itrCmd;
1731 	}
1732 
1733 	if (itrCmd == commands.end()) {
1734 		if (xmlrig.debug) LOG_INFO("%s not defined", symbol);
1735 		return 0;
1736 	}
1737 
1738 	modeCmd = *itrCmd;
1739 	if ( !modeCmd.str1.empty() ) strCmd.append(modeCmd.str1);
1740 	if ( !modeCmd.str2.empty() ) strCmd.append(modeCmd.str2);
1741 	if ( !modeCmd.info.size() ) return 0;
1742 
1743 	list<XMLIOS>::iterator preply;
1744 
1745 	for (preply = reply.begin(); preply != reply.end(); ++preply) {
1746 		if (preply->SYMBOL == modeCmd.info)
1747 			break;
1748 	}
1749 	if (preply == reply.end()) return 0;
1750 
1751 	XMLIOS  rTemp = *preply;
1752 	len1 = rTemp.str1.size();
1753 
1754 	int timeout = progdefaults.RigCatTimeout;
1755 	while (timeout > 50) {
1756 		MilliSleep(50);
1757 		Fl::awake();
1758 		timeout -= 50;
1759 	}
1760 	if (timeout) {
1761 		MilliSleep(timeout);
1762 		Fl::awake();
1763 	}
1764 
1765 // send the command
1766 	int sendok;
1767 	{
1768 		guard_lock ser_guard(&rigCAT_mutex);
1769 		sendok = sendCommand(symbol, strCmd, rTemp.size, progdefaults.RigCatWait );
1770 	}
1771 	if ( !sendok ) {
1772 		LOG_ERROR("sendCommand failed");
1773 		return 0;
1774 	}
1775 
1776 	bool is_on = true;
1777 	if (len1) {
1778 		for (size_t i = 0; i < len1; i++) {
1779 			if ((char)rTemp.str1[i] != (char)replybuff[i]) {
1780 				is_on = false;
1781 				break;
1782 			}
1783 		}
1784 	} else
1785 		is_on = false;
1786 
1787 //	if (xmlrig.debug) LOG_INFO("%s is %s", symbol, is_on ? "ON" : "OFF");
1788 	return is_on;
1789 }
1790 
rigCAT_get_notch()1791 void rigCAT_get_notch()
1792 {
1793 	const char symbol[] = "GET_NOTCH";
1794 
1795 	if (rigCAT_exit) return;
1796 
1797 	if (!rigCAT_notchON()) {
1798 		REQ(rigcat_notch, reinterpret_cast<void *>(0));
1799 		return;
1800 	}
1801 	XMLIOS modeCmd;
1802 	list<XMLIOS>::iterator itrCmd;
1803 	string strCmd;
1804 	size_t p = 0, len1 = 0, len2 = 0, pData = 0;
1805 	long ntch = 0;
1806 
1807 	itrCmd = commands.begin();
1808 	while (itrCmd != commands.end()) {
1809 		if ((*itrCmd).SYMBOL == symbol)
1810 			break;
1811 		++itrCmd;
1812 	}
1813 
1814 	if (itrCmd == commands.end()) {
1815 		if (xmlrig.debug) LOG_INFO("%s not defined", symbol);
1816 		return;
1817 	}
1818 
1819 	modeCmd = *itrCmd;
1820 	if ( !modeCmd.str1.empty() ) strCmd.append(modeCmd.str1);
1821 	if ( !modeCmd.str2.empty() ) strCmd.append(modeCmd.str2);
1822 	if ( !modeCmd.info.size() ) return;
1823 
1824 	list<XMLIOS>::iterator preply;
1825 
1826 	for (preply = reply.begin(); preply != reply.end(); ++preply) {
1827 		if (preply->SYMBOL == modeCmd.info)
1828 			break;
1829 	}
1830 	if (preply == reply.end()) return;
1831 
1832 	XMLIOS  rTemp = *preply;
1833 	len1 = rTemp.str1.size();
1834 	len2 = rTemp.str2.size();
1835 
1836 	int timeout = progdefaults.RigCatTimeout;
1837 	while (timeout > 50) {
1838 		MilliSleep(50);
1839 		Fl::awake();
1840 		timeout -= 50;
1841 	}
1842 	if (timeout) {
1843 		MilliSleep(timeout);
1844 		Fl::awake();
1845 	}
1846 
1847 // send the command
1848 	int sendok;
1849 	{
1850 		guard_lock ser_guard(&rigCAT_mutex);
1851 		sendok = sendCommand(symbol, strCmd, rTemp.size,progdefaults.RigCatWait);
1852 	}
1853 	if ( !sendok ) {
1854 		LOG_ERROR("sendCommand failed");
1855 		return;
1856 	}
1857 
1858 // check the pre data string
1859 	p = 0;
1860 	pData = 0;
1861 	if (len1) {
1862 		for (size_t i = 0; i < len1; i++) {
1863 			if ((char)rTemp.str1[i] != (char)replybuff[i]) {
1864 					unsigned int ui = i;
1865 					LOG_ERROR("failed pre data string test @ %u", ui);
1866 					return;
1867 			}
1868 		}
1869 		p = len1;
1870 	}
1871 	if (rTemp.fill1) p += rTemp.fill1;
1872 	pData = p;
1873 	if (rTemp.data.dtype == "BCD") {
1874 		p += rTemp.data.size / 2;
1875 		if (rTemp.data.size & 1) p++;
1876 	} else
1877 		p += rTemp.data.size;
1878 // check the post data string
1879 	if (rTemp.fill2) p += rTemp.fill2;
1880 	if (len2) {
1881 		for (size_t i = 0; i < len2; i++)
1882 			if ((char)rTemp.str2[i] != (char)replybuff[p + i]) {
1883 				LOG_ERROR("failed post data string test @ %d", static_cast<int>(i));
1884 				return;
1885 			}
1886 	}
1887 // convert the data field
1888 	ntch = notch_data(rTemp.data, pData);
1889 	if (xmlrig.debug) LOG_INFO("%s converted to %d", symbol, (int)ntch);
1890 
1891 	REQ(rigcat_notch, reinterpret_cast<void *>(ntch));
1892 
1893 }
1894 
rigCAT_notch_ON()1895 void rigCAT_notch_ON()
1896 {
1897 	const char symbol[] = "SET_NOTCH_ON";
1898 
1899 	if (rigCAT_exit) return;
1900 
1901 	XMLIOS modeCmd;
1902 	list<XMLIOS>::iterator itrCmd;
1903 	string strCmd;
1904 
1905 	itrCmd = commands.begin();
1906 	while (itrCmd != commands.end()) {
1907 		if ((*itrCmd).SYMBOL == symbol)
1908 			break;
1909 		++itrCmd;
1910 	}
1911 	if (itrCmd == commands.end()) {
1912 		if (xmlrig.debug) LOG_INFO("%s not defined", symbol);
1913 		return;
1914 	}
1915 
1916 	modeCmd = *itrCmd;
1917 
1918 	if ( modeCmd.str1.empty() == false)
1919 		strCmd.append(modeCmd.str1);
1920 	if (modeCmd.str2.empty() == false)
1921 		strCmd.append(modeCmd.str2);
1922 
1923 	if (modeCmd.ok.size()) {
1924 		list<XMLIOS>::iterator preply = reply.begin();
1925 		while (preply != reply.end()) {
1926 			if (preply->SYMBOL == modeCmd.ok) {
1927 				XMLIOS  rTemp = *preply;
1928 // send the command
1929 				for (int n = 0; n < progdefaults.RigCatRetries; n++) {
1930 					if (rigCAT_exit) return;
1931 					guard_lock ser_guard( &rigCAT_mutex );
1932 					if (sendCommand(symbol, strCmd, rTemp.size, progdefaults.RigCatWait)) return;
1933 					MilliSleep(50);
1934 				}
1935 				return;
1936 			}
1937 			preply++;
1938 		}
1939 	} else {
1940 		for (int n = 0; n < progdefaults.RigCatRetries; n++) {
1941 			if (rigCAT_exit) return;
1942 			guard_lock ser_guard( &rigCAT_mutex );
1943 			if (sendCommand(symbol, strCmd, 0, progdefaults.RigCatWait)) return;
1944 			MilliSleep(50);
1945 		}
1946 	}
1947 	LOG_ERROR("%s failed", symbol);
1948 }
1949 
rigCAT_notch_OFF()1950 void rigCAT_notch_OFF()
1951 {
1952 	const char symbol[] = "SET_NOTCH_OFF";
1953 
1954 	if (rigCAT_exit) return;
1955 
1956 	XMLIOS modeCmd;
1957 	list<XMLIOS>::iterator itrCmd;
1958 	string strCmd;
1959 
1960 	itrCmd = commands.begin();
1961 	while (itrCmd != commands.end()) {
1962 		if ((*itrCmd).SYMBOL == symbol)
1963 			break;
1964 		++itrCmd;
1965 	}
1966 	if (itrCmd == commands.end()) {
1967 		if (xmlrig.debug) LOG_INFO("%s not defined", symbol);
1968 		return;
1969 	}
1970 
1971 	modeCmd = *itrCmd;
1972 
1973 	if ( modeCmd.str1.empty() == false)
1974 		strCmd.append(modeCmd.str1);
1975 	if (modeCmd.str2.empty() == false)
1976 		strCmd.append(modeCmd.str2);
1977 
1978 	if (modeCmd.ok.size()) {
1979 		list<XMLIOS>::iterator preply = reply.begin();
1980 		while (preply != reply.end()) {
1981 			if (preply->SYMBOL == modeCmd.ok) {
1982 				XMLIOS  rTemp = *preply;
1983 // send the command
1984 				for (int n = 0; n < progdefaults.RigCatRetries; n++) {
1985 					if (rigCAT_exit) return;
1986 					guard_lock ser_guard( &rigCAT_mutex );
1987 					if (sendCommand(symbol, strCmd, rTemp.size, progdefaults.RigCatWait)) return;
1988 					MilliSleep(50);
1989 				}
1990 				return;
1991 			}
1992 			preply++;
1993 		}
1994 	} else {
1995 		for (int n = 0; n < progdefaults.RigCatRetries; n++) {
1996 			if (rigCAT_exit) return;
1997 			guard_lock ser_guard( &rigCAT_mutex );
1998 			if (sendCommand(symbol, strCmd, 0, progdefaults.RigCatWait)) return;
1999 			MilliSleep(50);
2000 		}
2001 	}
2002 	LOG_ERROR("%s failed", symbol);
2003 }
2004 
rigCAT_set_notch(int freq)2005 void rigCAT_set_notch(int freq)
2006 {
2007 	const char symbol[] = "SET_NOTCH_VAL";
2008 
2009 	if (rigCAT_exit) return;
2010 
2011 	if (!freq) {
2012 		rigCAT_notch_OFF();
2013 		return;
2014 	}
2015 	rigCAT_notch_ON();
2016 
2017 	XMLIOS modeCmd;
2018 	list<XMLIOS>::iterator itrCmd;
2019 	string strCmd;
2020 
2021 	itrCmd = commands.begin();
2022 	while (itrCmd != commands.end()) {
2023 		if ((*itrCmd).SYMBOL == symbol)
2024 			break;
2025 		++itrCmd;
2026 	}
2027 	if (itrCmd == commands.end()) {
2028 		if (xmlrig.debug) LOG_INFO("%s not defined", symbol);
2029 		return;
2030 	}
2031 
2032 	modeCmd = *itrCmd;
2033 
2034 	if ( modeCmd.str1.empty() == false)
2035 		strCmd.append(modeCmd.str1);
2036 
2037 	string strval = "";
2038 	long long int val = notch_val(freq);
2039 
2040 	if (modeCmd.data.size != 0) {
2041 		if (modeCmd.data.dtype == "BCD") {
2042 			if (modeCmd.data.reverse == true)
2043 				strval = to_bcd_be(val, modeCmd.data.size);
2044 		else
2045 			strval = to_bcd(val, modeCmd.data.size);
2046 		} else if (modeCmd.data.dtype == "BINARY") {
2047 			if (modeCmd.data.reverse == true)
2048 				strval = to_binary_be(val, modeCmd.data.size);
2049 			else
2050 				strval = to_binary(val, modeCmd.data.size);
2051 		} else if (modeCmd.data.dtype == "DECIMAL") {
2052 			if (modeCmd.data.reverse == true)
2053 				strval = to_decimal_be(val, modeCmd.data.size);
2054 			else
2055 				strval = to_decimal(val, modeCmd.data.size);
2056 		}
2057 	}
2058 	strCmd.append(strval);
2059 
2060 	if (modeCmd.str2.empty() == false)
2061 		strCmd.append(modeCmd.str2);
2062 
2063 	if (modeCmd.ok.size()) {
2064 		list<XMLIOS>::iterator preply = reply.begin();
2065 		while (preply != reply.end()) {
2066 			if (preply->SYMBOL == modeCmd.ok) {
2067 				XMLIOS  rTemp = *preply;
2068 // send the command
2069 				for (int n = 0; n < progdefaults.RigCatRetries; n++) {
2070 					if (rigCAT_exit) return;
2071 					guard_lock ser_guard( &rigCAT_mutex );
2072 					if (sendCommand(symbol, strCmd, rTemp.size, progdefaults.RigCatWait)) return;
2073 					MilliSleep(50);
2074 				}
2075 				return;
2076 			}
2077 			preply++;
2078 		}
2079 	} else {
2080 		for (int n = 0; n < progdefaults.RigCatRetries; n++) {
2081 			if (rigCAT_exit) return;
2082 			guard_lock ser_guard( &rigCAT_mutex );
2083 			if (sendCommand(symbol, strCmd, 0, progdefaults.RigCatWait)) return;
2084 			MilliSleep(50);
2085 		}
2086 	}
2087 	if (progdefaults.RigCatVSP == false)
2088 		LOG_ERROR("%s failed", symbol);
2089 }
2090 
pwrlevel_data(DATA d,size_t p)2091 long pwrlevel_data(DATA d, size_t p)
2092 {
2093 	long val = 0;
2094 
2095 	if (d.dtype == "BCD") {
2096 		if (d.reverse == true)
2097 			val = (int)(fm_bcd_be(p, d.size));
2098 		else
2099 			val = (int)(fm_bcd(p, d.size));
2100 	} else if (d.dtype == "BINARY") {
2101 		if (d.reverse == true)
2102 			val = (int)(fm_binary_be(p, d.size));
2103 		else
2104 			val = (int)(fm_binary(p, d.size));
2105 	} else if (d.dtype == "DECIMAL") {
2106 		if (d.reverse == true)
2107 			val = (int)(fm_decimal_be(p, d.size));
2108 		else
2109 			val = (int)(fm_decimal(p, d.size));
2110 	}
2111 
2112 	size_t n;
2113 	long pwr1, pwr2, val1, val2;
2114 	for (n = 0; n < xmlrig.pwrlevel.size() - 1; n++) {
2115 		if ((val > xmlrig.pwrlevel[n].val) && (val <= xmlrig.pwrlevel[n+1].val))
2116 			break;
2117 	}
2118 	if (n == xmlrig.pwrlevel.size() - 1)
2119 		return 0;
2120 
2121 	val1 = xmlrig.pwrlevel[n].val;
2122 	val2 = xmlrig.pwrlevel[n+1].val;
2123 	if (val1 == val2)
2124 		return 0;
2125 
2126 	pwr1 = xmlrig.pwrlevel[n].mtr;
2127 	pwr2 = xmlrig.pwrlevel[n+1].mtr;
2128 
2129 	return pwr1 + (val - val1) * (pwr2 - pwr1) / (val2 - val1);
2130 }
2131 
pwrlevel_val(int pwr)2132 int pwrlevel_val(int pwr)
2133 {
2134 	size_t n;
2135 	int val1, val2, pwr1, pwr2;
2136 	for (n = 0; n < xmlrig.pwrlevel.size() - 1; n++) {
2137 		if ((pwr >= xmlrig.pwrlevel[n].mtr) && (pwr <= xmlrig.pwrlevel[n+1].mtr))
2138 			break;
2139 	}
2140 	if (n == xmlrig.pwrlevel.size() - 1)
2141 		return 0;
2142 
2143 	pwr1 = xmlrig.pwrlevel[n].mtr;
2144 	pwr2 = xmlrig.pwrlevel[n+1].mtr;
2145 
2146 	if (pwr1 == pwr2)
2147 		return 0;
2148 
2149 	val1 = xmlrig.pwrlevel[n].val;
2150 	val2 = xmlrig.pwrlevel[n+1].val;
2151 
2152 	return val1 + (pwr - pwr1) * (val2 - val1) / (pwr2 - pwr1);
2153 
2154 }
2155 
2156 // called by rigio thread
2157 // must use REQ(...) to set the power level control
2158 
rigCAT_update_pwrlevel(const long v)2159 static void rigCAT_update_pwrlevel(const long v)
2160 {
2161 	long pwr = v;
2162 	char szpwr[10];
2163 	snprintf(szpwr, sizeof(szpwr), "%ld", pwr);
2164 	progdefaults.mytxpower = szpwr;
2165 
2166 	inpMyPower->value(szpwr);
2167 	pwr_level->value(pwr);
2168 
2169 //	if (xmlrig.debug) LOG_INFO("Read power level %s", szpwr);
2170 }
2171 
rigCAT_get_pwrlevel()2172 void rigCAT_get_pwrlevel()
2173 {
2174 	const char symbol[] = "GET_PWRLEVEL";
2175 
2176 	if (rigCAT_exit || xmlrig.noserial || !xmlrig.xmlok) return;
2177 
2178 	XMLIOS modeCmd;
2179 	list<XMLIOS>::iterator itrCmd;
2180 	string strCmd;
2181 	size_t p = 0, len1 = 0, len2 = 0, pData = 0;
2182 	long pwr = 0;
2183 
2184 	itrCmd = commands.begin();
2185 	while (itrCmd != commands.end()) {
2186 		if ((*itrCmd).SYMBOL == symbol)
2187 			break;
2188 		++itrCmd;
2189 	}
2190 
2191 	if (itrCmd == commands.end()) {
2192 		if (xmlrig.debug) LOG_INFO("%s not defined", symbol);
2193 		return;
2194 	}
2195 
2196 	modeCmd = *itrCmd;
2197 	if ( !modeCmd.str1.empty() ) strCmd.append(modeCmd.str1);
2198 	if ( !modeCmd.str2.empty() ) strCmd.append(modeCmd.str2);
2199 	if ( !modeCmd.info.size() ) return;
2200 
2201 	list<XMLIOS>::iterator preply;
2202 
2203 	for (preply = reply.begin(); preply != reply.end(); ++preply) {
2204 		if (preply->SYMBOL == modeCmd.info)
2205 			break;
2206 	}
2207 	if (preply == reply.end()) return;
2208 
2209 	XMLIOS  rTemp = *preply;
2210 	len1 = rTemp.str1.size();
2211 	len2 = rTemp.str2.size();
2212 
2213 	int timeout = progdefaults.RigCatTimeout;
2214 	while (timeout > 50) {
2215 		MilliSleep(50);
2216 		Fl::awake();
2217 		timeout -= 50;
2218 	}
2219 	if (timeout) {
2220 		MilliSleep(timeout);
2221 		Fl::awake();
2222 	}
2223 
2224 // send the command
2225 	{
2226 		guard_lock ser_guard( &rigCAT_mutex );
2227 		if ( !sendCommand(symbol, strCmd, rTemp.size, progdefaults.RigCatWait) ) {
2228 			LOG_ERROR("sendCommand failed");
2229 			return;
2230 		}
2231 	}
2232 // check the pre data string
2233 	p = 0;
2234 	pData = 0;
2235 	if (len1) {
2236 		for (size_t i = 0; i < len1; i++) {
2237 			if ((char)rTemp.str1[i] != (char)replybuff[i]) {
2238 					unsigned int ui = i;
2239 					LOG_ERROR("failed pre data string test @ %u", ui);
2240 					return;
2241 			}
2242 		}
2243 		p = len1;
2244 	}
2245 	if (rTemp.fill1) p += rTemp.fill1;
2246 	pData = p;
2247 	if (rTemp.data.dtype == "BCD") {
2248 		p += rTemp.data.size / 2;
2249 		if (rTemp.data.size & 1) p++;
2250 	} else
2251 		p += rTemp.data.size;
2252 // check the post data string
2253 	if (rTemp.fill2) p += rTemp.fill2;
2254 	if (len2) {
2255 		for (size_t i = 0; i < len2; i++)
2256 			if ((char)rTemp.str2[i] != (char)replybuff[p + i]) {
2257 				LOG_ERROR("failed post data string test @ %d", static_cast<int>(i));
2258 				return;
2259 			}
2260 	}
2261 // convert the data field
2262 	pwr = pwrlevel_data(rTemp.data, pData);
2263 
2264 	REQ(rigCAT_update_pwrlevel, pwr);
2265 }
2266 
rigCAT_set_pwrlevel(int pwr)2267 void rigCAT_set_pwrlevel(int pwr)
2268 {
2269 	const char symbol[] = "SET_PWRLEVEL";
2270 
2271 	if (rigCAT_exit || !xmlrig.use_pwrlevel) return;
2272 
2273 	XMLIOS modeCmd;
2274 	list<XMLIOS>::iterator itrCmd;
2275 	string strCmd;
2276 
2277 	itrCmd = commands.begin();
2278 	while (itrCmd != commands.end()) {
2279 		if ((*itrCmd).SYMBOL == symbol)
2280 			break;
2281 		++itrCmd;
2282 	}
2283 	if (itrCmd == commands.end()) {
2284 		if (xmlrig.debug) LOG_INFO("%s not defined", symbol);
2285 		return;
2286 	}
2287 
2288 	modeCmd = *itrCmd;
2289 
2290 	if ( modeCmd.str1.empty() == false)
2291 		strCmd.append(modeCmd.str1);
2292 
2293 	string strval = "";
2294 	int val = pwrlevel_val(pwr);
2295 
2296 	if (modeCmd.data.size != 0) {
2297 		if (modeCmd.data.dtype == "BCD") {
2298 			if (modeCmd.data.reverse == true)
2299 				strval = to_bcd_be(val, modeCmd.data.size);
2300 		else
2301 			strval = to_bcd(val, modeCmd.data.size);
2302 		} else if (modeCmd.data.dtype == "BINARY") {
2303 			if (modeCmd.data.reverse == true)
2304 				strval = to_binary_be(val, modeCmd.data.size);
2305 			else
2306 				strval = to_binary(val, modeCmd.data.size);
2307 		} else if (modeCmd.data.dtype == "DECIMAL") {
2308 			if (modeCmd.data.reverse == true)
2309 				strval = to_decimal_be(val, modeCmd.data.size);
2310 			else
2311 				strval = to_decimal(val, modeCmd.data.size);
2312 		}
2313 	}
2314 	strCmd.append(strval);
2315 
2316 	if (modeCmd.str2.empty() == false)
2317 		strCmd.append(modeCmd.str2);
2318 
2319 	if (modeCmd.ok.size()) {
2320 		list<XMLIOS>::iterator preply = reply.begin();
2321 		while (preply != reply.end()) {
2322 			if (preply->SYMBOL == modeCmd.ok) {
2323 				XMLIOS  rTemp = *preply;
2324 // send the command
2325 				for (int n = 0; n < progdefaults.RigCatRetries; n++) {
2326 					if (rigCAT_exit) return;
2327 					guard_lock ser_guard( &rigCAT_mutex );
2328 					if (sendCommand(symbol, strCmd, rTemp.size, progdefaults.RigCatWait)) {
2329 						if (xmlrig.debug) LOG_INFO("Power set to %s", strval.c_str());
2330 						return;
2331 					}
2332 					MilliSleep(50);
2333 				}
2334 				if (xmlrig.debug) LOG_ERROR("%s failed", symbol);
2335 				return;
2336 			}
2337 			preply++;
2338 		}
2339 	} else {
2340 		for (int n = 0; n < progdefaults.RigCatRetries; n++) {
2341 			if (rigCAT_exit) return;
2342 			guard_lock ser_guard( &rigCAT_mutex );
2343 			if (sendCommand(symbol, strCmd, 0, progdefaults.RigCatWait)) {
2344 				if (xmlrig.debug) LOG_INFO("Power set to %s", strval.c_str());
2345 				return;
2346 			MilliSleep(50);
2347 			}
2348 		}
2349 	}
2350 	if (progdefaults.RigCatVSP == false)
2351 		if (xmlrig.debug) LOG_ERROR("%s failed", symbol);
2352 }
2353 
rigCAT_loop(void * args)2354 static void *rigCAT_loop(void *args)
2355 {
2356 	SET_THREAD_ID(RIGCTL_TID);
2357 
2358 	long long freq = 0L;
2359 	string sWidth, sMode;
2360 	bool failed;
2361 
2362 	for (;;) {
2363 		for (int i = 0; i < xmlrig.pollinterval / 10; i++) {
2364 			MilliSleep(10);
2365 			if (rigCAT_exit == true) {
2366 				LOG_INFO("%s", "Exited rigCAT loop");
2367 				return NULL;
2368 			}
2369 		}
2370 
2371 		if (trx_state == STATE_RX) {
2372 			cmdque_exec();
2373 
2374 			freq = rigCAT_getfreq(progdefaults.RigCatRetries, failed);
2375 			if (rigCAT_exit) continue;
2376 
2377 			if ((freq > 0) && (freq != llFreq)) {
2378 				llFreq = freq;
2379 				show_frequency(freq);
2380 				wf->rfcarrier(freq);
2381 			}
2382 
2383 			sWidth = rigCAT_getwidth();
2384 			if (rigCAT_exit) continue;
2385 
2386 			if (sWidth.size() && sWidth != sRigWidth) {
2387 				sRigWidth = sWidth;
2388 				show_bw(sWidth);
2389 			}
2390 
2391 			sMode = rigCAT_getmode();
2392 			if (rigCAT_exit) continue;
2393 
2394 			if (sMode.size() && sMode != sRigMode) {
2395 				sRigMode = sMode;
2396 				if (ModeIsLSB(sMode))
2397 					wf->USB(false);
2398 				else
2399 					wf->USB(true);
2400 				show_mode(sMode);
2401 			}
2402 
2403 			if (xmlrig.use_pwrlevel) rigCAT_get_pwrlevel();
2404 
2405 			if (xmlrig.use_smeter) rigCAT_get_smeter();
2406 
2407 			if (xmlrig.use_notch) rigCAT_get_notch();
2408 
2409 		} else {
2410 			if ( (trx_state == STATE_TUNE) || (trx_state == STATE_TX) )
2411 				if (xmlrig.use_pwrmeter) rigCAT_get_pwrmeter();
2412 		}
2413 
2414 	}
2415 
2416 	return NULL;
2417 }
2418 
2419