dl-fldigi/src/rigcontrol/rigio.cxx

2345 wiersze
53 KiB
C++

// ----------------------------------------------------------------------------
// rigio.cxx
//
// Copyright (C) 2007-2009
// Dave Freese, W1HKJ
//
// This file is part of fldigi.
//
// Fldigi is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Fldigi is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with fldigi. If not, see <http://www.gnu.org/licenses/>.
// ----------------------------------------------------------------------------
#include <config.h>
#include <ctime>
#include <sys/time.h>
#include <iostream>
#include <list>
#include <vector>
#include <string>
#ifdef RIGCATTEST
#include "rigCAT.h"
#else
#include "fl_digi.h"
#include "misc.h"
#include "configuration.h"
#endif
#include "rigsupport.h"
#include "rigxml.h"
#include "trx.h"
#include "serial.h"
#include "rigio.h"
#include "debug.h"
#include "threads.h"
#include "qrunner.h"
#include "confdialog.h"
#include "status.h"
LOG_FILE_SOURCE(debug::LOG_RIGCONTROL);
using namespace std;
Cserial rigio;
static pthread_mutex_t rigCAT_mutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_t rigCAT_thread;
static bool rigCAT_exit = false;
static bool rigCAT_open = false;
static string sRigWidth = "";
static string sRigMode = "";
static long long llFreq = 0;
static void *rigCAT_loop(void *args);
#define RXBUFFSIZE 2000
static unsigned char replybuff[RXBUFFSIZE+1];
static unsigned char retbuf[3];
bool sendCommand (string s, int retnbr, int waitval)
{
int numwrite = (int)s.length();
int readafter = 0;
int numread = 0;
int retval = 0;
numread = retnbr;
if (progdefaults.RigCatECHO)
numread += numwrite;
readafter =
waitval + (int) ceilf (
numread * (9 + progdefaults.RigCatStopbits) *
1000.0 / rigio.Baud() );
if (xmlrig.debug)
LOG_INFO("%s",
xmlrig.ascii ? s.c_str() : str2hex(s.data(), s.length()));
if (xmlrig.noserial) {
memset(replybuff, 0, RXBUFFSIZE + 1);
numread = 0;
return true;
}
retval = rigio.WriteBuffer((unsigned char *)s.c_str(), numwrite);
if (retval <= 0)
LOG_ERROR("Write error %d", retval);
if (retnbr == 0) return true;
memset(replybuff, 0, RXBUFFSIZE + 1);
numread = 0;
while (readafter > 50) {
MilliSleep(50);
Fl::awake();
readafter -= 50;
}
if (readafter) {
MilliSleep(readafter);
Fl::awake();
}
while (numread < RXBUFFSIZE) {
memset(retbuf, 0, 2);
if (rigio.ReadBuffer(retbuf, 1) == 0) break;
replybuff[numread] = retbuf[0];
numread++;
}
if (xmlrig.debug)
LOG_INFO("reply %s",
xmlrig.ascii ? (const char *)(replybuff) : str2hex(replybuff, numread));
if (numread > retnbr) {
memmove(replybuff, replybuff + numread - retnbr, retnbr);
numread = retnbr;
}
return (numread == retnbr);
}
string to_bcd_be(long long freq, int len)
{
string bcd = "";
unsigned char a;
int numchars = len / 2;
if (len & 1) numchars ++;
for (int i = 0; i < numchars; i++) {
a = 0;
a |= freq%10;
freq /= 10;
a |= (freq%10)<<4;
freq /= 10;
bcd += a;
}
return bcd;
}
string to_bcd(long long freq, int len)
{
string bcd = "";
string bcd_be = to_bcd_be(freq, len);
int bcdlen = bcd_be.size();
for (int i = bcdlen - 1; i >= 0; i--)
bcd += bcd_be[i];
return bcd;
}
long long fm_bcd (size_t p, int len)
{
int i;
long long f = 0;
int numchars = len/2;
if (len & 1) numchars ++;
for (i = 0; i < numchars; i++) {
f *=10;
f += (replybuff[p + i] >> 4) & 0x0F;
f *= 10;
f += replybuff[p + i] & 0x0F;
}
return f;
}
long long fm_bcd_be(size_t p, int len)
{
unsigned char temp;
int numchars = len/2;
if (len & 1) numchars++;
for (int i = 0; i < numchars / 2; i++) {
temp = replybuff[p + i];
replybuff[p + i] = replybuff[p + numchars -1 - i];
replybuff[p + numchars -1 - i] = temp;
}
return fm_bcd(p, len);
}
string to_binary_be(long long freq, int len)
{
string bin = "";
for (int i = 0; i < len; i++) {
bin += freq & 0xFF;
freq >>= 8;
}
return bin;
}
string to_binary(long long freq, int len)
{
string bin = "";
string bin_be = to_binary_be(freq, len);
int binlen = bin_be.size();
for (int i = binlen - 1; i >= 0; i--)
bin += bin_be[i];
return bin;
}
long long fm_binary(size_t p, int len)
{
int i;
long long f = 0;
for (i = 0; i < len; i++) {
f *= 256;
f += replybuff[p + i];
}
return f;
}
long long fm_binary_be(size_t p, int len)
{
unsigned char temp;
int numchars = len/2;
if (len & 1) numchars++;
for (int i = 0; i < numchars / 2; i++) {
temp = replybuff[p + i];
replybuff[p + i] = replybuff[p + numchars -1 - i];
replybuff[p + numchars -1 - i] = temp;
}
return fm_binary(p, len);
}
string to_decimal_be(long long d, int len)
{
string sdec_be = "";
for (int i = 0; i < len; i++) {
sdec_be += (char)((d % 10) + '0');
d /= 10;
}
return sdec_be;
}
string to_decimal(long long d, int len)
{
string sdec = "";
string sdec_be = to_decimal_be(d, len);
int bcdlen = sdec_be.size();
for (int i = bcdlen - 1; i >= 0; i--)
sdec += sdec_be[i];
return sdec;
}
long long fm_decimal(size_t p, int len)
{
long long d = 0;
for (int i = 0; i < len; i++) {
d *= 10;
d += replybuff[p + i] - '0';
}
return d;
}
long long fm_decimal_be(size_t p, int len)
{
unsigned char temp;
int numchars = len/2;
if (len & 1) numchars++;
for (int i = 0; i < numchars / 2; i++) {
temp = replybuff[p + i];
replybuff[p + i] = replybuff[p + numchars -1 - i];
replybuff[p + numchars -1 - i] = temp;
}
return fm_decimal(p, len);
}
string to_freqdata(DATA d, long long f)
{
int num, den;
num = 100;
den = (int)(d.resolution * 100);
if (d.size == 0) return "";
if (d.dtype == "BCD") {
if (d.reverse == true)
return to_bcd_be((long long int)(f * num / den), d.size);
else
return to_bcd((long long int)(f * num / den), d.size);
} else if (d.dtype == "BINARY") {
if (d.reverse == true)
return to_binary_be((long long int)(f * num / den), d.size);
else
return to_binary((long long int)(f * num / den), d.size);
} else if (d.dtype == "DECIMAL") {
if (d.reverse == true)
return to_decimal_be((long long int)(f * num / den), d.size);
else
return to_decimal((long long int)(f * num / den), d.size);
}
return "";
}
long long fm_freqdata(DATA d, size_t p)
{
int num, den;
num = (int)(d.resolution * 100);
den = 100;
long long fret = 0;
if (d.dtype == "BCD") {
if (d.reverse == true)
fret = (long long int)(fm_bcd_be(p, d.size) * num / den);
else
fret = (long long int)(fm_bcd(p, d.size) * num / den);
} else if (d.dtype == "BINARY") {
if (d.reverse == true)
fret = (long long int)(fm_binary_be(p, d.size) * num / den);
else
fret = (long long int)(fm_binary(p, d.size) * num / den);
} else if (d.dtype == "DECIMAL") {
if (d.reverse == true)
fret = (long long int)(fm_decimal_be(p, d.size) * num / den);
else
fret = (long long int)(fm_decimal(p, d.size) * num / den);
}
return fret;
}
long long rigCAT_getfreq(int retries, bool &failed, int waitval)
{
const char symbol[] = "GETFREQ";
failed = false;
if (rigCAT_exit || xmlrig.noserial || !xmlrig.xmlok) {
failed = true;
return progStatus.noCATfreq;
}
XMLIOS modeCmd;
list<XMLIOS>::iterator itrCmd;
string strCmd;
size_t p = 0, len1 = 0, len2 = 0, pData = 0;
long long f = 0;
itrCmd = commands.begin();
while (itrCmd != commands.end()) {
if ((*itrCmd).SYMBOL == symbol)
break;
++itrCmd;
}
if (itrCmd == commands.end()) {
failed = true;
if (xmlrig.debug) LOG_INFO("%s not defined", symbol);
return progStatus.noCATfreq; // get_freq command is not defined!
}
modeCmd = *itrCmd;
if ( modeCmd.str1.empty() == false)
strCmd.append(modeCmd.str1);
if (modeCmd.str2.empty() == false)
strCmd.append(modeCmd.str2);
if ( !modeCmd.info.size() ) {
failed = true;
return 0;
}
for (list<XMLIOS>::iterator preply = reply.begin(); preply != reply.end(); ++preply) {
if (preply->SYMBOL != modeCmd.info)
continue;
XMLIOS rTemp = *preply;
len1 = rTemp.str1.size();
len2 = rTemp.str2.size();
// for (int n = 0; n < progdefaults.RigCatRetries; n++) {
for (int n = 0; n < retries; n++) {
if (n && progdefaults.RigCatTimeout > 0)
{
int timeout = progdefaults.RigCatTimeout;
while (timeout > 50) {
MilliSleep(50);
Fl::awake();
timeout -= 50;
}
if (timeout) {
MilliSleep(timeout);
Fl::awake();
}
}
// send the command
if ( !sendCommand(strCmd, rTemp.size, waitval) ) {
if (xmlrig.debug)
LOG_INFO("sendCommand failed");
goto retry_get_freq;
}
// check the pre data string
p = 0;
pData = 0;
if (len1) {
for (size_t i = 0; i < len1; i++) {
if ((char)rTemp.str1[i] != (char)replybuff[i]) {
LOG_ERROR("failed pre data string test @ %" PRIuSZ, i);
goto retry_get_freq;
}
}
p = len1;
}
if (rTemp.fill1) p += rTemp.fill1;
pData = p;
if (rTemp.data.dtype == "BCD") {
p += rTemp.data.size / 2;
if (rTemp.data.size & 1) p++;
} else
p += rTemp.data.size;
// check the post data string
if (rTemp.fill2) p += rTemp.fill2;
if (len2) {
for (size_t i = 0; i < len2; i++)
if ((char)rTemp.str2[i] != (char)replybuff[p + i]) {
LOG_ERROR("failed post data string test @ %d", static_cast<int>(i));
goto retry_get_freq;
}
}
// convert the data field
f = fm_freqdata(rTemp.data, pData);
if ( f >= rTemp.data.min && f <= rTemp.data.max)
return f;
LOG_VERBOSE("freq: %d", static_cast<int>(f));
retry_get_freq: ;
}
}
if (progdefaults.RigCatVSP == false)
LOG_ERROR("%s failed", symbol);
failed = true;
return 0;
}
void rigCAT_setfreq(long long f)
{
const char symbol[] = "SETFREQ";
if (rigCAT_exit || xmlrig.noserial || !xmlrig.xmlok) {
progStatus.noCATfreq = f;
}
if (rigCAT_exit || !xmlrig.xmlok) return;
XMLIOS modeCmd;
list<XMLIOS>::iterator itrCmd;
string strCmd;
itrCmd = commands.begin();
while (itrCmd != commands.end()) {
if ((*itrCmd).SYMBOL == symbol)
break;
++itrCmd;
}
if (itrCmd == commands.end()) {
if (xmlrig.debug) LOG_INFO("%s not defined", symbol);
return;
}
modeCmd = *itrCmd;
if ( modeCmd.str1.empty() == false)
strCmd.append(modeCmd.str1);
strCmd.append( to_freqdata(modeCmd.data, f) );
if (modeCmd.str2.empty() == false)
strCmd.append(modeCmd.str2);
if (modeCmd.ok.size()) {
list<XMLIOS>::iterator preply = reply.begin();
while (preply != reply.end()) {
if (preply->SYMBOL == modeCmd.ok) {
XMLIOS rTemp = *preply;
// send the command
for (int n = 0; n < progdefaults.RigCatRetries; n++) {
MilliSleep(50);
guard_lock ser_guard( &rigCAT_mutex );
if (rigCAT_exit) return;
if (sendCommand(strCmd, rTemp.size, progdefaults.RigCatWait)) return;
}
return;
}
preply++;
}
} else {
for (int n = 0; n < progdefaults.RigCatRetries; n++) {
MilliSleep(50);
guard_lock ser_guard( &rigCAT_mutex );
if (rigCAT_exit) return;
if (sendCommand(strCmd, 0, progdefaults.RigCatWait)) return;
}
}
if (progdefaults.RigCatVSP == false)
LOG_ERROR("%s failed", symbol);
}
string rigCAT_getmode()
{
const char symbol[] = "GETMODE";
if (rigCAT_exit || xmlrig.noserial || !xmlrig.xmlok)
return progStatus.noCATmode;
// guard_lock ser_guard( &rigCAT_mutex );
XMLIOS modeCmd;
list<XMLIOS>::iterator itrCmd;
list<MODE>::iterator mode;
list<MODE> *pmode;
string strCmd, mData;
size_t len;
itrCmd = commands.begin();
while (itrCmd != commands.end()) {
if ((*itrCmd).SYMBOL == symbol)
break;
++itrCmd;
}
if (itrCmd == commands.end()) {
if (xmlrig.debug) LOG_INFO("%s not defined", symbol);
return progStatus.noCATmode;
}
modeCmd = *itrCmd;
if ( modeCmd.str1.empty() == false)
strCmd.append(modeCmd.str1);
if (modeCmd.str2.empty() == false)
strCmd.append(modeCmd.str2);
if (!modeCmd.info.size()) return "";
for (list<XMLIOS>::iterator preply = reply.begin(); preply != reply.end(); ++preply) {
if (preply->SYMBOL != modeCmd.info)
continue;
XMLIOS rTemp = *preply;
for (int n = 0; n < progdefaults.RigCatRetries; n++) {
if (progdefaults.RigCatTimeout > 50)
{
int timeout = progdefaults.RigCatTimeout;
while (timeout > 50) {
MilliSleep(50);
Fl::awake();
timeout -= 50;
}
if (timeout) {
MilliSleep(timeout);
Fl::awake();
}
}
size_t p = 0, pData = 0;
// send the command
if (!sendCommand(strCmd, rTemp.size, progdefaults.RigCatWait)) goto retry_get_mode;
// check the pre data string
len = rTemp.str1.size();
if (len) {
for (size_t i = 0; i < len; i++)
if ((char)rTemp.str1[i] != (char)replybuff[i]) {
LOG_ERROR("failed pre data string test @ %" PRIuSZ, i);
goto retry_get_mode;
}
p = len;
}
if (rTemp.fill1) p += rTemp.fill1;
pData = p;
// check the post data string
p += rTemp.data.size;
len = rTemp.str2.size();
if (rTemp.fill2) p += rTemp.fill2;
if (len) {
for (size_t i = 0; i < len; i++)
if ((char)rTemp.str2[i] != (char)replybuff[p + i])
goto retry_get_mode;
}
// convert the data field
mData = "";
for (int i = 0; i < rTemp.data.size; i++)
mData += (char)replybuff[pData + i];
// for FT100 and the ilk that use bit fields
if (rTemp.data.size == 1) {
unsigned char d = mData[0];
if (rTemp.data.shiftbits)
d >>= rTemp.data.shiftbits;
d &= rTemp.data.andmask;
mData[0] = d;
}
if (lmodes.empty() == false)
pmode = &lmodes;
else if (lmodeREPLY.empty() == false)
pmode = &lmodeREPLY;
else
goto retry_get_mode;
mode = pmode->begin();
while (mode != pmode->end()) {
if ((*mode).BYTES == mData)
break;
mode++;
}
if (mode != pmode->end())
return ((*mode).SYMBOL);
retry_get_mode: ;
}
}
if (progdefaults.RigCatVSP == false)
LOG_ERROR("%s failed", symbol);
return "";
}
void rigCAT_setmode(const string& md)
{
const char symbol[] = "SETMODE";
if (rigCAT_exit || xmlrig.noserial || !xmlrig.xmlok)
progStatus.noCATmode = md;
if (rigCAT_exit || !xmlrig.xmlok) return;
XMLIOS modeCmd;
list<XMLIOS>::iterator itrCmd;
string strCmd;
itrCmd = commands.begin();
while (itrCmd != commands.end()) {
if ((*itrCmd).SYMBOL == symbol)
break;
++itrCmd;
}
modeCmd = *itrCmd;
if ( modeCmd.str1.empty() == false)
strCmd.append(modeCmd.str1);
if ( modeCmd.data.size > 0 ) {
list<MODE>::iterator mode;
list<MODE> *pmode;
if (lmodes.empty() == false)
pmode = &lmodes;
else if (lmodeCMD.empty() == false)
pmode = &lmodeCMD;
else
return;
mode = pmode->begin();
while (mode != pmode->end()) {
if ((*mode).SYMBOL == md)
break;
mode++;
}
if (mode != pmode->end())
strCmd.append( (*mode).BYTES );
}
if (modeCmd.str2.empty() == false)
strCmd.append(modeCmd.str2);
if (modeCmd.ok.size()) {
list<XMLIOS>::iterator preply = reply.begin();
while (preply != reply.end()) {
if (preply->SYMBOL == modeCmd.ok) {
XMLIOS rTemp = *preply;
// send the command
for (int n = 0; n < progdefaults.RigCatRetries; n++) {
MilliSleep(50);
guard_lock ser_guard( &rigCAT_mutex );
if (rigCAT_exit) return;
if (sendCommand(strCmd, rTemp.size, progdefaults.RigCatWait)) return;
}
return;
}
preply++;
}
} else {
for (int n = 0; n < progdefaults.RigCatRetries; n++) {
MilliSleep(50);
guard_lock ser_guard( &rigCAT_mutex );
if (rigCAT_exit) return;
if (sendCommand(strCmd, 0, progdefaults.RigCatWait)) return;
}
}
if (progdefaults.RigCatVSP == false)
LOG_ERROR("%s failed", symbol);
}
string rigCAT_getwidth()
{
const char symbol[] = "GETBW";
if (rigCAT_exit || xmlrig.noserial || !xmlrig.xmlok)
return progStatus.noCATwidth;
XMLIOS widthCmd;
list<XMLIOS>::iterator itrCmd;
list<BW>::iterator bw;
list<BW> *pbw;
string strCmd, mData;
size_t len = 0, p = 0, pData = 0;
itrCmd = commands.begin();
while (itrCmd != commands.end()) {
if ((*itrCmd).SYMBOL == symbol)
break;
++itrCmd;
}
if (itrCmd == commands.end()) {
if (xmlrig.debug) LOG_INFO("%s not defined", symbol);
return "";
}
widthCmd = *itrCmd;
if ( widthCmd.str1.empty() == false)
strCmd.append(widthCmd.str1);
if (widthCmd.str2.empty() == false)
strCmd.append(widthCmd.str2);
if (!widthCmd.info.size()) return "";
for (list<XMLIOS>::iterator preply = reply.begin(); preply != reply.end(); ++preply) {
if (preply->SYMBOL != widthCmd.info)
continue;
XMLIOS rTemp = *preply;
for (int n = 0; n < progdefaults.RigCatRetries; n++) {
if (progdefaults.RigCatTimeout > 50)
{
int timeout = progdefaults.RigCatTimeout;
while (timeout > 50) {
MilliSleep(50);
Fl::awake();
timeout -= 50;
}
if (timeout) {
MilliSleep(timeout);
Fl::awake();
}
}
p = 0;
pData = 0;
// send the command
if ( !sendCommand(strCmd, rTemp.size, progdefaults.RigCatWait) ) {
goto retry_get_width;
}
// check the pre data string
len = rTemp.str1.size();
if (len) {
for (size_t i = 0; i < len; i++)
if ((char)rTemp.str1[i] != (char)replybuff[i]) {
LOG_ERROR("failed pre data string test @ %" PRIuSZ, i);
goto retry_get_width;
}
p = pData = len;
}
if (rTemp.fill1) p += rTemp.fill1;
pData = p;
p += rTemp.data.size;
// check the post data string
if (rTemp.fill2) p += rTemp.fill2;
len = rTemp.str2.size();
if (len) {
for (size_t i = 0; i < len; i++)
if ((char)rTemp.str2[i] != (char)replybuff[p + i]) {
LOG_ERROR("failed post data string test @ %" PRIuSZ, i);
goto retry_get_width;
}
}
// convert the data field
mData = "";
for (int i = 0; i < rTemp.data.size; i++)
mData += (char)replybuff[pData + i];
// new for FT100 and the ilk that use bit fields
if (rTemp.data.size == 1) {
unsigned char d = mData[0];
if (rTemp.data.shiftbits)
d >>= rTemp.data.shiftbits;
d &= rTemp.data.andmask;
mData[0] = d;
}
if (!lbwREPLY.empty())
pbw = &lbwREPLY;
else if (lbws.empty() == false)
pbw = &lbws;
else
goto retry_get_width;
bw = pbw->begin();
while (bw != pbw->end()) {
if ((*bw).BYTES == mData)
break;
bw++;
}
if (bw != pbw->end())
return ((*bw).SYMBOL);
retry_get_width: ;
}
}
if (progdefaults.RigCatVSP == false)
LOG_ERROR("%s failed", symbol);
return "";
}
void rigCAT_setwidth(const string& w)
{
const char symbol[] = "SETBW";
if (rigCAT_exit || xmlrig.noserial || !xmlrig.xmlok)
progStatus.noCATwidth = w;
if (rigCAT_exit || !xmlrig.xmlok) return;
XMLIOS modeCmd;
list<XMLIOS>::iterator itrCmd;
string strCmd;
itrCmd = commands.begin();
while (itrCmd != commands.end()) {
if ((*itrCmd).SYMBOL == symbol)
break;
++itrCmd;
}
if (itrCmd == commands.end()) {
if (xmlrig.debug) LOG_INFO("%s not defined", symbol);
progStatus.noCATwidth = w;
return;
}
modeCmd = *itrCmd;
if ( modeCmd.str1.empty() == false)
strCmd.append(modeCmd.str1);
if ( modeCmd.data.size > 0 ) {
list<BW>::iterator bw;
list<BW> *pbw;
if (lbws.empty() == false)
pbw = &lbws;
else if (lbwCMD.empty() == false)
pbw = &lbwCMD;
else
return;
bw = pbw->begin();
while (bw != pbw->end()) {
if ((*bw).SYMBOL == w)
break;
bw++;
}
if (bw != pbw->end())
strCmd.append( (*bw).BYTES );
}
if (modeCmd.str2.empty() == false)
strCmd.append(modeCmd.str2);
if (modeCmd.ok.size()) {
list<XMLIOS>::iterator preply = reply.begin();
while (preply != reply.end()) {
if (preply->SYMBOL == modeCmd.ok) {
XMLIOS rTemp = *preply;
// send the command
for (int n = 0; n < progdefaults.RigCatRetries; n++) {
MilliSleep(50);
guard_lock ser_guard( &rigCAT_mutex );
if (rigCAT_exit) return;
if (sendCommand(strCmd, rTemp.size, progdefaults.RigCatWait)) return;
}
}
preply++;
}
} else {
for (int n = 0; n < progdefaults.RigCatRetries; n++) {
MilliSleep(50);
guard_lock ser_guard( &rigCAT_mutex );
if (rigCAT_exit) return;
if (sendCommand(strCmd, 0, progdefaults.RigCatWait)) return;
}
}
LOG_ERROR("%s failed", symbol);
}
void rigCAT_pttON()
{
const char symbol[] = "PTTON";
if (rigCAT_exit) return;
XMLIOS modeCmd;
list<XMLIOS>::iterator itrCmd;
string strCmd;
rigio.SetPTT(1); // always execute the h/w ptt if enabled
itrCmd = commands.begin();
while (itrCmd != commands.end()) {
if ((*itrCmd).SYMBOL == symbol)
break;
++itrCmd;
}
if (itrCmd == commands.end()) {
if (xmlrig.debug) LOG_INFO("%s not defined", symbol);
return;
}
modeCmd = *itrCmd;
if ( modeCmd.str1.empty() == false)
strCmd.append(modeCmd.str1);
if (modeCmd.str2.empty() == false)
strCmd.append(modeCmd.str2);
if (modeCmd.ok.size()) {
list<XMLIOS>::iterator preply = reply.begin();
while (preply != reply.end()) {
if (preply->SYMBOL == modeCmd.ok) {
XMLIOS rTemp = *preply;
// send the command
for (int n = 0; n < progdefaults.RigCatRetries; n++) {
MilliSleep(50);
guard_lock ser_guard( &rigCAT_mutex );
if (rigCAT_exit) return;
if (sendCommand(strCmd, rTemp.size, progdefaults.RigCatWait)) return;
}
return;
}
preply++;
}
} else {
for (int n = 0; n < progdefaults.RigCatRetries; n++) {
MilliSleep(50);
guard_lock ser_guard( &rigCAT_mutex );
if (rigCAT_exit) return;
if (sendCommand(strCmd, 0, progdefaults.RigCatWait)) return;
}
}
LOG_VERBOSE("%s failed", symbol);
}
void rigCAT_pttOFF()
{
const char symbol[] = "PTTOFF";
if (rigCAT_exit) return;
XMLIOS modeCmd;
list<XMLIOS>::iterator itrCmd;
string strCmd;
rigio.SetPTT(0); // always execute the h/w ptt if enabled
itrCmd = commands.begin();
while (itrCmd != commands.end()) {
if ((*itrCmd).SYMBOL == symbol)
break;
++itrCmd;
}
if (itrCmd == commands.end()) {
if (xmlrig.debug) LOG_INFO("%s not defined", symbol);
return;
}
modeCmd = *itrCmd;
if ( modeCmd.str1.empty() == false)
strCmd.append(modeCmd.str1);
if (modeCmd.str2.empty() == false)
strCmd.append(modeCmd.str2);
if (modeCmd.ok.size()) {
list<XMLIOS>::iterator preply = reply.begin();
while (preply != reply.end()) {
if (preply->SYMBOL == modeCmd.ok) {
XMLIOS rTemp = *preply;
// send the command
for (int n = 0; n < progdefaults.RigCatRetries; n++) {
MilliSleep(50);
guard_lock ser_guard( &rigCAT_mutex );
if (rigCAT_exit) return;
if (sendCommand(strCmd, rTemp.size, progdefaults.RigCatWait)) return;
}
return;
}
preply++;
}
} else {
for (int n = 0; n < progdefaults.RigCatRetries; n++) {
MilliSleep(50);
guard_lock ser_guard( &rigCAT_mutex );
if (rigCAT_exit) return;
if (sendCommand(strCmd, 0, progdefaults.RigCatWait)) return;
}
}
LOG_ERROR("%s failed", symbol);
}
void rigCAT_sendINIT(const string& icmd, int multiplier)
{
if (rigCAT_exit) return;
XMLIOS modeCmd;
list<XMLIOS>::iterator itrCmd;
string strCmd;
itrCmd = commands.begin();
while (itrCmd != commands.end()) {
if ((*itrCmd).SYMBOL == icmd)
break;
++itrCmd;
}
if (itrCmd == commands.end())
return;
modeCmd = *itrCmd;
if ( modeCmd.str1.empty() == false)
strCmd.append(modeCmd.str1);
if (modeCmd.str2.empty() == false)
strCmd.append(modeCmd.str2);
if (modeCmd.ok.size()) {
list<XMLIOS>::iterator preply = reply.begin();
while (preply != reply.end()) {
if (preply->SYMBOL == modeCmd.ok) {
XMLIOS rTemp = *preply;
// send the command
for (int n = 0; n < progdefaults.RigCatRetries; n++) {
MilliSleep(50);
guard_lock ser_guard( &rigCAT_mutex );
if (rigCAT_exit) return;
if (sendCommand(strCmd, rTemp.size, progdefaults.RigCatInitDelay)) return;
}
return;
}
preply++;
}
} else {
for (int n = 0; n < progdefaults.RigCatRetries; n++) {
MilliSleep(50);
guard_lock ser_guard( &rigCAT_mutex );
if (rigCAT_exit) return;
if (sendCommand(strCmd, 0, progdefaults.RigCatInitDelay)) return;
}
}
LOG_ERROR("INIT failed");
}
void rigCAT_defaults()
{
listbox_xml_rig_baudrate->index(xmlrig.baud);
valRigCatStopbits->value(xmlrig.stopbits);
btnRigCatRTSplus->value(xmlrig.rts);
btnRigCatDTRplus->value(xmlrig.dtr);
btnRigCatRTSptt->value(xmlrig.rtsptt);
btnRigCatDTRptt->value(xmlrig.dtrptt);
chk_restore_tio->value(xmlrig.restore_tio);
chkRigCatRTSCTSflow->value(xmlrig.rtscts);
cntRigCatRetries->value(xmlrig.retries);
cntRigCatTimeout->value(xmlrig.timeout);
cntRigCatWait->value(xmlrig.write_delay);
cntRigCatInitDelay->value(xmlrig.init_delay);
// cntRigCatWaitForDevice->value(xmlrig.wait_for_device);
btnRigCatEcho->value(xmlrig.echo);
btnRigCatCMDptt->value(xmlrig.cmdptt);
chkRigCatVSP->value(xmlrig.vsp);
}
void rigCAT_restore_defaults()
{
inpXmlRigDevice->value(progdefaults.XmlRigDevice.c_str());
listbox_xml_rig_baudrate->index(progdefaults.XmlRigBaudrate);
valRigCatStopbits->value(progdefaults.RigCatStopbits);
btnRigCatRTSplus->value(progdefaults.RigCatRTSplus);
btnRigCatDTRplus->value(progdefaults.RigCatDTRplus);
btnRigCatRTSptt->value(progdefaults.RigCatRTSptt);
btnRigCatDTRptt->value(progdefaults.RigCatDTRptt);
chk_restore_tio->value(progdefaults.RigCatRestoreTIO);
chkRigCatRTSCTSflow->value(progdefaults.RigCatRTSCTSflow);
cntRigCatRetries->value(progdefaults.RigCatRetries);
cntRigCatTimeout->value(progdefaults.RigCatTimeout);
cntRigCatWait->value(progdefaults.RigCatWait);
cntRigCatInitDelay->value(progdefaults.RigCatInitDelay);
// cntRigCatWaitForDevice->value(progdefaults.RicCatWaitForDevice);
btnRigCatEcho->value(progdefaults.RigCatECHO);
btnRigCatCMDptt->value(progdefaults.RigCatCMDptt);
chkRigCatVSP->value(progdefaults.RigCatVSP);
btnInitRIGCAT->labelcolor(FL_FOREGROUND_COLOR);
btnRevertRIGCAT->deactivate();
dlgConfig->redraw();
}
void rigCAT_init_defaults()
{
progdefaults.XmlRigDevice = inpXmlRigDevice->value();
progdefaults.XmlRigBaudrate = listbox_xml_rig_baudrate->index();
progdefaults.RigCatStopbits = static_cast<int>(valRigCatStopbits->value());
progdefaults.RigCatRTSplus = btnRigCatRTSplus->value();
progdefaults.RigCatDTRplus = btnRigCatDTRplus->value();
progdefaults.RigCatRTSptt = btnRigCatRTSptt->value();
progdefaults.RigCatDTRptt = btnRigCatDTRptt->value();
progdefaults.RigCatRestoreTIO = chk_restore_tio->value();
progdefaults.RigCatRTSCTSflow = chkRigCatRTSCTSflow->value();
progdefaults.RigCatRetries = static_cast<int>(cntRigCatRetries->value());
progdefaults.RigCatTimeout = static_cast<int>(cntRigCatTimeout->value());
progdefaults.RigCatWait = static_cast<int>(cntRigCatWait->value());
progdefaults.RigCatInitDelay = static_cast<int>(cntRigCatInitDelay->value());
progdefaults.RigCatECHO = btnRigCatEcho->value();
progdefaults.RigCatCMDptt = btnRigCatCMDptt->value();
progdefaults.RigCatVSP = chkRigCatVSP->value();
}
bool rigCAT_init()
{
if (rigCAT_open == true) {
LOG_ERROR("RigCAT already open");
return false;
}
sRigMode = "";
sRigWidth = "";
rigCAT_init_defaults();
rigio.Device(progdefaults.XmlRigDevice);
rigio.Baud(progdefaults.BaudRate(progdefaults.XmlRigBaudrate));
rigio.RTS(progdefaults.RigCatRTSplus);
rigio.DTR(progdefaults.RigCatDTRplus);
rigio.RTSptt(progdefaults.RigCatRTSptt);
rigio.DTRptt(progdefaults.RigCatDTRptt);
rigio.RestoreTIO(progdefaults.RigCatRestoreTIO);
rigio.RTSCTS(progdefaults.RigCatRTSCTSflow);
rigio.Stopbits(progdefaults.RigCatStopbits);
LOG_INFO("\n\
Serial port parameters:\n\
device : %s\n\
baudrate : %d\n\
stopbits : %d\n\
retries : %d\n\
timeout : %d\n\
wait : %d\n\
initial rts: %+d\n\
use rts ptt: %c\n\
initial dtr: %+d\n\
use dtr ptt: %c\n\
restore tio: %c\n\
flowcontrol: %c\n\
echo : %c\n",
rigio.Device().c_str(),
rigio.Baud(),
rigio.Stopbits(),
progdefaults.RigCatRetries,
progdefaults.RigCatTimeout,
progdefaults.RigCatWait,
(rigio.RTS() ? +12 : -12), (rigio.RTSptt() ? 'T' : 'F'),
(rigio.DTR() ? +12 : -12), (rigio.DTRptt() ? 'T' : 'F'),
(rigio.RestoreTIO() ? 'T' : 'F'),
(rigio.RTSCTS() ? 'T' : 'F'),
progdefaults.RigCatECHO ? 'T' : 'F');
if (xmlrig.noserial == false && xmlrig.xmlok) {
if (rigio.OpenPort() == false) {
LOG_ERROR("Cannot open serial port %s", rigio.Device().c_str());
xmlrig.xmlok = true;
}
}
sRigMode = "";
sRigWidth = "";
if (xmlrig.wait_for_device) {
int delay = xmlrig.wait_for_device / 10;
while (delay) {
MilliSleep(10);
if (delay % 10) Fl::awake();
delay--;
}
}
rigCAT_sendINIT("INIT", progdefaults.RigCatInitDelay);
bool failed = false;
if (xmlrig.noserial)
rigCAT_getfreq(1, failed, 0);
else if (xmlrig.xmlok) {
rigCAT_getfreq(3, failed, progdefaults.RigCatInitDelay);
if (failed) {
LOG_ERROR("*****************Failed to read xcvr frequency");
if (xmlrig.noserial == false)
rigio.ClosePort();
xmlrig.xmlok = false;
} else
LOG_INFO("Passed serial port test");
}
llFreq = 0;
if (pthread_create(&rigCAT_thread, NULL, rigCAT_loop, NULL) < 0) {
LOG_ERROR("%s", "pthread_create failed");
if (xmlrig.xmlok && !xmlrig.noserial)
rigio.ClosePort();
xmlrig.xmlok = false;
return false;
}
LOG_INFO("Created rigCAT thread");
rigCAT_open = true;
init_Xml_RigDialog();
return true;
}
void rigCAT_close(void)
{
if ( rigCAT_open == false || rigCAT_exit == true)
return;
rigCAT_sendINIT("CLOSE");
{
guard_lock ser_guard( &rigCAT_mutex );
rigCAT_exit = true;
}
LOG_INFO("%s", "Waiting for rigCAT_thread");
pthread_join(rigCAT_thread, NULL);
rigio.ClosePort();
rigCAT_exit = false;
rigCAT_open = false;
wf->USB(true);
}
bool rigCAT_active(void)
{
return (rigCAT_open);
}
void rigCAT_set_ptt(int ptt)
{
if (rigCAT_open == false)
return;
if (ptt) {
rigCAT_pttON();
} else{
rigCAT_pttOFF();
}
}
#ifndef RIGCATTEST
void rigCAT_set_qsy(long long f)
{
if (rigCAT_open == false)
return;
// send new freq to rig
rigCAT_setfreq(f);
wf->rfcarrier(f);
wf->movetocenter();
}
#endif
bool ModeIsLSB(string s)
{
if (connected_to_flrig) return !xmlrpc_USB();
#if USE_HAMLIB
if (hamlib_active()) return !hamlib_USB();
#endif
list<string>::iterator pM = LSBmodes.begin();
while (pM != LSBmodes.end() ) {
if (*pM == s)
return true;
pM++;
}
return false;
}
int smeter_data(DATA d, size_t p)
{
int val = 0;
if (d.dtype == "BCD") {
if (d.reverse == true)
val = (int)(fm_bcd_be(p, d.size));
else
val = (int)(fm_bcd(p, d.size));
} else if (d.dtype == "BINARY") {
if (d.reverse == true)
val = (int)(fm_binary_be(p, d.size));
else
val = (int)(fm_binary(p, d.size));
} else if (d.dtype == "DECIMAL") {
if (d.reverse == true)
val = (int)(fm_decimal_be(p, d.size));
else
val = (int)(fm_decimal(p, d.size));
}
size_t n;
int sm1, sm2, val1, val2;
for (n = 0; n < xmlrig.smeter.size() - 1; n++) {
if ((val >= xmlrig.smeter[n].val) && (val < xmlrig.smeter[n+1].val)) break;
}
if (n == xmlrig.smeter.size() - 1) return 0;
sm1 = xmlrig.smeter[n].mtr;
sm2 = xmlrig.smeter[n+1].mtr;
val1 = xmlrig.smeter[n].val;
val2 = xmlrig.smeter[n+1].val;
if (val1 == val2) return 0;
int mtr = sm1 + (val - val1) * (sm2 - sm1) / (val2 - val1);
return mtr;
}
static void rigcat_set_smeter(void *data)
{
if (pwrlevel_grp->visible()) return;
if (!smeter && !pwrmeter) return;
if (smeter && progStatus.meters) {
if (!smeter->visible()) {
pwrmeter->hide();
smeter->show();
}
int val = reinterpret_cast<long>(data);
smeter->value(val);
}
}
void rigCAT_get_smeter()
{
const char symbol[] = "GET_SMETER";
if (rigCAT_exit || xmlrig.noserial) return;
XMLIOS modeCmd;
list<XMLIOS>::iterator itrCmd;
string strCmd;
size_t p = 0, len1 = 0, len2 = 0, pData = 0;
long mtr = 0;
itrCmd = commands.begin();
while (itrCmd != commands.end()) {
if ((*itrCmd).SYMBOL == symbol)
break;
++itrCmd;
}
if (itrCmd == commands.end()) {
if (xmlrig.debug) LOG_INFO("%s not defined", symbol);
return;
}
modeCmd = *itrCmd;
if ( !modeCmd.str1.empty() ) strCmd.append(modeCmd.str1);
if ( !modeCmd.str2.empty() ) strCmd.append(modeCmd.str2);
if ( !modeCmd.info.size() ) return;
list<XMLIOS>::iterator preply;
for (preply = reply.begin(); preply != reply.end(); ++preply) {
if (preply->SYMBOL == modeCmd.info)
break;
}
if (preply == reply.end()) return;
XMLIOS rTemp = *preply;
len1 = rTemp.str1.size();
len2 = rTemp.str2.size();
int timeout = progdefaults.RigCatTimeout;
while (timeout > 50) {
MilliSleep(50);
Fl::awake();
timeout -= 50;
}
if (timeout) {
MilliSleep(timeout);
Fl::awake();
}
// send the command
if ( !sendCommand(strCmd, rTemp.size, progdefaults.RigCatWait) ) {
LOG_ERROR("sendCommand failed");
return;
}
// check the pre data string
p = 0;
pData = 0;
if (len1) {
for (size_t i = 0; i < len1; i++) {
if ((char)rTemp.str1[i] != (char)replybuff[i]) {
LOG_ERROR("failed pre data string test @ %" PRIuSZ, i);
return;
}
}
p = len1;
}
if (rTemp.fill1) p += rTemp.fill1;
pData = p;
if (rTemp.data.dtype == "BCD") {
p += rTemp.data.size / 2;
if (rTemp.data.size & 1) p++;
} else
p += rTemp.data.size;
// check the post data string
if (rTemp.fill2) p += rTemp.fill2;
if (len2) {
for (size_t i = 0; i < len2; i++)
if ((char)rTemp.str2[i] != (char)replybuff[p + i]) {
LOG_ERROR("failed post data string test @ %d", static_cast<int>(i));
return;
}
}
// convert the data field
mtr = smeter_data(rTemp.data, pData);
if (xmlrig.debug) LOG_INFO("Converted %s value to %d", symbol, (int)mtr);
REQ(rigcat_set_smeter, reinterpret_cast<void *>(mtr));
}
int pmeter_data(DATA d, size_t p)
{
int val = 0;
if (d.dtype == "BCD") {
if (d.reverse == true)
val = (int)(fm_bcd_be(p, d.size));
else
val = (int)(fm_bcd(p, d.size));
} else if (d.dtype == "BINARY") {
if (d.reverse == true)
val = (int)(fm_binary_be(p, d.size));
else
val = (int)(fm_binary(p, d.size));
} else if (d.dtype == "DECIMAL") {
if (d.reverse == true)
val = (int)(fm_decimal_be(p, d.size));
else
val = (int)(fm_decimal(p, d.size));
}
size_t n;
int pm1, pm2, val1, val2;
for (n = 0; n < xmlrig.pmeter.size() - 1; n++) {
if ((val > xmlrig.pmeter[n].val) && (val <= xmlrig.pmeter[n+1].val)) break;
}
if (n == xmlrig.pmeter.size() - 1) return 0;
pm1 = xmlrig.pmeter[n].mtr;
pm2 = xmlrig.pmeter[n+1].mtr;
val1 = xmlrig.pmeter[n].val;
val2 = xmlrig.pmeter[n+1].val;
if (val1 == val2) return 0;
int mtr = pm1 + (val - val1) * (pm2 - pm1) / (val2 - val1);
return mtr;
}
static void rigcat_set_pmeter(void *data)
{
if (pwrlevel_grp->visible()) return;
if (!smeter && !pwrmeter) return;
if (pwrmeter && progStatus.meters) {
if (!pwrmeter->visible()) {
smeter->hide();
pwrmeter->show();
}
int val = reinterpret_cast<long>(data);
pwrmeter->value(val);
}
}
void rigCAT_get_pwrmeter()
{
const char symbol[] = "GET_PWRMETER";
if (rigCAT_exit || xmlrig.noserial) return;
XMLIOS modeCmd;
list<XMLIOS>::iterator itrCmd;
string strCmd;
size_t p = 0, len1 = 0, len2 = 0, pData = 0;
long mtr = 0;
itrCmd = commands.begin();
while (itrCmd != commands.end()) {
if ((*itrCmd).SYMBOL == symbol)
break;
++itrCmd;
}
if (itrCmd == commands.end()) {
if (xmlrig.debug) LOG_INFO("%s not defined", symbol);
return;
}
modeCmd = *itrCmd;
if ( !modeCmd.str1.empty() ) strCmd.append(modeCmd.str1);
if ( !modeCmd.str2.empty() ) strCmd.append(modeCmd.str2);
if ( !modeCmd.info.size() ) return;
list<XMLIOS>::iterator preply;
for (preply = reply.begin(); preply != reply.end(); ++preply) {
if (preply->SYMBOL == modeCmd.info)
break;
}
if (preply == reply.end()) return;
XMLIOS rTemp = *preply;
len1 = rTemp.str1.size();
len2 = rTemp.str2.size();
int timeout = progdefaults.RigCatTimeout;
while (timeout > 50) {
MilliSleep(50);
Fl::awake();
timeout -= 50;
}
if (timeout) {
MilliSleep(timeout);
Fl::awake();
}
// send the command
if ( !sendCommand(strCmd, rTemp.size, progdefaults.RigCatWait) ) {
LOG_ERROR("sendCommand failed");
return;
}
// check the pre data string
p = 0;
pData = 0;
if (len1) {
for (size_t i = 0; i < len1; i++) {
if ((char)rTemp.str1[i] != (char)replybuff[i]) {
LOG_ERROR("failed pre data string test @ %" PRIuSZ, i);
return;
}
}
p = len1;
}
if (rTemp.fill1) p += rTemp.fill1;
pData = p;
if (rTemp.data.dtype == "BCD") {
p += rTemp.data.size / 2;
if (rTemp.data.size & 1) p++;
} else
p += rTemp.data.size;
// check the post data string
if (rTemp.fill2) p += rTemp.fill2;
if (len2) {
for (size_t i = 0; i < len2; i++)
if ((char)rTemp.str2[i] != (char)replybuff[p + i]) {
LOG_ERROR("failed post data string test @ %d", static_cast<int>(i));
return;
}
}
// convert the data field
mtr = pmeter_data(rTemp.data, pData);
if (xmlrig.debug) LOG_INFO("Converted %s to %d", symbol, (int)mtr);
REQ(rigcat_set_pmeter, reinterpret_cast<void *>(mtr));
}
static void rigcat_notch(void *data)
{
int val = reinterpret_cast<long>(data);
notch_frequency = val;
}
int notch_data(DATA d, size_t p)
{
int val = 0;
if (d.dtype == "BCD") {
if (d.reverse == true)
val = (int)(fm_bcd_be(p, d.size));
else
val = (int)(fm_bcd(p, d.size));
} else if (d.dtype == "BINARY") {
if (d.reverse == true)
val = (int)(fm_binary_be(p, d.size));
else
val = (int)(fm_binary(p, d.size));
} else if (d.dtype == "DECIMAL") {
if (d.reverse == true)
val = (int)(fm_decimal_be(p, d.size));
else
val = (int)(fm_decimal(p, d.size));
}
size_t n;
int ntch1, ntch2, val1, val2;
for (n = 0; n < xmlrig.notch.size() - 1; n++) {
if ((val > xmlrig.notch[n].val) && (val <= xmlrig.notch[n+1].val))
break;
}
if (n == xmlrig.notch.size() - 1)
return 0;
val1 = xmlrig.notch[n].val;
val2 = xmlrig.notch[n+1].val;
if (val1 == val2)
return 0;
ntch1 = xmlrig.notch[n].mtr;
ntch2 = xmlrig.notch[n+1].mtr;
return ntch1 + (val - val1) * (ntch2 - ntch1) / (val2 - val1);
}
int notch_val(int freq)
{
size_t n;
int val1, val2, freq1, freq2;
for (n = 0; n < xmlrig.notch.size() - 1; n++) {
if ((freq > xmlrig.notch[n].mtr) && (freq <= xmlrig.notch[n+1].mtr))
break;
}
if (n == xmlrig.notch.size() - 1)
return 0;
freq1 = xmlrig.notch[n].mtr;
freq2 = xmlrig.notch[n+1].mtr;
if (freq1 == freq2)
return 0;
val1 = xmlrig.notch[n].val;
val2 = xmlrig.notch[n+1].val;
return val1 + (freq - freq1) * (val2 - val1) / (freq2 - freq1);
}
bool rigCAT_notchON()
{
const char symbol[] = "GET_NOTCH_ON";
if (rigCAT_exit) return 0;
XMLIOS modeCmd;
list<XMLIOS>::iterator itrCmd;
string strCmd;
size_t len1 = 0;
itrCmd = commands.begin();
while (itrCmd != commands.end()) {
if ((*itrCmd).SYMBOL == symbol)
break;
++itrCmd;
}
if (itrCmd == commands.end()) {
if (xmlrig.debug) LOG_INFO("%s not defined", symbol);
return 0;
}
modeCmd = *itrCmd;
if ( !modeCmd.str1.empty() ) strCmd.append(modeCmd.str1);
if ( !modeCmd.str2.empty() ) strCmd.append(modeCmd.str2);
if ( !modeCmd.info.size() ) return 0;
list<XMLIOS>::iterator preply;
for (preply = reply.begin(); preply != reply.end(); ++preply) {
if (preply->SYMBOL == modeCmd.info)
break;
}
if (preply == reply.end()) return 0;
XMLIOS rTemp = *preply;
len1 = rTemp.str1.size();
int timeout = progdefaults.RigCatTimeout;
while (timeout > 50) {
MilliSleep(50);
Fl::awake();
timeout -= 50;
}
if (timeout) {
MilliSleep(timeout);
Fl::awake();
}
// send the command
if ( !sendCommand(strCmd, rTemp.size, progdefaults.RigCatWait) ) {
LOG_ERROR("sendCommand failed");
return 0;
}
bool is_on = true;
if (len1) {
for (size_t i = 0; i < len1; i++) {
if ((char)rTemp.str1[i] != (char)replybuff[i]) {
is_on = false;
break;
}
}
} else
is_on = false;
if (xmlrig.debug) LOG_INFO("%s is %s", symbol, is_on ? "ON" : "OFF");
return is_on;
}
void rigCAT_get_notch()
{
const char symbol[] = "GET_NOTCH";
if (rigCAT_exit) return;
if (!rigCAT_notchON()) {
REQ(rigcat_notch, reinterpret_cast<void *>(0));
return;
}
XMLIOS modeCmd;
list<XMLIOS>::iterator itrCmd;
string strCmd;
size_t p = 0, len1 = 0, len2 = 0, pData = 0;
long ntch = 0;
itrCmd = commands.begin();
while (itrCmd != commands.end()) {
if ((*itrCmd).SYMBOL == symbol)
break;
++itrCmd;
}
if (itrCmd == commands.end()) {
if (xmlrig.debug) LOG_INFO("%s not defined", symbol);
return;
}
modeCmd = *itrCmd;
if ( !modeCmd.str1.empty() ) strCmd.append(modeCmd.str1);
if ( !modeCmd.str2.empty() ) strCmd.append(modeCmd.str2);
if ( !modeCmd.info.size() ) return;
list<XMLIOS>::iterator preply;
for (preply = reply.begin(); preply != reply.end(); ++preply) {
if (preply->SYMBOL == modeCmd.info)
break;
}
if (preply == reply.end()) return;
XMLIOS rTemp = *preply;
len1 = rTemp.str1.size();
len2 = rTemp.str2.size();
int timeout = progdefaults.RigCatTimeout;
while (timeout > 50) {
MilliSleep(50);
Fl::awake();
timeout -= 50;
}
if (timeout) {
MilliSleep(timeout);
Fl::awake();
}
// send the command
if ( !sendCommand(strCmd, rTemp.size, progdefaults.RigCatWait) ) {
LOG_ERROR("sendCommand failed");
return;
}
// check the pre data string
p = 0;
pData = 0;
if (len1) {
for (size_t i = 0; i < len1; i++) {
if ((char)rTemp.str1[i] != (char)replybuff[i]) {
LOG_ERROR("failed pre data string test @ %" PRIuSZ, i);
return;
}
}
p = len1;
}
if (rTemp.fill1) p += rTemp.fill1;
pData = p;
if (rTemp.data.dtype == "BCD") {
p += rTemp.data.size / 2;
if (rTemp.data.size & 1) p++;
} else
p += rTemp.data.size;
// check the post data string
if (rTemp.fill2) p += rTemp.fill2;
if (len2) {
for (size_t i = 0; i < len2; i++)
if ((char)rTemp.str2[i] != (char)replybuff[p + i]) {
LOG_ERROR("failed post data string test @ %d", static_cast<int>(i));
return;
}
}
// convert the data field
ntch = notch_data(rTemp.data, pData);
if (xmlrig.debug) LOG_INFO("%s converted to %d", symbol, (int)ntch);
REQ(rigcat_notch, reinterpret_cast<void *>(ntch));
}
void rigCAT_notch_ON()
{
const char symbol[] = "SET_NOTCH_ON";
if (rigCAT_exit) return;
XMLIOS modeCmd;
list<XMLIOS>::iterator itrCmd;
string strCmd;
itrCmd = commands.begin();
while (itrCmd != commands.end()) {
if ((*itrCmd).SYMBOL == symbol)
break;
++itrCmd;
}
if (itrCmd == commands.end()) {
if (xmlrig.debug) LOG_INFO("%s not defined", symbol);
return;
}
modeCmd = *itrCmd;
if ( modeCmd.str1.empty() == false)
strCmd.append(modeCmd.str1);
if (modeCmd.str2.empty() == false)
strCmd.append(modeCmd.str2);
if (modeCmd.ok.size()) {
list<XMLIOS>::iterator preply = reply.begin();
while (preply != reply.end()) {
if (preply->SYMBOL == modeCmd.ok) {
XMLIOS rTemp = *preply;
// send the command
for (int n = 0; n < progdefaults.RigCatRetries; n++) {
MilliSleep(50);
guard_lock ser_guard( &rigCAT_mutex );
if (rigCAT_exit) return;
if (sendCommand(strCmd, rTemp.size, progdefaults.RigCatWait)) return;
}
return;
}
preply++;
}
} else {
for (int n = 0; n < progdefaults.RigCatRetries; n++) {
MilliSleep(50);
guard_lock ser_guard( &rigCAT_mutex );
if (rigCAT_exit) return;
if (sendCommand(strCmd, 0, progdefaults.RigCatWait)) return;
}
}
LOG_ERROR("%s failed", symbol);
}
void rigCAT_notch_OFF()
{
const char symbol[] = "SET_NOTCH_OFF";
if (rigCAT_exit) return;
XMLIOS modeCmd;
list<XMLIOS>::iterator itrCmd;
string strCmd;
itrCmd = commands.begin();
while (itrCmd != commands.end()) {
if ((*itrCmd).SYMBOL == symbol)
break;
++itrCmd;
}
if (itrCmd == commands.end()) {
if (xmlrig.debug) LOG_INFO("%s not defined", symbol);
return;
}
modeCmd = *itrCmd;
if ( modeCmd.str1.empty() == false)
strCmd.append(modeCmd.str1);
if (modeCmd.str2.empty() == false)
strCmd.append(modeCmd.str2);
if (modeCmd.ok.size()) {
list<XMLIOS>::iterator preply = reply.begin();
while (preply != reply.end()) {
if (preply->SYMBOL == modeCmd.ok) {
XMLIOS rTemp = *preply;
// send the command
for (int n = 0; n < progdefaults.RigCatRetries; n++) {
MilliSleep(50);
guard_lock ser_guard( &rigCAT_mutex );
if (rigCAT_exit) return;
if (sendCommand(strCmd, rTemp.size, progdefaults.RigCatWait)) return;
}
return;
}
preply++;
}
} else {
for (int n = 0; n < progdefaults.RigCatRetries; n++) {
MilliSleep(50);
guard_lock ser_guard( &rigCAT_mutex );
if (rigCAT_exit) return;
if (sendCommand(strCmd, 0, progdefaults.RigCatWait)) return;
}
}
LOG_ERROR("%s failed", symbol);
}
void rigCAT_set_notch(int freq)
{
const char symbol[] = "SET_NOTCH_VAL";
if (rigCAT_exit) return;
if (!freq) {
rigCAT_notch_OFF();
return;
}
rigCAT_notch_ON();
XMLIOS modeCmd;
list<XMLIOS>::iterator itrCmd;
string strCmd;
itrCmd = commands.begin();
while (itrCmd != commands.end()) {
if ((*itrCmd).SYMBOL == symbol)
break;
++itrCmd;
}
if (itrCmd == commands.end()) {
if (xmlrig.debug) LOG_INFO("%s not defined", symbol);
return;
}
modeCmd = *itrCmd;
if ( modeCmd.str1.empty() == false)
strCmd.append(modeCmd.str1);
string strval = "";
long long int val = notch_val(freq);
if (modeCmd.data.size != 0) {
if (modeCmd.data.dtype == "BCD") {
if (modeCmd.data.reverse == true)
strval = to_bcd_be(val, modeCmd.data.size);
else
strval = to_bcd(val, modeCmd.data.size);
} else if (modeCmd.data.dtype == "BINARY") {
if (modeCmd.data.reverse == true)
strval = to_binary_be(val, modeCmd.data.size);
else
strval = to_binary(val, modeCmd.data.size);
} else if (modeCmd.data.dtype == "DECIMAL") {
if (modeCmd.data.reverse == true)
strval = to_decimal_be(val, modeCmd.data.size);
else
strval = to_decimal(val, modeCmd.data.size);
}
}
strCmd.append(strval);
if (modeCmd.str2.empty() == false)
strCmd.append(modeCmd.str2);
if (modeCmd.ok.size()) {
list<XMLIOS>::iterator preply = reply.begin();
while (preply != reply.end()) {
if (preply->SYMBOL == modeCmd.ok) {
XMLIOS rTemp = *preply;
// send the command
for (int n = 0; n < progdefaults.RigCatRetries; n++) {
MilliSleep(50);
guard_lock ser_guard( &rigCAT_mutex );
if (rigCAT_exit) return;
if (sendCommand(strCmd, rTemp.size, progdefaults.RigCatWait)) return;
}
return;
}
preply++;
}
} else {
for (int n = 0; n < progdefaults.RigCatRetries; n++) {
MilliSleep(50);
guard_lock ser_guard( &rigCAT_mutex );
if (rigCAT_exit) return;
if (sendCommand(strCmd, 0, progdefaults.RigCatWait)) return;
}
}
if (progdefaults.RigCatVSP == false)
LOG_ERROR("%s failed", symbol);
}
int pwrlevel_data(DATA d, size_t p)
{
int val = 0;
if (d.dtype == "BCD") {
if (d.reverse == true)
val = (int)(fm_bcd_be(p, d.size));
else
val = (int)(fm_bcd(p, d.size));
} else if (d.dtype == "BINARY") {
if (d.reverse == true)
val = (int)(fm_binary_be(p, d.size));
else
val = (int)(fm_binary(p, d.size));
} else if (d.dtype == "DECIMAL") {
if (d.reverse == true)
val = (int)(fm_decimal_be(p, d.size));
else
val = (int)(fm_decimal(p, d.size));
}
size_t n;
int pwr1, pwr2, val1, val2;
for (n = 0; n < xmlrig.pwrlevel.size() - 1; n++) {
if ((val > xmlrig.pwrlevel[n].val) && (val <= xmlrig.pwrlevel[n+1].val))
break;
}
if (n == xmlrig.pwrlevel.size() - 1)
return 0;
val1 = xmlrig.pwrlevel[n].val;
val2 = xmlrig.pwrlevel[n+1].val;
if (val1 == val2)
return 0;
pwr1 = xmlrig.pwrlevel[n].mtr;
pwr2 = xmlrig.pwrlevel[n+1].mtr;
return pwr1 + (val - val1) * (pwr2 - pwr1) / (val2 - val1);
}
int pwrlevel_val(int pwr)
{
size_t n;
int val1, val2, pwr1, pwr2;
for (n = 0; n < xmlrig.pwrlevel.size() - 1; n++) {
if ((pwr >= xmlrig.pwrlevel[n].mtr) && (pwr <= xmlrig.pwrlevel[n+1].mtr))
break;
}
if (n == xmlrig.pwrlevel.size() - 1)
return 0;
pwr1 = xmlrig.pwrlevel[n].mtr;
pwr2 = xmlrig.pwrlevel[n+1].mtr;
if (pwr1 == pwr2)
return 0;
val1 = xmlrig.pwrlevel[n].val;
val2 = xmlrig.pwrlevel[n+1].val;
return val1 + (pwr - pwr1) * (val2 - val1) / (pwr2 - pwr1);
}
// called by rigio thread
// must use REQ(...) to set the power level control
static void rigCAT_update_pwrlevel(void *v)
{
long pwr = reinterpret_cast<long>(v);
char szpwr[10];
snprintf(szpwr, sizeof(szpwr), "%ld", pwr);
progdefaults.mytxpower = szpwr;
inpMyPower->value(szpwr);
pwr_level->value(pwr);
if (xmlrig.debug) LOG_INFO("Read power level %s", szpwr);
}
void rigCAT_get_pwrlevel()
{
const char symbol[] = "GET_PWRLEVEL";
if (rigCAT_exit || xmlrig.noserial || !xmlrig.xmlok) return;
XMLIOS modeCmd;
list<XMLIOS>::iterator itrCmd;
string strCmd;
size_t p = 0, len1 = 0, len2 = 0, pData = 0;
long pwr = 0;
itrCmd = commands.begin();
while (itrCmd != commands.end()) {
if ((*itrCmd).SYMBOL == symbol)
break;
++itrCmd;
}
if (itrCmd == commands.end()) {
if (xmlrig.debug) LOG_INFO("%s not defined", symbol);
return;
}
modeCmd = *itrCmd;
if ( !modeCmd.str1.empty() ) strCmd.append(modeCmd.str1);
if ( !modeCmd.str2.empty() ) strCmd.append(modeCmd.str2);
if ( !modeCmd.info.size() ) return;
list<XMLIOS>::iterator preply;
for (preply = reply.begin(); preply != reply.end(); ++preply) {
if (preply->SYMBOL == modeCmd.info)
break;
}
if (preply == reply.end()) return;
XMLIOS rTemp = *preply;
len1 = rTemp.str1.size();
len2 = rTemp.str2.size();
int timeout = progdefaults.RigCatTimeout;
while (timeout > 50) {
MilliSleep(50);
Fl::awake();
timeout -= 50;
}
if (timeout) {
MilliSleep(timeout);
Fl::awake();
}
// send the command
{
guard_lock ser_guard( &rigCAT_mutex );
if ( !sendCommand(strCmd, rTemp.size, progdefaults.RigCatWait) ) {
LOG_ERROR("sendCommand failed");
return;
}
}
// check the pre data string
p = 0;
pData = 0;
if (len1) {
for (size_t i = 0; i < len1; i++) {
if ((char)rTemp.str1[i] != (char)replybuff[i]) {
LOG_ERROR("failed pre data string test @ %" PRIuSZ, i);
return;
}
}
p = len1;
}
if (rTemp.fill1) p += rTemp.fill1;
pData = p;
if (rTemp.data.dtype == "BCD") {
p += rTemp.data.size / 2;
if (rTemp.data.size & 1) p++;
} else
p += rTemp.data.size;
// check the post data string
if (rTemp.fill2) p += rTemp.fill2;
if (len2) {
for (size_t i = 0; i < len2; i++)
if ((char)rTemp.str2[i] != (char)replybuff[p + i]) {
LOG_ERROR("failed post data string test @ %d", static_cast<int>(i));
return;
}
}
// convert the data field
pwr = pwrlevel_data(rTemp.data, pData);
REQ(rigCAT_update_pwrlevel, (void *)pwr);
}
void rigCAT_set_pwrlevel(int pwr)
{
const char symbol[] = "SET_PWRLEVEL";
if (rigCAT_exit || !xmlrig.use_pwrlevel) return;
XMLIOS modeCmd;
list<XMLIOS>::iterator itrCmd;
string strCmd;
itrCmd = commands.begin();
while (itrCmd != commands.end()) {
if ((*itrCmd).SYMBOL == symbol)
break;
++itrCmd;
}
if (itrCmd == commands.end()) {
if (xmlrig.debug) LOG_INFO("%s not defined", symbol);
return;
}
modeCmd = *itrCmd;
if ( modeCmd.str1.empty() == false)
strCmd.append(modeCmd.str1);
string strval = "";
int val = pwrlevel_val(pwr);
if (modeCmd.data.size != 0) {
if (modeCmd.data.dtype == "BCD") {
if (modeCmd.data.reverse == true)
strval = to_bcd_be(val, modeCmd.data.size);
else
strval = to_bcd(val, modeCmd.data.size);
} else if (modeCmd.data.dtype == "BINARY") {
if (modeCmd.data.reverse == true)
strval = to_binary_be(val, modeCmd.data.size);
else
strval = to_binary(val, modeCmd.data.size);
} else if (modeCmd.data.dtype == "DECIMAL") {
if (modeCmd.data.reverse == true)
strval = to_decimal_be(val, modeCmd.data.size);
else
strval = to_decimal(val, modeCmd.data.size);
}
}
strCmd.append(strval);
if (modeCmd.str2.empty() == false)
strCmd.append(modeCmd.str2);
if (modeCmd.ok.size()) {
list<XMLIOS>::iterator preply = reply.begin();
while (preply != reply.end()) {
if (preply->SYMBOL == modeCmd.ok) {
XMLIOS rTemp = *preply;
// send the command
for (int n = 0; n < progdefaults.RigCatRetries; n++) {
MilliSleep(50);
guard_lock ser_guard( &rigCAT_mutex );
if (rigCAT_exit) return;
if (sendCommand(strCmd, rTemp.size, progdefaults.RigCatWait)) {
if (xmlrig.debug) LOG_INFO("Power set to %s", strval.c_str());
return;
}
}
if (xmlrig.debug) LOG_ERROR("%s failed", symbol);
return;
}
preply++;
}
} else {
for (int n = 0; n < progdefaults.RigCatRetries; n++) {
MilliSleep(50);
guard_lock ser_guard( &rigCAT_mutex );
if (rigCAT_exit) return;
if (sendCommand(strCmd, 0, progdefaults.RigCatWait)) {
if (xmlrig.debug) LOG_INFO("Power set to %s", strval.c_str());
return;
}
}
}
if (progdefaults.RigCatVSP == false)
if (xmlrig.debug) LOG_ERROR("%s failed", symbol);
}
static void *rigCAT_loop(void *args)
{
SET_THREAD_ID(RIGCTL_TID);
long long freq = 0L;
string sWidth, sMode;
bool failed;
for (;;) {
for (int i = 0; i < xmlrig.pollinterval / 10; i++) {
MilliSleep(10);
guard_lock ser_guard( &rigCAT_mutex );
if (rigCAT_exit == true) {
LOG_INFO("%s", "Exited rigCAT loop");
return NULL;
}
}
if (trx_state == STATE_RX) {
freq = rigCAT_getfreq(progdefaults.RigCatRetries, failed);
if (rigCAT_exit) continue;
if ((freq > 0) && (freq != llFreq)) {
llFreq = freq;
show_frequency(freq);
wf->rfcarrier(freq);
}
sWidth = rigCAT_getwidth();
if (rigCAT_exit) continue;
if (sWidth.size() && sWidth != sRigWidth) {
sRigWidth = sWidth;
show_bw(sWidth);
}
sMode = rigCAT_getmode();
if (rigCAT_exit) continue;
if (sMode.size() && sMode != sRigMode) {
sRigMode = sMode;
if (ModeIsLSB(sMode))
wf->USB(false);
else
wf->USB(true);
show_mode(sMode);
}
if (xmlrig.use_pwrlevel) rigCAT_get_pwrlevel();
if (xmlrig.use_smeter) rigCAT_get_smeter();
if (xmlrig.use_notch) rigCAT_get_notch();
} else {
if ( (trx_state == STATE_TUNE) || (trx_state == STATE_TX) )
if (xmlrig.use_pwrmeter) rigCAT_get_pwrmeter();
}
}
return NULL;
}