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