Add FLRig backend

astyle-formatting
Michael Black W9MDB 2017-07-06 22:53:58 +01:00
rodzic 21a6909a9a
commit 8978d0ab9b
8 zmienionych plików z 887 dodań i 2 usunięć

Wyświetl plik

@ -2,7 +2,7 @@ LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES := dummy.c rot_dummy.c netrigctl.c netrotctl.c
LOCAL_SRC_FILES := dummy.c rot_dummy.c netrigctl.c netrotctl.c flrig.c
LOCAL_MODULE := dummy
LOCAL_CFLAGS := -DHAVE_CONFIG_H

Wyświetl plik

@ -1,4 +1,4 @@
DUMMYSRC = dummy.c dummy.h rot_dummy.c rot_dummy.h netrigctl.c netrotctl.c
DUMMYSRC = dummy.c dummy.h rot_dummy.c rot_dummy.h netrigctl.c netrotctl.c flrig.c flrig.h
noinst_LTLIBRARIES = libhamlib-dummy.la
libhamlib_dummy_la_SOURCES = $(DUMMYSRC)

Wyświetl plik

@ -1618,6 +1618,7 @@ DECLARE_INITRIG_BACKEND(dummy)
rig_register(&dummy_caps);
rig_register(&netrigctl_caps);
rig_register(&flrig_caps);
return RIG_OK;
}

Wyświetl plik

@ -38,5 +38,6 @@
extern const struct rig_caps dummy_caps;
extern const struct rig_caps netrigctl_caps;
extern const struct rig_caps flrig_caps;
#endif /* _DUMMY_H */

Wyświetl plik

@ -0,0 +1,5 @@
As of version 0.1 this works well with rigs have a full ack/nak protocol as coded in FLRig. So Kenwood, Icom and such.
But Yaesu rigs for example are not stable with applications like WSJT-X since the FLRig driver does not wait or obtain status after frequency change commands for example (fire and forget). Hamlib's Yaesu drivers always send and ID request after such commands and wait for an appropriate response but FLRig does not so can miss commands as a result. Slow operation (manual command from rigctl) works fine.
Rig drivers in FLRig will have to be changed to allow stable operation with fast comm programs like WJST-X.
de Mike W9MDB

837
dummy/flrig.c 100644
Wyświetl plik

