diff --git a/README.osx b/README.osx new file mode 100644 index 000000000..c77dcf71a --- /dev/null +++ b/README.osx @@ -0,0 +1,32 @@ +OSX Builds +---------- + +To compile Hamlib on OSX you have to install autoconf, automake and libtool. +The easiest way to install them is via the brew packet manager. + +http://brew.sh + +Once brew is installed, execute + +$ brew install automake autoconf libtool + +Build +----- + +Execute autogen.sh with the desired flags + +$ ./autogen.sh + +Then compile the hamlib files + +$ ./make + +Hint: "./make -jx" with x for the amount of CPU cores will speed up the +compilation + +Install hamlib +-------------- + +Install the Hamlib libraries and executables + +$ sudo ./make install diff --git a/autogen.sh b/autogen.sh index 0bc5daae7..816f8f066 100755 --- a/autogen.sh +++ b/autogen.sh @@ -13,6 +13,11 @@ LIBTOOLIZE=libtoolize AUTORECONF=autoreconf AUTOMAKE=automake +# Check if we compile on OSX and resolve the name conflict with +# Apple's tool for creating Mach-O dynamic libraries. + +case `uname` in Darwin*) LIBTOOLIZE=glibtoolize ;; esac + # variables below this line should not need modification SRCDIR=`dirname "$0"` test -z "$SRCDIR" && SRCDIR=. diff --git a/bindings/hamlib.swg b/bindings/hamlib.swg index 5b1cce8ad..9441b92c8 100644 --- a/bindings/hamlib.swg +++ b/bindings/hamlib.swg @@ -44,6 +44,87 @@ %include cstring.i #ifdef SWIGPYTHON %include python/file.i + +%typemap(out) int [ANY] { + int len,i; + len = $1_dim0; + $result = PyList_New(len); + for (i = 0; i < len; i++) { + PyList_SetItem($result,i,PyInt_FromLong((long)$1[i])); + } +} + +%typemap(varout) int [ANY] { + int len,i; + len = $1_dim0; + $result = PyList_New(len); + for (i = 0; i < len; i++) { + PyList_SetItem($result,i,PyInt_FromLong((long)$1[i])); + } +} + +#endif + +#ifdef SWIGPERL + +%typemap(out) int [ANY] { + AV * av = newAV(); + int i = 0,len = 0; + len = $1_dim0; + + for (i = 0; i < len ; i++) { + SV* perlval = newSV(0); + sv_setiv(perlval, (IV)$1[i]); + av_push(av, perlval); + } + $result = newRV_noinc((SV *)av); + sv_2mortal( $result ); + argvi++; +} + +%typemap(argout) int [ANY] { + AV * av = newAV(); + int i = 0,len = 0; + len = $1_dim0; + + for (i = 0; i < len ; i++) { + SV* perlval = newSV(0); + sv_setiv(perlval, (IV)$1[i]); + av_push(av, perlval); + } + $result = newRV_noinc((SV *)av); + sv_2mortal( $result ); + argvi++; +} + +#endif + +#ifdef SWIGTCL + +%typemap(out) int [ANY] { + int i, len, l; + len = $1_dim0; + + Tcl_Obj * list = Tcl_NewListObj(len, NULL); + for(i=0; i < len; i++) { + Tcl_ListObjAppendElement(interp, list, Tcl_NewIntObj($1[i])); + } + Tcl_SetObjResult(interp, list); +} + +%typemap(varout) int [ANY] { + int i, len, l; + len = $1_dim0; + + Tcl_Obj * list = Tcl_NewListObj(len, NULL); + for(i=0; i < len; i++) { + Tcl_ListObjAppendElement(interp, list, Tcl_NewIntObj($1[i])); + } + + $result = list; +} + + #endif %apply double *OUTPUT { double *distance, double *azimuth }; @@ -52,8 +133,10 @@ %apply double *OUTPUT { double *longitude, double *latitude }; %apply char *OUTPUT { char *locator_res }; +#ifndef SWIG_CSTRING_UNIMPL /* longlat2locator */ %cstring_bounded_output(char *locator_res, 13) +#endif %immutable confparams::name; %immutable confparams::label; @@ -81,6 +164,10 @@ %include %include +%inline { +typedef const char * const_char_string; +} + /* * The Rig "class" */ diff --git a/bindings/perltest.pl b/bindings/perltest.pl index edd4ad654..310d657c2 100755 --- a/bindings/perltest.pl +++ b/bindings/perltest.pl @@ -40,6 +40,9 @@ $rig->set_mode($Hamlib::RIG_MODE_CW, $Hamlib::RIG_PASSBAND_NORMAL); print "ITU region:\t\t$rig->{state}->{itu_region}\n"; print "Backend copyright:\t$rig->{caps}->{copyright}\n"; +print "Model:\t\t\t$rig->{caps}->{model_name}\n"; +print "Manufacturer:\t\t$rig->{caps}->{mfg_name}\n"; +print "Backend version:\t$rig->{caps}->{version}\n"; $inf = $rig->get_info(); print "get_info:\t\t$inf\n"; @@ -62,6 +65,9 @@ print "get_channel status:\t$rig->{error_status} = ".Hamlib::rigerror($rig->{err print "VFO:\t\t\t".Hamlib::rig_strvfo($chan->{vfo}).", $chan->{freq}\n"; +$att = $rig->{caps}->{attenuator}; +print "Attenuators:\t\t@$att\n"; + print "\nSending Morse, '73'\n"; $rig->send_morse($Hamlib::RIG_VFO_A, "73"); diff --git a/bindings/pytest.py b/bindings/pytest.py index 552a926d1..05a9f81b4 100755 --- a/bindings/pytest.py +++ b/bindings/pytest.py @@ -66,6 +66,7 @@ def StartUp (): print "get_channel status:\t",my_rig.error_status print "VFO:\t\t\t",Hamlib.rig_strvfo(chan.vfo),", ",chan.freq + print "Attenuators:\t\t", my_rig.caps.attenuator print "\nSending Morse, '73'" my_rig.send_morse(Hamlib.RIG_VFO_A, "73") diff --git a/bindings/rig.swg b/bindings/rig.swg index 69d7094d6..f54b98446 100644 --- a/bindings/rig.swg +++ b/bindings/rig.swg @@ -30,7 +30,6 @@ typedef struct Rig { } Rig; typedef char * char_string; -typedef const char * const_char_string; typedef channel_t * channel_t_p; typedef channel_t * const_channel_t_p; @@ -225,7 +224,9 @@ typedef channel_t * const_channel_t_p; */ %extend Rig { +#ifndef SWIG_CSTRING_UNIMPL %cstring_bounded_output(char *returnstr, MAX_RETURNSTR); +#endif Rig(int rig_model) { Rig *r; diff --git a/bindings/rotator.swg b/bindings/rotator.swg index 9e14e0797..544d98d8f 100644 --- a/bindings/rotator.swg +++ b/bindings/rotator.swg @@ -29,8 +29,6 @@ typedef struct Rot { int do_exception; } Rot; -typedef const char * const_char_string; - %} /* diff --git a/bindings/tcltest.tcl b/bindings/tcltest.tcl index c5dd223f7..722fe279d 100755 --- a/bindings/tcltest.tcl +++ b/bindings/tcltest.tcl @@ -36,6 +36,14 @@ puts "ITU_region:\t[$state cget -itu_region]" # The following works well also # puts ITU_region:[[my_rig cget -state] cget -itu_region] +set rigcaps [my_rig cget -caps] +#set model [$rigcaps cget -model_name] +puts "Model:\t\t[$rigcaps cget -model_name]" +puts "Manufacturer:\t\t[$rigcaps cget -mfg_name]" +puts "Backend version:\t[$rigcaps cget -version]" +puts "Backend license:\t[$rigcaps cget -copyright]" +puts "Attenuators:\t[$rigcaps cget -attenuator]" + puts "getinfo:\t[my_rig get_info]" my_rig set_level "VOX" 1 diff --git a/include/hamlib/rig.h b/include/hamlib/rig.h index f4cb1c64d..9ca80b98a 100644 --- a/include/hamlib/rig.h +++ b/include/hamlib/rig.h @@ -174,7 +174,9 @@ typedef enum rig_port_e { RIG_PORT_PARALLEL, /*!< Parallel port */ RIG_PORT_USB, /*!< USB port */ RIG_PORT_UDP_NETWORK, /*!< UDP Network socket type */ - RIG_PORT_CM108 /*!< CM108 GPIO */ + RIG_PORT_CM108, /*!< CM108 GPIO */ + RIG_PORT_GPIO, /*!< GPIO */ + RIG_PORT_GPION, /*!< GPIO inverted */ } rig_port_t; /** @@ -421,7 +423,9 @@ typedef enum { RIG_PTT_SERIAL_RTS, /*!< PTT control through serial RTS signal */ RIG_PTT_PARALLEL, /*!< PTT control through parallel port */ RIG_PTT_RIG_MICDATA, /*!< Legacy PTT (CAT PTT), supports RIG_PTT_ON_MIC/RIG_PTT_ON_DATA */ - RIG_PTT_CM108 /*!< PTT control through CM108 GPIO pin */ + RIG_PTT_CM108, /*!< PTT control through CM108 GPIO pin */ + RIG_PTT_GPIO, /*!< PTT control through GPIO pin */ + RIG_PTT_GPION, /*!< PTT control through inverted GPIO pin */ } ptt_type_t; /** @@ -1383,6 +1387,10 @@ typedef struct hamlib_port { char *vendor_name; /*!< Vendor name (opt.) */ char *product; /*!< Product (opt.) */ } usb; /*!< USB attributes */ + struct { + int on_value; + int value; + } gpio; } parm; /*!< Port parameter union */ } hamlib_port_t; diff --git a/kenwood/kenwood.c b/kenwood/kenwood.c index a45d736d1..3aeb99965 100644 --- a/kenwood/kenwood.c +++ b/kenwood/kenwood.c @@ -487,6 +487,7 @@ int kenwood_init(RIG *rig) memset(priv, 0x00, sizeof(struct kenwood_priv_data)); strcpy (priv->verify_cmd, RIG_MODEL_XG3 == rig->caps->rig_model ? ";" : "ID;"); priv->split = RIG_SPLIT_OFF; + priv->trn_state = -1; rig->state.priv = priv; /* default mode_table */ @@ -611,18 +612,15 @@ int kenwood_open(RIG *rig) rig_debug(RIG_DEBUG_TRACE, "%s: found match %s\n", __func__, kenwood_id_string_list[i].id); - if (kenwood_id_string_list[i].model == rig->caps->rig_model) - { - /* get current AI state so it can be restored */ - priv->trn_state = -1; - kenwood_get_trn (rig, &priv->trn_state); /* ignore errors */ - /* Currently we cannot cope with AI mode so turn it off in - case last client left it on */ - kenwood_set_trn(rig, RIG_TRN_OFF); /* ignore status in case - it's not supported */ - - return RIG_OK; - } + if (kenwood_id_string_list[i].model == rig->caps->rig_model) { + /* get current AI state so it can be restored */ + kenwood_get_trn (rig, &priv->trn_state); /* ignore errors */ + /* Currently we cannot cope with AI mode so turn it off in + case last client left it on */ + kenwood_set_trn(rig, RIG_TRN_OFF); /* ignore status in case + it's not supported */ + return RIG_OK; + } /* driver mismatch */ rig_debug(RIG_DEBUG_ERR, @@ -2584,6 +2582,14 @@ int kenwood_get_trn(RIG *rig, int *trn) if (!rig || !trn) return -RIG_EINVAL; + /* these rigs only have AI[0|1] set commands and no AI query */ + if (rig->caps->rig_model == RIG_MODEL_TS450S + || rig->caps->rig_model == RIG_MODEL_TS690S + || rig->caps->rig_model == RIG_MODEL_TS850 + || rig->caps->rig_model == RIG_MODEL_TS950SDX) { + return -RIG_ENAVAIL; + } + char trnbuf[6]; int retval; diff --git a/kenwood/ts570.c b/kenwood/ts570.c index fc97c2879..4c69ae69f 100644 --- a/kenwood/ts570.c +++ b/kenwood/ts570.c @@ -805,6 +805,7 @@ const struct rig_caps ts570s_caps = { .priv = (void *)&ts570_priv_caps, .rig_init = kenwood_init, +.rig_open = kenwood_open, .rig_cleanup = kenwood_cleanup, .set_freq = kenwood_set_freq, .get_freq = kenwood_get_freq, @@ -989,6 +990,7 @@ const struct rig_caps ts570d_caps = { .priv = (void *)&ts570_priv_caps, .rig_init = kenwood_init, +.rig_open = kenwood_open, .rig_cleanup = kenwood_cleanup, .set_freq = kenwood_set_freq, .get_freq = kenwood_get_freq, diff --git a/kenwood/ts850.c b/kenwood/ts850.c index 7751d32cd..9dac6be7b 100644 --- a/kenwood/ts850.c +++ b/kenwood/ts850.c @@ -208,6 +208,7 @@ const struct rig_caps ts850_caps = { .priv = (void *)&ts850_priv_caps, .rig_init = kenwood_init, + .rig_open = kenwood_open, .rig_cleanup = kenwood_cleanup, .set_freq = kenwood_set_freq, .get_freq = kenwood_get_freq, diff --git a/src/Makefile.am b/src/Makefile.am index ca39ab9d1..c1668542e 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -4,7 +4,7 @@ RIGSRC = rig.c serial.c serial.h misc.c misc.h register.c register.h event.c \ event.h cal.c cal.h conf.c tones.c tones.h rotator.c locator.c rot_reg.c \ rot_conf.c rot_conf.h iofunc.c iofunc.h ext.c mem.c settings.c \ parallel.c parallel.h usb_port.c usb_port.h debug.c network.c network.h \ - cm108.c cm108.h idx_builtin.h token.h par_nt.h + cm108.c cm108.h gpio.c gpio.h idx_builtin.h token.h par_nt.h lib_LTLIBRARIES = libhamlib.la libhamlib_la_SOURCES = $(RIGSRC) diff --git a/src/gpio.c b/src/gpio.c new file mode 100644 index 000000000..d787ab5fb --- /dev/null +++ b/src/gpio.c @@ -0,0 +1,101 @@ +/* + * Hamlib Interface - gpio support + * Copyright (c) 2016 by Jeroen Vreeken + * + * + * 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 + * + */ + +#include "gpio.h" + +#include +#include +#include +#include +#include +#include + + +int gpio_open(hamlib_port_t *port, int on_value) +{ + char pathname[FILPATHLEN]; + FILE *fexp, *fdir; + int fd; + + port->parm.gpio.on_value = on_value; + + snprintf(pathname, FILPATHLEN, "/sys/class/gpio/export"); + fexp = fopen(pathname, "w"); + if (!fexp) { + rig_debug(RIG_DEBUG_ERR, "Export GPIO%s (using %s): %s\n", + port->pathname, pathname, strerror(errno)); + return -RIG_EIO; + } + fprintf(fexp, "%s\n", port->pathname); + fclose(fexp); + + snprintf(pathname, FILPATHLEN, "/sys/class/gpio/gpio%s/direction", port->pathname); + fdir = fopen(pathname, "w"); + if (!fdir) { + rig_debug(RIG_DEBUG_ERR, "GPIO%s direction (using %s): %s\n", + port->pathname, pathname, strerror(errno)); + return -RIG_EIO; + } + fprintf(fdir, "out\n"); + fclose(fdir); + + snprintf(pathname, FILPATHLEN, "/sys/class/gpio/gpio%s/value", port->pathname); + fd = open(pathname, O_WRONLY); + if (fd < 0) { + rig_debug(RIG_DEBUG_ERR, "GPIO%s opening value file %s: %s\n", + port->pathname, pathname, strerror(errno)); + return -RIG_EIO; + } + + port->fd = fd; + return fd; +} + +int gpio_close(hamlib_port_t *port) +{ + return close(port->fd); +} + +int gpio_ptt_set(hamlib_port_t *port, ptt_t pttx) +{ + char *val; + port->parm.gpio.value = pttx != RIG_PTT_OFF; + + if ((port->parm.gpio.value && port->parm.gpio.on_value) || + (!port->parm.gpio.value && !port->parm.gpio.on_value)) { + val = "1\n"; + } else { + val = "0\n"; + } + + if (write(port->fd, val, strlen(val)) <= 0) + return -RIG_EIO; + return RIG_OK; +} + +int gpio_ptt_get(hamlib_port_t *port, ptt_t *pttx) +{ + if (port->parm.gpio.value) + return RIG_PTT_ON; + else + return RIG_PTT_OFF; +} + diff --git a/src/gpio.h b/src/gpio.h new file mode 100644 index 000000000..c72a2b53f --- /dev/null +++ b/src/gpio.h @@ -0,0 +1,38 @@ +/* + * Hamlib Interface - gpio support header + * Copyright (c) 2016 by Jeroen Vreeken + * + * + * 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 _GPIO_H +#define _GPIO_H + +#include + + +__BEGIN_DECLS + +/* Hamlib internal use, see rig.c */ +int gpio_open(hamlib_port_t *p, int on_value); +int gpio_close(hamlib_port_t *p); +int gpio_ptt_set(hamlib_port_t *p, ptt_t pttx); +int gpio_ptt_get(hamlib_port_t *p, ptt_t *pttx); + +__END_DECLS + +#endif /* _GPIO_H */ diff --git a/src/register.c b/src/register.c index 72103d1ec..4a28ab9a7 100644 --- a/src/register.c +++ b/src/register.c @@ -291,19 +291,22 @@ int HAMLIB_API rig_unregister(rig_model_t rig_model) */ int HAMLIB_API rig_list_foreach(int (*cfunc)(const struct rig_caps*, rig_ptr_t),rig_ptr_t data) { - struct rig_list *p; - int i; + struct rig_list *p; + int i; - if (!cfunc) - return -RIG_EINVAL; - - for (i=0; inext) - if ((*cfunc)(p->caps,data) == 0) - return RIG_OK; - } + if (!cfunc) + return -RIG_EINVAL; + for (i=0; inext; /* read before call in case it is unregistered */ + if ((*cfunc)(p->caps,data) == 0) return RIG_OK; + } + } + + return RIG_OK; } static int dummy_rig_probe(const hamlib_port_t *p, rig_model_t model, rig_ptr_t data) diff --git a/src/rig.c b/src/rig.c index f47c1826f..fdcfa8f07 100644 --- a/src/rig.c +++ b/src/rig.c @@ -67,6 +67,7 @@ #include "network.h" #include "event.h" #include "cm108.h" +#include "gpio.h" /** * \brief Hamlib release number @@ -134,6 +135,7 @@ const char hamlib_copyright[231] = /* hamlib 1.2 ABI specifies 231 bytes */ #define DEFAULT_CM108_PTT_BITNUM 2 #endif +#define DEFAULT_GPIO_PORT "0" #define CHECK_RIG_ARG(r) (!(r) || !(r)->caps || !(r)->state.comm_state) @@ -338,6 +340,10 @@ RIG * HAMLIB_API rig_init(rig_model_t rig_model) strncpy(rs->rigport.pathname, DEFAULT_CM108_PORT, FILPATHLEN); rs->rigport.parm.cm108.ptt_bitnum = DEFAULT_CM108_PTT_BITNUM; break; + + case RIG_PORT_GPIO: + strncpy(rs->rigport.pathname, DEFAULT_GPIO_PORT, FILPATHLEN); + break; case RIG_PORT_NETWORK: case RIG_PORT_UDP_NETWORK: @@ -582,6 +588,26 @@ int HAMLIB_API rig_open(RIG *rig) else cm108_ptt_set(&rs->pttport, RIG_PTT_OFF); break; + case RIG_PTT_GPIO: + rs->pttport.fd = gpio_open(&rs->pttport, 1); + if (rs->pttport.fd < 0) { + rig_debug(RIG_DEBUG_ERR, + "Cannot open PTT device \"%s\"\n", + rs->pttport.pathname); + status = -RIG_EIO; + } else + gpio_ptt_set(&rs->pttport, RIG_PTT_OFF); + break; + case RIG_PTT_GPION: + rs->pttport.fd = gpio_open(&rs->pttport, 0); + if (rs->pttport.fd < 0) { + rig_debug(RIG_DEBUG_ERR, + "Cannot open PTT device \"%s\"\n", + rs->pttport.pathname); + status = -RIG_EIO; + } else + gpio_ptt_set(&rs->pttport, RIG_PTT_OFF); + break; default: rig_debug(RIG_DEBUG_ERR, "Unsupported PTT type %d\n", rs->pttport.type.ptt); @@ -734,6 +760,10 @@ int HAMLIB_API rig_close(RIG *rig) cm108_ptt_set(&rs->pttport, RIG_PTT_OFF); port_close(&rs->pttport, RIG_PORT_CM108); break; + case RIG_PTT_GPIO: + case RIG_PTT_GPION: + gpio_ptt_set(&rs->pttport, RIG_PTT_OFF); + port_close(&rs->pttport, RIG_PORT_GPIO); default: rig_debug(RIG_DEBUG_ERR, "Unsupported PTT type %d\n", rs->pttport.type.ptt); @@ -1309,6 +1339,10 @@ int HAMLIB_API rig_set_ptt(RIG *rig, vfo_t vfo, ptt_t ptt) case RIG_PTT_CM108: return cm108_ptt_set(&rig->state.pttport, ptt); + case RIG_PTT_GPIO: + case RIG_PTT_GPION: + return gpio_ptt_set(&rig->state.pttport, ptt); + case RIG_PTT_NONE: return -RIG_ENAVAIL; /* not available */ default: @@ -1400,6 +1434,13 @@ int HAMLIB_API rig_get_ptt(RIG *rig, vfo_t vfo, ptt_t *ptt) return cm108_ptt_get(&rig->state.pttport, ptt); + case RIG_PTT_GPIO: + case RIG_PTT_GPION: + if (caps->get_ptt) + return caps->get_ptt(rig, vfo, ptt); + + return gpio_ptt_get(&rig->state.pttport, ptt); + case RIG_PTT_NONE: return -RIG_ENAVAIL; /* not available */ diff --git a/tests/rigctl.c b/tests/rigctl.c index 4c297b445..7eb7f331f 100644 --- a/tests/rigctl.c +++ b/tests/rigctl.c @@ -216,6 +216,10 @@ int main (int argc, char *argv[]) ptt_type = RIG_PTT_PARALLEL; else if (!strcmp(optarg, "CM108")) ptt_type = RIG_PTT_CM108; + else if (!strcmp(optarg, "GPIO")) + ptt_type = RIG_PTT_GPIO; + else if (!strcmp(optarg, "GPION")) + ptt_type = RIG_PTT_GPION; else if (!strcmp(optarg, "NONE")) ptt_type = RIG_PTT_NONE; else diff --git a/yaesu/ft1200.c b/yaesu/ft1200.c index 6e54c31c4..309bdfcd3 100644 --- a/yaesu/ft1200.c +++ b/yaesu/ft1200.c @@ -163,6 +163,9 @@ const struct rig_caps ft1200_caps = { .rig_open = newcat_open, /* port opened */ .rig_close = newcat_close, /* port closed */ + .cfgparams = newcat_cfg_params, + .set_conf = newcat_set_conf, + .get_conf = newcat_get_conf, .set_freq = newcat_set_freq, .get_freq = newcat_get_freq, .set_mode = newcat_set_mode, diff --git a/yaesu/ft2000.c b/yaesu/ft2000.c index 75496429a..e3e5e75eb 100644 --- a/yaesu/ft2000.c +++ b/yaesu/ft2000.c @@ -162,6 +162,9 @@ const struct rig_caps ft2000_caps = { .rig_open = newcat_open, /* port opened */ .rig_close = newcat_close, /* port closed */ + .cfgparams = newcat_cfg_params, + .set_conf = newcat_set_conf, + .get_conf = newcat_get_conf, .set_freq = newcat_set_freq, .get_freq = newcat_get_freq, .set_mode = newcat_set_mode, @@ -204,4 +207,3 @@ const struct rig_caps ft2000_caps = { .get_channel = newcat_get_channel, }; - diff --git a/yaesu/ft450.c b/yaesu/ft450.c index 7217a3dfd..ad11220bc 100644 --- a/yaesu/ft450.c +++ b/yaesu/ft450.c @@ -160,7 +160,10 @@ const struct rig_caps ft450_caps = { .rig_cleanup = newcat_cleanup, .rig_open = newcat_open, /* port opened */ .rig_close = newcat_close, /* port closed */ - + + .cfgparams = newcat_cfg_params, + .set_conf = newcat_set_conf, + .get_conf = newcat_get_conf, .set_freq = newcat_set_freq, .get_freq = newcat_get_freq, .set_mode = newcat_set_mode, @@ -199,4 +202,3 @@ const struct rig_caps ft450_caps = { .get_channel = newcat_get_channel, }; - diff --git a/yaesu/ft5000.c b/yaesu/ft5000.c index 9af9a2386..e04ae0284 100644 --- a/yaesu/ft5000.c +++ b/yaesu/ft5000.c @@ -162,6 +162,9 @@ const struct rig_caps ftdx5000_caps = { .rig_open = newcat_open, /* port opened */ .rig_close = newcat_close, /* port closed */ + .cfgparams = newcat_cfg_params, + .set_conf = newcat_set_conf, + .get_conf = newcat_get_conf, .set_freq = newcat_set_freq, .get_freq = newcat_get_freq, .set_mode = newcat_set_mode, @@ -204,4 +207,3 @@ const struct rig_caps ftdx5000_caps = { .get_channel = newcat_get_channel, }; - diff --git a/yaesu/ft9000.c b/yaesu/ft9000.c index bdb58a2ae..1110fe6d4 100644 --- a/yaesu/ft9000.c +++ b/yaesu/ft9000.c @@ -163,6 +163,9 @@ const struct rig_caps ft9000_caps = { .rig_open = newcat_open, /* port opened */ .rig_close = newcat_close, /* port closed */ + .cfgparams = newcat_cfg_params, + .set_conf = newcat_set_conf, + .get_conf = newcat_get_conf, .set_freq = newcat_set_freq, .get_freq = newcat_get_freq, .set_mode = newcat_set_mode, @@ -205,4 +208,3 @@ const struct rig_caps ft9000_caps = { .get_channel = newcat_get_channel, }; - diff --git a/yaesu/ft950.c b/yaesu/ft950.c index b0e79206a..8767e15bb 100644 --- a/yaesu/ft950.c +++ b/yaesu/ft950.c @@ -190,6 +190,9 @@ const struct rig_caps ft950_caps = { .rig_open = newcat_open, /* port opened */ .rig_close = newcat_close, /* port closed */ + .cfgparams = newcat_cfg_params, + .set_conf = newcat_set_conf, + .get_conf = newcat_get_conf, .set_freq = newcat_set_freq, .get_freq = newcat_get_freq, .set_mode = newcat_set_mode, @@ -232,4 +235,3 @@ const struct rig_caps ft950_caps = { .get_channel = newcat_get_channel, }; - diff --git a/yaesu/ft950.h b/yaesu/ft950.h index bb6609b44..ce4ac6f84 100644 --- a/yaesu/ft950.h +++ b/yaesu/ft950.h @@ -118,6 +118,7 @@ /* Delay sequential fast writes */ -#define FT950_POST_WRITE_DELAY 5 +//#define FT950_POST_WRITE_DELAY 5 +#define FT950_POST_WRITE_DELAY 0 #endif /* _FT950_H */ diff --git a/yaesu/newcat.c b/yaesu/newcat.c index 1636c5d17..4be24b414 100644 --- a/yaesu/newcat.c +++ b/yaesu/newcat.c @@ -12,7 +12,7 @@ * "new" text CAT interface. * * Models this code aims to support are FTDX-9000*, FT-2000, FT-DX5000, - * FT-950, FT-450. Much testing remains. -N0NB + * FT-950, FT-450 and FT-1200. Much testing remains. -N0NB * * * This library is free software; you can redistribute it and/or @@ -214,6 +214,19 @@ static const yaesu_newcat_commands_t valid_commands[] = { }; int valid_commands_count = sizeof(valid_commands) / sizeof(yaesu_newcat_commands_t); + /* + * configuration Tokens + * + */ + +#define TOK_FAST_SET_CMD TOKEN_BACKEND(1) + +const struct confparams newcat_cfg_params[] = { + { TOK_FAST_SET_CMD, "fast_commands_token", "High troughput of commands", "Enabled high throughput of >200 messages/sec by not waiting for ACK/NAK of messages", "0", RIG_CONF_NUMERIC, { .n = { 0, 1, 1 } } + }, + { RIG_CONF_END, NULL, } +}; + /* NewCAT Internal Functions */ static ncboolean newcat_is_rig(RIG * rig, rig_model_t model); static int newcat_get_tx_vfo(RIG * rig, vfo_t * tx_vfo); @@ -235,7 +248,6 @@ static ncboolean newcat_valid_command(RIG *rig, char *command); int newcat_get_cmd(RIG * rig); int newcat_set_cmd (RIG *rig); - /* * ************************************ * @@ -272,6 +284,7 @@ int newcat_init(RIG *rig) { priv->rig_id = NC_RIGID_NONE; priv->current_mem = NC_MEM_CHANNEL_NONE; + priv->fast_set_commands = FALSE; return RIG_OK; } @@ -354,6 +367,91 @@ int newcat_close(RIG *rig) { return RIG_OK; } + +/* + * rig_set_config + * + * Set Configuration Token for Yaesu Radios + */ + +int newcat_set_conf(RIG *rig, token_t token, const char *val){ + + if (rig == NULL){ + return -RIG_EARG; + } + + int ret = RIG_OK; + struct newcat_priv_data *priv; + + priv = (struct newcat_priv_data*)rig->state.priv; + + if (priv == NULL){ + return -RIG_EINTERNAL; + } + + switch (token) { + case TOK_FAST_SET_CMD: ; + char *end; + long value; + //using strtol because atoi can lead to undefined behaviour + value = strtol(val, &end, 10); + if (end == val){ + return -RIG_EINVAL; + } + if ((value == 0) || (value == 1)){ + priv->fast_set_commands = (int)value; + } + else { + return -RIG_EINVAL; + } + break; + + default: + ret = -RIG_EINVAL; + } + + return ret; +} + + +/* + * rig_get_config + * + * Get Configuration Token for Yaesu Radios + */ + +int newcat_get_conf(RIG *rig, token_t token, char *val){ + + if (rig == NULL){ + return -RIG_EARG; + } + + int ret = RIG_OK; + struct newcat_priv_data *priv; + + priv = (struct newcat_priv_data*)rig->state.priv; + + if (priv == NULL){ + return -RIG_EINTERNAL; + } + + switch (token) { + case TOK_FAST_SET_CMD: + if (sizeof(val) < 2){ + return -RIG_ENOMEM; + } + sprintf(val, "%d", priv->fast_set_commands); + break; + default: + ret = -RIG_EINVAL; + } + + return ret; +} + + + + /* * rig_set_freq * @@ -2684,22 +2782,6 @@ int newcat_get_ext_parm(RIG *rig, token_t token, value_t *val) } -int newcat_set_conf(RIG * rig, token_t token, const char *val) -{ - rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__); - - return -RIG_ENAVAIL; -} - - -int newcat_get_conf(RIG * rig, token_t token, char *val) -{ - rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__); - - return -RIG_ENAVAIL; -} - - int newcat_send_dtmf(RIG * rig, vfo_t vfo, const char *digits) { rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__); @@ -4349,6 +4431,7 @@ int newcat_set_cmd (RIG *rig) struct newcat_priv_data *priv = (struct newcat_priv_data *)rig->state.priv; int retry_count = 0; int rc = -RIG_EPROTO; + /* pick a basic quick query command for verification */ char const * const verify_cmd = RIG_MODEL_FT9000 == rig->caps->rig_model ? "AI;" : "ID;"; @@ -4362,6 +4445,11 @@ int newcat_set_cmd (RIG *rig) return rc; } + /* skip validation if high throughput is needed */ + if (priv->fast_set_commands == TRUE){ + return RIG_OK; + } + /* send the verification command */ rig_debug(RIG_DEBUG_TRACE, "cmd_str = %s\n", verify_cmd); if (RIG_OK != (rc = write_block(&state->rigport, verify_cmd, strlen(verify_cmd)))) @@ -4408,17 +4496,24 @@ int newcat_set_cmd (RIG *rig) case '?': /* Rig busy wait please */ - rig_debug(RIG_DEBUG_ERR, "%s: Rig busy\n", __func__, priv->cmd_str); + rig_debug(RIG_DEBUG_WARN, "%s: Rig busy - retrying\n", __func__, priv->cmd_str); /* read the verify command reply */ - read_string(&state->rigport, priv->ret_data, sizeof(priv->ret_data), - &cat_term, sizeof(cat_term)); - rig_debug(RIG_DEBUG_TRACE, "%s: read count = %d, ret_data = %s\n", - __func__, rc, priv->ret_data); - rc = -RIG_BUSBUSY; - break; /* retry */ + if ((rc = read_string(&state->rigport, priv->ret_data, sizeof(priv->ret_data), + &cat_term, sizeof(cat_term))) > 0) + { + rig_debug(RIG_DEBUG_TRACE, "%s: read count = %d, ret_data = %s\n", + __func__, rc, priv->ret_data); + rc = RIG_OK; /* probably recovered and read verification */ + } + else + { + /* probably a timeout */ + rc = -RIG_BUSBUSY; /* retry */ + } + break; } } - else + if (RIG_OK == rc) { /* Check that response prefix and response termination is correct - alternative is response is longer that the diff --git a/yaesu/newcat.h b/yaesu/newcat.h index b0b18b75d..fadf90cc9 100644 --- a/yaesu/newcat.h +++ b/yaesu/newcat.h @@ -34,6 +34,7 @@ #define _NEWCAT_H 1 #include +#include /* Handy constants */ @@ -49,7 +50,7 @@ typedef char ncboolean; /* shared function version */ -#define NEWCAT_VER "0.22" +#define NEWCAT_VER "0.23" /* Hopefully large enough for future use, 128 chars plus '\0' */ #define NEWCAT_DATA_LEN 129 @@ -68,6 +69,8 @@ typedef char ncboolean; .ctcss_sql = 1,\ } +extern const struct confparams newcat_cfg_params[]; + /* * future - private data * @@ -85,6 +88,7 @@ struct newcat_priv_data { int width_frequency; /* width of FA/FB freq response */ int offset_rit; /* offset of rit in response */ int trn_state; /* AI state found at startup */ + int fast_set_commands; /* do not check for ACK/NAK; needed for high throughput > 100 commands/s */ }; @@ -115,7 +119,6 @@ struct newcat_priv_data { * */ - /* * newcat function definitions. * @@ -126,6 +129,9 @@ int newcat_cleanup(RIG *rig); int newcat_open(RIG *rig); int newcat_close(RIG *rig); +int newcat_set_conf(RIG *rig, token_t token, const char *val); +int newcat_get_conf(RIG *rig, token_t token, char *val); + int newcat_set_freq(RIG *rig, vfo_t vfo, freq_t freq); int newcat_get_freq(RIG *rig, vfo_t vfo, freq_t *freq);