[Hamlib-commits] Hamlib -- Ham radio control libraries branch master updated. e59a7f09717406eef1842
Library to control radio transceivers and receivers
Brought to you by:
n0nb
From: Nate B. <n0...@us...> - 2021-02-19 02:44:06
|
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 e59a7f09717406eef184279920c5b657008ac2e2 (commit) via 7d31ab8823e4028ee0dd7918e0b1c076c1fcc8b8 (commit) via 8f5185bff8f7036111b3de3f95fe3434f6adb9d0 (commit) via fb3e3d11aa0ce7cfdbbd6026774e5d39c58095b5 (commit) via b8c9871b232e3de07823d877548381d90db2f747 (commit) via 185a938a7659fdca69ef5b5d8e7b5faf909f0b80 (commit) via 636d64d114bd29fe75d8a27ebfbdbdaa4219b7bf (commit) via bd2384e55ea5ef311ca750791a5b51ca3dd45b2c (commit) via aef70172f087e2518529cc48351ae65a731dc0de (commit) via 06723c959bb768d1f62a0c6b5eecc394b86597c7 (commit) via 1e9a991a2555a497a19678ad2dc6807a8bd9000f (commit) via 8f1efb6a70fd4cee5b619d8c4ca71339183b301e (commit) via 6766948dc1ee6082fb599728a23d8376797a7126 (commit) via 64e88e24612ce3f900cd50210b143c9a6fdbc016 (commit) via 5964e1de18f7ac77560e4f391f30cb14b98cfbb7 (commit) via 41f3fb5ce26d17bff663f8e445645a3f1170fa27 (commit) from 5ec2c5b4c64df45734986c29df77e62f3ce14d94 (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 e59a7f09717406eef184279920c5b657008ac2e2 Author: Michael Black W9MDB <mdb...@ya...> Date: Thu Feb 18 17:11:55 2021 -0600 Update JTSDK build instructions diff --git a/scripts/README.build-JTSDK.txt b/scripts/README.build-JTSDK.txt index b70dd946..5cd9333d 100644 --- a/scripts/README.build-JTSDK.txt +++ b/scripts/README.build-JTSDK.txt @@ -2,89 +2,94 @@ JTSDK DLL Qt MinGW/MSYS2 Supplementary Notes ============================================================== -This assumes you have an environment set up that conforms with -instructions in the WSJT-X Install notes that will build Hamlib +These instructions should work with JTSDk 3.2.0 Beta 3 and later. -Before you start.... RTFM at <hamlib-base>/scripts/README.build-Windows-JTSDK.txt +The JTSDK 3.2.0 Stream (and later) is available at +https://sourceforge.net/projects/hamlib-sdk/files/Windows/ +Future updates to the JTSDK may implement these steps into the +MSYS2 "menu" command. -1. Update Environ -================= -pacman -Syuu +1. Update Environment +===================== + +$ pacman -Syuu 2. Deploy MinGW =============== -Ensure that the ZIP, DOS2UNIX and GROFF packages are deployed -to and owrking in the MSYS2 Environment +Ensure that the 'zip' , 'dos2unix' and 'groff' packages are deployed +to and working in the MSYS2 Environment + +** Versions of JTSDK 3.2.0 Beta 4 and later will incorporate ** +** deployment of these tools into the Setup scripts. ** -pacman -S zip -pacman -S dos2unix -alias unix2dos='todos' -pacman -S groff +$ pacman -S zip +$ pacman -S dos2unix +$ pacman -S groff -The next step is possibly redudnant as it has been incorporated -into build-w64-jtsdk.sh +** The next step may be redundant as it has been incorporated ** +** into build-w64-jtsdk.sh ** -export PATH=$PATH:$GCCD_F:. +$ export PATH=$PATH:$GCCD_F:. 3. Create a dir $HOME/Builds ============================ -Open a MSYS2 Terminal fro a jtsdk64.ps1 environment +Open a MSYS2 Terminal from a jtsdk64.ps1 environment -In a JTSDK63 ENvironment type: +In a JTSDK PowerShell Environment launch MSYS2 with: msys2 -In the msys2 enviro nment type: +In the MSYS2 environment type: -cd ~ <== ensure you at home -mkdir builds -cd builds +$ cd ~ <== ensure you at home +$ mkdir builds +$ cd builds 4. Locate and unzip LibUSB matching version deployed above into builds ====================================================================== -These steps in the original build-w64.sh script are redundant. +** These steps in the original build-w64.sh script are redundant ** -You may skip this step. +** You should familiarise yourself with these steps - but may skip this ** JTSDK 3.2.0 (and later) points the environment to the libusb deployment in X:\JTSDK64-Tools\tools\libusb through environment variable $libusb_dir_f . -If you need the source for LinUSB use steps similar to those +If you need the source for LibUSB use steps similar to those below to obtain source: -wget https://sourceforge.net/projects/libusb/files/libusb-1.0/libusb-1.0.24/libusb-1.0.24.tar.bz2 -tar -xvf libusb-1.0.24.tar.bz2 +$ wget https://sourceforge.net/projects/libusb/files/libusb-1.0/libusb-1.0.24/libusb-1.0.24.tar.bz2 +$ tar -xvf libusb-1.0.24.tar.bz2 [ This creates a subdirectory libusb-1.0.24 ] -5. Obtain latest Hamlib sourceforge -=================================== +5. Obtain latest Hamlib Source from Github +========================================== -git clone git://git.code.sf.net/p/hamlib/code hamlib-4.2~git +$ git clone https://github.com/Hamlib/Hamlib.git hamlib-4.2~git 6. Start the Process Rolling ============================ -cd ./hamlib-4.2~git -./bootstrap <== Not included in Nate's notes ! -./scripts/build-w64-jtsdk.sh hamlib-4.2~git +$ cd ./hamlib-4.2~git +$ ./bootstrap +$ ./scripts/build-w64-jtsdk.sh hamlib-4.2~git 7. Tadaa - Drumroll ! ===================== -==> Package in ~/build/hamlib-4.2~git/hamlib-w64-4.2~git as hamlib-w64-4.2~git.zip -==> Headers in ~/build/hamlib-4.2~git/hamlib-w64-4.2~git/include -==> Library in ~/build/hamlib-4.2~git/hamlib-w64-4.2~git/lib/gcc as libhamlib.dll.a (rename to libhamlib.dll for application) +==> Package ......... ~/build/hamlib-4.2~git/hamlib-w64-4.2~git ==> hamlib-w64-4.2~git.zip +==> Headers ......... ~/build/hamlib-4.2~git/hamlib-w64-4.2~git/include +==> Library &tools .. ~/build/hamlib-4.2~git/hamlib-w64-4.2~git/bin commit 7d31ab8823e4028ee0dd7918e0b1c076c1fcc8b8 Author: Michael Black W9MDB <mdb...@ya...> Date: Thu Feb 18 14:36:39 2021 -0600 Update JTSDK build script and README diff --git a/scripts/README.build-JTSDK.txt b/scripts/README.build-JTSDK.txt new file mode 100644 index 00000000..b70dd946 --- /dev/null +++ b/scripts/README.build-JTSDK.txt @@ -0,0 +1,90 @@ +============================================================== +JTSDK DLL Qt MinGW/MSYS2 Supplementary Notes +============================================================== + +This assumes you have an environment set up that conforms with +instructions in the WSJT-X Install notes that will build Hamlib + +Before you start.... RTFM at <hamlib-base>/scripts/README.build-Windows-JTSDK.txt + + +1. Update Environ +================= + +pacman -Syuu + + +2. Deploy MinGW +=============== + +Ensure that the ZIP, DOS2UNIX and GROFF packages are deployed +to and owrking in the MSYS2 Environment + +pacman -S zip +pacman -S dos2unix +alias unix2dos='todos' +pacman -S groff + +The next step is possibly redudnant as it has been incorporated +into build-w64-jtsdk.sh + +export PATH=$PATH:$GCCD_F:. + + +3. Create a dir $HOME/Builds +============================ + +Open a MSYS2 Terminal fro a jtsdk64.ps1 environment + +In a JTSDK63 ENvironment type: + +msys2 + +In the msys2 enviro nment type: + +cd ~ <== ensure you at home +mkdir builds +cd builds + + +4. Locate and unzip LibUSB matching version deployed above into builds +====================================================================== + +These steps in the original build-w64.sh script are redundant. + +You may skip this step. + +JTSDK 3.2.0 (and later) points the environment to the libusb +deployment in X:\JTSDK64-Tools\tools\libusb through +environment variable $libusb_dir_f . + +If you need the source for LinUSB use steps similar to those +below to obtain source: + +wget https://sourceforge.net/projects/libusb/files/libusb-1.0/libusb-1.0.24/libusb-1.0.24.tar.bz2 +tar -xvf libusb-1.0.24.tar.bz2 + +[ This creates a subdirectory libusb-1.0.24 ] + + +5. Obtain latest Hamlib sourceforge +=================================== + +git clone git://git.code.sf.net/p/hamlib/code hamlib-4.2~git + + +6. Start the Process Rolling +============================ + +cd ./hamlib-4.2~git +./bootstrap <== Not included in Nate's notes ! +./scripts/build-w64-jtsdk.sh hamlib-4.2~git + + +7. Tadaa - Drumroll ! +===================== + +==> Package in ~/build/hamlib-4.2~git/hamlib-w64-4.2~git as hamlib-w64-4.2~git.zip +==> Headers in ~/build/hamlib-4.2~git/hamlib-w64-4.2~git/include +==> Library in ~/build/hamlib-4.2~git/hamlib-w64-4.2~git/lib/gcc as libhamlib.dll.a (rename to libhamlib.dll for application) + diff --git a/scripts/build-w64-jtsdk.sh b/scripts/build-w64-jtsdk.sh index 714b7539..c57a1f74 100755 --- a/scripts/build-w64-jtsdk.sh +++ b/scripts/build-w64-jtsdk.sh @@ -1,14 +1,17 @@ #!/bin/sh -# Builds Hamlib 4.x W64 binary distribution. +# Builds Hamlib 4.x W64 dl binary distribution under Windows Qt MinGW/MSYS2 +# Customised for >= JTSDK 3.2.0 B3 stream(s) -# A script to build a set of W64 binary DLLs and executables from a Hamlib -# source tarball. This script assumes that the Hamlib source tarball has been -# extracted to the directory specified in $BUILD_DIR and that libusb-1.x.y has -# also been extracted to $BUILD_DIR. +# A script to compile a set of W64 binary DLLs, executables and compiler +# packages from a Hamlib source tarball. This script assumes uses the +# JTSDK's previously deployed LibUSB (pointed to by JTSDK environment +# variable $libusb_dir_f) -# See README.build-Windows for complete details. +# See future README.build-JTSDK for complete details. +#Ensure that the Qt-supplied GCC compilers and tools can be found +export PATH=$PATH:$GCCD_F:. # Set this to a desired directory BUILD_DIR=~/builds @@ -22,6 +25,9 @@ HOST_ARCH=x86_64-w64-mingw32 # Set to the strip name for your version of minGW HOST_ARCH_STRIP=strip.exe +# Set to the name of the utility to provide Unix to DOS translation +UNIX_TO_DOS_TOOL=unix2dos.exe + # Error return codes. See /usr/include/sysexits.h EX_USAGE=64 EX_NOINPUT=66 @@ -68,7 +74,7 @@ What is it? =========== This ZIP archive or Windows installer contains a build of Hamlib-$RELEASE -cross-compiled for MS Windows 64 bit using MinGW under Debian GNU/Linux 10 +native compiled for MS Windows 64 bit using MinGW under Windows JTSDK 3.2.0 (nice, heh!). This software is copyrighted. The library license is LGPL, and the *.EXE files @@ -82,8 +88,8 @@ included after being converted to HTML. Installation and Configuration ============================== -Extract the ZIP archive into a convenient location, C:\Program Files is a -reasonable choice. +Extract the ZIP archive into a convenient location, C:\Program Files (being x64) +is a reasonable choice. Make sure *all* the .DLL files are in your PATH (leave them in the bin directory and set the PATH). To set the PATH environment variable in Windows @@ -211,6 +217,7 @@ Please report problems or success to ham...@li... Cheers, Stephane Fillod - F8CFE Nate Bargmann - N0NB +JTSDK Maintenance Team - JT...@GR... http://www.hamlib.org END_OF_README @@ -230,9 +237,9 @@ make -j 4 install mkdir -p ${ZIP_DIR}/bin ${ZIP_DIR}/lib/msvc ${ZIP_DIR}/lib/gcc ${ZIP_DIR}/include ${ZIP_DIR}/doc cp -a src/libhamlib.def ${ZIP_DIR}/lib/msvc/libhamlib-4.def -unix2dos ${ZIP_DIR}/lib/msvc/libhamlib-4.def +${UNIX_TO_DOS_TOOL} ${ZIP_DIR}/lib/msvc/libhamlib-4.def cp -a ${INST_DIR}/include/hamlib ${ZIP_DIR}/include/. -unix2dos ${ZIP_DIR}/include/hamlib/*.h +${UNIX_TO_DOS_TOOL} ${ZIP_DIR}/include/hamlib/*.h # C++ binding is useless on w64 because of ABI for f in *class.h @@ -243,7 +250,7 @@ done for f in AUTHORS ChangeLog COPYING COPYING.LIB LICENSE README README.betatester README.w64-bin THANKS do cp -a ${f} ${ZIP_DIR}/${f}.txt - unix2dos ${ZIP_DIR}/${f}.txt + ${UNIX_TO_DOS_TOOL} ${ZIP_DIR}/${f}.txt done # Generate HTML documents from nroff formatted man files @@ -271,8 +278,8 @@ ${HOST_ARCH_STRIP} ${ZIP_DIR}/bin/*.exe ${ZIP_DIR}/bin/*hamlib-*.dll cp -a ${QTD_F}/libwinpthread-1.dll ${ZIP_DIR}/bin/. cp -a ${libusb_dir_f}/MinGW64/dll/libusb-1.0.dll ${ZIP_DIR}/bin/libusb-1.0.dll -# Set for MinGW build -FILE="${QTD_F}/libgcc_s_sjlj-1.dll" +# Set for MinGW build - To Be safe ! +FILE="${QTD_F}/libgcc_s_seh-1.dll" if test -f "$FILE" then cp -a ${FILE} ${ZIP_DIR}/bin/. commit 8f5185bff8f7036111b3de3f95fe3434f6adb9d0 Author: Michael Black W9MDB <mdb...@ya...> Date: Thu Feb 18 14:20:21 2021 -0600 Change FTDX3000 antenna commands to use AN instead of menu commands that don't work https://github.com/Hamlib/Hamlib/issues/510 diff --git a/rigs/yaesu/ft3000.c b/rigs/yaesu/ft3000.c index da25ee41..3fbc3575 100644 --- a/rigs/yaesu/ft3000.c +++ b/rigs/yaesu/ft3000.c @@ -95,16 +95,16 @@ int ft3000_set_ant(RIG *rig, vfo_t vfo, ant_t ant, value_t option) switch (ant) { case 1: - cmd = "EX0321;"; // R3/1 ANT1/ANT3 + cmd = "AN01;"; // R3/1 ANT1/ANT3 break; case 2: - cmd = "EX0322;"; // RE/2 ANT2/ANT3 + cmd = "AN02;"; // RE/2 ANT2/ANT3 break; case 3: - cmd = "EX0320;"; // TRX ANT3 + cmd = "AN03;"; // TRX ANT3 break; default: - rig_debug(RIG_DEBUG_ERR, "%s: expected 3,4,5 got %d\n", __func__, ant); + rig_debug(RIG_DEBUG_ERR, "%s: expected 1,2,3 got %d\n", __func__, ant); RETURNFUNC(-RIG_EINVAL); } snprintf(priv->cmd_str, sizeof(priv->cmd_str), "%s", cmd); @@ -126,7 +126,7 @@ int ft3000_get_ant(RIG *rig, vfo_t vfo, ant_t dummy, value_t *option, option->i = 0; // default to no options // find out what ANT3 setting - snprintf(priv->cmd_str, sizeof(priv->cmd_str), "%s", "EX032;"); + snprintf(priv->cmd_str, sizeof(priv->cmd_str), "%s", "AN0;"); if (RIG_OK != (err = newcat_get_cmd(rig))) { RETURNFUNC(err); @@ -134,12 +134,9 @@ int ft3000_get_ant(RIG *rig, vfo_t vfo, ant_t dummy, value_t *option, if (strlen(priv->ret_data) >= 7) { - char c = priv->ret_data[5]; + char c = priv->ret_data[3]; switch(c) { - case '0': - *ant_rx = *ant_tx = RIG_ANT_3; - break; case '1': *ant_rx = RIG_ANT_3; *ant_tx = RIG_ANT_1; @@ -148,6 +145,9 @@ int ft3000_get_ant(RIG *rig, vfo_t vfo, ant_t dummy, value_t *option, *ant_rx = RIG_ANT_3; *ant_tx = RIG_ANT_2; break; + case '3': + *ant_rx = *ant_tx = RIG_ANT_3; + break; default: rig_debug(RIG_DEBUG_ERR, "%s: unknown antenna=%c\n", __func__, c); RETURNFUNC(-RIG_EPROTO); commit fb3e3d11aa0ce7cfdbbd6026774e5d39c58095b5 Author: Michael Black W9MDB <mdb...@ya...> Date: Thu Feb 18 12:52:33 2021 -0600 Fix FT3000 set_ant https://www.dropbox.com/s/2lqh0mp13244d9z/wsjtx-2.4.0-rc1-win64.exe?dl=0 diff --git a/rigs/yaesu/ft3000.c b/rigs/yaesu/ft3000.c index 761645c0..da25ee41 100644 --- a/rigs/yaesu/ft3000.c +++ b/rigs/yaesu/ft3000.c @@ -95,13 +95,13 @@ int ft3000_set_ant(RIG *rig, vfo_t vfo, ant_t ant, value_t option) switch (ant) { case 1: - cmd = "EX0321"; // R3/1 ANT1/ANT3 + cmd = "EX0321;"; // R3/1 ANT1/ANT3 break; case 2: - cmd = "EX0322"; // RE/2 ANT2/ANT3 + cmd = "EX0322;"; // RE/2 ANT2/ANT3 break; case 3: - cmd = "EX0320"; // TRX ANT3 + cmd = "EX0320;"; // TRX ANT3 break; default: rig_debug(RIG_DEBUG_ERR, "%s: expected 3,4,5 got %d\n", __func__, ant); @@ -171,7 +171,7 @@ const struct rig_caps ftdx3000_caps = RIG_MODEL(RIG_MODEL_FTDX3000), .model_name = "FTDX-3000", .mfg_name = "Yaesu", - .version = NEWCAT_VER ".3", + .version = NEWCAT_VER ".4", .copyright = "LGPL", .status = RIG_STATUS_STABLE, .rig_type = RIG_TYPE_TRANSCEIVER, commit b8c9871b232e3de07823d877548381d90db2f747 Author: Michael Black W9MDB <mdb...@ya...> Date: Thu Feb 18 11:54:23 2021 -0600 Fix compile error diff --git a/NEWS b/NEWS index 251a56f4..85782a0b 100644 --- a/NEWS +++ b/NEWS @@ -6,6 +6,13 @@ Copyright (C) 2000-2021 Michael Black W9MDB, and others Please send Hamlib bug reports to ham...@li... +Version 4.3 + Add twiddle_timeout and twiddle_rit --set-conf options + rigctld --set-conf=twiddle_timeout=5,twiddle_rit=1 + This will set the twiddle timeout to 5 seconds and turn on twiddle_rit + For twiddle timeout VFOB will not be poller for 5 seconds after VFO twiddling is detected + rigctld --twiddle is deprecated and will be removed in 5.0 + Version 4.2 2021-??-?? * Major rework for PRM80 commit 185a938a7659fdca69ef5b5d8e7b5faf909f0b80 Author: Michael Black W9MDB <mdb...@ya...> Date: Thu Feb 18 11:15:02 2021 -0600 Add twiddle_timeout and twiddle_rit --set-conf options rigctld --set-conf=twiddle_timeout=5,twiddle_rit=1 This will set the twiddle timeout to 5 seconds and turn on twiddle_rit For twiddle timeout VFOB will not be poller for 5 seconds after VFO twiddling is detected. For RIT VFOB get_freq is suppressed and returns the cached value only (set_freq on VFOB still works). rigctld --twiddle is deprecated and will be removed in 5.0 https://github.com/Hamlib/Hamlib/issues/444 diff --git a/src/conf.c b/src/conf.c index 40b096f2..685979bc 100644 --- a/src/conf.c +++ b/src/conf.c @@ -153,6 +153,16 @@ static const struct confparams frontend_cfg_params[] = "True enables flushing serial port with read instead of TCFLUSH -- MicroHam", "0", RIG_CONF_CHECKBUTTON, { } }, + { + TOK_TWIDDLE_TIMEOUT, "twiddle_timeout", "Timeout(secs) to resume VFO polling when twiddling VFO", + "For satellite ops when VFOB is twiddled will pause VFOB commands until timeout", + "Unset", RIG_CONF_COMBO, { .c = {{ "Unset", "ON", "OFF", NULL }} } + }, + { + TOK_TWIDDLE_RIT, "twiddle_rit", "RIT twiddle", + "Suppress get_freq on VFOB for RIT tuning satellites", + "Unset", RIG_CONF_COMBO, { .c = {{ "Unset", "ON", "OFF", NULL }} } + }, { RIG_CONF_END, NULL, } }; @@ -622,6 +632,22 @@ static int frontend_set_conf(RIG *rig, token_t token, const char *val) rs->rigport.flushx = val_i ? 1 : 0; break; + case TOK_TWIDDLE_TIMEOUT: + if (1 != sscanf(val, "%d", &val_i)) + { + return -RIG_EINVAL; //value format error + } + rs->twiddle_timeout = val_i; + break; + + case TOK_TWIDDLE_RIT: + if (1 != sscanf(val, "%d", &val_i)) + { + return -RIG_EINVAL; //value format error + } + rs->twiddle_rit = val_i ? 1: 0; + break; + default: return -RIG_EINVAL; } @@ -954,6 +980,14 @@ static int frontend_get_conf(RIG *rig, token_t token, char *val) sprintf(val, "%d", rs->disable_yaesu_bandselect); break; + case TOK_TWIDDLE_TIMEOUT: + sprintf(val, "%d", rs->twiddle_timeout); + break; + + case TOK_TWIDDLE_RIT: + sprintf(val, "%d", rs->twiddle_rit); + break; + default: return -RIG_EINVAL; diff --git a/src/token.h b/src/token.h index 2ae86f89..e12f1e28 100644 --- a/src/token.h +++ b/src/token.h @@ -114,6 +114,10 @@ #define TOK_AUTO_DISABLE_SCREENSAVER TOKEN_FRONTEND(125) /** \brief rig: Disable Yaesu band select logic */ #define TOK_DISABLE_YAESU_BANDSELECT TOKEN_FRONTEND(126) +/** \brief rig: Supporess get_freq on VFOB for satellite RIT tuning */ +#define TOK_TWIDDLE_TIMEOUT TOKEN_FRONTEND(127) +/** \brief rig: Supporess get_freq on VFOB for satellite RIT tuning */ +#define TOK_TWIDDLE_RIT TOKEN_FRONTEND(128) /* * rotator specific tokens * (strictly, should be documented as rotator_internal) diff --git a/tests/rigctld.c b/tests/rigctld.c index 0eb62900..e65efc97 100644 --- a/tests/rigctld.c +++ b/tests/rigctld.c @@ -107,7 +107,6 @@ static struct option long_options[] = {"help", 0, 0, 'h'}, {"version", 0, 0, 'V'}, {"twiddle_timeout", 1, 0, 'W'}, - {"twiddle_rit" , 0, 0, 'Y'}, {"uplink", 1, 0, 'x'}, {"debug-time-stamps", 0, 0, 'Z'}, {0, 0, 0, 0} @@ -248,8 +247,7 @@ int main(int argc, char *argv[]) struct addrinfo hints, *result, *saved_result; int sock_listen; int reuseaddr = 1; - int twiddle = 0; - int twiddle_rit = 0; + int twiddle_timeout = 0; int uplink = 0; char host[NI_MAXHOST]; char serv[NI_MAXSERV]; @@ -524,11 +522,8 @@ int main(int argc, char *argv[]) exit(1); } - twiddle = atoi(optarg); - break; - - case 'Y': - twiddle_rit=1; + twiddle_timeout = atoi(optarg); + fprintf(stderr,"twiddle_timeout is deprecated...use e.g. --set-conf=twiddle_timeout=5\n"); break; case 'x': @@ -590,8 +585,7 @@ int main(int argc, char *argv[]) strncpy(my_rig->state.rigport.pathname, rig_file, FILPATHLEN - 1); } - my_rig->state.twiddle_timeout = twiddle; - my_rig->state.twiddle_rit = twiddle_rit; + my_rig->state.twiddle_timeout = twiddle_timeout; my_rig->state.uplink = uplink; rig_debug(RIG_DEBUG_TRACE, "%s: twiddle=%d, uplink=%d, twiddle_rit=%d\n", __func__, my_rig->state.twiddle_timeout, my_rig->state.uplink, my_rig->state.twiddle_rit); commit 636d64d114bd29fe75d8a27ebfbdbdaa4219b7bf Author: Michael Black W9MDB <mdb...@ya...> Date: Thu Feb 18 07:11:03 2021 -0600 Fix compile warning try#2 in rigctl_parse.c diff --git a/tests/rigctl_parse.c b/tests/rigctl_parse.c index bb8ce821..1d7440df 100644 --- a/tests/rigctl_parse.c +++ b/tests/rigctl_parse.c @@ -722,7 +722,7 @@ int rigctl_parse(RIG *my_rig, FILE *fin, FILE *fout, char *argv[], int argc, /* command by name */ if (cmd == '\\') { - unsigned char cmd_name[MAXNAMSIZ], *pcmd = cmd_name; + char cmd_name[MAXNAMSIZ], *pcmd = cmd_name; if (scanfc(fin, "%c", pcmd) < 1) { @@ -730,7 +730,8 @@ int rigctl_parse(RIG *my_rig, FILE *fin, FILE *fout, char *argv[], int argc, return -1; } - (void)fscanf(fin, "%s", ++pcmd); + retcode = fscanf(fin, "%s", ++pcmd); + if (retcode == 0) rig_debug(RIG_DEBUG_WARN, "%s: unable to scan %c\n", __func__, *(pcmd-1)); while(*++pcmd); *pcmd = '\0'; commit bd2384e55ea5ef311ca750791a5b51ca3dd45b2c Author: Michael Black W9MDB <mdb...@ya...> Date: Thu Feb 18 07:04:21 2021 -0600 Fix compile warning in rigctl_parse.c diff --git a/tests/rigctl_parse.c b/tests/rigctl_parse.c index a33e9fcb..bb8ce821 100644 --- a/tests/rigctl_parse.c +++ b/tests/rigctl_parse.c @@ -730,7 +730,7 @@ int rigctl_parse(RIG *my_rig, FILE *fin, FILE *fout, char *argv[], int argc, return -1; } - fscanf(fin, "%s", ++pcmd); + (void)fscanf(fin, "%s", ++pcmd); while(*++pcmd); *pcmd = '\0'; commit aef70172f087e2518529cc48351ae65a731dc0de Author: Michael Black W9MDB <mdb...@ya...> Date: Thu Feb 18 06:57:40 2021 -0600 Add twiddle_rit rig option https://github.com/Hamlib/Hamlib/issues/444 diff --git a/include/hamlib/rig.h b/include/hamlib/rig.h index b943901f..b49b3620 100644 --- a/include/hamlib/rig.h +++ b/include/hamlib/rig.h @@ -2205,6 +2205,7 @@ struct rig_state { int power_min; /*!< Minimum RF power level in rig units */ int power_max; /*!< Maximum RF power level in rig units */ unsigned char disable_yaesu_bandselect; /*!< Disables Yaeus band select logic */ + int twiddle_rit; /*!< Suppresses VFOB reading (cached value used) so RIT control can be used */ }; //! @cond Doxygen_Suppress commit 06723c959bb768d1f62a0c6b5eecc394b86597c7 Author: Michael Black W9MDB <mdb...@ya...> Date: Thu Feb 18 06:48:06 2021 -0600 Limit the error retry in rigctld.c to 4 times https://github.com/Hamlib/Hamlib/issues/551 diff --git a/tests/rigctld.c b/tests/rigctld.c index 88cace9a..0eb62900 100644 --- a/tests/rigctld.c +++ b/tests/rigctld.c @@ -83,7 +83,6 @@ /* * 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 "m:r:p:d:P:D:s:c:T:t:C:W:x:z:lLuovhVZ" @@ -108,6 +107,7 @@ static struct option long_options[] = {"help", 0, 0, 'h'}, {"version", 0, 0, 'V'}, {"twiddle_timeout", 1, 0, 'W'}, + {"twiddle_rit" , 0, 0, 'Y'}, {"uplink", 1, 0, 'x'}, {"debug-time-stamps", 0, 0, 'Z'}, {0, 0, 0, 0} @@ -249,6 +249,7 @@ int main(int argc, char *argv[]) int sock_listen; int reuseaddr = 1; int twiddle = 0; + int twiddle_rit = 0; int uplink = 0; char host[NI_MAXHOST]; char serv[NI_MAXSERV]; @@ -526,6 +527,10 @@ int main(int argc, char *argv[]) twiddle = atoi(optarg); break; + case 'Y': + twiddle_rit=1; + break; + case 'x': if (!optarg) { @@ -586,9 +591,10 @@ int main(int argc, char *argv[]) } my_rig->state.twiddle_timeout = twiddle; + my_rig->state.twiddle_rit = twiddle_rit; my_rig->state.uplink = uplink; - rig_debug(RIG_DEBUG_TRACE, "%s: twiddle=%d, uplink=%d\n", __func__, - my_rig->state.twiddle_timeout, my_rig->state.uplink); + rig_debug(RIG_DEBUG_TRACE, "%s: twiddle=%d, uplink=%d, twiddle_rit=%d\n", __func__, + my_rig->state.twiddle_timeout, my_rig->state.uplink, my_rig->state.twiddle_rit); /* * ex: RIG_PTT_PARALLEL and /dev/parport0 @@ -1097,16 +1103,20 @@ void *handle_socket(void *arg) if (ferror(fsockout)) fsockout = get_fsockout(handle_data_arg); rig_debug(RIG_DEBUG_ERR, "%s: socket error in=%d, out=%d\n", __func__, ferror(fsockin), ferror(fsockout)); - - do + // if we get an error from the rig we'll try to repoen + // that may fix things when COM ports drop and such + int retry=4; + if (retcode == 2) { - retcode = rig_close(my_rig); - hl_usleep(1000 * 1000); - rig_debug(RIG_DEBUG_ERR, "%s: rig_close retcode=%d\n", __func__, retcode); - retcode = rig_open(my_rig); - rig_debug(RIG_DEBUG_ERR, "%s: rig_open retcode=%d\n", __func__, retcode); + do + { + retcode = rig_close(my_rig); + hl_usleep(1000 * 1000); + rig_debug(RIG_DEBUG_ERR, "%s: rig_close retcode=%d\n", __func__, retcode); + retcode = rig_open(my_rig); + rig_debug(RIG_DEBUG_ERR, "%s: rig_open retcode=%d\n", __func__, retcode); + } while (retry-- > 0 && retcode != RIG_OK); } - while (retcode != RIG_OK); } } while (retcode == 0 || retcode == 2 || retcode == -RIG_ENAVAIL); @@ -1213,6 +1223,7 @@ void usage(void) " -o, --vfo do not default to VFO_CURR, require extra vfo arg\n" " -v, --verbose set verbose mode, cumulative (-v to -vvvvv)\n" " -W, --twiddle_timeout timeout after detecting vfo manual change\n" + " -W, --twiddle_rit suppress VFOB getfreq so RIT can be twiddled" " -x, --uplink set uplink get_freq ignore, 1=Sub, 2=Main\n" " -Z, --debug-time-stamps enable time stamps for debug messages\n" " -h, --help display this help and exit\n" commit 1e9a991a2555a497a19678ad2dc6807a8bd9000f Author: Michael Black W9MDB <mdb...@ya...> Date: Wed Feb 17 22:52:48 2021 -0600 Add set_dsp_flt for IC7000 -- any other Icom rigs can use this? https://github.com/Hamlib/Hamlib/issues/521 diff --git a/rigs/icom/icom.c b/rigs/icom/icom.c index 26b7426f..fe5aadac 100644 --- a/rigs/icom/icom.c +++ b/rigs/icom/icom.c @@ -1488,8 +1488,6 @@ pbwidth_t icom_get_dsp_flt(RIG *rig, rmode_t mode) return 0; } -#ifdef XXREMOVEDXX -// not referenced anywhere int icom_set_dsp_flt(RIG *rig, rmode_t mode, pbwidth_t width) { int retval, rfstatus; @@ -1573,7 +1571,6 @@ int icom_set_dsp_flt(RIG *rig, rmode_t mode, pbwidth_t width) return RIG_OK; } -#endif /* * icom_set_mode_with_data @@ -1762,20 +1759,15 @@ int icom_set_mode(RIG *rig, vfo_t vfo, rmode_t mode, pbwidth_t width) return -RIG_ERJCTED; } -#if 0 - - /* Tentative DSP filter setting ($1A$03), but not supported by every rig, + /* DSP filter setting ($1A$03), but not supported by every rig, * and some models like IC910/Omni VI Plus have a different meaning for * this subcommand */ - if ((rig->caps->rig_model != RIG_MODEL_IC910) && - (rig->caps->rig_model != RIG_MODEL_OMNIVIP)) + if (rig->caps->rig_model == RIG_MODEL_IC7000) { icom_set_dsp_flt(rig, mode, width); } -#endif - return RIG_OK; } diff --git a/rigs/icom/icom.h b/rigs/icom/icom.h index 17ecbd5b..cf6bb011 100644 --- a/rigs/icom/icom.h +++ b/rigs/icom/icom.h @@ -30,7 +30,7 @@ #include <sys/time.h> #endif -#define BACKEND_VER "20210212" +#define BACKEND_VER "20210217" /* * defines used by comp_cal_str in rig.c commit 8f1efb6a70fd4cee5b619d8c4ca71339183b301e Merge: 5964e1de 6766948d Author: Michael Black <mdb...@ya...> Date: Wed Feb 17 12:12:21 2021 -0600 Merge pull request #550 from fillods/F8CFE/prm80_rework Major prm80 rework commit 6766948dc1ee6082fb599728a23d8376797a7126 Author: Stephane Fillod <fi...@us...> Date: Wed Feb 17 18:57:31 2021 +0100 Major rework for PRM80 Implementation done from tests performed by Claus, DC0CM documentation and rig assembly code at prm80 project. diff --git a/NEWS b/NEWS index 938f29fb..251a56f4 100644 --- a/NEWS +++ b/NEWS @@ -1,11 +1,15 @@ Hamlib -- History of visible changes. Copyright (C) 2000-2003 Frank Singleton -Copyright (C) 2000-2018 Stephane Fillod, and others -Copyright (C) 2000-2020 Michael Black W9MDB, and others +Copyright (C) 2000-2021 Stephane Fillod, and others +Copyright (C) 2000-2021 Michael Black W9MDB, and others Please send Hamlib bug reports to ham...@li... +Version 4.2 + 2021-??-?? + * Major rework for PRM80 + Version 4.1 2021-01-31 * rigctld and rigs should be more robust for disconnect problems diff --git a/rigs/prm80/prm80.c b/rigs/prm80/prm80.c index 36db7fe2..93df5af2 100644 --- a/rigs/prm80/prm80.c +++ b/rigs/prm80/prm80.c @@ -1,6 +1,6 @@ /* * Hamlib PRM80 backend - main file - * Copyright (c) 2010 by Stephane Fillod + * Copyright (c) 2010,2021 by Stephane Fillod * * * This library is free software; you can redistribute it and/or @@ -41,46 +41,23 @@ #define LF "\x0a" -#define PROMPT ">" - #define BUFSZ 64 -/* V3 commands - * retrieved from https://sourceforge.net/projects/prm80/ -MessageVersion: DB "PRM8060 V3.0", 0 +// Channel number min and max +#define CHAN_MIN 0 +#define CHAN_MAX 99 -MessageAide: DB "H",0Dh,0Ah - DB " Commandes disponibles :",0Dh,0Ah - DB " [0] = Reset.",0Dh,0Ah - DB " [1] a [5] = Show 80c552 port state P1 to P5.",0Dh,0Ah - DB " [A] = Set serial communication to 1200 bps.",0Dh,0Ah - DB " [B] = Set serial communication to 4800 bps.",0Dh,0Ah - DB " [C] = Print channels list.",0Dh,0Ah - DB " [D] = Set system byte.",0Dh,0Ah - DB " [E] = Show system state (Mode-Chan-Chanstate-Sql-Vol-Lock-RX freq-TX freq).",0Dh,0Ah - DB " [F] = Set squelch.",0Dh,0Ah - DB " [H] = Print this help page.",0Dh,0Ah - DB " [I] = Erase and init RAM and EEPROM.",0Dh,0Ah - DB " [K] = Set lock byte.",0Dh,0Ah - DB " [L] = Print latch state.",0Dh,0Ah - DB " [M] = Edit external RAM manualy.",0Dh,0Ah - DB " [N] = Set current channel.",0Dh,0Ah - DB " [O] = Set volume.",0Dh,0Ah - DB " [P] = Edit/Add channel.",0Dh,0Ah - DB " [Q] = Set channels number.",0Dh,0Ah - DB " [R] = Set synthetiser frequencies.",0Dh,0Ah - DB " [U] = Print 80c552 internal RAM.",0Dh,0Ah - DB " [S] = Copy EEPROM to external RAM.",0Dh,0Ah - DB " [T] = Set current channel state.",0Dh,0Ah - DB " [V] = Print firmware version.",0Dh,0Ah - DB " [X] = Copy external RAM to EEPROM.",0Dh,0Ah - DB " [Y] = Print first 2 kb from the EEPROM I2C 24c16.",0Dh,0Ah - DB " [Z] = Print external RAM ($0000 to $07FF).",0Dh,0Ah,0 -*/ +#define RX_IF_OFFSET MHz(21.4) + +// The rig's PLL only deals with freq in Hz divided by this value +#define FREQ_DIV 12500. /* V4 commands - * retrieved from https://sourceforge.net/projects/prm80/ - * + * retrieved from https://github.com/f4fez/prm80 + * and https://github.com/f4fez/prm80/blob/master/doc/Computer_commands_V4.md + * It used to be from https://sourceforge.net/projects/prm80/ + * and https://sourceforge.net/p/prm80/wiki/Computer%20commands%20V4/ + MessageVersion: IF TARGET EQ 8060 DB "PRM8060 V4.0" @@ -134,86 +111,173 @@ MessageAide: DB "H",0Dh,0Ah */ /* - * prm80_transaction - * We assume that rig!=NULL, rig->state!= NULL, data!=NULL, data_len!=NULL - * Otherwise, you'll get a nice seg fault. You've been warned! - * TODO: error case handling + * Mode byte, which holds the state of system basic features: + b0: Squelch mode is displayed on LCD if true. Channel mode if false. + b1: Power level (High or Low mode) + b2: Squelch open (Read only) + b3: TX mode (Read only) + b4: PLL locked (Read only) + b5: Long key push (Internal) + b6: Key bounce (Internal) + b7: Force LCD refresh when set. Automaticaly cleared. + + Channel state byte: + b0: Shift enable when true + b1: Reverse mode when true + b2: Positive shift when true. Negative if false + b3: Scanning locked out channel if set + b4-7: na. + + Lock byte, which disables user controls when connected to a computer + b0: Keys disabled when true + b1: TX disabled when true + b2: Volume button disabled when true + b3: RX disabled when true + b4-b7: na. + + * ********************************************************************* + */ + +/* + * TODO make read_colon_prompt_and_send() more generic to read + * a prompt terminated by "$" (without space afterwards) + */ +#define read_dollar_prompt_and_send read_colon_prompt_and_send + +/* + * Read a prompt terminated by ": ", then write an optional string s. + */ +static int read_colon_prompt_and_send(hamlib_port_t *rigport, + char *data, int *data_len, const char *s) +{ + char buf[BUFSZ]; + char spacebuf[4]; + int buflen, retval; + + /* no data wanted? flush it anyway by reading it */ + if (data == NULL) + { + data = buf; + } + + buflen = (data_len == NULL) ? sizeof(buf) : *data_len; + + retval = read_string(rigport, data, buflen, ":", 1); + + if (retval < 0) + { + return retval; + } + + // Place an end of string + data[(retval < buflen) ? retval : (buflen - 1)] = '\0'; + + if (data_len != NULL) + { + *data_len = retval; + } + + // Read one (dummy) space character after the colon + retval = read_block(rigport, spacebuf, 1); + + if (retval < 0 && retval != -RIG_ETIMEOUT) + { + return retval; + } + + // Here is the answer to the prompt + retval = write_block(rigport, s, strlen(s)); + + return retval; +} + +/* + * After each executed command, the rig generally sends "\r\n>" */ -static int prm80_transaction(RIG *rig, const char *cmd, int cmd_len, char *data, - int *data_len) +static int prm80_wait_for_prompt(hamlib_port_t *rigport) { - int retval, i; - struct rig_state *rs; + char buf[BUFSZ * 2]; + int retval; + + // Read up to the '>' prompt and discard content. + retval = read_string(rigport, buf, sizeof(buf), ">", 1); + + if (retval < 0) + { + return retval; + } + + return RIG_OK; +} - rs = &rig->state; +/* + * + * \param cmd is string of generally one letter (or digit) + * \param arg1 is an optional string string sent + * \param wait_prompt boolean when non-nul, will wait for "\r\n>" afterwards + */ +static int prm80_transaction(RIG *rig, const char *cmd, + const char *arg1, int wait_prompt) +{ + int retval; + struct rig_state *rs = &rig->state; + // Get rid of possible prompt sent by the rig rig_flush(&rs->rigport); - retval = write_block(&rs->rigport, cmd, cmd_len); + // Start with the command + retval = write_block(&rs->rigport, cmd, strlen(cmd)); if (retval != RIG_OK) { return retval; } - /* no data wanted, but flush it anyway */ - if (!data || !data_len) + if (arg1 != NULL) { - char retbuf[BUFSZ + 1]; - - retval = read_string(&rs->rigport, retbuf, BUFSZ, LF, strlen(LF)); + retval = read_colon_prompt_and_send(&rs->rigport, NULL, NULL, arg1); if (retval < 0) { return retval; } - -#if 0 - - /* - * Does transceiver sends back ">" ? - */ - if (strstr(retbuf, PROMPT)) - { - return RIG_OK; - } - else - { - return -RIG_ERJCTED; - } - -#else - return RIG_OK; -#endif } - retval = read_string(&rs->rigport, data, BUFSZ, LF, strlen(LF)); - - if (retval == -RIG_ETIMEOUT) + if (wait_prompt) { - retval = 0; + prm80_wait_for_prompt(&rs->rigport); } - if (retval < 0) + return RIG_OK; +} + +int prm80_init(RIG *rig) +{ + if (!rig) { - return retval; + return -RIG_EINVAL; } - /* Clear possible MSB, because of 7S1 */ - for (i = 0; i < retval; i++) + rig->state.priv = (void *)calloc(1, sizeof(struct prm80_priv_data)); + + if (!rig->state.priv) { - data[i] &= 0x7f; + /* whoops! memory shortage! */ + return -RIG_ENOMEM; } - *data_len = retval; + return RIG_OK; +} - /* chomp CR/LF from string */ - if (*data_len >= 2 && data[*data_len - 1] == '\x0a') +int prm80_cleanup(RIG *rig) +{ + if (rig == NULL) { - *data_len -= 2; + return -RIG_EINVAL; } - data[*data_len] = '\0'; + free(rig->state.priv); + rig->state.priv = NULL; return RIG_OK; } @@ -228,9 +292,9 @@ int prm80_reset(RIG *rig, reset_t reset) int retval; /* - * master reset ? + * Reset CPU */ - retval = prm80_transaction(rig, "0", 1, NULL, NULL); + retval = prm80_transaction(rig, "0", NULL, 1); if (retval != RIG_OK) { @@ -242,33 +306,107 @@ int prm80_reset(RIG *rig, reset_t reset) /* - * prm80_set_freq - * Assumes rig!=NULL + * Set RX and TX freq + * + * See https://github.com/f4fez/prm80/blob/master/doc/Computer_control.md + * "Adding a new channel" regarding freq format. + */ +int prm80_set_rx_tx_freq(RIG *rig, freq_t rx_freq, freq_t tx_freq) +{ + struct rig_state *rs = &rig->state; + char rx_freq_buf[BUFSZ]; + char tx_freq_buf[BUFSZ]; + int rc; + + // for RX, compute the PLL word without the IF + sprintf(rx_freq_buf, "%04X", + (unsigned)((rx_freq - RX_IF_OFFSET) / FREQ_DIV)); + sprintf(tx_freq_buf, "%04X", + (unsigned)(tx_freq / FREQ_DIV)); + + // The protocol is like this : + // "RX frequency : " XXXX + // CRLF"TX frequency : " XXXX + + rc = prm80_transaction(rig, "R", rx_freq_buf, 0); + + if (rc != RIG_OK) + { + return rc; + } + + // There's a second line to process after prm80_transaction() + rc = read_colon_prompt_and_send(&rs->rigport, NULL, NULL, tx_freq_buf); + + if (rc != RIG_OK) + { + return rc; + } + + // quid timeout in trx waiting for freq ? + + // NB: the [R] command does not update the checksum of the RAM! + + prm80_wait_for_prompt(&rs->rigport); + + return rc; +} + +/* + * Set (RX) freq */ int prm80_set_freq(RIG *rig, vfo_t vfo, freq_t freq) { - char freqbuf[BUFSZ]; - char data[BUFSZ]; - int freq_len; + struct prm80_priv_data *priv = (struct prm80_priv_data *)rig->state.priv; + freq_t tx_freq; int rc; - struct rig_state *rs = &rig->state; - /* wild guess */ - freq_len = sprintf(freqbuf, "R%04X%04X", - (unsigned)(freq / 12500.), - (unsigned)(freq / 12500.)); + if (priv->split == RIG_SPLIT_OFF) + { + tx_freq = freq; + } + else + { + tx_freq = (priv->tx_freq == 0.) ? freq : priv->tx_freq; + } + + rc = prm80_set_rx_tx_freq(rig, freq, tx_freq); + + if (rc == RIG_OK) + { + priv->rx_freq = freq; + } - rc = prm80_transaction(rig, freqbuf, freq_len, NULL, NULL); - read_string(&rs->rigport, data, BUFSZ, LF, strlen(LF)); return rc; } /* - * prm80_get_freq - * Assumes rig!=NULL + * Set TX freq depending on emulated split state + */ +int prm80_set_split_freq(RIG *rig, vfo_t vfo, freq_t tx_freq) +{ + struct prm80_priv_data *priv = (struct prm80_priv_data *)rig->state.priv; + freq_t rx_freq; + int rc; + + rx_freq = (priv->rx_freq == 0.) ? tx_freq : priv->rx_freq; + + rc = prm80_set_rx_tx_freq(rig, rx_freq, tx_freq); + + if (rc == RIG_OK) + { + priv->tx_freq = tx_freq; + } + + return rc; +} + +/* + * Get RX freq depending on emulated split state */ int prm80_get_freq(RIG *rig, vfo_t vfo, freq_t *freq) { + struct prm80_priv_data *priv = (struct prm80_priv_data *)rig->state.priv; int ret; channel_t chan; @@ -283,29 +421,96 @@ int prm80_get_freq(RIG *rig, vfo_t vfo, freq_t *freq) } *freq = chan.freq; + priv->tx_freq = chan.tx_freq; + + return RIG_OK; +} + +/* + * Enable/disable Split + * + * Rem: don't care about vfo + */ +int prm80_set_split_vfo(RIG *rig, vfo_t vfo, split_t split, vfo_t tx_vfo) +{ + struct prm80_priv_data *priv = (struct prm80_priv_data *)rig->state.priv; + + priv->split = split; + + return RIG_OK; +} + +/* + * Get Split + */ +int prm80_get_split_vfo(RIG *rig, vfo_t vfo, split_t *split, vfo_t *tx_vfo) +{ + struct prm80_priv_data *priv = (struct prm80_priv_data *)rig->state.priv; + + *split = priv->split; + *tx_vfo = RIG_VFO_CURR; + + return RIG_OK; +} + +/* + * Get TX freq + */ +int prm80_get_split_freq(RIG *rig, vfo_t vfo, freq_t *tx_freq) +{ + struct prm80_priv_data *priv = (struct prm80_priv_data *)rig->state.priv; + int ret; + channel_t chan; + + memset(&chan, 0, sizeof(chan)); + chan.vfo = RIG_VFO_CURR; + + ret = prm80_get_channel(rig, vfo, &chan, 0); + + if (ret != RIG_OK) + { + return ret; + } + + *tx_freq = chan.tx_freq; + priv->rx_freq = chan.freq; + + return RIG_OK; +} + +/* + * Basic helper to ease some generic applications + */ +int prm80_get_mode(RIG *rig, vfo_t vfo, rmode_t *mode, pbwidth_t *width) +{ + // Can only do FM + *mode = RIG_MODE_FM; + *width = rig_passband_normal(rig, *mode); return RIG_OK; } + /* * prm80_set_mem * Assumes rig!=NULL */ int prm80_set_mem(RIG *rig, vfo_t vfo, int ch) { - int cmd_len; - char cmdbuf[BUFSZ]; + char chbuf[BUFSZ]; /* [N] = Set current channel. */ - if (ch < 0 || ch > 99) + if (ch < CHAN_MIN || ch > CHAN_MAX) { return -RIG_EINVAL; } - cmd_len = sprintf(cmdbuf, "N%02d", ch); + sprintf(chbuf, "%02u", (unsigned)ch); + + // Send command, no answer expected from rig except ">" prompt - return prm80_transaction(rig, cmdbuf, cmd_len, NULL, NULL); + return prm80_transaction(rig, "N", chbuf, 1); } /* @@ -352,9 +557,11 @@ static int hhtoi(const char *p) */ int prm80_get_channel(RIG *rig, vfo_t vfo, channel_t *chan, int read_only) { + struct prm80_priv_data *priv = (struct prm80_priv_data *)rig->state.priv; + struct rig_state *rs = &rig->state; char statebuf[BUFSZ]; - int statebuf_len = BUFSZ; - int ret, chanstate; + char *p; + int ret, chanstate, mode_byte, lock_byte; if (chan->vfo == RIG_VFO_MEM) { @@ -366,30 +573,75 @@ int prm80_get_channel(RIG *rig, vfo_t vfo, channel_t *chan, int read_only) } } - /* [E] = Show system state (Mode-Chan-Chanstate-Sql-Vol-Lock-RX freq-TX freq). */ - ret = prm80_transaction(rig, "E", 1, statebuf, &statebuf_len); + // Get rid of possible prompt sent by the rig + rig_flush(&rs->rigport); + + /* [E] = Show system state */ + ret = write_block(&rs->rigport, "E", 1); - if (ret != RIG_OK) + if (ret < 0) { RETURNFUNC(ret); } - if (statebuf_len < 20) + // The response length is fixed + ret = read_block(&rs->rigport, statebuf, 20); + + if (ret < 0) { - rig_debug(RIG_DEBUG_ERR, "%s: statebuf_len < 20, statebuf='%s'\n", __func__, - statebuf); + return ret; + } + + if (ret >= 0) + { + statebuf[ret] = '\0'; + } + + if (ret < 20) + { + rig_debug(RIG_DEBUG_ERR, "%s: len=%d < 20, statebuf='%s'\n", __func__, + ret, statebuf); RETURNFUNC(-RIG_EPROTO); } - /* Example: 1240080AFF0033F02D40 */ - if (hhtoi(statebuf) != 0x12) - rig_debug(RIG_DEBUG_WARN, "%s: Unknown mode 0x%c%c\n", - __func__, statebuf[0], statebuf[1]); + p = strchr(statebuf, '>'); + + if (p) + { + int left_to_read = (p - statebuf) + 1; + memmove(statebuf, p + 1, 20 - left_to_read); + ret = read_block(&rs->rigport, statebuf + 20 - left_to_read, left_to_read); + + if (ret >= 0) + { + statebuf[20] = '\0'; + } + + rig_debug(RIG_DEBUG_WARN, "%s: len=%d, statebuf='%s'\n", __func__, ret, + statebuf); + } + + /* (Mode-Chan-Chanstate-Sql-Vol-Lock-RX freq-TX freq). */ + /* Examples: 1240080AFF0033F02D40 or 14000C00FD0079708020 */ + + /* Current mode: + ; b0: Squelch b1: power + ; b2: Squelch open b3: TX + ; b4: PLL locked b5: Long press memorize + ; b6: Debouncing in effect b7: LCD refresh + */ + mode_byte = hhtoi(statebuf); chan->mode = RIG_MODE_FM; chan->width = rig_passband_normal(rig, chan->mode); chan->channel_num = hhtoi(statebuf + 2); + chan->tx_mode = chan->mode; + chan->tx_width = chan->width; + /* Chan state: + ; b0: shift enabled b1: reverse + ; b2: shift + b3: lock out + */ chanstate = hhtoi(statebuf + 4) & 0x0f; /* is it rptr_shift or split mode ? */ chan->rptr_shift = (chanstate & 0x01) == 0 ? RIG_RPT_SHIFT_NONE : @@ -400,39 +652,160 @@ int prm80_get_channel(RIG *rig, vfo_t vfo, channel_t *chan, int read_only) // cppcheck-suppress * chan->levels[LVL_SQL].f = ((float)(hhtoi(statebuf + 6) >> 4)) / 15.; chan->levels[LVL_AF].f = ((float)(hhtoi(statebuf + 8) >> 4)) / 15.; - /* same as chanstate bit 1 */ - chan->flags = hhtoi(statebuf + 10) == 0 ? 0 : RIG_CHFLAG_SKIP; - chan->freq = ((hhtoi(statebuf + 12) << 8) + hhtoi(statebuf + 14)) * 12500; - chan->tx_freq = ((hhtoi(statebuf + 16) << 8) + hhtoi(statebuf + 18)) * 12500; - chan->rptr_offs = chan->tx_freq - chan->freq; + chan->levels[LVL_RFPOWER].f = (mode_byte & 0x02) ? 1.0 : 0.0; + + chan->funcs |= (chanstate & 0x02) ? RIG_FUNC_REV : 0; + + lock_byte = hhtoi(statebuf + 10) & 0x0f; + chan->funcs = (lock_byte != 0) ? RIG_FUNC_LOCK : 0; + + chan->freq = ((hhtoi(statebuf + 12) << 8) + hhtoi(statebuf + 14)) * FREQ_DIV + + RX_IF_OFFSET; + chan->tx_freq = ((hhtoi(statebuf + 16) << 8) + hhtoi(statebuf + 18)) * FREQ_DIV; + + if (chan->rptr_shift != RIG_RPT_SHIFT_NONE) + { + chan->rptr_offs = chan->tx_freq - chan->freq; + chan->split = RIG_SPLIT_OFF; + } + else + { + chan->rptr_offs = 0; + chan->split = priv->split; // RIG_SPLIT_ON; ? + } if (!read_only) { // Set rig to channel values - rig_debug(RIG_DEBUG_ERR, - "%s: please contact hamlib mailing list to implement this, rxfreq=%.0f, txfreq=%.0f\n", - __func__, chan->freq, chan->tx_freq); - rig_debug(RIG_DEBUG_ERR, + rig_debug(RIG_DEBUG_WARN, + "%s: please contact hamlib mailing list to implement this\n", __func__); + rig_debug(RIG_DEBUG_WARN, "%s: need to know if rig updates when channel read or not\n", __func__); //return -RIG_ENIMPL; } + prm80_wait_for_prompt(&rs->rigport); + return RIG_OK; } /* - * prm80_set_channel - * Assumes rig!=NULL + * prm80_set_channel handles RIG_VFO_MEM and RIG_VFO_CURR */ int prm80_set_channel(RIG *rig, vfo_t vfo, const channel_t *chan) { - char statebuf[BUFSZ]; - int statebuf_len = BUFSZ; - int ret; + struct prm80_priv_data *priv = (struct prm80_priv_data *)rig->state.priv; + struct rig_state *rs = &rig->state; + char buf[BUFSZ]; + int ret, chanstate; + freq_t tx_freq; if (chan->vfo == RIG_VFO_MEM) { - ret = prm80_set_mem(rig, RIG_VFO_CURR, chan->channel_num); + // setting channel without calling set_mem() + + if (chan->channel_num < CHAN_MIN || chan->channel_num > CHAN_MAX) + { + return -RIG_EINVAL; + } + + /* [P] = Edit/Add channel */ + /* Example + Channel to set : 00 + PLL value to load : $8020 + Channel state : $00 + + TODO: handle the possible query from the rig: + "This channel number doesn't exist. Add new channel (Y/N) ? " + TODO implement correctly read_dollar_prompt_and_send (dollar prompt) + */ + + sprintf(buf, "%02u", (unsigned)chan->channel_num); + + ret = prm80_transaction(rig, "P", buf, 0); + + if (ret != RIG_OK) + { + return ret; + } + + // Set the RX frequency as PLL word + sprintf(buf, "%04X", (unsigned)((chan->freq - RX_IF_OFFSET) / FREQ_DIV)); + ret = read_dollar_prompt_and_send(&rs->rigport, NULL, NULL, buf); + + if (ret != RIG_OK) + { + return ret; + } + + // the channel status byte. + switch (chan->rptr_shift) + { + case RIG_RPT_SHIFT_NONE : chanstate = 0x00; break; + + case RIG_RPT_SHIFT_MINUS : chanstate = 0x03; break; + + case RIG_RPT_SHIFT_PLUS : chanstate = 0x05; break; + + default: chanstate = 0x00; break; + } + + chanstate |= (chan->flags & RIG_CHFLAG_SKIP) ? 0x08 : 0; + + sprintf(buf, "%02X", chanstate); + ret = read_dollar_prompt_and_send(&rs->rigport, NULL, NULL, buf); + + if (ret != RIG_OK) + { + return ret; + } + + prm80_wait_for_prompt(&rs->rigport); + } + else + { + // assume here chan->vfo == RIG_VFO_CURR + // that is the "RAM" VFO not backed by memory + + tx_freq = (chan->split == RIG_SPLIT_ON) ? chan->tx_freq : chan->freq; + + ret = prm80_set_rx_tx_freq(rig, chan->freq, tx_freq); + + if (ret != RIG_OK) + { + return ret; + } + + priv->split = chan->split; + priv->rx_freq = chan->freq; + priv->tx_freq = tx_freq; + + ret = prm80_set_level(rig, vfo, RIG_LEVEL_SQL, chan->levels[LVL_SQL]); + + if (ret != RIG_OK) + { + return ret; + } + + ret = prm80_set_level(rig, vfo, RIG_LEVEL_AF, chan->levels[LVL_AF]); + + if (ret != RIG_OK) + { + return ret; + } + +#if 0 + // Not implemented yet.. + ret = prm80_set_level(rig, vfo, RIG_LEVEL_RFPOWER, chan->levels[LVL_RFPOWER]); + + if (ret != RIG_OK) + { + return ret; + } + +#endif + + ret = prm80_set_func(rig, vfo, RIG_FUNC_LOCK, chan->funcs & RIG_FUNC_LOCK); if (ret != RIG_OK) { @@ -440,52 +813,91 @@ int prm80_set_channel(RIG *rig, vfo_t vfo, const channel_t *chan) } } - /* [T] = Set current channel state. (Mode-Chan-Chanstate-Sql-Vol-Lock-RX freq-TX freq) ? */ - /* Example: 1240080AFF0033F02D40 ? */ - statebuf_len = sprintf(statebuf, "T%02X%02X%02X%02X%02X%02X%04X%04X", - 0x12, - chan->channel_num, - (chan->flags & RIG_CHFLAG_SKIP) ? 0x08 : 0, /* TODO: tx shift */ - (unsigned)(chan->levels[LVL_SQL].f * 15), - (unsigned)(chan->levels[LVL_AF].f * 15), - (chan->flags & RIG_CHFLAG_SKIP) ? 0x01 : 0x00, /* Lock */ - (unsigned)(chan->freq / 12500.), - (unsigned)(chan->tx_freq / 12500.) - ); + return RIG_OK; +} - ret = prm80_transaction(rig, statebuf, statebuf_len, NULL, NULL); + +// TODO FUNC_REV ? +int prm80_set_func(RIG *rig, vfo_t vfo, setting_t func, int status) +{ + int ret; + + if (func & RIG_FUNC_LOCK) + { + /* Lock keys/TX/Vol */ + ret = prm80_transaction(rig, "K", (status != 0) ? "03" : "00", 1); + } + else + { + ret = -RIG_EINVAL; + } + + return ret; +} + +int prm80_get_func(RIG *rig, vfo_t vfo, setting_t func, int *status) +{ + int ret; + channel_t chan; + + memset(&chan, 0, sizeof(chan)); + chan.vfo = RIG_VFO_CURR; + + ret = prm80_get_channel(rig, vfo, &chan, 0); if (ret != RIG_OK) { return ret; } + *status = (chan.funcs & func); + return RIG_OK; } - /* * prm80_set_level * Assumes rig!=NULL */ int prm80_set_level(RIG *rig, vfo_t vfo, setting_t level, value_t val) { - int cmd_len; - char cmdbuf[BUFSZ]; + char buf[BUFSZ]; + + // do some clamping, all levels are float values. + if (val.f < 0.0) + { + val.f = 0.0; + } + else if (val.f > 1.0) + { + val.f = 1.0; + } switch (level) { case RIG_LEVEL_AF: - cmd_len = sprintf(cmdbuf, "O%02u", (unsigned)(val.f * 15)); + sprintf(buf, "%02u", (unsigned)(val.f * 15)); - return prm80_transaction(rig, cmdbuf, cmd_len, NULL, NULL); + return prm80_transaction(rig, "O", buf, 1); case RIG_LEVEL_SQL: - cmd_len = sprintf(cmdbuf, "F%02u", (unsigned)(val.f * 15)); + sprintf(buf, "%02u", (unsigned)(val.f * 15)); - return prm80_transaction(rig, cmdbuf, cmd_len, NULL, NULL); + return prm80_transaction(rig, "F", buf, 1); case RIG_LEVEL_RFPOWER: + // TODO : modify the Mode byte b1 ? +#if 0 + /* Current mode: + ; b0: Squelch b1: power + ; b2: Squelch open b3: TX + ; b4: PLL locked b5: Long press memorize + ; b6: Debouncing in effect b7: LCD refresh + */ + // TODO perform a "Read-Modify-Write" of the mode_byte + mode_byte = 0x10; + mode_byte |= (chan->levels[LVL_RFPOWER].f == 0.) ? 0 : 0x02; +#endif return -RIG_ENIMPL; default: @@ -528,6 +940,11 @@ int prm80_get_level(RIG *rig, vfo_t vfo, setting_t level, value_t *val) break; + case RIG_LEVEL_RFPOWER: + val->f = chan.levels[LVL_RFPOWER].f; + + break; + default: rig_debug(RIG_DEBUG_ERR, "%s: unsupported set_level %s\n", __func__, rig_strlevel(level)); @@ -537,26 +954,47 @@ int prm80_get_level(RIG *rig, vfo_t vfo, setting_t level, value_t *val) return RIG_OK; } +// TODO vfo_op : MCL FROM_VFO .. + /* * prm80_get_info * Assumes rig!=NULL */ const char *prm80_get_info(RIG *rig) { - static char buf[BUFSZ]; - int ret, buf_len = BUFSZ; + static char s_buf[BUFSZ]; + struct rig_state *rs = &rig->state; + char *p; + int ret; + + // Get rid of possible prompt sent by the rig + rig_flush(&rs->rigport); /* [V] = Print firmware version. */ - ret = prm80_transaction(rig, "V", 1, buf, &buf_len); + ret = write_block(&rs->rigport, "V", 1); if (ret < 0) { return NULL; } - return buf; -} + ret = read_string(&rs->rigport, s_buf, BUFSZ, ">", 1); + if (ret < 0) + { + return NULL; + } + + p = strchr(s_buf, '\r'); + + if (p) + { + // chomp + *p = '\0'; + } + + return s_buf; +} /* diff --git a/rigs/prm80/prm80.h b/rigs/prm80/prm80.h index 71e96a13..fbaf50fb 100644 --- a/rigs/prm80/prm80.h +++ b/rigs/prm80/prm80.h @@ -1,6 +1,6 @@ /* * Hamlib PRM80 backend - main header - * Copyright (c) 2010 by Stephane Fillod + * Copyright (c) 2010,2021 by Stephane Fillod * * * This library is free software; you can redistribute it and/or @@ -24,28 +24,41 @@ #include <hamlib/rig.h> -#define BACKEND_VER "20101027" +#define BACKEND_VER "20210217" #define PRM80_MEM_CAP { \ .freq = 1, \ - .mode = 1, \ .rptr_shift = 1, \ - .rptr_offs = 1, \ - .flags = 1, /* lockout*/ \ - .levels = RIG_LEVEL_SQL|RIG_LEVEL_AF, \ + .flags = 1, /* lockout */ \ } +struct prm80_priv_data +{ + freq_t rx_freq; /* last RX freq set */ + freq_t tx_freq; /* last TX freq set */ + split_t split; /* emulated split on/off */ +}; + +int prm80_init(RIG *rig); +int prm80_cleanup(RIG *rig); int prm80_reset(RIG *rig, reset_t reset); int prm80_set_freq(RIG *rig, vfo_t vfo, freq_t freq); int prm80_get_freq(RIG *rig, vfo_t vfo, freq_t *freq); +int prm80_set_split_vfo(RIG *rig, vfo_t vfo, split_t split, vfo_t tx_vfo); +int prm80_get_split_vfo(RIG *rig, vfo_t vfo, split_t *split, vfo_t *tx_vfo); +int prm80_set_split_freq(RIG *rig, vfo_t vfo, freq_t tx_freq); +int prm80_get_split_freq(RIG *rig, vfo_t vfo, freq_t *tx_freq); +int prm80_get_mode(RIG *rig, vfo_t vfo, rmode_t *mode, pbwidth_t *width); +int prm80_set_func(RIG *rig, vfo_t vfo, setting_t func, int status); +int prm80_get_func(RIG *rig, vfo_t vfo, setting_t func, int *status); int prm80_set_level(RIG *rig, vfo_t vfo, setting_t level, value_t val); int prm80_get_level(RIG *rig, vfo_t vfo, setting_t level, value_t *val); -int prm80_set_mem (RIG *rig, vfo_t vfo, int ch); -int prm80_get_mem (RIG *rig, vfo_t vfo, int *ch); -int prm80_set_channel(RIG * rig, vfo_t vfo, const channel_t * chan); -int prm80_get_channel(RIG * rig, vfo_t vfo, channel_t * chan, int read_only); +int prm80_set_mem(RIG *rig, vfo_t vfo, int ch); +int prm80_get_mem(RIG *rig, vfo_t vfo, int *ch); +int prm80_set_channel(RIG *rig, vfo_t vfo, const channel_t *chan); +int prm80_get_channel(RIG *rig, vfo_t vfo, channel_t *chan, int read_only); -const char* prm80_get_info(RIG *rig); +const char *prm80_get_info(RIG *rig); extern const struct rig_caps prm8060_caps; diff --git a/rigs/prm80/prm8060.c b/rigs/prm80/prm8060.c index 9f60d09d..ff690e88 100644 --- a/rigs/prm80/prm8060.c +++ b/rigs/prm80/prm8060.c @@ -1,6 +1,6 @@ /* * Hamlib PR... [truncated message content] |