Add rigctlsync utility to allow synchornizing a rig to SDR#

pull/1242/head
Mike Black W9MDB 2023-01-27 23:35:31 -06:00
rodzic 8a25a3be90
commit 9bc5c4a883
4 zmienionych plików z 1051 dodań i 1 usunięć

1
NEWS
Wyświetl plik

@ -14,6 +14,7 @@ Version 5.x -- future
Version 4.6
* 2023-11-XX -- Planned for Nov 2023
* Add rigctlsync utility to synchronize frequency from a rig to SDR# (or others)
* Add SDR# rig for use with SDR#'s gpredict plugin -- can only get/set freq
* Add Apex Shared Loop rotator -- unidirectional only so far
* Add client_version to rigctld so client can report it's version for future use/compatility/alternatives

Wyświetl plik

@ -0,0 +1,329 @@
.\" Hey, EMACS: -*- nroff -*-
.\"
.\" For layout and available macros, see man(7), man-pages(7), groff_man(7)
.\" Please adjust the date whenever revising the manpage.
.\"
.\" Note: Please keep this page in sync with the source, rigctlsync.c
.\"
.TH RIGCTLSYNC "1" "2023-01-27" "Hamlib" "Hamlib Utilities"
.
.
.SH NAME
.
rigctlsync \- synchronize a rig to SDR# (or other rig)
.
.SH SYNOPSIS
.
.
.SY rigctlsync
.OP \-hlLuV
.OP \-m id
.OP \-r device
.OP \-R device
.OP \-s baud
.OP \-S baud
.OP \-c id
.OP \-C parm=val
.OP \-B
.RB [ \-v [ \-Z ]]
.YS
.
.SH DESCRIPTION
Allows you to synchornize frequence from a rig to SDR#.
Best when used with rigctld, FlRig, or a multiport radio.
.
.PP
Please report bugs and provide feedback at the e-mail address given in the
.B BUGS
section below. Patches and code enhancements sent to the same address are
welcome.
.
.
.SH OPTIONS
.
This program follows the usual GNU command line syntax. Short options that
take an argument may have the value follow immediately or be separated by a
space. Long options starting with two dashes (\(oq\-\(cq) require an
\(oq=\(cq between the option and any argument.
.
.PP
Here is a summary of the supported options:
.
.TP
.BR \-m ", " \-\-model = \fIid\fP
Select radio model number.
.IP
See model list (use \(lqrigctlsync -l\(rq).
.IP
.BR Note :
.B rigctlsync
(or third party software using the C API) will use radio model 2 for
.B NET rigctl
(communicating with
.BR rigctld ).
.
.TP
.BR \-r ", " \-\-rig\-file = \fIdevice\fP
Use
.I device
as the file name of the port connected to the radio.
.IP
Often a serial port, but could be a USB to serial adapter. Typically
.IR /dev/ttyS0 ", " /dev/ttyS1 ", " /dev/ttyUSB0 ,
etc. on Linux,
.IR COM1 ", " COM2 ,
etc. on MS Windows. The BSD flavors and Mac OS/X have their own designations.
See your system's documentation.
.IP
The special string \(lquh\-rig\(rq may be given to enable micro-ham device
support.
.
.TP
.BR \-R ", " \-\-rig\-file2 = \fIdevice\fP
Use
.I device
as the file name of one of the virtual com ports -- your program will connect
to the other com port of the virtual pair.
.
.TP
.BR \-s ", " \-\-serial\-speed = \fIbaud\fP
Set serial speed to
.I baud
rate.
.IP
Uses maximum serial speed from radio backend capabilities (set by
.B -m
above) as the default.
.
.TP
.BR \-S ", " \-\-serial\-speed2 = \fIbaud\fP
Set serial speed to
.I baud
rate for virtual com port (see
.BR -R ).
.
.IP
Uses maximum serial speed from radio backend capabilities (set by
.B -m
above) as the default.
.
.TP
.BR \-c ", " \-\-civaddr = \fIid\fP
Use
.I id
as the CI-V address to communicate with the rig.
.IP
Only useful for Icom and some Ten-Tec rigs.
.IP
.BR Note :
The
.I id
is in decimal notation, unless prefixed by
.IR 0x ,
in which case it is hexadecimal.
.
.TP
.BR \-L ", " \-\-show\-conf
List all config parameters for the radio defined with
.B \-m
above.
.
.TP
.BR \-C ", " \-\-set\-conf = \fIparm=val\fP [ \fI,parm=val\fP ]
Set radio configuration parameter(s), e.g.
.IR stop_bits=2 .
.IP
Use the
.B -L
option above for a list of configuration parameters for a given model number.
.
.TP
.BR \-u ", " \-\-dump\-caps
Dump capabilities for the radio defined with
.B -m
above and exit.
.
.TP
.BR \-l ", " \-\-list
List all model numbers defined in
.B Hamlib
and exit.
.IP
The list is sorted by model number.
.IP
.BR Note :
In Linux the list can be scrolled back using
.BR Shift-PageUp / Shift-PageDown ,
or using the scrollbars of a virtual terminal in X or the cmd window in
Windows. The output can be piped to
.BR more (1)
or
.BR less (1),
e.g. \(lqrigctl -l | more\(rq.
.
.TP
.BR \-n ", " \-\-no\-restore\-ai
.B rigctl
restores the state of auto information (AI) on the controlled rig.
.IP
If this is not desired, for example if you are using
.B rigctl
to turn AI mode on or off, pass this option.
.
.TP
.BR \-B ", " \-\-mapa2b
Maps set_freq on VFOA to VFOB instead.
This allows using CW skimmer with the rig in split mode and clicking on a frequency in CW skimmer
will set VFOB to the transmit frequency.
.
.TP
.BR \-v ", " \-\-verbose
Set verbose mode, cumulative (see
.B DIAGNOSTICS
below).
.
.TP
.BR \-Z ", " \-\-debug\-time\-stamps
Enable time stamps for the debug messages.
.IP
Use only in combination with the
.B -v
option as it generates no output on its own.
.
.TP
.BR \-h ", " \-\-help
Show a summary of these options and exit.
.
.TP
.BR \-V ", " \-\-version
Show version of
.B rigctl
and exit.
.
.PP
.BR Note :
Some options may not be implemented by a given backend and will return an
error. This is most likely to occur with the
.B \-\-set\-conf
and
.B \-\-show\-conf
options.
.
.
.SH DIAGNOSTICS
.
The
.BR \-v ,
.B \-\-verbose
option allows different levels of diagnostics
to be output to
.B stderr
and correspond to \-v for
.BR BUG ,
\-vv for
.BR ERR ,
\-vvv for
.BR WARN ,
\-vvvv for
.BR VERBOSE ,
or \-vvvvv for
.BR TRACE .
.
.PP
A given verbose level is useful for providing needed debugging information to
the email address below. For example, TRACE output shows all of the values
sent to and received from the radio which is very useful for radio backend
library development and may be requested by the developers.
.
.
.SH EXIT STATUS
.B rigctlsync
exits with:
.
.TP
.B 0
if all operations completed normally;
.
.TP
.B 1
if there was an invalid command line option or argument;
.
.TP
.B 2
if an error was returned by
.BR Hamlib .
.
.
.SH EXAMPLE
.
Start
.B rigctlsync
with FLRig as the Hamlib model
.UE
.
.PP
.in +4n
.EX
.RB $ " rigctlsync -m 4 -M 9"
.EE
.in
.
.PP
The following diagram shows the communications flow that allows N1MM Logger+
to communicate with a radio connected to Flrig:
.
.PP
.in +4n
.EE
.in
.
.
.SH BUGS
.
.PP
Report bugs to:
.IP
.nf
.MT hamlib\-developer@lists.sourceforge.net
Hamlib Developer mailing list
.ME
.fi
.
.
.SH COPYING
.
This file is part of Hamlib, a project to develop a library that simplifies
radio, rotator, and amplifier control functions for developers of software
primarily of interest to radio amateurs and those interested in radio
communications.
.
.PP
Copyright \(co 2000-2011 Stephane Fillod
.br
Copyright \(co 2000-2018 the Hamlib Group (various contributors)
.br
Copyright \(co 2010-2020 Nate Bargmann
.br
Copyright \(co 2019 Michael Black W9MDB
.
.PP
This is free software; see the file COPYING for copying conditions. There is
NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
.
.
.SH SEE ALSO
.
.BR rigctld (1),
.BR rigctl (1),
.BR socat (1),
.BR hamlib (7)
.
.
.SH COLOPHON
.
Links to the Hamlib Wiki, Git repository, release archives, and daily snapshot
archives are available via
.
.UR http://www.hamlib.org
hamlib.org
.UE .

Wyświetl plik

@ -14,7 +14,7 @@ endif
DISTCLEANFILES = rigctl.log rigctl.sum testbcd.log testbcd.sum
bin_PROGRAMS = rigctl rigctld rigmem rigsmtr rigswr rotctl rotctld rigctlcom rigctltcp ampctl ampctld $(TESTLIBUSB)
bin_PROGRAMS = rigctl rigctld rigmem rigsmtr rigswr rotctl rotctld rigctlcom rigctltcp rigctlsync ampctl ampctld $(TESTLIBUSB)
#check_PROGRAMS = dumpmem testrig testrigopen testrigcaps testtrn testbcd testfreq listrigs testloc rig_bench testcache cachetest cachetest2 testcookie testgrid testsecurity
check_PROGRAMS = dumpmem testrig testrigopen testrigcaps testtrn testbcd testfreq listrigs testloc rig_bench testcache cachetest cachetest2 testcookie testgrid hamlibmodels
@ -27,6 +27,7 @@ rigctl_SOURCES = rigctl.c $(RIGCOMMONSRC)
rigctld_SOURCES = rigctld.c $(RIGCOMMONSRC)
rigctlcom_SOURCES = rigctlcom.c $(RIGCOMMONSRC)
rigctltcp_SOURCES = rigctltcp.c $(RIGCOMMONSRC)
rigctlsync_SOURCES = rigctlsync.c $(RIGCOMMONSRC)
rotctl_SOURCES = rotctl.c $(ROTCOMMONSRC)
rotctld_SOURCES = rotctld.c $(ROTCOMMONSRC)
ampctl_SOURCES = ampctl.c $(AMPCOMMONSRC)
@ -52,6 +53,7 @@ ampctl_CFLAGS = $(AM_CFLAGS) $(PTHREAD_CFLAGS) -I$(top_builddir)/src
ampctld_CFLAGS = $(AM_CFLAGS) $(PTHREAD_CFLAGS) -I$(top_builddir)/src
rigctlcom_CFLAGS = $(AM_CFLAGS) $(PTHREAD_CFLAGS) -I$(top_builddir)/security
rigctltcp_CFLAGS = $(AM_CFLAGS) $(PTHREAD_CFLAGS) -I$(top_builddir)/security
rigctlsync_CFLAGS = $(AM_CFLAGS) $(PTHREAD_CFLAGS) -I$(top_builddir)/security
if HAVE_LIBUSB
rigtestlibusb_CFLAGS = $(AM_CFLAGS) $(PTHREAD_CFLAGS) $(LIBUSB_CFLAGS)
endif
@ -66,6 +68,7 @@ ampctld_LDADD = $(NET_LIBS) $(PTHREAD_LIBS) $(LDADD) $(READLINE_LIBS)
rigmem_LDADD = $(LIBXML2_LIBS) $(LDADD)
rigctlcom_LDADD = $(NET_LIBS) $(PTHREAD_LIBS) $(LDADD) $(READLINE_LIBS)
rigctltcp_LDADD = $(NET_LIBS) $(PTHREAD_LIBS) $(LDADD) $(READLINE_LIBS)
rigctlsync_LDADD = $(NET_LIBS) $(PTHREAD_LIBS) $(LDADD) $(READLINE_LIBS)
if HAVE_LIBUSB
rigtestlibusb_LDADD = $(LIBUSB_LIBS)
endif
@ -82,6 +85,7 @@ rotctld_LDFLAGS = $(WINEXELDFLAGS)
ampctld_LDFLAGS = $(WINEXELDFLAGS)
rigctlcom_LDFLAGS = $(WINEXELDFLAGS)
rigctltcp_LDFLAGS = $(WINEXELDFLAGS)
rigctlsync_LDFLAGS = $(WINEXELDFLAGS)
if HAVE_LIBUSB
rigtestlibusb_LDFLAGS = $(WINEXELDFLAGS)
endif

716
tests/rigctlsync.c 100644
Wyświetl plik

@ -0,0 +1,716 @@
/*
* rigctlsync.c - (C) Stephane Fillod 2000-2011
* (C) The Hamlib Group 2012
* (C) Nate Bargmann 2008,2010,2011,2012,2013
* (C) Michael Black W9MDB 2023 - derived from rigctlcom.c
*
* This program will synchronize frequency from one rig to another
* Implemented for AirSpy SDR# to keep freq synced with a real rig
* It simply polls the real rig and when freq changes sends it to SDR# (or whatever rig is hooked up)
*
* This program 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 2 of the License, or
* (at your option) any later version.
*
* This program 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 this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
*/
#include <hamlib/config.h>
#ifdef WIN32
#define WIN32_LEAN_AND_MEAN
// cppcheck-suppress *
#include <windows.h>
#endif
// cppcheck-suppress *
#include <stdio.h>
// cppcheck-suppress *
#include <stdlib.h>
// cppcheck-suppress *
#include <string.h>
// cppcheck-suppress *
// cppcheck-suppress *
#include <ctype.h>
// cppcheck-suppress *
#include <errno.h>
// cppcheck-suppress *
#include <signal.h>
// cppcheck-suppress *
#include <getopt.h>
// cppcheck-suppress *
#include <sys/types.h>
#ifdef HAVE_NETINET_IN_H
// cppcheck-suppress *
# include <netinet/in.h>
#endif
#ifdef HAVE_ARPA_INET_H
// cppcheck-suppress *
# include <arpa/inet.h>
#endif
#ifdef HAVE_SYS_SOCKET_H
// cppcheck-suppress *
# include <sys/socket.h>
#elif HAVE_WS2TCPIP_H
# include <ws2tcpip.h>
# include <fcntl.h>
# if defined(HAVE_WSPIAPI_H)
# include <wspiapi.h>
# endif
#endif
#include <hamlib/rig.h>
#include "misc.h"
#include "iofunc.h"
#include "serial.h"
#include "sprintflst.h"
#include "rigctl_parse.h"
#include "sleep.h"
/*
* Reminder: when adding long options,
* keep up to date SHORT_OPTIONS, usage()'s output and man page. thanks.
* NB: do NOT use -W since it's reserved by POSIX.
* TODO: add an option to read from a file
*/
#define SHORT_OPTIONS "B:m:M:r:R:p:d:P:D:s:S:c:C:lLuvhVZ"
static struct option long_options[] =
{
{"mapa2b", 0, 0, 'B'},
{"model", 1, 0, 'm'},
{"rig-file", 1, 0, 'r'},
{"rig-file2", 1, 0, 'R'},
{"ptt-file", 1, 0, 'p'},
{"dcd-file", 1, 0, 'd'},
{"ptt-type", 1, 0, 'P'},
{"dcd-type", 1, 0, 'D'},
{"serial-speed", 1, 0, 's'},
{"serial-speed2", 1, 0, 'S'},
{"civaddr", 1, 0, 'c'},
{"set-conf", 1, 0, 'C'},
{"list", 0, 0, 'l'},
{"show-conf", 0, 0, 'L'},
{"dump-caps", 0, 0, 'u'},
{"verbose", 0, 0, 'v'},
{"help", 0, 0, 'h'},
{"version", 0, 0, 'V'},
{"debug-time-stamps", 0, 0, 'Z'},
{0, 0, 0, 0}
};
void usage();
static RIG *my_rig; /* handle to rig */
static RIG
*my_rig_sync; /* rig the gets synchronized -- freq only for now */
static int verbose;
/* CW Skimmer can only set VFOA */
/* IC7300 for example can run VFOA on FM and VFOB on CW */
/* So -A/--mapa2b changes set_freq on VFOA to VFOB */
/* This allows working CW Skimmer in split mode and transmit on VFOB */
static int mapa2b; /* maps set_freq on VFOA to VFOB instead */
#ifdef HAVE_SIG_ATOMIC_T
static sig_atomic_t volatile ctrl_c;
#else
static int volatile ctrl_c;
#endif
#define MAXCONFLEN 1024
#if 0
# ifdef WIN32
static BOOL WINAPI CtrlHandler(DWORD fdwCtrlType)
{
rig_debug(RIG_DEBUG_VERBOSE, "CtrlHandler called\n");
switch (fdwCtrlType)
{
case CTRL_C_EVENT:
case CTRL_CLOSE_EVENT:
ctrl_c = 1;
return TRUE;
default:
return FALSE;
}
}
# else
static void signal_handler(int sig)
{
switch (sig)
{
case SIGINT:
ctrl_c = 1;
break;
default:
/* do nothing */
break;
}
}
# endif /* ifdef WIN32 */
#endif /* if 0 */
#if 0
static void handle_error(enum rig_debug_level_e lvl, const char *msg)
{
int e;
# ifdef __MINGW32__
LPVOID lpMsgBuf;
lpMsgBuf = (LPVOID)"Unknown error";
e = WSAGetLastError();
if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER
| FORMAT_MESSAGE_FROM_SYSTEM
| FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
e,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
// Default language
(LPTSTR)&lpMsgBuf,
0,
NULL))
{
rig_debug(lvl, "%s: Network error %d: %s\n", msg, e, lpMsgBuf);
LocalFree(lpMsgBuf);
}
else
{
rig_debug(lvl, "%s: Network error %d\n", msg, e);
}
# else
e = errno;
rig_debug(lvl, "%s: Network error %d: %s\n", msg, e, strerror(e));
# endif /* ifdef __MINGW32__ */
}
#endif /* if 0 */
int main(int argc, char *argv[])
{
rig_model_t my_model[] = { RIG_MODEL_DUMMY, RIG_MODEL_SDRSHARP };
int retcode; /* generic return code from functions */
int show_conf = 0;
int dump_caps_opt = 0;
const char *rig_file = NULL, *rig_file2 = NULL;
//const char **ptt_file = NULL, *dcd_file = NULL;
//ptt_type_t ptt_type = RIG_PTT_NONE;
//dcd_type_t dcd_type = RIG_DCD_NONE;
int serial_rate = 0;
int serial_rate2 = 0; /* virtual com port default speed */
char *civaddr = NULL; /* NULL means no need to set conf */
char conf_parms[MAXCONFLEN] = "";
printf("rigctlcom Version 1.4\n");
if (argc < 3)
{
usage();
return 1;
}
while (1)
{
int c;
int option_index = 0;
char dummy[2];
c = getopt_long(argc,
argv,
SHORT_OPTIONS,
long_options,
&option_index);
if (c == -1)
{
break;
}
switch (c)
{
case 'h':
usage();
exit(0);
case 'V':
version();
exit(0);
case 'B':
mapa2b = 1;
break;
case 'm':
case 'M':
if (!optarg)
{
usage(); /* wrong arg count */
exit(1);
}
if (c == 'm')
{
my_model[0] = atoi(optarg);
}
else
{
my_model[1] = atoi(optarg);
}
break;
case 'r':
if (!optarg)
{
usage(); /* wrong arg count */
exit(1);
}
rig_file = optarg;
break;
case 'R':
if (!optarg)
{
usage(); /* wrong arg count */
exit(1);
}
rig_file2 = optarg;
break;
#if 0
case 'p':
if (!optarg)
{
usage(); /* wrong arg count */
exit(1);
}
ptt_file = optarg;
break;
#endif
#if 0
case 'd':
if (!optarg)
{
usage(); /* wrong arg count */
exit(1);
}
dcd_file = optarg;
break;
#endif
#if 0
case 'P':
if (!optarg)
{
usage(); /* wrong arg count */
exit(1);
}
if (!strcmp(optarg, "RIG"))
{
ptt_type = RIG_PTT_RIG;
}
else if (!strcmp(optarg, "DTR"))
{
ptt_type = RIG_PTT_SERIAL_DTR;
}
else if (!strcmp(optarg, "RTS"))
{
ptt_type = RIG_PTT_SERIAL_RTS;
}
else if (!strcmp(optarg, "PARALLEL"))
{
ptt_type = RIG_PTT_PARALLEL;
}
else if (!strcmp(optarg, "CM108"))
{
ptt_type = RIG_PTT_CM108;
}
else if (!strcmp(optarg, "NONE"))
{
ptt_type = RIG_PTT_NONE;
}
else
{
ptt_type = atoi(optarg);
}
break;
#endif
#if 0
case 'D':
if (!optarg)
{
usage(); /* wrong arg count */
exit(1);
}
if (!strcmp(optarg, "RIG"))
{
dcd_type = RIG_DCD_RIG;
}
else if (!strcmp(optarg, "DSR"))
{
dcd_type = RIG_DCD_SERIAL_DSR;
}
else if (!strcmp(optarg, "CTS"))
{
dcd_type = RIG_DCD_SERIAL_CTS;
}
else if (!strcmp(optarg, "CD"))
{
dcd_type = RIG_DCD_SERIAL_CAR;
}
else if (!strcmp(optarg, "PARALLEL"))
{
dcd_type = RIG_DCD_PARALLEL;
}
else if (!strcmp(optarg, "NONE"))
{
dcd_type = RIG_DCD_NONE;
}
else
{
dcd_type = atoi(optarg);
}
break;
#endif
case 'c':
if (!optarg)
{
usage(); /* wrong arg count */
exit(1);
}
civaddr = optarg;
break;
case 's':
if (!optarg)
{
usage(); /* wrong arg count */
exit(1);
}
if (sscanf(optarg, "%d%1s", &serial_rate, dummy) != 1)
{
fprintf(stderr, "Invalid baud rate of %s\n", optarg);
exit(1);
}
break;
case 'S':
if (!optarg)
{
usage(); /* wrong arg count */
exit(1);
}
serial_rate2 = atoi(optarg);
break;
case 'C':
if (!optarg)
{
usage(); /* wrong arg count */
exit(1);
}
if (*conf_parms != '\0')
{
strcat(conf_parms, ",");
}
if (strlen(conf_parms) + strlen(optarg) > MAXCONFLEN - 24)
{
printf("Length of conf_parms exceeds internal maximum of %d\n",
MAXCONFLEN - 24);
return 1;
}
strncat(conf_parms, optarg, MAXCONFLEN - strlen(conf_parms));
break;
case 'v':
verbose++;
break;
case 'L':
show_conf++;
break;
case 'l':
rig_set_debug(verbose);
list_models();
exit(0);
case 'u':
dump_caps_opt++;
break;
case 'Z':
rig_set_debug_time_stamp(1);
break;
default:
usage(); /* unknown option? */
exit(1);
}
}
rig_set_debug(verbose);
rig_debug(RIG_DEBUG_VERBOSE, "%s, %s\n", "rigctlcom", hamlib_version2);
rig_debug(RIG_DEBUG_VERBOSE, "%s",
"Report bugs to <hamlib-developer@lists.sourceforge.net>\n\n");
if (argc == 1)
{
usage();
exit(2);
}
my_rig = rig_init(my_model[0]);
if (!my_rig)
{
fprintf(stderr,
"Unknown rig num %d, or initialization error.\n",
my_model[0]);
fprintf(stderr, "Please check with --list option.\n");
exit(2);
}
my_rig_sync = rig_init(my_model[1]);
if (!my_rig_sync)
{
fprintf(stderr,
"Unknown rig num %d, or initialization error.\n",
my_model[1]);
fprintf(stderr, "Please check with --list option.\n");
exit(2);
}
#if 0
retcode = set_conf(my_rig, conf_parms);
if (retcode != RIG_OK)
{
fprintf(stderr, "Config parameter error: %s\n", rigerror(retcode));
exit(2);
}
#endif
if (my_model[0] > 5 && !rig_file)
{
fprintf(stderr, "-r rig com port not provided\n");
exit(2);
}
if (rig_file)
{
strncpy(my_rig->state.rigport.pathname, rig_file, HAMLIB_FILPATHLEN - 1);
}
if (!rig_file2)
{
fprintf(stderr, "-R com port not provided\n");
exit(2);
}
strncpy(my_rig_sync->state.rigport.pathname, rig_file2, HAMLIB_FILPATHLEN - 1);
#if 0
/*
* ex: RIG_PTT_PARALLEL and /dev/parport0
*/
if (ptt_type != RIG_PTT_NONE)
{
my_rig->state.pttport.type.ptt = ptt_type;
}
if (dcd_type != RIG_DCD_NONE)
{
my_rig->state.dcdport.type.dcd = dcd_type;
}
if (ptt_file)
{
strncpy(my_rig->state.pttport.pathname, ptt_file, HAMLIB_FILPATHLEN - 1);
}
if (dcd_file)
{
strncpy(my_rig->state.dcdport.pathname, dcd_file, HAMLIB_FILPATHLEN - 1);
}
#endif
/* FIXME: bound checking and port type == serial */
if (serial_rate != 0)
{
my_rig->state.rigport.parm.serial.rate = serial_rate;
}
if (serial_rate2 != 0)
{
my_rig_sync->state.rigport.parm.serial.rate = serial_rate2;
}
if (civaddr)
{
rig_set_conf(my_rig, rig_token_lookup(my_rig, "civaddr"), civaddr);
}
/*
* print out conf parameters
*/
if (show_conf)
{
rig_token_foreach(my_rig, print_conf_list, (rig_ptr_t)my_rig);
}
/*
* print out conf parameters, and exits immediately
* We may be interested only in only caps, and rig_open may fail.
*/
if (dump_caps_opt)
{
dumpcaps(my_rig, stdout);
rig_cleanup(my_rig); /* if you care about memory */
exit(0);
}
/* open and close rig connection to check early for issues */
retcode = rig_open(my_rig);
if (retcode != RIG_OK)
{
fprintf(stderr, "rig_open: error = %s \n", rigerror(retcode));
exit(2);
}
retcode = rig_open(my_rig_sync);
if (retcode != RIG_OK)
{
fprintf(stderr, "rig_open sync: error = %s \n", rigerror(retcode));
exit(2);
}
if (verbose > 0)
{
printf("Opened rig model %d, '%s'\n",
my_rig->caps->rig_model,
my_rig->caps->model_name);
}
rig_debug(RIG_DEBUG_VERBOSE, "Backend version: %s, Status: %s\n",
my_rig->caps->version, rig_strstatus(my_rig->caps->status));
/*
* main loop
*/
do
{
freq_t freq;
int retval = rig_get_freq(my_rig, RIG_VFO_CURR, &freq);
if (retval != RIG_OK)
{
rig_debug(RIG_DEBUG_ERR, "%s: Error in rig_get_freq: %s\n", __func__,
rigerror(retval));
}
if (retval != RIG_OK)
{
rig_debug(RIG_DEBUG_ERR, "%s: Error in rig_set_freq: %s\n", __func__,
rigerror(retval));
}
retval = rig_set_freq(my_rig_sync, RIG_VFO_CURR, freq);
hl_usleep(400 * 1000); // fairly fast to keep up
}
while (retcode == 0 && !ctrl_c);
rig_close(my_rig); /* close port */
rig_cleanup(my_rig); /* if you care about memory */
return 0;
}
void usage()
{
char *name = "rigctlsync";
printf("Usage: %s -m rignumber -r comport -s baud -M rignumber -R comport [OPTIONS]...\n\n"
"Will copy frequency from -m rig to -M rig\n"
"e.g. will keep SDR# synchronized to a rig.\n\n",
name);
printf("Example: Sync freq from rigctld to SDR#\n");
printf("\t%s -m 2 -M 9 127.0.0.1:4532\n\n", name);
printf("See the %s.1 manual page for complete details.\n\n", name);
printf(
" -m, --model=ID select radio model number. See model list (-l)\n"
" -r, --rig-file=DEVICE set device of the radio to operate on\n"
" -R, --rig-file2=DEVICE set device of the virtual com port to operate on\n"
" -s, --serial-speed=BAUD set serial speed of the serial port\n"
" -S, --serial-speed2=BAUD set serial speed of the virtual com port [default=115200]\n"
" -c, --civaddr=ID set CI-V address, decimal (for Icom rigs only)\n"
" -C, --set-conf=PARM=VAL set config parameters\n"
" -L, --show-conf list all config parameters\n"
" -l, --list list all model numbers and exit\n"
" -u, --dump-caps dump capabilities and exit\n"
" -v, --verbose set verbose mode, cumulative (-v to -vvvvv)\n"
" -Z, --debug-time-stamps enable time stamps for debug messages\n"
" -h, --help display this help and exit\n"
" -V, --version output version information and exit\n\n"
);
printf("\nReport bugs to <hamlib-developer@lists.sourceforge.net>.\n");
}