[Hamlib-commits] Hamlib -- Ham radio control libraries branch master updated. ac2892913cdfe706ee4d6
Library to control radio transceivers and receivers
Brought to you by:
n0nb
From: Michael B. <mdb...@us...> - 2020-11-15 13:43:48
|
This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "Hamlib -- Ham radio control libraries". The branch, master has been updated via ac2892913cdfe706ee4d6496d639bae8467a202f (commit) via 8ba011eaf7dbcd9ae9b7f36d4d36cbd3b9b94627 (commit) via 801e16ac97bb1a8596953897f52953f2cadeac6e (commit) via 2deeca86dc95c02f8cb92cbc5a447a4525535215 (commit) via cf3b528ea7f9c4274524f7793b9d9bc0df7d1234 (commit) via 6ecaed955f268fca4c3c59653cd18153dc0789a7 (commit) via 1d07b1d6b6fda08f5b94ec9480c86a038272a44f (commit) via 056e0b2359ec67a373b649d50027b703483bfb8a (commit) via cabe9ea35466e72e99ec46d7dac2a4b578590e8f (commit) via 81d02e22f160e81032e7e5c2dfac5161cbe517f5 (commit) via ff012234435559fc5ecaf5b00c01e55547c95d4d (commit) via 4102e8c1e5157e71a1ac908ffcd4c24e6589f5bf (commit) via e122955213fc9f1e277add81bf07c71ef9c2d48d (commit) from f3cb1a09aead849dcfc25ad53c0f94e1cf5267cd (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit ac2892913cdfe706ee4d6496d639bae8467a202f Merge: 801e16ac 8ba011ea Author: Michael Black <mdb...@ya...> Date: Sun Nov 15 07:40:23 2020 -0600 Merge pull request #442 from nonoo/master Add INDI rotator backend commit 8ba011eaf7dbcd9ae9b7f36d4d36cbd3b9b94627 Author: Nonoo <no...@no...> Date: Sun Nov 15 12:46:35 2020 +0100 Add INDI rotator backend This backend lets Hamlib control an astronomical (telescope) rotator through an INDI (https://indilib.org/) server. diff --git a/AUTHORS b/AUTHORS index 7f48f478..36aa525a 100644 --- a/AUTHORS +++ b/AUTHORS @@ -265,6 +265,10 @@ C: Chris Bryant, G3WIE M: Øystein Hårberg, LA7LKA +[indi] +M: Norbert Varga, HA2NON + + [Frontend] M: Stephane Fillod, F8CFE @@ -362,3 +366,4 @@ Alexander Sack <pisymbol (at) gmail.com> Nirgal Vourgère <contact_hamlib (at) nirgal.com> Andrew Errington <a.errington (at) lancaster.ac.uk> Kārlis Millers YL3ALK <yl3alk (at) lrg.lv> +Norbert Varga HA2NON <nonoo (at) nonoo.hu> diff --git a/INSTALL b/INSTALL index 81b451bf..23034b25 100644 --- a/INSTALL +++ b/INSTALL @@ -287,6 +287,7 @@ are: --with-tcl-binding build Tcl binding and demo [default=no] --with-tcl=PATH directory containing tcl configuration (tclConfig.sh) --with-lua-binding build lua binding and demo [default=no] + --without-indi disable INDI rotator support [default=no] Optional features that may require specialized hardware are: diff --git a/configure.ac b/configure.ac index 5ac3056c..ab2e38af 100644 --- a/configure.ac +++ b/configure.ac @@ -363,6 +363,46 @@ AS_IF([test x"$ax_cv_lib_readline" = "xno"], [ cf_with_readline_support=no ]) +dnl Check if INDI support in rigctl/rotctl is wanted +AC_MSG_CHECKING([whether to use INDI in rigctl/rotctl]) +AC_ARG_WITH([indi], + [AS_HELP_STRING([--without-indi], + [disable INDI in rigctl/rotctl @<:@default=yes@:>@])], + [cf_with_indi_support=no], + [cf_with_indi_support=yes] + ) + +AS_IF([test x"$cf_with_indi_support" != "xno"], [ + # INDI support needs a C++ compiler, tested for presence above. + AS_IF([test x"${cf_with_cxx}" != "xyes"], [ + AC_MSG_WARN([INDI support needs a C++ compiler.]) + cf_with_indi_support=no + ]) +]) + +AS_IF([test x"$cf_with_indi_support" != "xno"], [ + # macros/ax_lib_nova.m4 + AX_LIB_NOVA + + AS_IF([test x"$ax_cv_lib_nova" = "xno"], [ + AC_MSG_WARN([libnova support not found, required by INDI.]) + cf_with_indi_support=no + ]) + + AS_IF([test x"$ax_cv_lib_nova" != "xno"], [ + # macros/ax_lib_indi.m4 + AX_LIB_INDI + + AS_IF([test x"$ax_cv_lib_indi" = "xno"], [ + AC_MSG_WARN([INDI support not found.]) + cf_with_indi_support=no + ]) + + AS_IF([test x"$cf_with_indi_support" != "xno"], [ + ROT_BACKEND_LIST="$ROT_BACKEND_LIST rotators/indi" + ]) + ]) +]) dnl Check if libgd-dev is installed, so we can enable rigmatrix AC_MSG_CHECKING([whether to build HTML rig feature matrix]) @@ -801,6 +841,7 @@ rotators/rotorez/Makefile rotators/sartek/Makefile rotators/spid/Makefile rotators/ts7400/Makefile +rotators/indi/Makefile rigs/adat/Makefile rigs/alinco/Makefile rigs/aor/Makefile @@ -857,6 +898,7 @@ echo \ With Lua binding ${cf_with_lua_binding} With rigmem XML support ${cf_with_xml_support} With Readline support ${cf_with_readline_support} + With INDI support ${cf_with_indi_support} Enable HTML rig feature matrix ${cf_enable_html_matrix} Enable WinRadio ${cf_with_winradio} diff --git a/include/hamlib/rotlist.h b/include/hamlib/rotlist.h index 4481c22f..53706e2a 100644 --- a/include/hamlib/rotlist.h +++ b/include/hamlib/rotlist.h @@ -455,6 +455,20 @@ #define ROT_MODEL_IOPTRON ROT_MAKE_MODEL(ROT_IOPTRON, 1) +/** ++ * \def ROT_MODEL_INDI ++ * \brief A macro that returns the model number of the INDI backend. ++ * ++ * The INDI backend can be used with rotators that support, among other, the ++ * INDI interface. ++ */ +//! @cond Doxygen_Suppress +#define ROT_INDI 20 +#define ROT_BACKEND_INDI "indi" +//! @endcond +#define ROT_MODEL_INDI ROT_MAKE_MODEL(ROT_INDI, 1) + + /** diff --git a/macros/Makefile.am b/macros/Makefile.am index c058a606..3507bbcf 100644 --- a/macros/Makefile.am +++ b/macros/Makefile.am @@ -6,6 +6,8 @@ MACROS = \ ax_pkg_swig.m4 \ ax_pthread.m4 \ ax_python_devel.m4 \ + ax_lib_indi.m4 \ + ax_lib_nova.m4 \ gr_doxygen.m4 \ gr_pwin32.m4 \ hl_getaddrinfo.m4 \ diff --git a/macros/ax_lib_indi.m4 b/macros/ax_lib_indi.m4 new file mode 100644 index 00000000..d74538e5 --- /dev/null +++ b/macros/ax_lib_indi.m4 @@ -0,0 +1,23 @@ +AU_ALIAS([VL_LIB_INDI], [AX_LIB_INDI]) +AC_DEFUN([AX_LIB_INDI], [ + AC_CACHE_CHECK([for INDI library], + ax_cv_lib_indi, [ + AC_LANG_PUSH(C++) + AC_CHECK_HEADER(libindi/baseclient.h, ax_cv_lib_indi="-lindiclient -lstdc++ -lz") + AC_LANG_POP() + + if test -z "$ax_cv_lib_indi"; then + ax_cv_lib_indi="no" + fi + ]) + + if test "$ax_cv_lib_indi" != "no"; then + ORIG_LIBS="$LIBS" + LIBS="$LIBS $ax_cv_lib_indi" + AC_DEFINE(HAVE_LIBINDI, 1, + [Define if you have an INDI compatible library]) + LIBS="$ORIG_LIBS" + INDI_LIBS="$ax_cv_lib_indi" + AC_SUBST([INDI_LIBS]) + fi +]) diff --git a/macros/ax_lib_nova.m4 b/macros/ax_lib_nova.m4 new file mode 100644 index 00000000..6eb0f0eb --- /dev/null +++ b/macros/ax_lib_nova.m4 @@ -0,0 +1,23 @@ +AU_ALIAS([VL_LIB_NOVA], [AX_LIB_NOVA]) +AC_DEFUN([AX_LIB_NOVA], [ + AC_CACHE_CHECK([for nova library], + ax_cv_lib_nova, [ + AC_LANG_PUSH(C++) + AC_CHECK_HEADER(libnova/libnova.h, ax_cv_lib_nova="-lnova -lstdc++ -lz") + AC_LANG_POP() + + if test -z "$ax_cv_lib_nova"; then + ax_cv_lib_nova="no" + fi + ]) + + if test "$ax_cv_lib_nova" != "no"; then + ORIG_LIBS="$LIBS" + LIBS="$LIBS $ax_cv_lib_nova" + AC_DEFINE(HAVE_LIBNOVA, 1, + [Define if you have a nova compatible library]) + LIBS="$ORIG_LIBS" + NOVA_LIBS="$ax_cv_lib_nova" + AC_SUBST([NOVA_LIBS]) + fi +]) diff --git a/rotators/indi/Android.mk b/rotators/indi/Android.mk new file mode 100644 index 00000000..4152c67a --- /dev/null +++ b/rotators/indi/Android.mk @@ -0,0 +1,12 @@ +LOCAL_PATH:= $(call my-dir) + +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := indi.c indi_wrapper.cpp +LOCAL_MODULE := indi + +LOCAL_CFLAGS := -DHAVE_CONFIG_H +LOCAL_C_INCLUDES := android include src +LOCAL_LDLIBS := -lhamlib -Lobj/local/armeabi + +include $(BUILD_STATIC_LIBRARY) diff --git a/rotators/indi/Makefile.am b/rotators/indi/Makefile.am new file mode 100644 index 00000000..20b7bcd0 --- /dev/null +++ b/rotators/indi/Makefile.am @@ -0,0 +1,6 @@ + +noinst_LTLIBRARIES = libhamlib-indi.la +libhamlib_indi_la_SOURCES = indi.c indi_wrapper.cpp indi_wrapper.hpp indi_wrapper.h +libhamlib_indi_la_LDFLAGS = $(INDI_LIBS) + +EXTRA_DIST = Android.mk diff --git a/rotators/indi/README.indi.md b/rotators/indi/README.indi.md new file mode 100644 index 00000000..1fbb2712 --- /dev/null +++ b/rotators/indi/README.indi.md @@ -0,0 +1,8 @@ +INDI rotator backend +==================== + +This backend lets Hamlib control an astronomical (telescope) rotator through an +[INDI](https://indilib.org/) server. + +The easiest way to set up an INDI server is to use [EKOS](https://www.indilib.org/about/ekos.html), +which is available in [KStars](https://edu.kde.org/kstars/). diff --git a/rotators/indi/indi.c b/rotators/indi/indi.c new file mode 100644 index 00000000..07996fbb --- /dev/null +++ b/rotators/indi/indi.c @@ -0,0 +1,70 @@ +/* + * Hamlib Rotator backend - INDI integration + * Copyright (c) 2020 by Norbert Varga HA2NON <no...@no...> + * + * + * 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 "indi_wrapper.h" + +#include <hamlib/rotator.h> +#include <register.h> + +const struct rot_caps indi_rot_caps = +{ + ROT_MODEL(ROT_MODEL_INDI), + .model_name = "INDI", + .mfg_name = "INDI", + .version = "0.1", + .copyright = "LGPL", + .status = RIG_STATUS_ALPHA, + .rot_type = ROT_TYPE_OTHER, + .port_type = RIG_PORT_NONE, + .write_delay = 0, + .post_write_delay = 0, + .timeout = 200, + .retry = 3, + + .min_az = 0, + .max_az = 360, + .min_el = -90, + .max_el = 90, + + .set_position = indi_wrapper_set_position, + .get_position = indi_wrapper_get_position, + .stop = indi_wrapper_stop, + .park = indi_wrapper_park, + .move = indi_wrapper_move, + .get_info = indi_wrapper_get_info, + .rot_open = indi_wrapper_open, + .rot_close = indi_wrapper_close, +}; + +/* ************************************************************************* */ + +DECLARE_INITROT_BACKEND(indi) +{ + rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__); + + rot_register(&indi_rot_caps); + + return RIG_OK; +} diff --git a/rotators/indi/indi_wrapper.cpp b/rotators/indi/indi_wrapper.cpp new file mode 100644 index 00000000..df616999 --- /dev/null +++ b/rotators/indi/indi_wrapper.cpp @@ -0,0 +1,621 @@ +/* + * Hamlib Rotator backend - INDI integration + * Copyright (c) 2020 by Norbert Varga HA2NON <no...@no...> + * + * + * 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 "indi_wrapper.hpp" + +#include <math.h> +#include <limits.h> + +#define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d)) + +static std::unique_ptr<RotINDIClient> indi_wrapper_client(new RotINDIClient()); + +int RotINDIClient::setSpeed(int speedPercent) +{ + if (!mTelescope || !mTelescope->isConnected()) + { + rig_debug(RIG_DEBUG_ERR, "indi: telescope not connected\n"); + return -RIG_EIO; + } + + ISwitchVectorProperty *switchVector = + mTelescope->getSwitch("TELESCOPE_SLEW_RATE"); + + if (!switchVector) + { + rig_debug(RIG_DEBUG_ERR, + "indi: unable to find telescope or TELESCOPE_SLEW_RATE switch\n"); + return -RIG_EPROTO; + } + + if (speedPercent < 0) + { + speedPercent = 0; + } + + if (speedPercent > 100) + { + speedPercent = 100; + } + + int speed = DIV_ROUND_UP(speedPercent, 10); + + for (int i = 1; i <= 10; i++) + { + char switchName[4]; + snprintf(switchName, sizeof(switchName), "%ux", i); + + ISwitch *slewrate = IUFindSwitch(switchVector, switchName); + + if (slewrate) + { + if (speed == i) + { + rig_debug(RIG_DEBUG_VERBOSE, "indi: setting speed %s\n", switchName); + slewrate->s = ISS_ON; + } + else + { + slewrate->s = ISS_OFF; + } + } + else + { + rig_debug(RIG_DEBUG_ERR, "indi: unable to find switch member %s\n", switchName); + return -RIG_EPROTO; + } + } + + sendNewSwitch(switchVector); + + return RIG_OK; +} + +int RotINDIClient::move(int direction, int speedPercent) +{ + if (!mTelescope || !mTelescope->isConnected()) + { + rig_debug(RIG_DEBUG_ERR, "indi: telescope not connected\n"); + return -RIG_EIO; + } + + int err = setSpeed(speedPercent); + + if (err != RIG_OK) + { + return err; + } + + ISwitchVectorProperty *switchVector = + mTelescope->getSwitch("TELESCOPE_MOTION_NS"); + + if (!switchVector) + { + rig_debug(RIG_DEBUG_ERR, + "indi: unable to find telescope or TELESCOPE_MOTION_NS switch\n"); + return -RIG_EPROTO; + } + + ISwitch *motion_north = IUFindSwitch(switchVector, "MOTION_NORTH"); + + if (!motion_north) + { + rig_debug(RIG_DEBUG_ERR, "indi: unable to find switch member MOTION_NORTH\n"); + return -RIG_EPROTO; + } + + if (direction & ROT_MOVE_UP) + { + rig_debug(RIG_DEBUG_VERBOSE, "indi: moving up\n"); + motion_north->s = ISS_ON; + } + else + { + motion_north->s = ISS_OFF; + } + + ISwitch *motion_south = IUFindSwitch(switchVector, "MOTION_SOUTH"); + + if (!motion_south) + { + rig_debug(RIG_DEBUG_ERR, "indi: unable to find switch member MOTION_SOUTH\n"); + return -RIG_EPROTO; + } + + if (direction & ROT_MOVE_DOWN) + { + rig_debug(RIG_DEBUG_VERBOSE, "indi: moving down\n"); + motion_south->s = ISS_ON; + } + else + { + motion_south->s = ISS_OFF; + } + + sendNewSwitch(switchVector); + + switchVector = mTelescope->getSwitch("TELESCOPE_MOTION_WE"); + + if (!switchVector) + { + rig_debug(RIG_DEBUG_ERR, + "indi: unable to find telescope or TELESCOPE_MOTION_WE switch\n"); + return -RIG_EPROTO; + } + + ISwitch *motion_west = IUFindSwitch(switchVector, "MOTION_WEST"); + + if (!motion_west) + { + rig_debug(RIG_DEBUG_ERR, "indi: unable to find switch member MOTION_WEST\n"); + return -RIG_EPROTO; + } + + if (direction & ROT_MOVE_LEFT) + { + rig_debug(RIG_DEBUG_VERBOSE, "indi: moving left\n"); + motion_west->s = ISS_ON; + } + else + { + motion_west->s = ISS_OFF; + } + + ISwitch *motion_east = IUFindSwitch(switchVector, "MOTION_EAST"); + + if (!motion_east) + { + rig_debug(RIG_DEBUG_ERR, "indi: unable to find switch member MOTION_RIGHT\n"); + return -RIG_EPROTO; + } + + if (direction & ROT_MOVE_RIGHT) + { + rig_debug(RIG_DEBUG_VERBOSE, "indi: moving right\n"); + motion_east->s = ISS_ON; + } + else + { + motion_east->s = ISS_OFF; + } + + sendNewSwitch(switchVector); + + return RIG_OK; +} + +int RotINDIClient::stop() +{ + if (!mTelescope || !mTelescope->isConnected()) + { + rig_debug(RIG_DEBUG_ERR, "indi: telescope not connected\n"); + return -RIG_EIO; + } + + ISwitchVectorProperty *switchVector = + mTelescope->getSwitch("TELESCOPE_ABORT_MOTION"); + + if (!switchVector) + { + rig_debug(RIG_DEBUG_ERR, + "indi: unable to find telescope or TELESCOPE_ABORT_MOTION switch\n"); + return -RIG_EPROTO; + } + + ISwitch *sw = IUFindSwitch(switchVector, "ABORT"); + + if (!sw) + { + rig_debug(RIG_DEBUG_ERR, "indi: unable to find switch member ABORT_MOTION\n"); + return -RIG_EPROTO; + } + + sw->s = ISS_ON; + sendNewSwitch(switchVector); + + return RIG_OK; +} + +int RotINDIClient::park() +{ + if (!mTelescope) + { + return -RIG_EIO; + } + + if (!mTelescope->isConnected()) + { + rig_debug(RIG_DEBUG_ERR, "indi: telescope not connected\n"); + return -RIG_EIO; + } + + ISwitchVectorProperty *switchVector = mTelescope->getSwitch("TELESCOPE_PARK"); + + if (!switchVector) + { + rig_debug(RIG_DEBUG_ERR, + "indi: unable to find telescope or TELESCOPE_PARK switch\n"); + return -RIG_EPROTO; + } + + ISwitch *unpark = IUFindSwitch(switchVector, "UNPARK"); + + if (!unpark) + { + rig_debug(RIG_DEBUG_ERR, "indi: unable to find switch member UNPARK\n"); + return -RIG_EPROTO; + } + + unpark->s = ISS_OFF; + + ISwitch *park = IUFindSwitch(switchVector, "PARK"); + + if (!park) + { + rig_debug(RIG_DEBUG_ERR, "indi: unable to find switch member PARK\n"); + return -RIG_EPROTO; + } + + park->s = ISS_ON; + + sendNewSwitch(switchVector); + + return RIG_OK; +} + +int RotINDIClient::unPark() +{ + if (!mTelescope || !mTelescope->isConnected()) + { + rig_debug(RIG_DEBUG_ERR, "indi: telescope not connected\n"); + return -RIG_EIO; + } + + ISwitchVectorProperty *switchVector = mTelescope->getSwitch("TELESCOPE_PARK"); + + if (!switchVector) + { + rig_debug(RIG_DEBUG_ERR, + "indi: unable to find telescope or TELESCOPE_PARK switch\n"); + return -RIG_EPROTO; + } + + ISwitch *park = IUFindSwitch(switchVector, "PARK"); + + if (!park) + { + rig_debug(RIG_DEBUG_ERR, "indi: unable to find switch member PARK\n"); + return -RIG_EPROTO; + } + + park->s = ISS_OFF; + + ISwitch *unpark = IUFindSwitch(switchVector, "UNPARK"); + + if (!unpark) + { + rig_debug(RIG_DEBUG_ERR, "indi: unable to find switch member UNPARK\n"); + return -RIG_EPROTO; + } + + unpark->s = ISS_ON; + + sendNewSwitch(switchVector); + + return RIG_OK; +} + +void RotINDIClient::position(azimuth_t *az, elevation_t *el) +{ + *az = mAz; + *el = mEl; +} + +double RotINDIClient::getPositionDiffBetween(double deg1, double deg2) +{ + return fabs(deg1 - deg2); +} + +double RotINDIClient::getPositionDiffOutside(double deg1, double deg2, + double minDeg, double maxDeg) +{ + if (deg1 < deg2) + { + return getPositionDiffBetween(minDeg, deg1) + getPositionDiffBetween(deg2, + maxDeg); + } + + return getPositionDiffBetween(minDeg, deg2) + getPositionDiffBetween(deg1, + maxDeg); +} + +double RotINDIClient::getPositionDiff(double deg1, double deg2, double minDeg, + double maxDeg) +{ + double between = getPositionDiffBetween(deg1, deg2); + double outside = getPositionDiffOutside(deg1, deg2, minDeg, maxDeg); + + if (between < outside) + { + return between; + } + + return outside; +} + +int RotINDIClient::setPosition(azimuth_t az, elevation_t el) +{ + if (!mTelescope || !mTelescope->isConnected()) + { + rig_debug(RIG_DEBUG_ERR, "indi: telescope not connected\n"); + return -RIG_EIO; + } + + if (fabs(mDstAz - az) < 0.001 && fabs(mDstEl - el) < 0.001) + { + rig_debug(RIG_DEBUG_VERBOSE, + "indi: ignoring new position, already approaching\n"); + return RIG_OK; + } + + // Each coordinate set command stops and restarts the rotator, so we have to avoid unnecessary + // set calls by defining a range of distance from the new az/el coords which we ignore until + // we are closer to the new az/el coords than this value. + const int quickJumpRangeDegrees = 10; + + double currDstNewDstAzDiff = getPositionDiff(mDstAz, az, 0, 360); + double currDstNewDstElDiff = getPositionDiff(mDstEl, el, -90, 90); + double currDstNewDstDistance = sqrt(pow(currDstNewDstAzDiff, + 2) + pow(currDstNewDstElDiff, 2)); + double currPosNewDstAzDiff = getPositionDiff(mAz, az, 0, 360); + double currPosNewDstElDiff = getPositionDiff(mEl, el, -90, 90); + double currPosNewDstDistance = sqrt(pow(currPosNewDstAzDiff, + 2) + pow(currPosNewDstElDiff, 2)); + + if (currDstNewDstDistance < quickJumpRangeDegrees + && currPosNewDstDistance > quickJumpRangeDegrees) + { + rig_debug(RIG_DEBUG_VERBOSE, + "indi: ignoring new position, approaching quickly, newDst/currDst distance: %f newDst/currPos distance: %f\n", + currDstNewDstDistance, currPosNewDstDistance); + return RIG_OK; + } + + rig_debug(RIG_DEBUG_VERBOSE, "indi: setting position to az: %f el: %f\n", az, + el); + + mDstAz = az; + mDstEl = el; + + ISwitchVectorProperty *switchVector = mTelescope->getSwitch("ON_COORD_SET"); + + if (!switchVector) + { + rig_debug(RIG_DEBUG_ERR, + "indi: unable to find telescope or ON_COORD_SET switch\n"); + return -RIG_EPROTO; + } + + ISwitch *slew = IUFindSwitch(switchVector, "SLEW"); + + if (!slew) + { + rig_debug(RIG_DEBUG_ERR, "indi: unable to find switch member SLEW\n"); + return -RIG_EPROTO; + } + + slew->s = ISS_OFF; + + ISwitch *track = IUFindSwitch(switchVector, "TRACK"); + + if (!track) + { + rig_debug(RIG_DEBUG_ERR, "indi: unable to find switch member TRACK\n"); + return -RIG_EPROTO; + } + + track->s = ISS_ON; + + ISwitch *sync = IUFindSwitch(switchVector, "SYNC"); + + if (!sync) + { + rig_debug(RIG_DEBUG_ERR, "indi: unable to find switch member SYNC\n"); + return -RIG_EPROTO; + } + + sync->s = ISS_OFF; + + sendNewSwitch(switchVector); + + INumberVectorProperty *property = mTelescope->getNumber("HORIZONTAL_COORD"); + + if (!property) + { + rig_debug(RIG_DEBUG_ERR, + "indi: unable to find telescope or HORIZONTAL_COORD property\n"); + return -RIG_EPROTO; + } + + property->np[0].value = az; + property->np[1].value = el; + sendNewNumber(property); + + return RIG_OK; +} + +void RotINDIClient::removeDevice(INDI::BaseDevice *dp) {} +void RotINDIClient::newProperty(INDI::Property *property) +{ + std::string name(property->getName()); + + if (!mTelescope && name == "TELESCOPE_INFO") + { + mTelescope = property->getBaseDevice(); + rig_debug(RIG_DEBUG_VERBOSE, "indi: using device %s\n", + mTelescope->getDeviceName()); + watchDevice(mTelescope->getDeviceName()); + + if (!mTelescope->isConnected()) + { + connectDevice(mTelescope->getDeviceName()); + } + + mDstAz = INT_MAX; + mDstEl = INT_MAX; + } + + if (name == "HORIZONTAL_COORD") + { + mAz = property->getNumber()->np[0].value; + mEl = property->getNumber()->np[1].value; + } +} +void RotINDIClient::removeProperty(INDI::Property *property) {} +void RotINDIClient::newBLOB(IBLOB *bp) {} +void RotINDIClient::newSwitch(ISwitchVectorProperty *svp) {} +void RotINDIClient::newNumber(INumberVectorProperty *nvp) +{ + std::string name(nvp->name); + + if (name == "HORIZONTAL_COORD") + { + mAz = nvp->np[0].value; + mEl = nvp->np[1].value; + } +} +void RotINDIClient::newMessage(INDI::BaseDevice *dp, int messageID) {} +void RotINDIClient::newText(ITextVectorProperty *tvp) {} +void RotINDIClient::newLight(ILightVectorProperty *lvp) {} +void RotINDIClient::newDevice(INDI::BaseDevice *dp) {} + +void RotINDIClient::serverConnected() +{ + rig_debug(RIG_DEBUG_VERBOSE, "indi: server connected\n"); +} + +void RotINDIClient::serverDisconnected(int exit_code) +{ + rig_debug(RIG_DEBUG_VERBOSE, "indi: server disconnected\n"); +} + +const char *RotINDIClient::getInfo(void) +{ + static char info[128]; + + if (mTelescope && mTelescope->isConnected()) + { + snprintf(info, sizeof(info), "using INDI device %s", + mTelescope->getDeviceName()); + return info; + } + + return "no INDI device connected"; +} + +void RotINDIClient::close(void) +{ + if (mTelescope && mTelescope->isConnected()) + { + disconnectDevice(mTelescope->getDeviceName()); + } + + disconnectServer(); +} + +extern "C" int indi_wrapper_set_position(ROT *rot, azimuth_t az, + elevation_t el) +{ + int res; + + rig_debug(RIG_DEBUG_TRACE, "%s called: az=%f el=%f\n", __func__, az, el); + + res = indi_wrapper_client->unPark(); + + if (res != RIG_OK) + { + return res; + } + + return indi_wrapper_client->setPosition(az, el); +} + +extern "C" int indi_wrapper_get_position(ROT *rot, azimuth_t *az, + elevation_t *el) +{ + rig_debug(RIG_DEBUG_TRACE, "%s called\n", __func__); + + indi_wrapper_client->position(az, el); + + return RIG_OK; +} + +extern "C" int indi_wrapper_stop(ROT *rot) +{ + rig_debug(RIG_DEBUG_TRACE, "%s called\n", __func__); + + return indi_wrapper_client->stop(); +} + +extern "C" int indi_wrapper_park(ROT *rot) +{ + rig_debug(RIG_DEBUG_TRACE, "%s called\n", __func__); + + return indi_wrapper_client->park(); +} + +extern "C" int indi_wrapper_move(ROT *rot, int direction, int speed) +{ + rig_debug(RIG_DEBUG_TRACE, "%s called\n", __func__); + + return indi_wrapper_client->move(direction, speed); +} + +extern "C" const char *indi_wrapper_get_info(ROT *rot) +{ + rig_debug(RIG_DEBUG_TRACE, "%s called\n", __func__); + + return indi_wrapper_client->getInfo(); +} + +extern "C" int indi_wrapper_open(ROT *rot) +{ + rig_debug(RIG_DEBUG_TRACE, "%s called\n", __func__); + + indi_wrapper_client->setServer("localhost", 7624); + + if (!indi_wrapper_client->connectServer()) + { + rig_debug(RIG_DEBUG_ERR, "indi: server refused connection\n"); + return -RIG_EPROTO; + } + + return RIG_OK; +} + +extern "C" int indi_wrapper_close(ROT *rot) +{ + rig_debug(RIG_DEBUG_TRACE, "%s called\n", __func__); + + indi_wrapper_client->close(); + + return RIG_OK; +} diff --git a/rotators/indi/indi_wrapper.h b/rotators/indi/indi_wrapper.h new file mode 100644 index 00000000..cfd83682 --- /dev/null +++ b/rotators/indi/indi_wrapper.h @@ -0,0 +1,36 @@ +/* + * Hamlib Rotator backend - INDI integration + * Copyright (c) 2020 by Norbert Varga HA2NON <no...@no...> + * + * + * 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 _INDI_WRAPPER_H +#define _INDI_WRAPPER_H 1 + +#include <hamlib/rotator.h> + +int indi_wrapper_set_position(ROT *rot, azimuth_t az, elevation_t el); +int indi_wrapper_get_position(ROT *rot, azimuth_t *az, elevation_t *el); +int indi_wrapper_stop(ROT *rot); +int indi_wrapper_park(ROT *rot); +int indi_wrapper_move(ROT *rot, int direction, int speed); +const char *indi_wrapper_get_info(ROT *rot); +int indi_wrapper_open(ROT *rot); +int indi_wrapper_close(ROT *rot); + +#endif // _INDI_WRAPPER_H diff --git a/rotators/indi/indi_wrapper.hpp b/rotators/indi/indi_wrapper.hpp new file mode 100644 index 00000000..3f5efef0 --- /dev/null +++ b/rotators/indi/indi_wrapper.hpp @@ -0,0 +1,71 @@ +/* + * Hamlib Rotator backend - INDI integration + * Copyright (c) 2020 by Norbert Varga HA2NON <no...@no...> + * + * + * 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 _INDI_WRAPPER_HPP +#define _INDI_WRAPPER_HPP 1 + +#include <libindi/basedevice.h> +#include <libindi/baseclient.h> + +#include <hamlib/rotator.h> + +class RotINDIClient : public INDI::BaseClient +{ +public: + int setSpeed(int speedPercent); + int move(int direction, int speedPercent); + int stop(); + int park(); + int unPark(); + void position(azimuth_t *az, elevation_t *el); + int setPosition(azimuth_t az, elevation_t el); + const char *getInfo(); + void close(void); + +protected: + virtual void newDevice(INDI::BaseDevice *dp); + virtual void removeDevice(INDI::BaseDevice *dp); + virtual void newProperty(INDI::Property *property); + virtual void removeProperty(INDI::Property *property); + virtual void newBLOB(IBLOB *bp); + virtual void newSwitch(ISwitchVectorProperty *svp); + virtual void newNumber(INumberVectorProperty *nvp); + virtual void newMessage(INDI::BaseDevice *dp, int messageID); + virtual void newText(ITextVectorProperty *tvp); + virtual void newLight(ILightVectorProperty *lvp); + virtual void serverConnected(); + virtual void serverDisconnected(int exit_code); + +private: + double getPositionDiffBetween(double deg1, double deg2); + double getPositionDiffOutside(double deg1, double deg2, double minDeg, double maxDeg); + double getPositionDiff(double deg1, double deg2, double minDeg, double maxDeg); + + INDI::BaseDevice *mTelescope; + + azimuth_t mDstAz; + elevation_t mDstEl; + + azimuth_t mAz; + elevation_t mEl; +}; + +#endif // _INDI_WRAPPER_HPP diff --git a/src/Makefile.am b/src/Makefile.am index b53926a4..f3a9a22c 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -12,7 +12,7 @@ libhamlib_la_SOURCES = $(RIGSRC) libhamlib_la_LDFLAGS = $(WINLDFLAGS) $(OSXLDFLAGS) -no-undefined -version-info $(ABI_VERSION):$(ABI_REVISION):$(ABI_AGE) libhamlib_la_LIBADD = $(top_builddir)/lib/libmisc.la \ - $(BACKENDEPS) $(RIG_BACKENDEPS) $(ROT_BACKENDEPS) $(AMP_BACKENDEPS) $(NET_LIBS) $(MATH_LIBS) $(LIBUSB_LIBS) + $(BACKENDEPS) $(RIG_BACKENDEPS) $(ROT_BACKENDEPS) $(AMP_BACKENDEPS) $(NET_LIBS) $(MATH_LIBS) $(LIBUSB_LIBS) $(INDI_LIBS) libhamlib_la_DEPENDENCIES = $(top_builddir)/lib/libmisc.la $(BACKENDEPS) $(RIG_BACKENDEPS) $(ROT_BACKENDEPS) $(AMP_BACKENDEPS) diff --git a/src/rot_reg.c b/src/rot_reg.c index ab77990a..3353e7bc 100644 --- a/src/rot_reg.c +++ b/src/rot_reg.c @@ -84,6 +84,9 @@ DEFINE_INITROT_BACKEND(cnctrk); DEFINE_INITROT_BACKEND(prosistel); DEFINE_INITROT_BACKEND(meade); DEFINE_INITROT_BACKEND(ioptron); +#if HAVE_LIBINDI +DEFINE_INITROT_BACKEND(indi); +#endif //! @endcond /** @@ -123,6 +126,9 @@ static struct { ROT_PROSISTEL, ROT_BACKEND_PROSISTEL, ROT_FUNCNAMA(prosistel) }, { ROT_MEADE, ROT_BACKEND_MEADE, ROT_FUNCNAMA(meade) }, { ROT_IOPTRON, ROT_BACKEND_IOPTRON, ROT_FUNCNAMA(ioptron) }, +#if HAVE_LIBINDI + { ROT_INDI, ROT_BACKEND_INDI, ROT_FUNCNAMA(indi) }, +#endif { 0, NULL }, /* end */ }; commit 801e16ac97bb1a8596953897f52953f2cadeac6e Merge: cf3b528e 2deeca86 Author: Michael Black <mdb...@ya...> Date: Sat Nov 14 08:45:08 2020 -0600 Merge pull request #441 from nonoo/master Fix decimal separators which sscanf can't handle commit 2deeca86dc95c02f8cb92cbc5a447a4525535215 Author: Nonoo <no...@no...> Date: Sat Nov 14 08:56:37 2020 +0100 Fix decimal separators which sscanf can't handle This is a workaround for some apps like Gpredict, which use comma as a decimal separator (depending on locale settings), but sscanf in Hamlib can only handle dots. diff --git a/tests/rotctl_parse.c b/tests/rotctl_parse.c index 95f5064a..63873ad1 100644 --- a/tests/rotctl_parse.c +++ b/tests/rotctl_parse.c @@ -1692,6 +1692,22 @@ declare_proto_rot(set_position) { azimuth_t az; elevation_t el; + char *comma_pos; + + /* Fixing args with an invalid decimal separator. */ + comma_pos = strchr(arg1, ','); + + if (comma_pos) + { + *comma_pos = '.'; + } + + comma_pos = strchr(arg2, ','); + + if (comma_pos) + { + *comma_pos = '.'; + } CHKSCN1ARG(sscanf(arg1, "%f", &az)); CHKSCN1ARG(sscanf(arg2, "%f", &el)); commit cf3b528ea7f9c4274524f7793b9d9bc0df7d1234 Author: Michael Black W9MDB <mdb...@ya...> Date: Wed Nov 11 16:40:06 2020 -0600 Change newcat.c RIG_FUNC_TUNER to send AC001 instead of AC002 to turn off TUNE G TUNE 1 is used to start tuning diff --git a/rigs/yaesu/newcat.c b/rigs/yaesu/newcat.c index 2822278b..372dbc2e 100644 --- a/rigs/yaesu/newcat.c +++ b/rigs/yaesu/newcat.c @@ -4884,9 +4884,6 @@ int newcat_set_func(RIG *rig, vfo_t vfo, setting_t func, int status) return -RIG_ENAVAIL; } - // some rigs use AC02 to actually start tuning - if (status == 1 && (is_ftdx101 || is_ftdx5000)) { status = 2; } - snprintf(priv->cmd_str, sizeof(priv->cmd_str), "AC00%d%c", status == 0 ? 0 : status, cat_term); commit 6ecaed955f268fca4c3c59653cd18153dc0789a7 Author: Michael Black W9MDB <mdb...@ya...> Date: Wed Nov 11 08:21:38 2020 -0600 Add RIG_METER_TEMP for FTDX101D and other newcat.c rigs Update documentation on TONE and TSQL to make it clear diff --git a/include/hamlib/rig.h b/include/hamlib/rig.h index 9d6aada6..ba916435 100644 --- a/include/hamlib/rig.h +++ b/include/hamlib/rig.h @@ -812,7 +812,8 @@ enum meter_level_e { RIG_METER_IC = (1 << 3), /*< IC */ RIG_METER_DB = (1 << 4), /*< DB */ RIG_METER_PO = (1 << 5), /*< Power Out */ - RIG_METER_VDD = (1 << 6) /*< Final Amp Voltage */ + RIG_METER_VDD = (1 << 6), /*< Final Amp Voltage */ + RIG_METER_TEMP = (1 << 7) /*< Final Amp Voltage */ }; @@ -1006,8 +1007,8 @@ typedef uint64_t setting_t; #define RIG_FUNC_NB CONSTANT_64BIT_FLAG (1) /*!< \c NB -- Noise Blanker */ #define RIG_FUNC_COMP CONSTANT_64BIT_FLAG (2) /*!< \c COMP -- Speech Compression */ #define RIG_FUNC_VOX CONSTANT_64BIT_FLAG (3) /*!< \c VOX -- Voice Operated Relay */ -#define RIG_FUNC_TONE CONSTANT_64BIT_FLAG (4) /*!< \c TONE -- CTCSS Tone */ -#define RIG_FUNC_TSQL CONSTANT_64BIT_FLAG (5) /*!< \c TSQL -- CTCSS Activate/De-activate and Encode-only value=2 if available */ +#define RIG_FUNC_TONE CONSTANT_64BIT_FLAG (4) /*!< \c TONE -- CTCSS Tone TX */ +#define RIG_FUNC_TSQL CONSTANT_64BIT_FLAG (5) /*!< \c TSQL -- CTCSS Activate/De-activate RX */ #define RIG_FUNC_SBKIN CONSTANT_64BIT_FLAG (6) /*!< \c SBKIN -- Semi Break-in (CW mode) */ #define RIG_FUNC_FBKIN CONSTANT_64BIT_FLAG (7) /*!< \c FBKIN -- Full Break-in (CW mode) */ #define RIG_FUNC_ANF CONSTANT_64BIT_FLAG (8) /*!< \c ANF -- Automatic Notch Filter (DSP) */ commit 1d07b1d6b6fda08f5b94ec9480c86a038272a44f Author: Michael Black W9MDB <mdb...@ya...> Date: Wed Nov 11 07:26:51 2020 -0600 Undo last commit...FUNC_TONE and FUNC_TSQL handle this correctly diff --git a/rigs/yaesu/newcat.c b/rigs/yaesu/newcat.c index fb81777f..2822278b 100644 --- a/rigs/yaesu/newcat.c +++ b/rigs/yaesu/newcat.c @@ -4777,8 +4777,7 @@ int newcat_set_func(RIG *rig, vfo_t vfo, setting_t func, int status) return -RIG_ENAVAIL; } - // FTDX101D has 3 states 0,1,2 - snprintf(priv->cmd_str, sizeof(priv->cmd_str), "CT0%d%c", status , cat_term); + snprintf(priv->cmd_str, sizeof(priv->cmd_str), "CT0%d%c", status ? 1 : 0 , cat_term); if (rig->caps->targetable_vfo & RIG_TARGETABLE_TONE) { commit 056e0b2359ec67a373b649d50027b703483bfb8a Author: Michael Black W9MDB <mdb...@ya...> Date: Wed Nov 11 07:06:51 2020 -0600 Chance TSQL in newcat.c to allow more than 2 states FTDX101D has state=2 for encode-only diff --git a/include/hamlib/rig.h b/include/hamlib/rig.h index 040b953d..9d6aada6 100644 --- a/include/hamlib/rig.h +++ b/include/hamlib/rig.h @@ -1007,7 +1007,7 @@ typedef uint64_t setting_t; #define RIG_FUNC_COMP CONSTANT_64BIT_FLAG (2) /*!< \c COMP -- Speech Compression */ #define RIG_FUNC_VOX CONSTANT_64BIT_FLAG (3) /*!< \c VOX -- Voice Operated Relay */ #define RIG_FUNC_TONE CONSTANT_64BIT_FLAG (4) /*!< \c TONE -- CTCSS Tone */ -#define RIG_FUNC_TSQL CONSTANT_64BIT_FLAG (5) /*!< \c TSQL -- CTCSS Activate/De-activate */ +#define RIG_FUNC_TSQL CONSTANT_64BIT_FLAG (5) /*!< \c TSQL -- CTCSS Activate/De-activate and Encode-only value=2 if available */ #define RIG_FUNC_SBKIN CONSTANT_64BIT_FLAG (6) /*!< \c SBKIN -- Semi Break-in (CW mode) */ #define RIG_FUNC_FBKIN CONSTANT_64BIT_FLAG (7) /*!< \c FBKIN -- Full Break-in (CW mode) */ #define RIG_FUNC_ANF CONSTANT_64BIT_FLAG (8) /*!< \c ANF -- Automatic Notch Filter (DSP) */ diff --git a/rigs/yaesu/newcat.c b/rigs/yaesu/newcat.c index 354e6e88..fb81777f 100644 --- a/rigs/yaesu/newcat.c +++ b/rigs/yaesu/newcat.c @@ -4777,8 +4777,8 @@ int newcat_set_func(RIG *rig, vfo_t vfo, setting_t func, int status) return -RIG_ENAVAIL; } - snprintf(priv->cmd_str, sizeof(priv->cmd_str), "CT0%d%c", status ? 1 : 0, - cat_term); + // FTDX101D has 3 states 0,1,2 + snprintf(priv->cmd_str, sizeof(priv->cmd_str), "CT0%d%c", status , cat_term); if (rig->caps->targetable_vfo & RIG_TARGETABLE_TONE) { diff --git a/rigs/yaesu/newcat.h b/rigs/yaesu/newcat.h index a1e416f0..0ddbf4de 100644 --- a/rigs/yaesu/newcat.h +++ b/rigs/yaesu/newcat.h @@ -50,7 +50,7 @@ typedef char ncboolean; /* shared function version */ -#define NEWCAT_VER "20201103" +#define NEWCAT_VER "20201111" /* Hopefully large enough for future use, 128 chars plus '\0' */ #define NEWCAT_DATA_LEN 129 commit cabe9ea35466e72e99ec46d7dac2a4b578590e8f Merge: ff012234 81d02e22 Author: Michael Black <mdb...@ya...> Date: Tue Nov 10 14:20:42 2020 -0600 Merge pull request #437 from mikaelnousiainen/yaesu-filter-fixes Remove RIG_PASSBAND_ROOF commit 81d02e22f160e81032e7e5c2dfac5161cbe517f5 Author: Mikael Nousiainen <mik...@ik...> Date: Tue Nov 10 22:17:15 2020 +0200 Remove RIG_PASSBAND_ROOF as it was not necessary to use it diff --git a/include/hamlib/rig.h b/include/hamlib/rig.h index f0dbd038..040b953d 100644 --- a/include/hamlib/rig.h +++ b/include/hamlib/rig.h @@ -495,16 +495,13 @@ typedef unsigned int vfo_t; * \brief Macro for bandpass to be set to normal * \def RIG_PASSBAND_NORMAL */ -#define RIG_PASSBAND_NORMAL s_Hz(0) // was 0 but collided with Yaesu SH00; capability +#define RIG_PASSBAND_NORMAL s_Hz(0) /** * \brief Macro for bandpass to be left alone */ #define RIG_PASSBAND_NOCHANGE s_Hz(-1) -/** - * \brief Macro for selecting roofing filter on set_mode/width -- FTDX101D - */ -#define RIG_PASSBAND_ROOF s_Hz(-3) + /** * * \sa rig_passband_normal(), rig_passband_narrow(), rig_passband_wide() diff --git a/rigs/yaesu/newcat.c b/rigs/yaesu/newcat.c index cabb74e9..354e6e88 100644 --- a/rigs/yaesu/newcat.c +++ b/rigs/yaesu/newcat.c @@ -6503,6 +6503,8 @@ int newcat_set_rx_bandwidth(RIG *rig, vfo_t vfo, rmode_t mode, pbwidth_t width) main_sub_vfo = (RIG_VFO_SUB == vfo) ? '1' : '0'; } + // NOTE: RIG_PASSBAND_NORMAL (0) should select the default filter width (SH00) + if (is_ft950) { switch (mode) @@ -7045,7 +7047,7 @@ int newcat_set_rx_bandwidth(RIG *rig, vfo_t vfo, rmode_t mode, pbwidth_t width) case RIG_MODE_RTTYR: case RIG_MODE_CW: case RIG_MODE_CWR: - if (width == RIG_PASSBAND_ROOF) { w = 0; } + if (width == RIG_PASSBAND_NORMAL) { w = 0; } else if (width <= 50) { w = 1; } else if (width <= 100) { w = 2; } else if (width <= 150) { w = 3; } @@ -7068,7 +7070,7 @@ int newcat_set_rx_bandwidth(RIG *rig, vfo_t vfo, rmode_t mode, pbwidth_t width) case RIG_MODE_LSB: case RIG_MODE_USB: - if (width == RIG_PASSBAND_ROOF) { w = 0; } + if (width == RIG_PASSBAND_NORMAL) { w = 0; } else if (width <= 300) { w = 1; } else if (width <= 400) { w = 2; } else if (width <= 600) { w = 3; } commit ff012234435559fc5ecaf5b00c01e55547c95d4d Merge: f3cb1a09 4102e8c1 Author: Michael Black <mdb...@ya...> Date: Tue Nov 10 07:34:00 2020 -0600 Merge pull request #436 from mikaelnousiainen/yaesu-repeater-offset Implement Yaesu newcat repeater offset commands commit 4102e8c1e5157e71a1ac908ffcd4c24e6589f5bf Author: Mikael Nousiainen <mik...@ik...> Date: Tue Nov 10 10:20:51 2020 +0200 Yaesu newcat repeater offset step size confirmed on an FTDX 5000 diff --git a/rigs/yaesu/newcat.c b/rigs/yaesu/newcat.c index 4d8069c9..cabb74e9 100644 --- a/rigs/yaesu/newcat.c +++ b/rigs/yaesu/newcat.c @@ -1641,7 +1641,7 @@ int newcat_set_rptr_offs(RIG *rig, vfo_t vfo, shortfreq_t offs) return -RIG_EINVAL; } - // TODO: Confirm: Step size is 1 kHz or 10 kHz -- CAT documentation is difficult to interpret + // Step size is 1 kHz offs /= 1000; snprintf(priv->cmd_str, sizeof(priv->cmd_str), "%s%04li%c", command, offs, cat_term); @@ -1662,7 +1662,7 @@ int newcat_set_rptr_offs(RIG *rig, vfo_t vfo, shortfreq_t offs) return -RIG_EINVAL; } - // TODO: Confirm: Step size is 1 kHz or 10 kHz -- CAT documentation is difficult to interpret + // Step size is 1 kHz offs /= 1000; snprintf(priv->cmd_str, sizeof(priv->cmd_str), "%s%04li%c", command, offs, cat_term); @@ -1846,7 +1846,7 @@ int newcat_get_rptr_offs(RIG *rig, vfo_t vfo, shortfreq_t *offs) return RIG_OK; } - // TODO: Confirm: Step size is 1 kHz or 10 kHz -- CAT documentation is difficult to interpret + // Step size is 1 kHz step = 1000; } else if (is_ftdx5000) @@ -1866,7 +1866,7 @@ int newcat_get_rptr_offs(RIG *rig, vfo_t vfo, shortfreq_t *offs) return RIG_OK; } - // TODO: Confirm: Step size is 1 kHz or 10 kHz -- CAT documentation is difficult to interpret + // Step size is 1 kHz step = 1000; } else if (is_ftdx101) commit e122955213fc9f1e277add81bf07c71ef9c2d48d Author: Mikael Nousiainen <mik...@ik...> Date: Mon Nov 9 22:18:57 2020 +0200 Add repeater offset support for many Yaesu newcat rigs and fix FT-991 repeater offset step diff --git a/rigs/yaesu/ft1200.c b/rigs/yaesu/ft1200.c index 14dacd3f..f6af9d52 100644 --- a/rigs/yaesu/ft1200.c +++ b/rigs/yaesu/ft1200.c @@ -235,6 +235,8 @@ const struct rig_caps ftdx1200_caps = .mW2power = newcat_mW2power, .set_rptr_shift = newcat_set_rptr_shift, .get_rptr_shift = newcat_get_rptr_shift, + .set_rptr_offs = newcat_set_rptr_offs, + .get_rptr_offs = newcat_get_rptr_offs, .set_ctcss_tone = newcat_set_ctcss_tone, .get_ctcss_tone = newcat_get_ctcss_tone, .set_ctcss_sql = newcat_set_ctcss_sql, diff --git a/rigs/yaesu/ft2000.c b/rigs/yaesu/ft2000.c index af7a73d6..c33bcdfd 100644 --- a/rigs/yaesu/ft2000.c +++ b/rigs/yaesu/ft2000.c @@ -236,6 +236,8 @@ const struct rig_caps ft2000_caps = .mW2power = newcat_mW2power, .set_rptr_shift = newcat_set_rptr_shift, .get_rptr_shift = newcat_get_rptr_shift, + .set_rptr_offs = newcat_set_rptr_offs, + .get_rptr_offs = newcat_get_rptr_offs, .set_ctcss_tone = newcat_set_ctcss_tone, .get_ctcss_tone = newcat_get_ctcss_tone, .set_ctcss_sql = newcat_set_ctcss_sql, diff --git a/rigs/yaesu/ft3000.c b/rigs/yaesu/ft3000.c index 32f24550..dc416780 100644 --- a/rigs/yaesu/ft3000.c +++ b/rigs/yaesu/ft3000.c @@ -238,6 +238,8 @@ const struct rig_caps ftdx3000_caps = .mW2power = newcat_mW2power, .set_rptr_shift = newcat_set_rptr_shift, .get_rptr_shift = newcat_get_rptr_shift, + .set_rptr_offs = newcat_set_rptr_offs, + .get_rptr_offs = newcat_get_rptr_offs, .set_ctcss_tone = newcat_set_ctcss_tone, .get_ctcss_tone = newcat_get_ctcss_tone, .set_ctcss_sql = newcat_set_ctcss_sql, diff --git a/rigs/yaesu/ft450.c b/rigs/yaesu/ft450.c index 98857ed4..d0be5671 100644 --- a/rigs/yaesu/ft450.c +++ b/rigs/yaesu/ft450.c @@ -32,19 +32,13 @@ #include "hamlib/rig.h" #include "bandplan.h" -#include "serial.h" -#include "misc.h" -#include "yaesu.h" #include "newcat.h" #include "ft450.h" #include "idx_builtin.h" /* - * ft450 rigs capabilities. - * Also this struct is READONLY! - * + * FT-450 rig capabilities */ - const struct rig_caps ft450_caps = { RIG_MODEL(RIG_MODEL_FT450), @@ -192,6 +186,8 @@ const struct rig_caps ft450_caps = .mW2power = newcat_mW2power, .set_rptr_shift = newcat_set_rptr_shift, .get_rptr_shift = newcat_get_rptr_shift, + .set_rptr_offs = newcat_set_rptr_offs, + .get_rptr_offs = newcat_get_rptr_offs, .set_ctcss_tone = newcat_set_ctcss_tone, .get_ctcss_tone = newcat_get_ctcss_tone, .set_ctcss_sql = newcat_set_ctcss_sql, diff --git a/rigs/yaesu/ft5000.c b/rigs/yaesu/ft5000.c index cfb13e23..7928da03 100644 --- a/rigs/yaesu/ft5000.c +++ b/rigs/yaesu/ft5000.c @@ -233,6 +233,8 @@ const struct rig_caps ftdx5000_caps = .mW2power = newcat_mW2power, .set_rptr_shift = newcat_set_rptr_shift, .get_rptr_shift = newcat_get_rptr_shift, + .set_rptr_offs = newcat_set_rptr_offs, + .get_rptr_offs = newcat_get_rptr_offs, .set_ctcss_tone = newcat_set_ctcss_tone, .get_ctcss_tone = newcat_get_ctcss_tone, .set_ctcss_sql = newcat_set_ctcss_sql, diff --git a/rigs/yaesu/ft891.c b/rigs/yaesu/ft891.c index 3a73d4fb..f33e2652 100644 --- a/rigs/yaesu/ft891.c +++ b/rigs/yaesu/ft891.c @@ -215,6 +215,8 @@ const struct rig_caps ft891_caps = .mW2power = newcat_mW2power, .set_rptr_shift = newcat_set_rptr_shift, .get_rptr_shift = newcat_get_rptr_shift, + .set_rptr_offs = newcat_set_rptr_offs, + .get_rptr_offs = newcat_get_rptr_offs, .set_ctcss_tone = newcat_set_ctcss_tone, .get_ctcss_tone = newcat_get_ctcss_tone, .set_ctcss_sql = newcat_set_ctcss_sql, diff --git a/rigs/yaesu/ft950.c b/rigs/yaesu/ft950.c index 27bba7c0..bf30d435 100644 --- a/rigs/yaesu/ft950.c +++ b/rigs/yaesu/ft950.c @@ -262,6 +262,8 @@ const struct rig_caps ft950_caps = .mW2power = newcat_mW2power, .set_rptr_shift = newcat_set_rptr_shift, .get_rptr_shift = newcat_get_rptr_shift, + .set_rptr_offs = newcat_set_rptr_offs, + .get_rptr_offs = newcat_get_rptr_offs, .set_ctcss_tone = newcat_set_ctcss_tone, .get_ctcss_tone = newcat_get_ctcss_tone, .set_ctcss_sql = newcat_set_ctcss_sql, diff --git a/rigs/yaesu/ft991.c b/rigs/yaesu/ft991.c index e643c025..60568197 100644 --- a/rigs/yaesu/ft991.c +++ b/rigs/yaesu/ft991.c @@ -207,8 +207,8 @@ const struct rig_caps ft991_caps = .mW2power = newcat_mW2power, .set_rptr_shift = newcat_set_rptr_shift, .get_rptr_shift = newcat_get_rptr_shift, - .set_rptr_offs = newcat_set_rptr_offs, /*ve9gj */ - .get_rptr_offs = newcat_get_rptr_offs, /*ve9gj */ + .set_rptr_offs = newcat_set_rptr_offs, + .get_rptr_offs = newcat_get_rptr_offs, .set_ctcss_tone = ft991_set_ctcss_tone, .get_ctcss_tone = ft991_get_ctcss_tone, .set_dcs_code = ft991_set_dcs_code, diff --git a/rigs/yaesu/ftdx101.c b/rigs/yaesu/ftdx101.c index 75b3668a..c7f517fb 100644 --- a/rigs/yaesu/ftdx101.c +++ b/rigs/yaesu/ftdx101.c @@ -229,6 +229,8 @@ const struct rig_caps ftdx101d_caps = .mW2power = newcat_mW2power, .set_rptr_shift = newcat_set_rptr_shift, .get_rptr_shift = newcat_get_rptr_shift, + .set_rptr_offs = newcat_set_rptr_offs, + .get_rptr_offs = newcat_get_rptr_offs, .set_ctcss_tone = newcat_set_ctcss_tone, .get_ctcss_tone = newcat_get_ctcss_tone, .set_ctcss_sql = newcat_set_ctcss_sql, diff --git a/rigs/yaesu/newcat.c b/rigs/yaesu/newcat.c index 24e76019..4d8069c9 100644 --- a/rigs/yaesu/newcat.c +++ b/rigs/yaesu/newcat.c @@ -1492,21 +1492,91 @@ int newcat_set_rptr_offs(RIG *rig, vfo_t vfo, shortfreq_t offs) { struct newcat_priv_data *priv = (struct newcat_priv_data *)rig->state.priv; int err; - char command[16] ; - freq_t freq; + char command[32]; + freq_t freq = 0; rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__); - if (newcat_is_rig(rig, RIG_MODEL_FT991)) + err = newcat_get_freq(rig, vfo, &freq); // Need to get freq to determine band + if (err < 0) + { + return err; + } + + if (is_ft450) { - freq = 0; - err = newcat_get_freq(rig, vfo, &freq); // Need to get freq to determine band + strcpy(command, "EX050"); + + // Step size is 100 kHz + offs /= 100000; - if (err < 0) + snprintf(priv->cmd_str, sizeof(priv->cmd_str), "%s%03li%c", command, offs, cat_term); + } + else if (is_ft2000) + { + if (freq >= 28000000 && freq <= 29700000) { - return err; + strcpy(command, "EX076"); + } + else if (freq >= 50000000 && freq <= 54000000) + { + strcpy(command, "EX077"); + } + else + { + // only valid on 10m and 6m bands + return -RIG_EINVAL; } + // Step size is 1 kHz + offs /= 1000; + + snprintf(priv->cmd_str, sizeof(priv->cmd_str), "%s%04li%c", command, offs, cat_term); + } + else if (is_ft950) + { + if (freq >= 28000000 && freq <= 29700000) + { + strcpy(command, "EX057"); + } + else if (freq >= 50000000 && freq <= 54000000) + { + strcpy(command, "EX058"); + } + else + { + // only valid on 10m and 6m bands + return -RIG_EINVAL; + } + + // Step size is 1 kHz + offs /= 1000; + + snprintf(priv->cmd_str, sizeof(priv->cmd_str), "%s%04li%c", command, offs, cat_term); + } + else if (is_ft891) + { + if (freq >= 28000000 && freq <= 29700000) + { + strcpy(command, "EX0904"); + } + else if (freq >= 50000000 && freq <= 54000000) + { + strcpy(command, "EX0905"); + } + else + { + // only valid on 10m and 6m bands + return -RIG_EINVAL; + } + + // Step size is 1 kHz + offs /= 1000; + + snprintf(priv->cmd_str, sizeof(priv->cmd_str), "%s%04li%c", command, offs, cat_term); + } + else if (is_ft991) + { if (freq >= 28000000 && freq <= 29700000) { strcpy(command, "EX080"); @@ -1526,15 +1596,104 @@ int newcat_set_rptr_offs(RIG *rig, vfo_t vfo, shortfreq_t offs) else { // only valid on 10m to 70cm bands - return RIG_OK; + return -RIG_EINVAL; } - snprintf(priv->cmd_str, sizeof(priv->cmd_str), "%s%04li%c", command, offs, - cat_term); - return newcat_set_cmd(rig); + // Step size is 1 kHz + offs /= 1000; + + snprintf(priv->cmd_str, sizeof(priv->cmd_str), "%s%04li%c", command, offs, cat_term); } + else if (is_ftdx1200) + { + if (freq >= 28000000 && freq <= 29700000) + { + strcpy(command, "EX087"); + } + else if (freq >= 50000000 && freq <= 54000000) + { + strcpy(command, "EX088"); + } + else + { + // only valid on 10m and 6m bands + return -RIG_EINVAL; + } - return -RIG_ENAVAIL; + // Step size is 1 kHz + offs /= 1000; + + snprintf(priv->cmd_str, sizeof(priv->cmd_str), "%s%04li%c", command, offs, cat_term); + } + else if (is_ftdx3000) + { + if (freq >= 28000000 && freq <= 29700000) + { + strcpy(command, "EX086"); + } + else if (freq >= 50000000 && freq <= 54000000) + { + strcpy(command, "EX087"); + } + else + { + // only valid on 10m and 6m bands + return -RIG_EINVAL; + } + + // TODO: Confirm: Step size is 1 kHz or 10 kHz -- CAT documentation is difficult to interpret + offs /= 1000; + + snprintf(priv->cmd_str, sizeof(priv->cmd_str), "%s%04li%c", command, offs, cat_term); + } + else if (is_ftdx5000) + { + if (freq >= 28000000 && freq <= 29700000) + { + strcpy(command, "EX081"); + } + else if (freq >= 50000000 && freq <= 54000000) + { + strcpy(command, "EX082"); + } + else + { + // only valid on 10m and 6m bands + return -RIG_EINVAL; + } + + // TODO: Confirm: Step size is 1 kHz or 10 kHz -- CAT documentation is difficult to interpret + offs /= 1000; + + snprintf(priv->cmd_str, sizeof(priv->cmd_str), "%s%04li%c", command, offs, cat_term); + } + else if (is_ftdx101) + { + if (freq >= 28000000 && freq <= 29700000) + { + strcpy(command, "EX010315"); + } + else if (freq >= 50000000 && freq <= 54000000) + { + strcpy(command, "EX010316"); + } + else + { + // only valid on 10m and 6m bands + return -RIG_EINVAL; + } + + // Step size is 1 kHz + offs /= 1000; + + snprintf(priv->cmd_str, sizeof(priv->cmd_str), "%s%04li%c", command, offs, cat_term); + } + else + { + return -RIG_ENAVAIL; + } + + return newcat_set_cmd(rig); } @@ -1544,20 +1703,86 @@ int newcat_get_rptr_offs(RIG *rig, vfo_t vfo, shortfreq_t *offs) int err; int ret_data_len; char *retoffs; - freq_t freq; + freq_t freq = 0; + int step; rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__); - if (newcat_is_rig(rig, RIG_MODEL_FT991)) + err = newcat_get_freq(rig, vfo, &freq); // Need to get freq to determine band + if (err < 0) + { + return err; + } + + if (is_ft450) { - freq = 0; - err = newcat_get_freq(rig, vfo, &freq); // Need to get freq to determine band + snprintf(priv->cmd_str, sizeof(priv->cmd_str), "EX050%c", cat_term); - if (err < 0) + // Step size is 100 kHz + step = 100000; + } + else if (is_ft2000) + { + if (freq >= 28000000 && freq <= 29700000) { - return err; + snprintf(priv->cmd_str, sizeof(priv->cmd_str), "EX076%c", cat_term); + } + else if (freq >= 50000000 && freq <= 54000000) + { + snprintf(priv->cmd_str, sizeof(priv->cmd_str), "EX077%c", cat_term); + } + else + { + // only valid on 10m and 6m bands + *offs = 0; + return RIG_OK; } + // Step size is 1 kHz + step = 1000; + } + else if (is_ft950) + { + if (freq >= 28000000 && freq <= 29700000) + { + snprintf(priv->cmd_str, sizeof(priv->cmd_str), "EX057%c", cat_term); + } + else if (freq >= 50000000 && freq <= 54000000) + { + snprintf(priv->cmd_str, sizeof(priv->cmd_str), "EX058%c", cat_term); + } + else + { + // only valid on 10m and 6m bands + *offs = 0; + return RIG_OK; + } + + // Step size is 1 kHz + step = 1000; + } + else if (is_ft891) + { + if (freq >= 28000000 && freq <= 29700000) + { + snprintf(priv->cmd_str, sizeof(priv->cmd_str), "EX0904%c", cat_term); + } + else if (freq >= 50000000 && freq <= 54000000) + { + snprintf(priv->cmd_str, sizeof(priv->cmd_str), "EX0905%c", cat_term); + } + else + { + // only valid on 10m and 6m bands + *offs = 0; + return RIG_OK; + } + + // Step size is 1 kHz + step = 1000; + } + else if (is_ft991) + { if (freq >= 28000000 && freq <= 29700000) { snprintf(priv->cmd_str, sizeof(priv->cmd_str), "EX080%c", cat_term); @@ -1576,28 +1801,114 @@ int newcat_get_rptr_offs(RIG *rig, vfo_t vfo, shortfreq_t *offs) } else { - *offs = 0; // only valid on 10m to 70cm bands + // only valid on 10m to 70cm bands + *offs = 0; return RIG_OK; } - if (RIG_OK != (err = newcat_get_cmd(rig))) + // Step size is 1 kHz + step = 1000; + } + else if (is_ftdx1200) + { + if (freq >= 28000000 && freq <= 29700000) { - return err; + snprintf(priv->cmd_str, sizeof(priv->cmd_str), "EX087%c", cat_term); + } + else if (freq >= 50000000 && freq <= 54000000) + { + snprintf(priv->cmd_str, sizeof(priv->cmd_str), "EX088%c", cat_term); + } + else + { + // only valid on 10m and 6m bands + *offs = 0; + return RIG_OK; + } + + // Step size is 1 kHz + step = 1000; + } + else if (is_ftdx3000) + { + if (freq >= 28000000 && freq <= 29700000) + { + snprintf(priv->cmd_str, sizeof(priv->cmd_str), "EX086%c", cat_term); + } + else if (freq >= 50000000 && freq <= 54000000) + { + snprintf(priv->cmd_str, sizeof(priv->cmd_str), "EX087%c", cat_term); + } + else + { + // only valid on 10m and 6m bands + *offs = 0; + return RIG_OK; + } + + // TODO: Confirm: Step size is 1 kHz or 10 kHz -- CAT documentation is difficult to interpret + step ... [truncated message content] |