@ -0,0 +1,837 @@
/*
* Hamlib FLRig backend - main file
* Copyright (c) 2017 by Michael Black W9MDB
*
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h> /* String function definitions */
#include <unistd.h> /* UNIX standard function definitions */
#include <math.h>
#include <hamlib/rig.h>
#include <serial.h>
#include <misc.h>
#include <cal.h>
#include <token.h>
#include <register.h>
#include <network.h>
#include "flrig.h"
#define DEBUG 1
#define MAXCMDLEN 8192
#define DEFAULTPATH "localhost:12345"
#define FLRIG_VFOS (RIG_VFO_A|RIG_VFO_B|RIG_VFO_TX)
#define FLRIG_MODES (RIG_MODE_AM | RIG_MODE_CW | RIG_MODE_RTTY | \
RIG_MODE_SSB | RIG_MODE_FM)
#define RIG_DEBUG_TRACE RIG_DEBUG_VERBOSE
static int flrig_init(RIG *rig);
//int flrig_cleanup(RIG *rig);
static int flrig_set_freq(RIG *rig, vfo_t vfo, freq_t freq);
static int flrig_get_freq(RIG *rig, vfo_t vfo, freq_t *freq);
static int flrig_set_ptt(RIG *rig, vfo_t vfo, ptt_t ptt);
static int flrig_set_mode(RIG *rig, vfo_t vfo, rmode_t mode,
pbwidth_t width);
static int flrig_get_vfo(RIG *rig, vfo_t *vfo);
static int flrig_set_vfo(RIG *rig, vfo_t vfo);
static int flrig_set_ptt(RIG *rig, vfo_t vfo, ptt_t ptt);
static int flrig_get_ptt(RIG *rig, vfo_t vfo, ptt_t *ptt);
static int flrig_set_split_freq(RIG *rig, vfo_t vfo, freq_t tx_freq);
static int flrig_get_split_freq(RIG *rig, vfo_t vfo, freq_t *tx_freq);
static int flrig_set_split_vfo(RIG *rig, vfo_t vfo, split_t split,
vfo_t tx_vfo);
static int flrig_get_split_vfo(RIG *rig, vfo_t vfo, split_t *split,
vfo_t *tx_vfo);
struct flrig_priv_data {
vfo_t vfo_curr;
};
const struct rig_caps flrig_caps = {
.rig_model = RIG_MODEL_FLRIG,
.model_name = "FLRig",
.mfg_name = "FLRig",
.version = BACKEND_VER,
.copyright = "LGPL",
.status = RIG_STATUS_ALPHA,
.rig_type = RIG_TYPE_TRANSCEIVER,
.targetable_vfo = 0,
.ptt_type = RIG_PTT_RIG,
.port_type = RIG_PORT_NETWORK,
.write_delay = 0,
.post_write_delay = 50,
.timeout = 1000,
.retry = 3,
.has_get_func = RIG_FUNC_NONE,
.has_set_func = RIG_FUNC_NONE,
.has_get_level = (RIG_LEVEL_RAWSTR | RIG_LEVEL_STRENGTH),
.has_set_level = RIG_LEVEL_NONE,
.has_get_parm = RIG_PARM_NONE,
.has_set_parm = RIG_PARM_NONE,
// .level_gran = { [LVL_CWPITCH] = { .step = { .i = 10 } } },
// .ctcss_list = common_ctcss_list,
// .dcs_list = full_dcs_list,
// .chan_list = {
// { 0, 18, RIG_MTYPE_MEM, DUMMY_MEM_CAP },
// { 19, 19, RIG_MTYPE_CALL },
// { 20, NB_CHAN-1, RIG_MTYPE_EDGE },
// RIG_CHAN_END,
// },
// .vfo_ops = DUMMY_VFO_OP,
.transceive = RIG_TRN_RIG,
// .attenuator = { 10, 20, 30, RIG_DBLST_END, },
// .preamp = { 10, RIG_DBLST_END, },
// .rx_range_list1 = {{.start = kHz(150),.end = MHz(1500),.modes = FLRIG_MODES,
// .low_power = -1,.high_power = -1, FLRIG_VFOS, RIG_ANT_1 | RIG_ANT_2},
// RIG_FRNG_END,},
// .tx_range_list1 = {RIG_FRNG_END,},
// .rx_range_list2 = {{.start = kHz(150),.end = MHz(1500),.modes = FLRIG_MODES,
// .low_power = -1,.high_power = -1, FLRIG_VFOS, RIG_ANT_1 | RIG_ANT_2},
// RIG_FRNG_END,},
// .tx_range_list2 = {RIG_FRNG_END,},
// .tuning_steps = { {DUMMY_MODES,1}, {DUMMY_MODES,RIG_TS_ANY}, RIG_TS_END, },
// .filters = {
// {RIG_MODE_SSB | RIG_MODE_CW | RIG_MODE_RTTY, kHz(2.4)},
// {RIG_MODE_CW, Hz(500)},
// {RIG_MODE_AM, kHz(8)},
// {RIG_MODE_AM, kHz(2.4)},
// {RIG_MODE_FM, kHz(15)},
// {RIG_MODE_FM, kHz(8)},
// {RIG_MODE_WFM, kHz(230)},
// RIG_FLT_END,
// },
// .max_rit = 9990,
// .max_xit = 9990,
// .max_ifshift = 10000,
.priv = NULL, /* priv */
// .extlevels = dummy_ext_levels,
// .extparms = dummy_ext_parms,
// .cfgparams = dummy_cfg_params,
.rig_init = flrig_init,
// .rig_cleanup = dummy_cleanup,
// .rig_open = dummy_open,
// .rig_close = dummy_close,
// .set_conf = dummy_set_conf,
// .get_conf = dummy_get_conf,
.set_freq = flrig_set_freq,
.get_freq = flrig_get_freq,
.set_mode = flrig_set_mode,
// .get_mode = dummy_get_mode,
.set_vfo = flrig_set_vfo,
.get_vfo = flrig_get_vfo,
// .set_powerstat = dummy_set_powerstat,
// .get_powerstat = dummy_get_powerstat,
// .set_level = dummy_set_level,
// .get_level = dummy_get_level,
// .set_func = dummy_set_func,
// .get_func = dummy_get_func,
// .set_parm = dummy_set_parm,
// .get_parm = dummy_get_parm,
// .set_ext_level = dummy_set_ext_level,
// .get_ext_level = dummy_get_ext_level,
// .set_ext_parm = dummy_set_ext_parm,
// .get_ext_parm = dummy_get_ext_parm,
// .get_info = dummy_get_info,
.set_ptt = flrig_set_ptt,
.get_ptt = flrig_get_ptt,
.set_split_freq = flrig_set_split_freq,
.get_split_freq = flrig_get_split_freq,
// .set_split_mode = flrig_set_split_mode,
// .get_split_mode = flrig_get_split_mode,
.set_split_vfo = flrig_set_split_vfo,
.get_split_vfo = flrig_get_split_vfo,
// .set_ant = dummy_set_ant,
// .get_ant = dummy_get_ant,
// .set_bank = dummy_set_bank,
// .set_mem = dummy_set_mem,
// .get_mem = dummy_get_mem,
// .vfo_op = dummy_vfo_op,
// .set_trn = dummy_set_trn,
// .get_trn = dummy_get_trn,
};
DECLARE_INITRIG_BACKEND(flrig)
{
rig_debug(RIG_DEBUG_TRACE, "flrig: _init called\n");
rig_register(&flrig_caps);
return RIG_OK;
}
static int check_vfo(vfo_t vfo)
{
switch (vfo) { // Omni VII only has A & B
case RIG_VFO_A:
break;
case RIG_VFO_B:
break;
case RIG_VFO_TX:
break;
case RIG_VFO_CURR:
break; // will default to A in which_vfo
default:
return FALSE;
}
return TRUE;
}
static int vfo_curr(RIG *rig, vfo_t vfo)
{
int retval = 0;
struct flrig_priv_data *priv =
(struct flrig_priv_data *) rig->state.priv;
retval = (vfo == priv->vfo_curr);
return retval;
}
// Rather than use some huge XML library we only need a few things
// So we'll hand craft them
static char *xml_build(char *cmd, char *value)
{
char xml[4096];
char tmp[32];
static char xmlpost[4096];
// Standard 50ms sleep borrowed from ts200.c settings
// Tested with ANAN 100
usleep(50 * 1000);
sprintf(xmlpost,
"POST /RPC2 HTTP/1.1\n" "User-Agent: XMLRPC++ 0.8\n"
"Host: 127.0.0.1:12345\n" "Content-type: text/xml\n");
sprintf(xml, "<?xml version=\"1.0\"?>\n");
strcat(xml, "<methodCall><methodName>");
strcat(xml, cmd);
strcat(xml, "</methodName>");
if (value && strlen(value) > 0) {
strcat(xml, value);
}
strcat(xml, "</methodCall>\n");
strcat(xmlpost, "Content-length: ");
sprintf(tmp, "%ld\n\n", strlen(xml));
strcat(xmlpost, tmp);
strcat(xmlpost, xml);
rig_debug(RIG_DEBUG_VERBOSE, "XML:\n%s", xmlpost);
return xmlpost;
}
// This is a very crude xml parse specific to what we need from FLRig
// This will not handle array returns for example yet...only simple values
// It simply grabs the first element before the first closing tag
// This works for strings, doubles, and I4-type values
char *xml_parse2(char *xml, char *value, int valueLen)
{
char *pstart = strchr(xml, '<');
while (pstart[0] == '<' && pstart[1] != '/') {
char *p2 = strchr(pstart, '>') + 1;
pstart = strchr(p2, '<');
strncpy(value, p2, pstart - p2);
value[pstart - p2] = 0;
}
return value;
}
static char *xml_parse(char *xml, char *value, int value_len)
{
/* first off we should have an OK on the 1st line */
if (strstr(xml, " 200 OK") == NULL) {
return NULL;
}
// find the xml skipping the other stuff above it
char *pxml = strstr(xml, "<?xml");
if (pxml == NULL) {
return NULL;
}
char *next = strchr(pxml + 1, '<');
char value2[16384];
xml_parse2(next, value2, sizeof(value2));
strcpy(value, value2);
return value;
}
static int read_transaction(RIG *rig, char *xml, int xml_len)
{
struct rig_state *rs = &rig->state;
int retval;
char cmd_buf[16384]; // plenty big for expected flrig responses
char delim[1];
delim[0] = 0x0a;
xml[0] = cmd_buf[0] = 0;
do {
retval =
read_string(&rs->rigport, cmd_buf, sizeof(cmd_buf), delim,
sizeof(delim));
if (strlen(xml) > 8192 - retval) {
return -RIG_EINVAL;
}
if (retval > 0) {
strcat(xml, cmd_buf);
}
} while (retval > 0 && strstr(cmd_buf, "</methodResponse>") == NULL);
return RIG_OK;
}
int flrig_init(RIG *rig)
{
rig_debug(RIG_DEBUG_TRACE, "%s\n", __FUNCTION__);
struct flrig_priv_data *priv = NULL;
memset(priv, 0, sizeof(struct flrig_priv_data));
/*
* set arbitrary initial status
*/
priv->vfo_curr = RIG_VFO_A;
rig->state.priv = (rig_ptr_t) priv;
if (!rig || !rig->caps) {
return -RIG_EINVAL;
}
strncpy(rig->state.rigport.pathname, DEFAULTPATH,
sizeof(rig->state.rigport.pathname));
return RIG_OK;
}
/*
* flrig_get_freq
* Assumes rig!=NULL, rig->state.priv!=NULL, freq!=NULL
*/
int flrig_get_freq(RIG *rig, vfo_t vfo, freq_t *freq)
{
char value[MAXCMDLEN];
char *pxml;
int retval;
struct rig_state *rs;
char xml[8192];
rig_debug(RIG_DEBUG_TRACE, "%s: vfo=%s\n", __FUNCTION__,
rig_strvfo(vfo));
rs = &rig->state;
if (check_vfo(vfo) == FALSE) {
rig_debug(RIG_DEBUG_ERR, "%s: unsupported VFO %s\n",
__FUNCTION__, rig_strvfo(vfo));
return -RIG_EINVAL;
}
if (vfo == RIG_VFO_CURR) {
vfo = RIG_VFO_A;
}
flrig_set_vfo(rig, vfo);
pxml = xml_build("rig.get_vfo", NULL);
retval = write_block(&rs->rigport, pxml, strlen(pxml));
if (retval < 0) {
return retval;
}
read_transaction(rig, xml, sizeof(xml));
xml_parse(xml, value, sizeof(value));
*freq = atof(value);
rig_debug(RIG_DEBUG_VERBOSE, "%s: '%s'\n", __FUNCTION__, value);
return RIG_OK;
}
/*
* flrig_set_freq
* assumes rig!=NULL, rig->state.priv!=NULL
*/
int flrig_set_freq(RIG *rig, vfo_t vfo, freq_t freq)
{
char value[MAXCMDLEN];
char *pxml;
int retval;
struct rig_state *rs;
char xml[8192];
rig_debug(RIG_DEBUG_TRACE, "%s: vfo=%s freq=%.1f\n", __FUNCTION__,
rig_strvfo(vfo), freq);
rs = &rig->state;
if (check_vfo(vfo) == FALSE) {
rig_debug(RIG_DEBUG_ERR, "%s: unsupported VFO %s\n",
__FUNCTION__, rig_strvfo(vfo));
return -RIG_EINVAL;
}
if (vfo == RIG_VFO_CURR) {
if ((retval = flrig_get_vfo(rig, &vfo)) != RIG_OK) {
return retval;
}
rig_debug(RIG_DEBUG_VERBOSE, "%s: set_freq2 vfo=%s\n",
__FUNCTION__, rig_strvfo(vfo));
}
if (!vfo_curr(rig, vfo)) {
flrig_set_vfo(rig, vfo);
}
sprintf(value,
"<params><param><value><double>%.6f</double></value></param></params>",
freq);
pxml = xml_build("rig.set_vfo", value);
retval = write_block(&rs->rigport, pxml, strlen(pxml));
if (retval < 0) {
return retval;
}
read_transaction(rig, xml, sizeof(xml));
//don't care about the response right now
//xml_parse(xml, value, sizeof(value));
flrig_set_vfo(rig, vfo);
return RIG_OK;
}
/*
* flrig_set_ptt
* Assumes rig!=NULL
*/
int flrig_set_ptt(RIG *rig, vfo_t vfo, ptt_t ptt)
{
int retval;
char cmd_buf[MAXCMDLEN];
char *pxml;
char xml[8192];
struct rig_state *rs;
rig_debug(RIG_DEBUG_TRACE, "%s: ptt=%d\n", __FUNCTION__, ptt);
rs = &rig->state;
if (check_vfo(vfo) == FALSE) {
rig_debug(RIG_DEBUG_ERR, "%s: unsupported VFO %s\n",
__FUNCTION__, rig_strvfo(vfo));
return -RIG_EINVAL;
}
if (vfo == RIG_VFO_CURR) {
vfo = RIG_VFO_A;
}
if (!vfo_curr(rig, vfo)) {
flrig_set_vfo(rig, vfo);
}
sprintf(cmd_buf,
"<params><param><value><i4>%d</i4></value></param></params>",
ptt);
pxml = xml_build("rig.set_ptt", cmd_buf);
retval = write_block(&rs->rigport, pxml, strlen(pxml));
if (retval < 0) {
return retval;
}
read_transaction(rig, xml, sizeof(xml));
xml_parse(xml, cmd_buf, sizeof(cmd_buf));
return RIG_OK;
}
int flrig_get_ptt(RIG *rig, vfo_t vfo, ptt_t *ptt)
{
char value[MAXCMDLEN];
char *pxml;
int retval;
struct rig_state *rs;
char xml[8192];
rig_debug(RIG_DEBUG_TRACE, "%s: vfo=%s\n", __FUNCTION__,
rig_strvfo(vfo));
rs = &rig->state;
pxml = xml_build("rig.get_ptt", NULL);
retval = write_block(&rs->rigport, pxml, strlen(pxml));
if (retval < 0) {
return retval;
}
read_transaction(rig, xml, sizeof(xml));
xml_parse(xml, value, sizeof(value));
*ptt = atoi(value);
rig_debug(RIG_DEBUG_VERBOSE, "%s: '%s'\n", __FUNCTION__, value);
return RIG_OK;
}
/*
* flrig_set_mode
* Assumes rig!=NULL
*/
int flrig_set_mode(RIG *rig, vfo_t vfo, rmode_t mode, pbwidth_t width)
{
char cmd_buf[32], ttmode;
int cmd_len, retval;
struct rig_state *rs;
//struct tt588_priv_data *priv = (struct tt588_priv_data *) rig->state.priv;
rig_debug(RIG_DEBUG_TRACE, "%s: vfo=%s mode=%d width=%d\n",
__FUNCTION__, rig_strvfo(vfo), mode, width);
rs = &rig->state;
if (check_vfo(vfo) == FALSE) {
rig_debug(RIG_DEBUG_ERR, "%s: unsupported VFO %s\n",
__FUNCTION__, rig_strvfo(vfo));
return -RIG_EINVAL;
}
switch (mode) {
case RIG_MODE_USB:
ttmode = 'U';
break;
case RIG_MODE_LSB:
ttmode = 'L';
break;
case RIG_MODE_CW:
ttmode = 'C';
break;
case RIG_MODE_AM:
ttmode = 'A';
break;
//case RIG_MODE_FSK: ttmode = 'F'; break;
default:
rig_debug(RIG_DEBUG_ERR, "%s: unsupported mode %d\n",
__FUNCTION__, mode);
return -RIG_EINVAL;
}
cmd_len = sprintf((char *) cmd_buf, "XB%c" EOM, ttmode);
retval = write_block(&rs->rigport, cmd_buf, cmd_len);
if (retval < 0) {
return retval;
}
return RIG_OK;
}
#if 0
static int flrig_flush(RIG *rig, vfo_t vfo)
{
char value[MAXCMDLEN];
char *pxml;
int retval;
struct rig_state *rs;
char xml[8192];
rig_debug(RIG_DEBUG_TRACE, "%s: vfo=%s\n", __FUNCTION__,
rig_strvfo(vfo));
rs = &rig->state;
sprintf(value, "<params><param><value>%s</value></param></params>",
vfo == RIG_VFO_A ? "A" : "B");
pxml = xml_build("rig.flush", value);
network_flush(&rs->rigport);
retval = write_block(&rs->rigport, pxml, strlen(pxml));
if (retval < 0) {
return retval;
}
read_transaction(rig, xml, sizeof(xml));
return RIG_OK;
}
#endif
int flrig_set_vfo(RIG *rig, vfo_t vfo)
{
char value[MAXCMDLEN];
char *pxml;
int retval;
struct rig_state *rs;
char xml[8192];
rig_debug(RIG_DEBUG_TRACE, "%s: vfo=%s\n", __FUNCTION__,
rig_strvfo(vfo));
rs = &rig->state;
if (check_vfo(vfo) == FALSE) {
rig_debug(RIG_DEBUG_ERR, "%s: unsupported VFO %s\n",
__FUNCTION__, rig_strvfo(vfo));
return -RIG_EINVAL;
}
if (vfo == RIG_VFO_CURR) {
struct flrig_priv_data *priv =
(struct flrig_priv_data *) rig->state.priv;
vfo = priv->vfo_curr;
}
sprintf(value, "<params><param><value>%s</value></param></params>",
vfo == RIG_VFO_A ? "A" : "B");
pxml = xml_build("rig.set_AB", value);
retval = write_block(&rs->rigport, pxml, strlen(pxml));
if (retval < 0) {
return retval;
}
read_transaction(rig, xml, sizeof(xml));
//xml_parse(xml,value,sizeof(value));
vfo_t vfotmp;
flrig_get_vfo(rig, &vfotmp);
return RIG_OK;
}
int flrig_get_vfo(RIG *rig, vfo_t *vfo)
{
char value[MAXCMDLEN];
char *pxml;
int retval;
struct rig_state *rs;
char xml[8192];
rig_debug(RIG_DEBUG_TRACE, "%s\n", __FUNCTION__);
rs = &rig->state;
pxml = xml_build("rig.get_AB", NULL);
retval = write_block(&rs->rigport, pxml, strlen(pxml));
if (retval < 0) {
return retval;
}
read_transaction(rig, xml, sizeof(xml));
xml_parse(xml, value, sizeof(value));
switch (value[0]) {
case 'A':
*vfo = RIG_VFO_A;
break;
case 'B':
*vfo = RIG_VFO_B;
break;
default:
*vfo = RIG_VFO_CURR;
return -RIG_EINVAL;
}
if (check_vfo(*vfo) == FALSE) {
rig_debug(RIG_DEBUG_ERR, "%s: unsupported VFO %s\n",
__FUNCTION__, rig_strvfo(*vfo));
return -RIG_EINVAL;
}
struct flrig_priv_data *priv =
(struct flrig_priv_data *) rig->state.priv;
priv->vfo_curr = *vfo;
rig_debug(RIG_DEBUG_VERBOSE, "%s: vfo=%s\n", __FUNCTION__,
rig_strvfo(*vfo));
return RIG_OK;
}
/*
* flrig_set_split_freq
* Note that split doesn't work for FLRig models that don't have reply codes
* Like most Yaesu rigs. The commands will overrun FLRig in those cases.
* Rigs that do have replies for all cat commands will work with split
*/
int flrig_set_split_freq(RIG *rig, vfo_t vfo, freq_t tx_freq)
{
char value[MAXCMDLEN];
char *pxml;
int retval;
struct rig_state *rs;
char xml[8192];
rig_debug(RIG_DEBUG_TRACE, "%s: vfo=%s freq=%.1f\n", __FUNCTION__,
rig_strvfo(vfo), tx_freq);
rs = &rig->state;
if (vfo == RIG_VFO_SUB) {
vfo = RIG_VFO_B;
}
if (check_vfo(vfo) == FALSE) {
rig_debug(RIG_DEBUG_ERR, "%s: unsupported VFO %s\n",
__FUNCTION__, rig_strvfo(vfo));
return -RIG_EINVAL;
}
if (!vfo_curr(rig, vfo)) {
flrig_set_vfo(rig, vfo);
}
sprintf(value,
"<params><param><value><double>%.6f</double></value></param></params>",
tx_freq);
pxml = xml_build("rig.set_vfo", value);
retval = write_block(&rs->rigport, pxml, strlen(pxml));
if (retval < 0) {
return retval;
}
read_transaction(rig, xml, sizeof(xml));
xml_parse(xml, value, sizeof(value));
return RIG_OK;
}
/*
* flrig_get_split_freq
* assumes rig!=NULL, tx_freq!=NULL
*/
int flrig_get_split_freq(RIG *rig, vfo_t vfo, freq_t *tx_freq)
{
rig_debug(RIG_DEBUG_TRACE, "%s: vfo=%s\n", __FUNCTION__,
rig_strvfo(vfo));
return flrig_get_freq(rig, vfo, tx_freq);
}
/*
* flrig_set_split_vfo
* assumes rig!=NULL, tx_freq!=NULL
*/
int flrig_set_split_vfo(RIG *rig, vfo_t vfo, split_t split, vfo_t tx_vfo)
{
char value[MAXCMDLEN];
char *pxml;
int retval;
struct rig_state *rs;
char xml[8192];
rig_debug(RIG_DEBUG_TRACE, "%s: tx_vfo=%s\n", __FUNCTION__,
rig_strvfo(tx_vfo));
rs = &rig->state;
if (tx_vfo == RIG_VFO_SUB) {
tx_vfo = RIG_VFO_B;
}
if (!vfo_curr(rig, vfo)) {
flrig_set_vfo(rig, vfo);
}
sprintf(value,
"<params><param><value><i4>%d</i4></value></param></params>",
split);
pxml = xml_build("rig.set_split", value);
retval = write_block(&rs->rigport, pxml, strlen(pxml));
if (retval < 0) {
return retval;
}
read_transaction(rig, xml, sizeof(xml));
//xml_parse(xml, value, sizeof(value));
//flrig_set_vfo(rig,RIG_VFO_A);
return RIG_OK;
}
/*
* flrig_get_split_vfo
* assumes rig!=NULL, tx_freq!=NULL
*/
int flrig_get_split_vfo(RIG *rig, vfo_t vfo, split_t *split,
vfo_t *tx_vfo)
{
char value[MAXCMDLEN];
char *pxml;
int retval;
struct rig_state *rs;
char xml[8192];
rig_debug(RIG_DEBUG_TRACE, "%s\n", __FUNCTION__);
rs = &rig->state;
//flrig_set_vfo(rig,RIG_VFO_B);
pxml = xml_build("rig.get_split", NULL);
retval = write_block(&rs->rigport, pxml, strlen(pxml));
if (retval < 0) {
return retval;
}
read_transaction(rig, xml, sizeof(xml));
xml_parse(xml, value, sizeof(value));
//flrig_set_vfo(rig,RIG_VFO_A);
*tx_vfo = RIG_VFO_B;
*split = atoi(value);
return RIG_OK;
}
/*
.set_split_freq = flrig_set_split_freq,
.get_split_freq = flrig_get_split_freq,
.set_split_mode = flrig_set_split_mode,
.get_split_mode = flrig_get_split_mode,
*/

40
dummy/flrig.h 100644
Wyświetl plik

@ -0,0 +1,40 @@
/*
* Hamlib FLRig backend - main header
* Copyright (c) 2017 by Michael Black W9MDB
*
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#ifndef _FLRIG_H
#define _FLRIG_H 1
#include "hamlib/rig.h"
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
#endif
#define BACKEND_VER "0.1"
#define EOM "\r"
#define TRUE 1
#define FALSE 0
#define BUF_MAX 32768
extern const struct rig_caps flrig_caps;
#endif /* _FLRIG_H */

Wyświetl plik

@ -56,6 +56,7 @@
#define RIG_MODEL_DUMMY RIG_MAKE_MODEL(RIG_DUMMY, 1)
#define RIG_MODEL_NETRIGCTL RIG_MAKE_MODEL(RIG_DUMMY, 2)
#define RIG_MODEL_ARMSTRONG RIG_MAKE_MODEL(RIG_DUMMY, 3)
#define RIG_MODEL_FLRIG RIG_MAKE_MODEL(RIG_DUMMY, 4)
/*
* Yaesu