hamlib-cvs-digest Mailing List for Ham Radio Control Libraries
Library to control radio transceivers and receivers
Brought to you by:
n0nb
You can subscribe to this list here.
| 2000 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
(57) |
Nov
(27) |
Dec
(25) |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 2001 |
Jan
(41) |
Feb
(101) |
Mar
(60) |
Apr
(32) |
May
(32) |
Jun
(198) |
Jul
(95) |
Aug
(60) |
Sep
(48) |
Oct
(96) |
Nov
(27) |
Dec
(222) |
| 2002 |
Jan
(180) |
Feb
(46) |
Mar
(68) |
Apr
(11) |
May
(36) |
Jun
(34) |
Jul
(113) |
Aug
(42) |
Sep
(71) |
Oct
(65) |
Nov
(116) |
Dec
(40) |
| 2003 |
Jan
(32) |
Feb
(92) |
Mar
(29) |
Apr
(102) |
May
(21) |
Jun
(34) |
Jul
(3) |
Aug
(60) |
Sep
(30) |
Oct
(62) |
Nov
(57) |
Dec
(33) |
| 2004 |
Jan
(28) |
Feb
(46) |
Mar
(16) |
Apr
(14) |
May
(31) |
Jun
(21) |
Jul
(10) |
Aug
(80) |
Sep
(42) |
Oct
(11) |
Nov
(28) |
Dec
(13) |
| 2005 |
Jan
(35) |
Feb
(26) |
Mar
(20) |
Apr
(118) |
May
(2) |
Jun
(5) |
Jul
|
Aug
|
Sep
(5) |
Oct
(1) |
Nov
(13) |
Dec
(1) |
| 2006 |
Jan
(9) |
Feb
(25) |
Mar
(22) |
Apr
(6) |
May
|
Jun
|
Jul
(2) |
Aug
(1) |
Sep
(3) |
Oct
(46) |
Nov
(13) |
Dec
(7) |
| 2007 |
Jan
(9) |
Feb
(14) |
Mar
(3) |
Apr
|
May
(6) |
Jun
(1) |
Jul
|
Aug
(11) |
Sep
(7) |
Oct
(8) |
Nov
(41) |
Dec
(3) |
| 2008 |
Jan
(27) |
Feb
(16) |
Mar
(13) |
Apr
(23) |
May
(39) |
Jun
(4) |
Jul
(7) |
Aug
(1) |
Sep
(13) |
Oct
(52) |
Nov
(44) |
Dec
(55) |
| 2009 |
Jan
(72) |
Feb
(69) |
Mar
|
Apr
|
May
|
Jun
(13) |
Jul
(1) |
Aug
(6) |
Sep
(15) |
Oct
(11) |
Nov
(31) |
Dec
(20) |
| 2010 |
Jan
(24) |
Feb
(21) |
Mar
(22) |
Apr
(40) |
May
(38) |
Jun
(4) |
Jul
(2) |
Aug
(22) |
Sep
(19) |
Oct
(14) |
Nov
(5) |
Dec
(8) |
| 2011 |
Jan
(14) |
Feb
(36) |
Mar
(6) |
Apr
|
May
|
Jun
(23) |
Jul
(13) |
Aug
(8) |
Sep
(7) |
Oct
|
Nov
(3) |
Dec
(9) |
| 2012 |
Jan
(17) |
Feb
(13) |
Mar
(10) |
Apr
|
May
(1) |
Jun
(14) |
Jul
(4) |
Aug
(12) |
Sep
(2) |
Oct
(24) |
Nov
(14) |
Dec
(2) |
| 2013 |
Jan
(4) |
Feb
(3) |
Mar
(3) |
Apr
(3) |
May
(10) |
Jun
(4) |
Jul
(7) |
Aug
|
Sep
(15) |
Oct
(5) |
Nov
(1) |
Dec
(2) |
| 2014 |
Jan
|
Feb
(8) |
Mar
(1) |
Apr
(3) |
May
(1) |
Jun
|
Jul
|
Aug
(1) |
Sep
(3) |
Oct
(7) |
Nov
(6) |
Dec
(3) |
| 2015 |
Jan
(4) |
Feb
(5) |
Mar
(8) |
Apr
(8) |
May
(2) |
Jun
|
Jul
(4) |
Aug
(7) |
Sep
(8) |
Oct
|
Nov
(6) |
Dec
(4) |
| 2016 |
Jan
(6) |
Feb
(26) |
Mar
(3) |
Apr
(10) |
May
(6) |
Jun
(5) |
Jul
(1) |
Aug
(4) |
Sep
(3) |
Oct
(4) |
Nov
(3) |
Dec
(10) |
| 2017 |
Jan
(11) |
Feb
(11) |
Mar
(2) |
Apr
(1) |
May
(7) |
Jun
(2) |
Jul
(11) |
Aug
(9) |
Sep
(5) |
Oct
(5) |
Nov
(1) |
Dec
(2) |
| 2018 |
Jan
(5) |
Feb
(2) |
Mar
(19) |
Apr
(7) |
May
(11) |
Jun
(3) |
Jul
(4) |
Aug
(10) |
Sep
(2) |
Oct
(8) |
Nov
(6) |
Dec
(9) |
| 2019 |
Jan
(9) |
Feb
(6) |
Mar
(2) |
Apr
(4) |
May
(6) |
Jun
(9) |
Jul
(6) |
Aug
(3) |
Sep
(5) |
Oct
(2) |
Nov
(8) |
Dec
(9) |
| 2020 |
Jan
(15) |
Feb
(1) |
Mar
(18) |
Apr
(33) |
May
(43) |
Jun
(87) |
Jul
(45) |
Aug
(8) |
Sep
(43) |
Oct
(3) |
Nov
(5) |
Dec
(42) |
| 2021 |
Jan
(116) |
Feb
(40) |
Mar
(58) |
Apr
(48) |
May
(29) |
Jun
(2) |
Jul
|
Aug
(22) |
Sep
(18) |
Oct
(1) |
Nov
|
Dec
(3) |
| 2022 |
Jan
(1) |
Feb
(1) |
Mar
|
Apr
(1) |
May
(2) |
Jun
(1) |
Jul
|
Aug
(1) |
Sep
|
Oct
(6) |
Nov
(2) |
Dec
(9) |
| 2023 |
Jan
(10) |
Feb
|
Mar
|
Apr
(10) |
May
(3) |
Jun
(1) |
Jul
(2) |
Aug
(4) |
Sep
(1) |
Oct
|
Nov
(2) |
Dec
(3) |
| 2024 |
Jan
(4) |
Feb
(1) |
Mar
(2) |
Apr
(2) |
May
(5) |
Jun
(3) |
Jul
(1) |
Aug
(2) |
Sep
|
Oct
(2) |
Nov
(3) |
Dec
(9) |
| 2025 |
Jan
(5) |
Feb
(5) |
Mar
|
Apr
(10) |
May
(20) |
Jun
(43) |
Jul
(24) |
Aug
(47) |
Sep
(38) |
Oct
(5) |
Nov
(3) |
Dec
(18) |
| 2026 |
Jan
(17) |
Feb
(13) |
Mar
(17) |
Apr
(28) |
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
|
From: n0nb <n0...@us...> - 2026-04-24 19:17:40
|
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, Hamlib-4.7 has been updated
via 993a2f284b68bd52b32aa9e369b17fbcf1191f64 (commit)
via eea7094ae73d6c8abaf18168cb34207eac9c7827 (commit)
via 5bc8f19f13fa52b4fc2daf45250342287e0e5798 (commit)
from 3856ff650ae64a597d41207b52c43946769af9dd (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 993a2f284b68bd52b32aa9e369b17fbcf1191f64
Author: Nate Bargmann <n0...@n0...>
Date: Fri Apr 24 14:16:14 2026 -0500
Update NEWS for new model, Hamgeek uSDX
diff --git a/NEWS b/NEWS
index f4c6a700c..90677b90d 100644
--- a/NEWS
+++ b/NEWS
@@ -28,6 +28,7 @@ Version 4.7.2
GitHub PR #2040 (TNX George Baltz)
* Icom: Add CWR to modes eligible for DSP filtering. GitHub PR #2041.
(TNX George Baltz)
+ * Kenwood: New model Hamgeek uSGX. GitHub PR #2043 (TNX Leo Pizzolante)
Version 4.7.1
* 2026-04-15
commit eea7094ae73d6c8abaf18168cb34207eac9c7827
Author: Nate Bargmann <n0...@n0...>
Date: Fri Apr 24 13:08:02 2026 -0500
Rename macro to quell warning
GCC on Debian 13 generated this warning:
CC hamgeek.lo
../../../../rigs/kenwood/hamgeek.c:71:9: warning: "BACKEND_VER" redefined
71 | #define BACKEND_VER "20260423"
| ^~~~~~~~~~~
In file included from ../../../../rigs/kenwood/hamgeek.c:35:
../../../../rigs/kenwood/kenwood.h:33:9: note: this is the location of the previous definition
33 | #define BACKEND_VER "20250515"
| ^~~~~~~~~~~
Renamimg the macro to USDX_BACKEND_VER quelled the warning.
(cherry picked from commit 07bd3b365090b37179bbcfbfaa54bfb5100b7f08)
diff --git a/rigs/kenwood/hamgeek.c b/rigs/kenwood/hamgeek.c
index a5527baf1..b5902279c 100644
--- a/rigs/kenwood/hamgeek.c
+++ b/rigs/kenwood/hamgeek.c
@@ -68,7 +68,7 @@
/* Only VFO A is present on uSDX hardware (FB; returns '?;') */
#define USDX_VFO RIG_VFO_A
-#define BACKEND_VER "20260423"
+#define USDX_BACKEND_VER "20260423"
/*
* Minimal TS-480 subset: no slope filters, no special filter width table.
@@ -220,7 +220,7 @@ struct rig_caps hamgeek_usdx_caps =
RIG_MODEL(RIG_MODEL_HAMGEEK_USDX),
.model_name = "uSDX",
.mfg_name = "Hamgeek",
- .version = BACKEND_VER ".0",
+ .version = USDX_BACKEND_VER ".0",
.copyright = "LGPL",
.status = RIG_STATUS_ALPHA,
.rig_type = RIG_TYPE_TRANSCEIVER,
commit 5bc8f19f13fa52b4fc2daf45250342287e0e5798
Author: Leo Pizzolante <leo...@gm...>
Date: Fri Apr 24 17:40:34 2026 +0200
Add Hamgeek uSDX
(cherry picked from commit 2691e10cee7b5896d5a4f5dab880c2d0260e5467)
diff --git a/bindings/python/test_Hamlib_class.py b/bindings/python/test_Hamlib_class.py
index 6b0deff43..f47f8f15a 100755
--- a/bindings/python/test_Hamlib_class.py
+++ b/bindings/python/test_Hamlib_class.py
@@ -677,6 +677,7 @@ class TestClass:
'RIG_MODEL_GRAUDIO',
'RIG_MODEL_GRAUDIOIQ',
'RIG_MODEL_GS100',
+'RIG_MODEL_HAMGEEK_USDX',
'RIG_MODEL_HF1000',
'RIG_MODEL_HF1000A',
'RIG_MODEL_HF150',
diff --git a/include/hamlib/riglist.h b/include/hamlib/riglist.h
index 7c6d683fe..378915e9a 100644
--- a/include/hamlib/riglist.h
+++ b/include/hamlib/riglist.h
@@ -247,7 +247,8 @@
#define RIG_MODEL_THETIS RIG_MAKE_MODEL(RIG_KENWOOD, 54)
#define RIG_MODEL_TRUSDX RIG_MAKE_MODEL(RIG_KENWOOD, 55)
#define RIG_MODEL_SDRCONSOLE RIG_MAKE_MODEL(RIG_KENWOOD, 56)
-#define RIG_MODEL_QRPLABS_QMX RIG_MAKE_MODEL(RIG_KENWOOD,57)
+#define RIG_MODEL_QRPLABS_QMX RIG_MAKE_MODEL(RIG_KENWOOD, 57)
+#define RIG_MODEL_HAMGEEK_USDX RIG_MAKE_MODEL(RIG_KENWOOD, 58)
///@}
/*
diff --git a/rigs/kenwood/Android.mk b/rigs/kenwood/Android.mk
index 28e3c39dc..efaa9c77e 100644
--- a/rigs/kenwood/Android.mk
+++ b/rigs/kenwood/Android.mk
@@ -8,7 +8,7 @@ LOCAL_SRC_FILES := ts850.c ts870s.c ts570.c ts450s.c ts950.c ts50s.c \
ts440.c ts940.c ts711.c ts811.c r5000.c \
thd7.c thf7.c thg71.c tmd700.c tmv7.c thf6a.c thd72.c tmd710.c \
kenwood.c th.c ic10.c elecraft.c transfox.c flex6xxx.c ts990s.c \
- xg3.c thd74.c flex.c pihpsdr.c ts890s.c
+ xg3.c thd74.c flex.c pihpsdr.c ts890s.c hamgeek.c
LOCAL_MODULE := kenwood
LOCAL_CFLAGS :=
diff --git a/rigs/kenwood/Makefile.am b/rigs/kenwood/Makefile.am
index c9fa89158..a01b043c4 100644
--- a/rigs/kenwood/Makefile.am
+++ b/rigs/kenwood/Makefile.am
@@ -9,7 +9,8 @@ IC10SRC = ts440.c ts940.c ts711.c ts811.c r5000.c
THSRC = thd7.c thf7.c thg71.c tmd700.c tmv7.c thf6a.c thd72.c tmd710.c thd74.c
KENWOODSRC = kenwood.c kenwood.h th.c th.h ic10.c ic10.h elecraft.c elecraft.h \
- transfox.c flex.c flex.h level_gran_kenwood.h level_gran_elecraft.h
+ transfox.c flex.c flex.h level_gran_kenwood.h level_gran_elecraft.h \
+ hamgeek.c hamgeek.h
noinst_LTLIBRARIES = libhamlib-kenwood.la
libhamlib_kenwood_la_SOURCES = $(TSSRC) $(THSRC) $(IC10SRC) $(KENWOODSRC)
diff --git a/rigs/kenwood/hamgeek.c b/rigs/kenwood/hamgeek.c
new file mode 100644
index 000000000..a5527baf1
--- /dev/null
+++ b/rigs/kenwood/hamgeek.c
@@ -0,0 +1,323 @@
+/*
+ * Hamlib Hamgeek uSDX support using supported Kenwood commands
+ * Copyright (c) 2026 Leo Pizzolante IU7TUY, ci...@iu...
+ *
+ * Currently supports:
+ * - Hamgeek uSDX: Arduino-based HF transceiver, TS-480 CAT subset over
+ * Bluetooth.
+ *
+ *
+ * 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
+ *
+ * See the file 'COPYING.LIB' in the main Hamlib distribution directory for
+ * the complete text of the GNU Lesser Public License version 2.1.
+ *
+ */
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "hamlib/rig.h"
+#include "kenwood.h"
+#include "hamgeek.h"
+
+/* ======================================================================
+ * Hamgeek uSDX
+ *
+ * Arduino-based HF transceiver with optional Bluetooth connectivity that
+ * implements a subset of the Kenwood TS-480 CAT protocol.
+ *
+ * Firmware mode encoding: MD1=LSB MD2=USB MD3=CW MD4=FM MD5=AM (1-indexed).
+ *
+ * Supported CAT commands:
+ * FA<freq>; FA; - VFO A frequency
+ * MD<n>; MD; - mode (1=LSB 2=USB 3=CW 4=FM 5=AM)
+ * TX; TX0; RX; - PTT on/off (TX sends no reply; RX replies "RX0;")
+ * IF; - full status (38-char response, same layout as TS-480;
+ * mode at position [29])
+ * PS; - power status (replies PS1;)
+ * ID; - replies "ID020;" (TS-480 ID)
+ *
+ * Not supported (returns '?;'):
+ * FB; - VFO B frequency (only VFO A accessible via CAT)
+ * FR; - VFO select (FR0;/FR1; not implemented)
+ * TQ; - transmit query (TX state not readable via CAT)
+ * ====================================================================== */
+
+/* Modes confirmed by hardware test: MD1=LSB MD2=USB MD3=CW MD4=FM MD5=AM */
+#define USDX_ALL_MODES (RIG_MODE_LSB | RIG_MODE_USB | RIG_MODE_CW | \
+ RIG_MODE_CWR | RIG_MODE_AM | RIG_MODE_FM | \
+ RIG_MODE_PKTUSB | RIG_MODE_PKTLSB)
+#define USDX_TX_MODES (RIG_MODE_LSB | RIG_MODE_USB | RIG_MODE_CW | \
+ RIG_MODE_AM | RIG_MODE_FM | RIG_MODE_PKTUSB | \
+ RIG_MODE_PKTLSB)
+/* Only VFO A is present on uSDX hardware (FB; returns '?;') */
+#define USDX_VFO RIG_VFO_A
+
+#define BACKEND_VER "20260423"
+
+/*
+ * Minimal TS-480 subset: no slope filters, no special filter width table.
+ * mode_table=NULL so kenwood_get_mode / kenwood_set_mode fall back to the
+ * default kenwood_mode_table; PKTUSB/PKTLSB are remapped in hamgeek_usdx_set_mode.
+ */
+static struct kenwood_priv_caps hamgeek_usdx_priv_caps =
+{
+ .cmdtrm = EOM_KEN,
+ .mode_table = NULL,
+};
+
+/*
+ * hamgeek_usdx_open - rig_open callback
+ *
+ * Calls kenwood_open() then disables the post-open ID verification probe
+ * (no_id=1). The uSDX firmware replies '?;' to ID;, and after TX; it sends
+ * an unsolicited "TX0;" echo that would corrupt the reply to ID; if the probe
+ * were left enabled.
+ */
+static int hamgeek_usdx_open(RIG *rig)
+{
+ struct kenwood_priv_data *priv;
+ int retval;
+
+ rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
+
+ retval = kenwood_open(rig);
+
+ if (retval != RIG_OK)
+ {
+ return retval;
+ }
+
+ priv = (struct kenwood_priv_data *)STATE(rig)->priv;
+ priv->no_id = 1; /* ID; not implemented in uSDX firmware */
+
+ return RIG_OK;
+}
+
+/*
+ * hamgeek_usdx_set_mode - kenwood_set_mode wrapper
+ *
+ * The uSDX firmware accepts MD1..MD5 only (LSB/USB/CW/FM/AM).
+ * Map unsupported Hamlib modes to the nearest implemented firmware mode:
+ * PKTUSB -> USB (MD2) digital ops via USB audio
+ * PKTLSB -> LSB (MD1)
+ * CWR -> CW (MD3) firmware has no reverse-CW mode
+ * RTTY/R -> USB/LSB
+ */
+static int hamgeek_usdx_set_mode(RIG *rig, vfo_t vfo, rmode_t mode,
+ pbwidth_t width)
+{
+ rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
+
+ if (mode == RIG_MODE_PKTUSB)
+ {
+ mode = RIG_MODE_USB;
+ }
+ else if (mode == RIG_MODE_PKTLSB)
+ {
+ mode = RIG_MODE_LSB;
+ }
+ else if (mode == RIG_MODE_CWR)
+ {
+ /* MD7 would be out-of-range; send CW (MD3) instead */
+ mode = RIG_MODE_CW;
+ }
+ else if (mode == RIG_MODE_RTTY || mode == RIG_MODE_RTTYR)
+ {
+ mode = (mode == RIG_MODE_RTTYR) ? RIG_MODE_LSB : RIG_MODE_USB;
+ }
+
+ return kenwood_set_mode(rig, vfo, mode, width);
+}
+
+/*
+ * hamgeek_usdx_set_vfo - set_vfo wrapper
+ *
+ * The uSDX firmware does not implement FR0;/FR1; (Kenwood VFO select);
+ * only VFO A is accessible via CAT. VFO_A and VFO_CURR are accepted
+ * silently; all other targets return -RIG_ENTARGET.
+ */
+static int hamgeek_usdx_set_vfo(RIG *rig, vfo_t vfo)
+{
+ rig_debug(RIG_DEBUG_VERBOSE, "%s called vfo=%s\n", __func__,
+ rig_strvfo(vfo));
+
+ if (vfo == RIG_VFO_B || vfo == RIG_VFO_SUB || vfo == RIG_VFO_MEM)
+ {
+ return -RIG_ENTARGET; /* VFO B / memory not accessible via CAT */
+ }
+
+ return RIG_OK; /* VFO_A or VFO_CURR: already selected, nothing to send */
+}
+
+/*
+ * hamgeek_usdx_set_ptt - set_ptt wrapper
+ *
+ * PTT ON: TX; / TX0; / TX1; — firmware sends NO serial reply.
+ * PTT OFF: RX; — firmware replies with "RX0;".
+ *
+ * kenwood_set_ptt calls kenwood_transaction with datasize=0 (no reply read).
+ * For PTT OFF the stray "RX0;" would accumulate in the serial buffer and
+ * corrupt the next response, so we read it explicitly here.
+ */
+static int hamgeek_usdx_set_ptt(RIG *rig, vfo_t vfo, ptt_t ptt)
+{
+ char buf[8];
+ int retval;
+
+ rig_debug(RIG_DEBUG_VERBOSE, "%s called ptt=%d\n", __func__, ptt);
+
+ if (ptt == RIG_PTT_OFF)
+ {
+ /* RX; — firmware replies "RX0;" — read and discard to keep buffer clean */
+ retval = kenwood_transaction(rig, "RX", buf, sizeof(buf));
+ }
+ else
+ {
+ /* TX / TX0 (mic) / TX1 (data) — no reply from firmware */
+ const char *cmd = (ptt == RIG_PTT_ON_MIC) ? "TX0" :
+ (ptt == RIG_PTT_ON_DATA) ? "TX1" : "TX";
+ retval = kenwood_transaction(rig, cmd, NULL, 0);
+ }
+
+ return retval;
+}
+
+/*
+ * hamgeek_usdx_get_ptt - get_ptt wrapper
+ *
+ * TQ; is not supported by the uSDX firmware (returns '?;'). The IF; field
+ * at position [29] carries the mode, not TX state; the TX status byte is
+ * always '0' regardless of PTT. Return RIG_PTT_OFF unconditionally to avoid
+ * protocol errors.
+ */
+static int hamgeek_usdx_get_ptt(RIG *rig, vfo_t vfo, ptt_t *ptt)
+{
+ rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
+
+ *ptt = RIG_PTT_OFF; /* TQ; not supported by uSDX firmware */
+ return RIG_OK;
+}
+
+/* Hamgeek uSDX rig capabilities */
+struct rig_caps hamgeek_usdx_caps =
+{
+ RIG_MODEL(RIG_MODEL_HAMGEEK_USDX),
+ .model_name = "uSDX",
+ .mfg_name = "Hamgeek",
+ .version = BACKEND_VER ".0",
+ .copyright = "LGPL",
+ .status = RIG_STATUS_ALPHA,
+ .rig_type = RIG_TYPE_TRANSCEIVER,
+ .ptt_type = RIG_PTT_RIG,
+ .dcd_type = RIG_DCD_RIG,
+ .port_type = RIG_PORT_SERIAL,
+ .serial_rate_min = 9600,
+ .serial_rate_max = 115200,
+ .serial_data_bits = 8,
+ .serial_stop_bits = 1,
+ .serial_parity = RIG_PARITY_NONE,
+ .serial_handshake = RIG_HANDSHAKE_NONE,
+ .write_delay = 0,
+ .post_write_delay = 50,
+ .timeout = 2000,
+ .retry = 3,
+
+ .preamp = { RIG_DBLST_END },
+ .attenuator = { RIG_DBLST_END },
+ .max_rit = Hz(0),
+ .max_xit = Hz(0),
+ .max_ifshift = Hz(0),
+ .targetable_vfo = RIG_TARGETABLE_FREQ,
+ .transceive = RIG_TRN_OFF,
+ .agc_level_count = 0,
+
+ .rx_range_list1 = {
+ {kHz(1800), MHz(30), USDX_ALL_MODES, -1, -1, RIG_VFO_A},
+ RIG_FRNG_END,
+ },
+ .tx_range_list1 = {
+ {kHz(1810), kHz(1850), USDX_TX_MODES, 100, 5000, RIG_VFO_A},
+ {kHz(3500), kHz(3800), USDX_TX_MODES, 100, 5000, RIG_VFO_A},
+ {kHz(5351), kHz(5367), USDX_TX_MODES, 100, 5000, RIG_VFO_A},
+ {MHz(7), kHz(7200), USDX_TX_MODES, 100, 5000, RIG_VFO_A},
+ {kHz(10100), kHz(10150), USDX_TX_MODES, 100, 5000, RIG_VFO_A},
+ {MHz(14), kHz(14350), USDX_TX_MODES, 100, 5000, RIG_VFO_A},
+ {kHz(18068), kHz(18168), USDX_TX_MODES, 100, 5000, RIG_VFO_A},
+ {MHz(21), kHz(21450), USDX_TX_MODES, 100, 5000, RIG_VFO_A},
+ {kHz(24890), kHz(24990), USDX_TX_MODES, 100, 5000, RIG_VFO_A},
+ {MHz(28), kHz(29700), USDX_TX_MODES, 100, 5000, RIG_VFO_A},
+ RIG_FRNG_END,
+ },
+ .rx_range_list2 = {
+ {kHz(1800), MHz(30), USDX_ALL_MODES, -1, -1, RIG_VFO_A},
+ RIG_FRNG_END,
+ },
+ .tx_range_list2 = {
+ {kHz(1800), MHz(2) - 1, USDX_TX_MODES, 100, 5000, RIG_VFO_A},
+ {kHz(3500), MHz(4) - 1, USDX_TX_MODES, 100, 5000, RIG_VFO_A},
+ {kHz(5351), kHz(5367), USDX_TX_MODES, 100, 5000, RIG_VFO_A},
+ {MHz(7), kHz(7300), USDX_TX_MODES, 100, 5000, RIG_VFO_A},
+ {kHz(10100), kHz(10150), USDX_TX_MODES, 100, 5000, RIG_VFO_A},
+ {MHz(14), kHz(14350), USDX_TX_MODES, 100, 5000, RIG_VFO_A},
+ {kHz(18068), kHz(18168), USDX_TX_MODES, 100, 5000, RIG_VFO_A},
+ {MHz(21), kHz(21450), USDX_TX_MODES, 100, 5000, RIG_VFO_A},
+ {kHz(24890), kHz(24990), USDX_TX_MODES, 100, 5000, RIG_VFO_A},
+ {MHz(28), kHz(29700), USDX_TX_MODES, 100, 5000, RIG_VFO_A},
+ RIG_FRNG_END,
+ },
+ .tuning_steps = {
+ {USDX_ALL_MODES, Hz(10)},
+ {USDX_ALL_MODES, Hz(100)},
+ {USDX_ALL_MODES, kHz(1)},
+ {USDX_ALL_MODES, kHz(5)},
+ {USDX_ALL_MODES, kHz(10)},
+ {USDX_ALL_MODES, kHz(100)},
+ {USDX_ALL_MODES, MHz(1)},
+ {USDX_ALL_MODES, 0}, /* any step */
+ RIG_TS_END,
+ },
+ .filters = {
+ {RIG_MODE_USB | RIG_MODE_LSB | RIG_MODE_PKTUSB | RIG_MODE_PKTLSB, kHz(2.4)},
+ {RIG_MODE_CW | RIG_MODE_CWR, Hz(500)},
+ {RIG_MODE_AM, kHz(6)},
+ {RIG_MODE_FM, kHz(12)},
+ RIG_FLT_END,
+ },
+
+ .priv = (void *)&hamgeek_usdx_priv_caps,
+ .rig_init = kenwood_init,
+ .rig_open = hamgeek_usdx_open,
+ .rig_cleanup = kenwood_cleanup,
+
+ .set_freq = kenwood_set_freq,
+ .get_freq = kenwood_get_freq,
+
+ .set_mode = hamgeek_usdx_set_mode,
+ .get_mode = kenwood_get_mode,
+
+ .set_vfo = hamgeek_usdx_set_vfo,
+ .get_vfo = kenwood_get_vfo_if,
+
+ .set_ptt = hamgeek_usdx_set_ptt,
+ .get_ptt = hamgeek_usdx_get_ptt,
+
+ .get_info = kenwood_get_info,
+
+ .hamlib_check_rig_caps = HAMLIB_CHECK_RIG_CAPS
+};
diff --git a/rigs/kenwood/hamgeek.h b/rigs/kenwood/hamgeek.h
new file mode 100644
index 000000000..1a1cc0f40
--- /dev/null
+++ b/rigs/kenwood/hamgeek.h
@@ -0,0 +1,31 @@
+/*
+ * Hamlib Hamgeek uSDX support using supported Kenwood commands
+ * Copyright (c) 2026 Leo Pizzolante IU7TUY, ci...@iu...
+ *
+ *
+ * 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
+ *
+ */
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+
+#ifndef _HAMGEEK_H
+#define _HAMGEEK_H 1
+
+#include "hamlib/rig.h"
+
+/* Hamgeek model capabilities */
+extern struct rig_caps hamgeek_usdx_caps;
+
+#endif /* _HAMGEEK_H */
diff --git a/rigs/kenwood/kenwood.c b/rigs/kenwood/kenwood.c
index 7929a8ae5..65e83f59e 100644
--- a/rigs/kenwood/kenwood.c
+++ b/rigs/kenwood/kenwood.c
@@ -6560,6 +6560,7 @@ DECLARE_INITRIG_BACKEND(kenwood)
rig_register(&fx4_caps);
rig_register(&thetis_caps);
rig_register(&trudx_caps);
+ rig_register(&hamgeek_usdx_caps);
return (RIG_OK);
}
diff --git a/rigs/kenwood/kenwood.h b/rigs/kenwood/kenwood.h
index 229bac445..7cfa96975 100644
--- a/rigs/kenwood/kenwood.h
+++ b/rigs/kenwood/kenwood.h
@@ -341,6 +341,7 @@ extern struct rig_caps qrplabs_qmx_caps;
extern struct rig_caps fx4_caps;
extern struct rig_caps thetis_caps;
extern struct rig_caps trudx_caps;
+extern struct rig_caps hamgeek_usdx_caps;
/* use when not interested in the answer, but want to check its len */
static int inline kenwood_simple_transaction(RIG *rig, const char *cmd,
-----------------------------------------------------------------------
Summary of changes:
NEWS | 1 +
bindings/python/test_Hamlib_class.py | 1 +
include/hamlib/riglist.h | 3 +-
rigs/kenwood/Android.mk | 2 +-
rigs/kenwood/Makefile.am | 3 +-
rigs/kenwood/hamgeek.c | 323 ++++++++++++++++++++++++++++++
rigs/{dummy/flrig.h => kenwood/hamgeek.h} | 18 +-
rigs/kenwood/kenwood.c | 1 +
rigs/kenwood/kenwood.h | 1 +
9 files changed, 340 insertions(+), 13 deletions(-)
create mode 100644 rigs/kenwood/hamgeek.c
copy rigs/{dummy/flrig.h => kenwood/hamgeek.h} (72%)
hooks/post-receive
--
Hamlib -- Ham radio control libraries
|
|
From: n0nb <n0...@us...> - 2026-04-24 18:17:04
|
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 07bd3b365090b37179bbcfbfaa54bfb5100b7f08 (commit)
via 2691e10cee7b5896d5a4f5dab880c2d0260e5467 (commit)
from 7a64176bd06d5e618d3e4bc279fc0f2f6f9c7a15 (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 07bd3b365090b37179bbcfbfaa54bfb5100b7f08
Author: Nate Bargmann <n0...@n0...>
Date: Fri Apr 24 13:08:02 2026 -0500
Rename macro to quell warning
GCC on Debian 13 generated this warning:
CC hamgeek.lo
../../../../rigs/kenwood/hamgeek.c:71:9: warning: "BACKEND_VER" redefined
71 | #define BACKEND_VER "20260423"
| ^~~~~~~~~~~
In file included from ../../../../rigs/kenwood/hamgeek.c:35:
../../../../rigs/kenwood/kenwood.h:33:9: note: this is the location of the previous definition
33 | #define BACKEND_VER "20250515"
| ^~~~~~~~~~~
Renamimg the macro to USDX_BACKEND_VER quelled the warning.
diff --git a/rigs/kenwood/hamgeek.c b/rigs/kenwood/hamgeek.c
index a5527baf1..b5902279c 100644
--- a/rigs/kenwood/hamgeek.c
+++ b/rigs/kenwood/hamgeek.c
@@ -68,7 +68,7 @@
/* Only VFO A is present on uSDX hardware (FB; returns '?;') */
#define USDX_VFO RIG_VFO_A
-#define BACKEND_VER "20260423"
+#define USDX_BACKEND_VER "20260423"
/*
* Minimal TS-480 subset: no slope filters, no special filter width table.
@@ -220,7 +220,7 @@ struct rig_caps hamgeek_usdx_caps =
RIG_MODEL(RIG_MODEL_HAMGEEK_USDX),
.model_name = "uSDX",
.mfg_name = "Hamgeek",
- .version = BACKEND_VER ".0",
+ .version = USDX_BACKEND_VER ".0",
.copyright = "LGPL",
.status = RIG_STATUS_ALPHA,
.rig_type = RIG_TYPE_TRANSCEIVER,
commit 2691e10cee7b5896d5a4f5dab880c2d0260e5467
Author: Leo Pizzolante <leo...@gm...>
Date: Fri Apr 24 17:40:34 2026 +0200
Add Hamgeek uSDX
diff --git a/bindings/python/test_Hamlib_class.py b/bindings/python/test_Hamlib_class.py
index 950a6d6db..be555c33b 100755
--- a/bindings/python/test_Hamlib_class.py
+++ b/bindings/python/test_Hamlib_class.py
@@ -688,6 +688,7 @@ class TestClass:
'RIG_MODEL_GRAUDIO',
'RIG_MODEL_GRAUDIOIQ',
'RIG_MODEL_GS100',
+'RIG_MODEL_HAMGEEK_USDX',
'RIG_MODEL_HF1000',
'RIG_MODEL_HF1000A',
'RIG_MODEL_HF150',
diff --git a/include/hamlib/riglist.h b/include/hamlib/riglist.h
index eb523e28f..aa43c29dd 100644
--- a/include/hamlib/riglist.h
+++ b/include/hamlib/riglist.h
@@ -247,7 +247,8 @@
#define RIG_MODEL_THETIS RIG_MAKE_MODEL(RIG_KENWOOD, 54)
#define RIG_MODEL_TRUSDX RIG_MAKE_MODEL(RIG_KENWOOD, 55)
#define RIG_MODEL_SDRCONSOLE RIG_MAKE_MODEL(RIG_KENWOOD, 56)
-#define RIG_MODEL_QRPLABS_QMX RIG_MAKE_MODEL(RIG_KENWOOD,57)
+#define RIG_MODEL_QRPLABS_QMX RIG_MAKE_MODEL(RIG_KENWOOD, 57)
+#define RIG_MODEL_HAMGEEK_USDX RIG_MAKE_MODEL(RIG_KENWOOD, 58)
///@}
/*
diff --git a/rigs/kenwood/Android.mk b/rigs/kenwood/Android.mk
index 28e3c39dc..efaa9c77e 100644
--- a/rigs/kenwood/Android.mk
+++ b/rigs/kenwood/Android.mk
@@ -8,7 +8,7 @@ LOCAL_SRC_FILES := ts850.c ts870s.c ts570.c ts450s.c ts950.c ts50s.c \
ts440.c ts940.c ts711.c ts811.c r5000.c \
thd7.c thf7.c thg71.c tmd700.c tmv7.c thf6a.c thd72.c tmd710.c \
kenwood.c th.c ic10.c elecraft.c transfox.c flex6xxx.c ts990s.c \
- xg3.c thd74.c flex.c pihpsdr.c ts890s.c
+ xg3.c thd74.c flex.c pihpsdr.c ts890s.c hamgeek.c
LOCAL_MODULE := kenwood
LOCAL_CFLAGS :=
diff --git a/rigs/kenwood/Makefile.am b/rigs/kenwood/Makefile.am
index c9fa89158..a01b043c4 100644
--- a/rigs/kenwood/Makefile.am
+++ b/rigs/kenwood/Makefile.am
@@ -9,7 +9,8 @@ IC10SRC = ts440.c ts940.c ts711.c ts811.c r5000.c
THSRC = thd7.c thf7.c thg71.c tmd700.c tmv7.c thf6a.c thd72.c tmd710.c thd74.c
KENWOODSRC = kenwood.c kenwood.h th.c th.h ic10.c ic10.h elecraft.c elecraft.h \
- transfox.c flex.c flex.h level_gran_kenwood.h level_gran_elecraft.h
+ transfox.c flex.c flex.h level_gran_kenwood.h level_gran_elecraft.h \
+ hamgeek.c hamgeek.h
noinst_LTLIBRARIES = libhamlib-kenwood.la
libhamlib_kenwood_la_SOURCES = $(TSSRC) $(THSRC) $(IC10SRC) $(KENWOODSRC)
diff --git a/rigs/kenwood/hamgeek.c b/rigs/kenwood/hamgeek.c
new file mode 100644
index 000000000..a5527baf1
--- /dev/null
+++ b/rigs/kenwood/hamgeek.c
@@ -0,0 +1,323 @@
+/*
+ * Hamlib Hamgeek uSDX support using supported Kenwood commands
+ * Copyright (c) 2026 Leo Pizzolante IU7TUY, ci...@iu...
+ *
+ * Currently supports:
+ * - Hamgeek uSDX: Arduino-based HF transceiver, TS-480 CAT subset over
+ * Bluetooth.
+ *
+ *
+ * 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
+ *
+ * See the file 'COPYING.LIB' in the main Hamlib distribution directory for
+ * the complete text of the GNU Lesser Public License version 2.1.
+ *
+ */
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "hamlib/rig.h"
+#include "kenwood.h"
+#include "hamgeek.h"
+
+/* ======================================================================
+ * Hamgeek uSDX
+ *
+ * Arduino-based HF transceiver with optional Bluetooth connectivity that
+ * implements a subset of the Kenwood TS-480 CAT protocol.
+ *
+ * Firmware mode encoding: MD1=LSB MD2=USB MD3=CW MD4=FM MD5=AM (1-indexed).
+ *
+ * Supported CAT commands:
+ * FA<freq>; FA; - VFO A frequency
+ * MD<n>; MD; - mode (1=LSB 2=USB 3=CW 4=FM 5=AM)
+ * TX; TX0; RX; - PTT on/off (TX sends no reply; RX replies "RX0;")
+ * IF; - full status (38-char response, same layout as TS-480;
+ * mode at position [29])
+ * PS; - power status (replies PS1;)
+ * ID; - replies "ID020;" (TS-480 ID)
+ *
+ * Not supported (returns '?;'):
+ * FB; - VFO B frequency (only VFO A accessible via CAT)
+ * FR; - VFO select (FR0;/FR1; not implemented)
+ * TQ; - transmit query (TX state not readable via CAT)
+ * ====================================================================== */
+
+/* Modes confirmed by hardware test: MD1=LSB MD2=USB MD3=CW MD4=FM MD5=AM */
+#define USDX_ALL_MODES (RIG_MODE_LSB | RIG_MODE_USB | RIG_MODE_CW | \
+ RIG_MODE_CWR | RIG_MODE_AM | RIG_MODE_FM | \
+ RIG_MODE_PKTUSB | RIG_MODE_PKTLSB)
+#define USDX_TX_MODES (RIG_MODE_LSB | RIG_MODE_USB | RIG_MODE_CW | \
+ RIG_MODE_AM | RIG_MODE_FM | RIG_MODE_PKTUSB | \
+ RIG_MODE_PKTLSB)
+/* Only VFO A is present on uSDX hardware (FB; returns '?;') */
+#define USDX_VFO RIG_VFO_A
+
+#define BACKEND_VER "20260423"
+
+/*
+ * Minimal TS-480 subset: no slope filters, no special filter width table.
+ * mode_table=NULL so kenwood_get_mode / kenwood_set_mode fall back to the
+ * default kenwood_mode_table; PKTUSB/PKTLSB are remapped in hamgeek_usdx_set_mode.
+ */
+static struct kenwood_priv_caps hamgeek_usdx_priv_caps =
+{
+ .cmdtrm = EOM_KEN,
+ .mode_table = NULL,
+};
+
+/*
+ * hamgeek_usdx_open - rig_open callback
+ *
+ * Calls kenwood_open() then disables the post-open ID verification probe
+ * (no_id=1). The uSDX firmware replies '?;' to ID;, and after TX; it sends
+ * an unsolicited "TX0;" echo that would corrupt the reply to ID; if the probe
+ * were left enabled.
+ */
+static int hamgeek_usdx_open(RIG *rig)
+{
+ struct kenwood_priv_data *priv;
+ int retval;
+
+ rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
+
+ retval = kenwood_open(rig);
+
+ if (retval != RIG_OK)
+ {
+ return retval;
+ }
+
+ priv = (struct kenwood_priv_data *)STATE(rig)->priv;
+ priv->no_id = 1; /* ID; not implemented in uSDX firmware */
+
+ return RIG_OK;
+}
+
+/*
+ * hamgeek_usdx_set_mode - kenwood_set_mode wrapper
+ *
+ * The uSDX firmware accepts MD1..MD5 only (LSB/USB/CW/FM/AM).
+ * Map unsupported Hamlib modes to the nearest implemented firmware mode:
+ * PKTUSB -> USB (MD2) digital ops via USB audio
+ * PKTLSB -> LSB (MD1)
+ * CWR -> CW (MD3) firmware has no reverse-CW mode
+ * RTTY/R -> USB/LSB
+ */
+static int hamgeek_usdx_set_mode(RIG *rig, vfo_t vfo, rmode_t mode,
+ pbwidth_t width)
+{
+ rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
+
+ if (mode == RIG_MODE_PKTUSB)
+ {
+ mode = RIG_MODE_USB;
+ }
+ else if (mode == RIG_MODE_PKTLSB)
+ {
+ mode = RIG_MODE_LSB;
+ }
+ else if (mode == RIG_MODE_CWR)
+ {
+ /* MD7 would be out-of-range; send CW (MD3) instead */
+ mode = RIG_MODE_CW;
+ }
+ else if (mode == RIG_MODE_RTTY || mode == RIG_MODE_RTTYR)
+ {
+ mode = (mode == RIG_MODE_RTTYR) ? RIG_MODE_LSB : RIG_MODE_USB;
+ }
+
+ return kenwood_set_mode(rig, vfo, mode, width);
+}
+
+/*
+ * hamgeek_usdx_set_vfo - set_vfo wrapper
+ *
+ * The uSDX firmware does not implement FR0;/FR1; (Kenwood VFO select);
+ * only VFO A is accessible via CAT. VFO_A and VFO_CURR are accepted
+ * silently; all other targets return -RIG_ENTARGET.
+ */
+static int hamgeek_usdx_set_vfo(RIG *rig, vfo_t vfo)
+{
+ rig_debug(RIG_DEBUG_VERBOSE, "%s called vfo=%s\n", __func__,
+ rig_strvfo(vfo));
+
+ if (vfo == RIG_VFO_B || vfo == RIG_VFO_SUB || vfo == RIG_VFO_MEM)
+ {
+ return -RIG_ENTARGET; /* VFO B / memory not accessible via CAT */
+ }
+
+ return RIG_OK; /* VFO_A or VFO_CURR: already selected, nothing to send */
+}
+
+/*
+ * hamgeek_usdx_set_ptt - set_ptt wrapper
+ *
+ * PTT ON: TX; / TX0; / TX1; — firmware sends NO serial reply.
+ * PTT OFF: RX; — firmware replies with "RX0;".
+ *
+ * kenwood_set_ptt calls kenwood_transaction with datasize=0 (no reply read).
+ * For PTT OFF the stray "RX0;" would accumulate in the serial buffer and
+ * corrupt the next response, so we read it explicitly here.
+ */
+static int hamgeek_usdx_set_ptt(RIG *rig, vfo_t vfo, ptt_t ptt)
+{
+ char buf[8];
+ int retval;
+
+ rig_debug(RIG_DEBUG_VERBOSE, "%s called ptt=%d\n", __func__, ptt);
+
+ if (ptt == RIG_PTT_OFF)
+ {
+ /* RX; — firmware replies "RX0;" — read and discard to keep buffer clean */
+ retval = kenwood_transaction(rig, "RX", buf, sizeof(buf));
+ }
+ else
+ {
+ /* TX / TX0 (mic) / TX1 (data) — no reply from firmware */
+ const char *cmd = (ptt == RIG_PTT_ON_MIC) ? "TX0" :
+ (ptt == RIG_PTT_ON_DATA) ? "TX1" : "TX";
+ retval = kenwood_transaction(rig, cmd, NULL, 0);
+ }
+
+ return retval;
+}
+
+/*
+ * hamgeek_usdx_get_ptt - get_ptt wrapper
+ *
+ * TQ; is not supported by the uSDX firmware (returns '?;'). The IF; field
+ * at position [29] carries the mode, not TX state; the TX status byte is
+ * always '0' regardless of PTT. Return RIG_PTT_OFF unconditionally to avoid
+ * protocol errors.
+ */
+static int hamgeek_usdx_get_ptt(RIG *rig, vfo_t vfo, ptt_t *ptt)
+{
+ rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
+
+ *ptt = RIG_PTT_OFF; /* TQ; not supported by uSDX firmware */
+ return RIG_OK;
+}
+
+/* Hamgeek uSDX rig capabilities */
+struct rig_caps hamgeek_usdx_caps =
+{
+ RIG_MODEL(RIG_MODEL_HAMGEEK_USDX),
+ .model_name = "uSDX",
+ .mfg_name = "Hamgeek",
+ .version = BACKEND_VER ".0",
+ .copyright = "LGPL",
+ .status = RIG_STATUS_ALPHA,
+ .rig_type = RIG_TYPE_TRANSCEIVER,
+ .ptt_type = RIG_PTT_RIG,
+ .dcd_type = RIG_DCD_RIG,
+ .port_type = RIG_PORT_SERIAL,
+ .serial_rate_min = 9600,
+ .serial_rate_max = 115200,
+ .serial_data_bits = 8,
+ .serial_stop_bits = 1,
+ .serial_parity = RIG_PARITY_NONE,
+ .serial_handshake = RIG_HANDSHAKE_NONE,
+ .write_delay = 0,
+ .post_write_delay = 50,
+ .timeout = 2000,
+ .retry = 3,
+
+ .preamp = { RIG_DBLST_END },
+ .attenuator = { RIG_DBLST_END },
+ .max_rit = Hz(0),
+ .max_xit = Hz(0),
+ .max_ifshift = Hz(0),
+ .targetable_vfo = RIG_TARGETABLE_FREQ,
+ .transceive = RIG_TRN_OFF,
+ .agc_level_count = 0,
+
+ .rx_range_list1 = {
+ {kHz(1800), MHz(30), USDX_ALL_MODES, -1, -1, RIG_VFO_A},
+ RIG_FRNG_END,
+ },
+ .tx_range_list1 = {
+ {kHz(1810), kHz(1850), USDX_TX_MODES, 100, 5000, RIG_VFO_A},
+ {kHz(3500), kHz(3800), USDX_TX_MODES, 100, 5000, RIG_VFO_A},
+ {kHz(5351), kHz(5367), USDX_TX_MODES, 100, 5000, RIG_VFO_A},
+ {MHz(7), kHz(7200), USDX_TX_MODES, 100, 5000, RIG_VFO_A},
+ {kHz(10100), kHz(10150), USDX_TX_MODES, 100, 5000, RIG_VFO_A},
+ {MHz(14), kHz(14350), USDX_TX_MODES, 100, 5000, RIG_VFO_A},
+ {kHz(18068), kHz(18168), USDX_TX_MODES, 100, 5000, RIG_VFO_A},
+ {MHz(21), kHz(21450), USDX_TX_MODES, 100, 5000, RIG_VFO_A},
+ {kHz(24890), kHz(24990), USDX_TX_MODES, 100, 5000, RIG_VFO_A},
+ {MHz(28), kHz(29700), USDX_TX_MODES, 100, 5000, RIG_VFO_A},
+ RIG_FRNG_END,
+ },
+ .rx_range_list2 = {
+ {kHz(1800), MHz(30), USDX_ALL_MODES, -1, -1, RIG_VFO_A},
+ RIG_FRNG_END,
+ },
+ .tx_range_list2 = {
+ {kHz(1800), MHz(2) - 1, USDX_TX_MODES, 100, 5000, RIG_VFO_A},
+ {kHz(3500), MHz(4) - 1, USDX_TX_MODES, 100, 5000, RIG_VFO_A},
+ {kHz(5351), kHz(5367), USDX_TX_MODES, 100, 5000, RIG_VFO_A},
+ {MHz(7), kHz(7300), USDX_TX_MODES, 100, 5000, RIG_VFO_A},
+ {kHz(10100), kHz(10150), USDX_TX_MODES, 100, 5000, RIG_VFO_A},
+ {MHz(14), kHz(14350), USDX_TX_MODES, 100, 5000, RIG_VFO_A},
+ {kHz(18068), kHz(18168), USDX_TX_MODES, 100, 5000, RIG_VFO_A},
+ {MHz(21), kHz(21450), USDX_TX_MODES, 100, 5000, RIG_VFO_A},
+ {kHz(24890), kHz(24990), USDX_TX_MODES, 100, 5000, RIG_VFO_A},
+ {MHz(28), kHz(29700), USDX_TX_MODES, 100, 5000, RIG_VFO_A},
+ RIG_FRNG_END,
+ },
+ .tuning_steps = {
+ {USDX_ALL_MODES, Hz(10)},
+ {USDX_ALL_MODES, Hz(100)},
+ {USDX_ALL_MODES, kHz(1)},
+ {USDX_ALL_MODES, kHz(5)},
+ {USDX_ALL_MODES, kHz(10)},
+ {USDX_ALL_MODES, kHz(100)},
+ {USDX_ALL_MODES, MHz(1)},
+ {USDX_ALL_MODES, 0}, /* any step */
+ RIG_TS_END,
+ },
+ .filters = {
+ {RIG_MODE_USB | RIG_MODE_LSB | RIG_MODE_PKTUSB | RIG_MODE_PKTLSB, kHz(2.4)},
+ {RIG_MODE_CW | RIG_MODE_CWR, Hz(500)},
+ {RIG_MODE_AM, kHz(6)},
+ {RIG_MODE_FM, kHz(12)},
+ RIG_FLT_END,
+ },
+
+ .priv = (void *)&hamgeek_usdx_priv_caps,
+ .rig_init = kenwood_init,
+ .rig_open = hamgeek_usdx_open,
+ .rig_cleanup = kenwood_cleanup,
+
+ .set_freq = kenwood_set_freq,
+ .get_freq = kenwood_get_freq,
+
+ .set_mode = hamgeek_usdx_set_mode,
+ .get_mode = kenwood_get_mode,
+
+ .set_vfo = hamgeek_usdx_set_vfo,
+ .get_vfo = kenwood_get_vfo_if,
+
+ .set_ptt = hamgeek_usdx_set_ptt,
+ .get_ptt = hamgeek_usdx_get_ptt,
+
+ .get_info = kenwood_get_info,
+
+ .hamlib_check_rig_caps = HAMLIB_CHECK_RIG_CAPS
+};
diff --git a/rigs/kenwood/hamgeek.h b/rigs/kenwood/hamgeek.h
new file mode 100644
index 000000000..1a1cc0f40
--- /dev/null
+++ b/rigs/kenwood/hamgeek.h
@@ -0,0 +1,31 @@
+/*
+ * Hamlib Hamgeek uSDX support using supported Kenwood commands
+ * Copyright (c) 2026 Leo Pizzolante IU7TUY, ci...@iu...
+ *
+ *
+ * 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
+ *
+ */
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+
+#ifndef _HAMGEEK_H
+#define _HAMGEEK_H 1
+
+#include "hamlib/rig.h"
+
+/* Hamgeek model capabilities */
+extern struct rig_caps hamgeek_usdx_caps;
+
+#endif /* _HAMGEEK_H */
diff --git a/rigs/kenwood/kenwood.c b/rigs/kenwood/kenwood.c
index 5034ce954..71acf50c3 100644
--- a/rigs/kenwood/kenwood.c
+++ b/rigs/kenwood/kenwood.c
@@ -6564,6 +6564,7 @@ DECLARE_INITRIG_BACKEND(kenwood)
rig_register(&fx4_caps);
rig_register(&thetis_caps);
rig_register(&trudx_caps);
+ rig_register(&hamgeek_usdx_caps);
return (RIG_OK);
}
diff --git a/rigs/kenwood/kenwood.h b/rigs/kenwood/kenwood.h
index 9acf187ef..04072d9ae 100644
--- a/rigs/kenwood/kenwood.h
+++ b/rigs/kenwood/kenwood.h
@@ -343,6 +343,7 @@ extern struct rig_caps qrplabs_qmx_caps;
extern struct rig_caps fx4_caps;
extern struct rig_caps thetis_caps;
extern struct rig_caps trudx_caps;
+extern struct rig_caps hamgeek_usdx_caps;
/* use when not interested in the answer, but want to check its len */
static int inline kenwood_simple_transaction(RIG *rig, const char *cmd,
-----------------------------------------------------------------------
Summary of changes:
bindings/python/test_Hamlib_class.py | 1 +
include/hamlib/riglist.h | 3 +-
rigs/kenwood/Android.mk | 2 +-
rigs/kenwood/Makefile.am | 3 +-
rigs/kenwood/hamgeek.c | 323 ++++++++++++++++++++++++++++++
rigs/{dummy/flrig.h => kenwood/hamgeek.h} | 18 +-
rigs/kenwood/kenwood.c | 1 +
rigs/kenwood/kenwood.h | 1 +
8 files changed, 339 insertions(+), 13 deletions(-)
create mode 100644 rigs/kenwood/hamgeek.c
copy rigs/{dummy/flrig.h => kenwood/hamgeek.h} (72%)
hooks/post-receive
--
Hamlib -- Ham radio control libraries
|
|
From: n0nb <n0...@us...> - 2026-04-22 20:30:29
|
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, Hamlib-4.7 has been updated
via 3856ff650ae64a597d41207b52c43946769af9dd (commit)
via 8498864c8054e76299ae949929a31c68a92111a6 (commit)
via 57f7120a783ce982c3d31ccb0869ff9e8ab151db (commit)
via 9179a3c41c80fa36118fc93ce61c3383f6506926 (commit)
via baee8db63cfda87341be689f480895021ec2164c (commit)
from bd551aad73d207d2a00a7f5ea21f710b7ca4c304 (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 3856ff650ae64a597d41207b52c43946769af9dd
Author: Nate Bargmann <n0...@n0...>
Date: Wed Apr 22 15:27:09 2026 -0500
Update NEWS for most recent patches included in 4.7.2
diff --git a/NEWS b/NEWS
index 0b4490662..f4c6a700c 100644
--- a/NEWS
+++ b/NEWS
@@ -14,6 +14,20 @@ Version 5.x -- future
* Change FT1000MP Mark V model names to align with FT1000MP
* Internal data structures moved out of rig_struct to individual
heap buffers
+ * FTDX-3000DM: Remove all traces of this model--per Yaesu tech support,
+ its command set is unchanged from the base model. GitHub PR #2041
+ (TNX George Baltz)
+
+Version 4.7.2
+ * 2026-??-??
+ * FTX-1: Rewrite set_channel using VFO-B + BM workaround, also fix
+ the get_channel side, auto-exit Memory mode before VFO-state
+ setters, and MC cursor targeting in ftx1_set_channel. GitHub
+ PR # 2035. (TNX Terrell Deppe)
+ * IC-7600/IC-7610: Update clock routines; fix IC-7610 clock commands.
+ GitHub PR #2040 (TNX George Baltz)
+ * Icom: Add CWR to modes eligible for DSP filtering. GitHub PR #2041.
+ (TNX George Baltz)
Version 4.7.1
* 2026-04-15
commit 8498864c8054e76299ae949929a31c68a92111a6
Author: George Baltz N3GB <Geo...@gm...>
Date: Tue Apr 21 19:12:10 2026 -0400
Add CWR to modes eligible for dsp filtering
Fix issue #2038
(cherry picked from commit 147a233ed95d494a78908edb709bc6d2b6e72d8f)
diff --git a/rigs/icom/icom.c b/rigs/icom/icom.c
index fba355f59..d9239c4b7 100644
--- a/rigs/icom/icom.c
+++ b/rigs/icom/icom.c
@@ -2106,8 +2106,8 @@ pbwidth_t icom_get_dsp_flt(RIG *rig, rmode_t mode)
return ((i + 1) * 200); /* All Icoms that we know of */
}
else if (mode &
- (RIG_MODE_CW | RIG_MODE_USB | RIG_MODE_LSB | RIG_MODE_RTTY |
- RIG_MODE_RTTYR | RIG_MODE_PKTUSB | RIG_MODE_PKTLSB))
+ (RIG_MODE_CW | RIG_MODE_CWR | RIG_MODE_USB | RIG_MODE_LSB |
+ RIG_MODE_RTTY | RIG_MODE_RTTYR | RIG_MODE_PKTUSB | RIG_MODE_PKTLSB))
{
rig_debug(RIG_DEBUG_TRACE, "%s: using filtericom width=%d\n", __func__, i);
@@ -2174,8 +2174,8 @@ int icom_set_dsp_flt(RIG *rig, vfo_t vfo, rmode_t mode, pbwidth_t width)
{
flt_idx = (width / 200) - 1; /* TBC: IC_7800? */
}
- else if (mode & (RIG_MODE_CW | RIG_MODE_USB | RIG_MODE_LSB | RIG_MODE_RTTY |
- RIG_MODE_RTTYR | RIG_MODE_PKTUSB | RIG_MODE_PKTLSB))
+ else if (mode & (RIG_MODE_CW | RIG_MODE_CWR | RIG_MODE_USB | RIG_MODE_LSB |
+ RIG_MODE_RTTY | RIG_MODE_RTTYR | RIG_MODE_PKTUSB | RIG_MODE_PKTLSB))
{
if (width == 0)
{
commit 57f7120a783ce982c3d31ccb0869ff9e8ab151db
Author: George Baltz N3GB <Geo...@gm...>
Date: Wed Apr 22 11:57:32 2026 -0400
Fix IC-7610 clock commands
Values taken from previous code were wrong - new values from
IC-7610 CI-V REFERENCE GUIDE
(cherry picked from commit 912cdd963df4807cb9a4736d7d9e226d157082d2)
diff --git a/rigs/icom/ic7610.c b/rigs/icom/ic7610.c
index 9a86204b3..7e5639340 100644
--- a/rigs/icom/ic7610.c
+++ b/rigs/icom/ic7610.c
@@ -150,7 +150,7 @@ static int ic7610_ext_tokens[] =
static const struct icom_clock_cmds ic7610_clock_cmds =
{
- .date_cmds = { 0x00, 0x58 }, .time_cmds = { 0x00, 0x59 }, .offset_cmds = { 0x00, 0x62 }
+ .date_cmds = { 0x01, 0x58 }, .time_cmds = { 0x01, 0x59 }, .offset_cmds = { 0x01, 0x62 }
};
/*
commit 9179a3c41c80fa36118fc93ce61c3383f6506926
Author: George Baltz N3GB <Geo...@gm...>
Date: Mon Apr 20 05:15:06 2026 -0400
Update the last of the Icom clocks
(cherry picked from commit ee0ddd02737612e614ac2d0f44b626057a2457b3)
diff --git a/rigs/icom/ic7700.c b/rigs/icom/ic7700.c
index 095634f76..464285926 100644
--- a/rigs/icom/ic7700.c
+++ b/rigs/icom/ic7700.c
@@ -103,17 +103,22 @@
{ 241, 15.0f } \
} }
-struct cmdparams ic7700_extcmds[] =
+static struct cmdparams ic7700_extcmds[] =
{
{ {.s = RIG_LEVEL_VOXDELAY}, CMD_PARAM_TYPE_LEVEL, C_CTL_MEM, S_MEM_PARM, SC_MOD_RW, 2, {0x01, 0x82}, CMD_DAT_INT, 1 },
{ { 0 } }
};
-int ic7700_ext_tokens[] =
+static int ic7700_ext_tokens[] =
{
TOK_DRIVE_GAIN, TOK_DIGI_SEL_FUNC, TOK_DIGI_SEL_LEVEL, TOK_BACKEND_NONE
};
+static const struct icom_clock_cmds ic7700_clock_cmds =
+{
+ .date_cmds = { 0x00, 0x58 }, .time_cmds = { 0x00, 0x59 }, .offset_cmds = { 0x00, 0x61 }
+};
+
/*
* IC-7700 rig capabilities.
*/
@@ -140,120 +145,10 @@ static const struct icom_priv_caps ic7700_priv_caps =
.x1cx03_possibly = 1,
.x1ax03_supported = 1,
.mode_with_filter = 1,
- .data_mode_supported = 1
+ .data_mode_supported = 1,
+ .clock_cmds = &ic7700_clock_cmds
};
-// if hour < 0 then only date will be set
-static int ic7700_set_clock(RIG *rig, int year, int month, int day, int hour, int min,
- int sec, double msec, int utc_offset)
-{
- int cmd = 0x1a;
- int subcmd = 0x05;
- int retval = RIG_OK;
- unsigned char prmbuf[MAXFRAMELEN];
-
- if (year >= 0)
- {
- prmbuf[0] = 0x00;
- prmbuf[1] = 0x58;
- to_bcd(&prmbuf[2], year / 100, 2);
- to_bcd(&prmbuf[3], year % 100, 2);
- to_bcd(&prmbuf[4], month, 2);
- to_bcd(&prmbuf[5], day, 2);
- retval = icom_transaction(rig, cmd, subcmd, prmbuf, 6, NULL, NULL);
-
- if (retval != RIG_OK)
- {
- rig_debug(RIG_DEBUG_ERR, "%s(%d): %s\b", __func__, __LINE__, rigerror(retval));
- }
- }
-
- if (hour >= 0)
- {
- prmbuf[0] = 0x00;
- prmbuf[1] = 0x59;
- to_bcd(&prmbuf[2], hour, 2);
- to_bcd(&prmbuf[3], min, 2);
- retval = icom_transaction(rig, cmd, subcmd, prmbuf, 4, NULL, NULL);
-
- if (retval != RIG_OK)
- {
- rig_debug(RIG_DEBUG_ERR, "%s(%d): %s\b", __func__, __LINE__, rigerror(retval));
- }
-
- prmbuf[0] = 0x00;
- prmbuf[1] = 0x61;
- rig_debug(RIG_DEBUG_ERR, "%s: utc_offset=%d\n", __func__, utc_offset);
- to_bcd(&prmbuf[2], abs(utc_offset) / 100, 2);
- to_bcd(&prmbuf[3], abs(utc_offset) % 100, 2);
- to_bcd(&prmbuf[4], utc_offset >= 0 ? 0 : 1, 2);
- retval = icom_transaction(rig, cmd, subcmd, prmbuf, 5, NULL, NULL);
-
- if (retval != RIG_OK)
- {
- rig_debug(RIG_DEBUG_ERR, "%s(%d): %s\b", __func__, __LINE__, rigerror(retval));
- }
- }
-
- return retval;
-}
-
-static int ic7700_get_clock(RIG *rig, int *year, int *month, int *day, int *hour,
- int *min, int *sec, double *msec, int *utc_offset)
-{
- int cmd = 0x1a;
- int subcmd = 0x05;
- int retval = RIG_OK;
- int resplen;
- unsigned char prmbuf[MAXFRAMELEN];
- unsigned char respbuf[MAXFRAMELEN];
-
- prmbuf[0] = 0x00;
- prmbuf[1] = 0x58;
- resplen = sizeof(respbuf);
- retval = icom_transaction(rig, cmd, subcmd, prmbuf, 2, respbuf, &resplen);
- *year = from_bcd(&respbuf[4], 2) * 100 + from_bcd(&respbuf[5], 2);
- *month = from_bcd(&respbuf[6], 2);
- *day = from_bcd(&respbuf[7], 2);
-
- if (hour != NULL)
- {
- prmbuf[0] = 0x00;
- prmbuf[1] = 0x59;
- retval = icom_transaction(rig, cmd, subcmd, prmbuf, 2, respbuf, &resplen);
-
- if (retval != RIG_OK)
- {
- return retval;
- }
-
- *hour = from_bcd(&respbuf[4], 2);
- *min = from_bcd(&respbuf[5], 2);
- *sec = 0;
- *msec = 0;
-
- prmbuf[0] = 0x00;
- prmbuf[1] = 0x61;
- retval = icom_transaction(rig, cmd, subcmd, prmbuf, 2, respbuf, &resplen);
-
- if (retval != RIG_OK)
- {
- return retval;
- }
-
- *utc_offset = from_bcd(&respbuf[4], 2) * 100;
- *utc_offset += from_bcd(&respbuf[5], 2);
-
- if (respbuf[6] != 0x00) { *utc_offset *= -1; }
-
- //rig_debug(RIG_DEBUG_VERBOSE,
- // "%s: %02d-%02d-%02dT%02d:%02d:%06.3lf%s%04d\n'",
- // __func__, *year, *month, *day, *hour, *min, *sec + *msec / 1000,
- // *utc_offset >= 0 ? "+" : "-", (unsigned)abs(*utc_offset));
- }
-
- return retval;
-}
static int ic7700_rig_open(RIG *rig)
{
@@ -453,7 +348,7 @@ struct rig_caps ic7700_caps =
.send_morse = icom_send_morse,
.stop_morse = icom_stop_morse,
.wait_morse = rig_wait_morse,
- .set_clock = ic7700_set_clock,
- .get_clock = ic7700_get_clock,
+ .set_clock = icom_set_clock,
+ .get_clock = icom_get_clock,
.hamlib_check_rig_caps = HAMLIB_CHECK_RIG_CAPS
};
diff --git a/rigs/icom/ic7760.c b/rigs/icom/ic7760.c
index c57385517..7eac7d01d 100644
--- a/rigs/icom/ic7760.c
+++ b/rigs/icom/ic7760.c
@@ -102,17 +102,22 @@
{ 241, 15.0f } \
} }
-struct cmdparams ic7760_extcmds[] =
+static struct cmdparams ic7760_extcmds[] =
{
{ {.s = RIG_LEVEL_VOXDELAY}, CMD_PARAM_TYPE_LEVEL, C_CTL_MEM, S_MEM_PARM, SC_MOD_RW, 2, {0x01, 0x82}, CMD_DAT_INT, 1 },
{ { 0 } }
};
-int ic7760_ext_tokens[] =
+static int ic7760_ext_tokens[] =
{
TOK_DRIVE_GAIN, TOK_DIGI_SEL_FUNC, TOK_DIGI_SEL_LEVEL, TOK_BACKEND_NONE
};
+static const struct icom_clock_cmds ic7760_clock_cmds =
+{
+ .date_cmds = { 0x02, 0x00 }, .time_cmds = { 0x02, 0x01 }, .offset_cmds = { 0x02, 0x04 }
+};
+
/*
* IC-7760 rig capabilities.
*/
@@ -139,120 +144,10 @@ static const struct icom_priv_caps ic7760_priv_caps =
.x1cx03_possibly = 1,
.x1ax03_supported = 1,
.mode_with_filter = 1,
- .data_mode_supported = 1
+ .data_mode_supported = 1,
+ .clock_cmds = &ic7760_clock_cmds
};
-// if hour < 0 then only date will be set
-static int ic7760_set_clock(RIG *rig, int year, int month, int day, int hour, int min,
- int sec, double msec, int utc_offset)
-{
- int cmd = 0x1a;
- int subcmd = 0x05;
- int retval = RIG_OK;
- unsigned char prmbuf[MAXFRAMELEN];
-
- if (year >= 0)
- {
- prmbuf[0] = 0x02;
- prmbuf[1] = 0x05;
- to_bcd(&prmbuf[2], year / 100, 2);
- to_bcd(&prmbuf[3], year % 100, 2);
- to_bcd(&prmbuf[4], month, 2);
- to_bcd(&prmbuf[5], day, 2);
- retval = icom_transaction(rig, cmd, subcmd, prmbuf, 6, NULL, NULL);
-
- if (retval != RIG_OK)
- {
- rig_debug(RIG_DEBUG_ERR, "%s(%d): %s\b", __func__, __LINE__, rigerror(retval));
- }
- }
-
- if (hour >= 0)
- {
- prmbuf[0] = 0x02;
- prmbuf[1] = 0x06;
- to_bcd(&prmbuf[2], hour, 2);
- to_bcd(&prmbuf[3], min, 2);
- retval = icom_transaction(rig, cmd, subcmd, prmbuf, 4, NULL, NULL);
-
- if (retval != RIG_OK)
- {
- rig_debug(RIG_DEBUG_ERR, "%s(%d): %s\b", __func__, __LINE__, rigerror(retval));
- }
-
- prmbuf[0] = 0x02;
- prmbuf[1] = 0x04;
- rig_debug(RIG_DEBUG_ERR, "%s: utc_offset=%d\n", __func__, utc_offset);
- to_bcd(&prmbuf[2], abs(utc_offset) / 100, 2);
- to_bcd(&prmbuf[3], abs(utc_offset) % 100, 2);
- to_bcd(&prmbuf[4], utc_offset >= 0 ? 0 : 1, 2);
- retval = icom_transaction(rig, cmd, subcmd, prmbuf, 5, NULL, NULL);
-
- if (retval != RIG_OK)
- {
- rig_debug(RIG_DEBUG_ERR, "%s(%d): %s\b", __func__, __LINE__, rigerror(retval));
- }
- }
-
- return retval;
-}
-
-static int ic7760_get_clock(RIG *rig, int *year, int *month, int *day, int *hour,
- int *min, int *sec, double *msec, int *utc_offset)
-{
- int cmd = 0x1a;
- int subcmd = 0x05;
- int retval = RIG_OK;
- int resplen;
- unsigned char prmbuf[MAXFRAMELEN];
- unsigned char respbuf[MAXFRAMELEN];
-
- prmbuf[0] = 0x00;
- prmbuf[1] = 0x58;
- resplen = sizeof(respbuf);
- retval = icom_transaction(rig, cmd, subcmd, prmbuf, 2, respbuf, &resplen);
- *year = from_bcd(&respbuf[4], 2) * 100 + from_bcd(&respbuf[5], 2);
- *month = from_bcd(&respbuf[6], 2);
- *day = from_bcd(&respbuf[7], 2);
-
- if (hour != NULL)
- {
- prmbuf[0] = 0x00;
- prmbuf[1] = 0x59;
- retval = icom_transaction(rig, cmd, subcmd, prmbuf, 2, respbuf, &resplen);
-
- if (retval != RIG_OK)
- {
- return retval;
- }
-
- *hour = from_bcd(&respbuf[4], 2);
- *min = from_bcd(&respbuf[5], 2);
- *sec = 0;
- *msec = 0;
-
- prmbuf[0] = 0x00;
- prmbuf[1] = 0x61;
- retval = icom_transaction(rig, cmd, subcmd, prmbuf, 2, respbuf, &resplen);
-
- if (retval != RIG_OK)
- {
- return retval;
- }
-
- *utc_offset = from_bcd(&respbuf[4], 2) * 100;
- *utc_offset += from_bcd(&respbuf[5], 2);
-
- if (respbuf[6] != 0x00) { *utc_offset *= -1; }
-
- //rig_debug(RIG_DEBUG_VERBOSE,
- // "%s: %02d-%02d-%02dT%02d:%02d:%06.3lf%s%04d\n'",
- // __func__, *year, *month, *day, *hour, *min, *sec + *msec / 1000,
- // *utc_offset >= 0 ? "+" : "-", (unsigned)abs(*utc_offset));
- }
-
- return retval;
-}
static int ic7760_rig_open(RIG *rig)
{
@@ -450,7 +345,7 @@ struct rig_caps ic7760_caps =
.send_morse = icom_send_morse,
.stop_morse = icom_stop_morse,
.wait_morse = rig_wait_morse,
- .set_clock = ic7760_set_clock,
- .get_clock = ic7760_get_clock,
+ .set_clock = icom_set_clock,
+ .get_clock = icom_get_clock,
.hamlib_check_rig_caps = HAMLIB_CHECK_RIG_CAPS
};
commit baee8db63cfda87341be689f480895021ec2164c
Author: George Baltz N3GB <Geo...@gm...>
Date: Sun Apr 19 22:35:04 2026 -0400
Update clock routines for IC-7600 & IC-7610
Resturns rigs/icom/ic7600.c and rigs/icom/ic7610.c to data only.
(cherry picked from commit 99e63bf6414895b6d20ee70388bab44887349364)
diff --git a/rigs/icom/ic7600.c b/rigs/icom/ic7600.c
index b01c8c53e..0b4610bd7 100644
--- a/rigs/icom/ic7600.c
+++ b/rigs/icom/ic7600.c
@@ -127,7 +127,7 @@
{ 241, 25.0f } \
} }
-struct cmdparams ic7600_extcmds[] =
+static struct cmdparams ic7600_extcmds[] =
{
{ {.s = RIG_PARM_BEEP}, CMD_PARAM_TYPE_PARM, C_CTL_MEM, S_MEM_PARM, SC_MOD_RW, 2, {0x00, 0x59}, CMD_DAT_BOL, 1 },
{ {.s = RIG_PARM_BACKLIGHT}, CMD_PARAM_TYPE_PARM, C_CTL_MEM, S_MEM_PARM, SC_MOD_RW, 2, {0x00, 0x38}, CMD_DAT_LVL, 2 },
@@ -137,11 +137,16 @@ struct cmdparams ic7600_extcmds[] =
{ { 0 } }
};
-int ic7600_ext_tokens[] =
+static int ic7600_ext_tokens[] =
{
TOK_DRIVE_GAIN, TOK_BACKEND_NONE
};
+static const struct icom_clock_cmds ic7600_clock_cmds =
+{
+ .date_cmds = { 0x00, 0x53 }, .time_cmds = { 0x00, 0x54 }, .offset_cmds = { 0x00, 0x56 }
+};
+
/*
* IC-7600 rig capabilities.
*/
@@ -167,122 +172,10 @@ static const struct icom_priv_caps ic7600_priv_caps =
.x1cx03_possibly = 1,
.x1ax03_supported = 1,
.mode_with_filter = 1,
- .data_mode_supported = 1
+ .data_mode_supported = 1,
+ .clock_cmds = &ic7600_clock_cmds
};
-
-// if hour < 0 then only date will be set
-static int ic7600_set_clock(RIG *rig, int year, int month, int day, int hour, int min,
- int sec, double msec, int utc_offset)
-{
- int cmd = 0x1a;
- int subcmd = 0x05;
- int retval = RIG_OK;
- unsigned char prmbuf[MAXFRAMELEN];
-
- if (year >= 0)
- {
- prmbuf[0] = 0x00;
- prmbuf[1] = 0x53;
- to_bcd(&prmbuf[2], year / 100, 2);
- to_bcd(&prmbuf[3], year % 100, 2);
- to_bcd(&prmbuf[4], month, 2);
- to_bcd(&prmbuf[5], day, 2);
- retval = icom_transaction(rig, cmd, subcmd, prmbuf, 6, NULL, NULL);
-
- if (retval != RIG_OK)
- {
- rig_debug(RIG_DEBUG_ERR, "%s(%d): %s\b", __func__, __LINE__, rigerror(retval));
- }
- }
-
- if (hour >= 0)
- {
- prmbuf[0] = 0x00;
- prmbuf[1] = 0x54;
- to_bcd(&prmbuf[2], hour, 2);
- to_bcd(&prmbuf[3], min, 2);
- retval = icom_transaction(rig, cmd, subcmd, prmbuf, 4, NULL, NULL);
-
- if (retval != RIG_OK)
- {
- rig_debug(RIG_DEBUG_ERR, "%s(%d): %s\b", __func__, __LINE__, rigerror(retval));
- }
-
- prmbuf[0] = 0x00;
- prmbuf[1] = 0x56;
- rig_debug(RIG_DEBUG_ERR, "%s: utc_offset=%d\n", __func__, utc_offset);
- to_bcd(&prmbuf[2], abs(utc_offset) / 100, 2);
- to_bcd(&prmbuf[3], abs(utc_offset) % 100, 2);
- to_bcd(&prmbuf[4], utc_offset >= 0 ? 0 : 1, 2);
- retval = icom_transaction(rig, cmd, subcmd, prmbuf, 5, NULL, NULL);
-
- if (retval != RIG_OK)
- {
- rig_debug(RIG_DEBUG_ERR, "%s(%d): %s\b", __func__, __LINE__, rigerror(retval));
- }
- }
-
- return retval;
-}
-
-static int ic7600_get_clock(RIG *rig, int *year, int *month, int *day, int *hour,
- int *min, int *sec, double *msec, int *utc_offset)
-{
- int cmd = 0x1a;
- int subcmd = 0x05;
- int retval = RIG_OK;
- int resplen;
- unsigned char prmbuf[MAXFRAMELEN];
- unsigned char respbuf[MAXFRAMELEN];
-
- prmbuf[0] = 0x00;
- prmbuf[1] = 0x53;
- resplen = sizeof(respbuf);
- retval = icom_transaction(rig, cmd, subcmd, prmbuf, 2, respbuf, &resplen);
- *year = from_bcd(&respbuf[4], 2) * 100 + from_bcd(&respbuf[5], 2);
- *month = from_bcd(&respbuf[6], 2);
- *day = from_bcd(&respbuf[7], 2);
-
- if (hour != NULL)
- {
- prmbuf[0] = 0x00;
- prmbuf[1] = 0x54;
- retval = icom_transaction(rig, cmd, subcmd, prmbuf, 2, respbuf, &resplen);
-
- if (retval != RIG_OK)
- {
- return retval;
- }
-
- *hour = from_bcd(&respbuf[4], 2);
- *min = from_bcd(&respbuf[5], 2);
- *sec = 0;
- *msec = 0;
-
- prmbuf[0] = 0x00;
- prmbuf[1] = 0x56;
- retval = icom_transaction(rig, cmd, subcmd, prmbuf, 2, respbuf, &resplen);
-
- if (retval != RIG_OK)
- {
- return retval;
- }
-
- *utc_offset = from_bcd(&respbuf[4], 2) * 100;
- *utc_offset += from_bcd(&respbuf[5], 2);
-
- if (respbuf[6] != 0x00) { *utc_offset *= -1; }
-
- //rig_debug(RIG_DEBUG_VERBOSE,
- // "%s: %02d-%02d-%02dT%02d:%02d:%06.3lf%s%04d\n'",
- // __func__, *year, *month, *day, *hour, *min, *sec + *msec / 1000,
- // *utc_offset >= 0 ? "+" : "-", (unsigned)abs(*utc_offset));
- }
-
- return retval;
-}
-
struct rig_caps ic7600_caps =
{
RIG_MODEL(RIG_MODEL_IC7600),
@@ -478,7 +371,7 @@ struct rig_caps ic7600_caps =
.get_powerstat = icom_get_powerstat,
.send_morse = icom_send_morse,
.wait_morse = rig_wait_morse,
- .set_clock = ic7600_set_clock,
- .get_clock = ic7600_get_clock,
+ .set_clock = icom_set_clock,
+ .get_clock = icom_get_clock,
.hamlib_check_rig_caps = HAMLIB_CHECK_RIG_CAPS
};
diff --git a/rigs/icom/ic7610.c b/rigs/icom/ic7610.c
index 9f6e322fb..9a86204b3 100644
--- a/rigs/icom/ic7610.c
+++ b/rigs/icom/ic7610.c
@@ -128,7 +128,7 @@
{ 241, 30.0f } \
} }
-struct cmdparams ic7610_extcmds[] =
+static struct cmdparams ic7610_extcmds[] =
{
{ {.s = RIG_PARM_BEEP}, CMD_PARAM_TYPE_PARM, C_CTL_MEM, S_MEM_PARM, SC_MOD_RW, 2, {0x00, 0x24}, CMD_DAT_BOL, 1 },
{ {.s = RIG_PARM_BACKLIGHT}, CMD_PARAM_TYPE_PARM, C_CTL_MEM, S_MEM_PARM, SC_MOD_RW, 2, {0x01, 0x41}, CMD_DAT_LVL, 2 },
@@ -141,13 +141,18 @@ struct cmdparams ic7610_extcmds[] =
{ { 0 } }
};
-int ic7610_ext_tokens[] =
+static int ic7610_ext_tokens[] =
{
TOK_DRIVE_GAIN, TOK_DIGI_SEL_FUNC, TOK_DIGI_SEL_LEVEL,
TOK_SCOPE_MSS, TOK_SCOPE_SDS, TOK_SCOPE_STX, TOK_SCOPE_CFQ, TOK_SCOPE_EDG, TOK_SCOPE_VBW, TOK_SCOPE_RBW, TOK_SCOPE_MKP, TOK_IPP_FUNC, TOK_TX_INHIBIT_FUNC, TOK_DPP_FUNC, TOK_ICPW2_FUNC,
TOK_BACKEND_NONE
};
+static const struct icom_clock_cmds ic7610_clock_cmds =
+{
+ .date_cmds = { 0x00, 0x58 }, .time_cmds = { 0x00, 0x59 }, .offset_cmds = { 0x00, 0x62 }
+};
+
/*
* IC-7610 rig capabilities.
*/
@@ -248,122 +253,10 @@ static const struct icom_priv_caps ic7610_priv_caps =
.x1cx03_possibly = 1,
.x1ax03_supported = 1,
.mode_with_filter = 1,
- .data_mode_supported = 1
+ .data_mode_supported = 1,
+ .clock_cmds = &ic7610_clock_cmds
};
-
-// if hour < 0 then only date will be set
-static int ic7610_set_clock(RIG *rig, int year, int month, int day, int hour, int min,
- int sec, double msec, int utc_offset)
-{
- int cmd = 0x1a;
- int subcmd = 0x05;
- int retval = RIG_OK;
- unsigned char prmbuf[MAXFRAMELEN];
-
- if (year >= 0)
- {
- prmbuf[0] = 0x00;
- prmbuf[1] = 0x58;
- to_bcd(&prmbuf[2], year / 100, 2);
- to_bcd(&prmbuf[3], year % 100, 2);
- to_bcd(&prmbuf[4], month, 2);
- to_bcd(&prmbuf[5], day, 2);
- retval = icom_transaction(rig, cmd, subcmd, prmbuf, 6, NULL, NULL);
-
- if (retval != RIG_OK)
- {
- rig_debug(RIG_DEBUG_ERR, "%s(%d): %s\b", __func__, __LINE__, rigerror(retval));
- }
- }
-
- if (hour >= 0)
- {
- prmbuf[0] = 0x00;
- prmbuf[1] = 0x59;
- to_bcd(&prmbuf[2], hour, 2);
- to_bcd(&prmbuf[3], min, 2);
- retval = icom_transaction(rig, cmd, subcmd, prmbuf, 4, NULL, NULL);
-
- if (retval != RIG_OK)
- {
- rig_debug(RIG_DEBUG_ERR, "%s(%d): %s\b", __func__, __LINE__, rigerror(retval));
- }
-
- prmbuf[0] = 0x00;
- prmbuf[1] = 0x62;
- rig_debug(RIG_DEBUG_ERR, "%s: utc_offset=%d\n", __func__, utc_offset);
- to_bcd(&prmbuf[2], abs(utc_offset) / 100, 2);
- to_bcd(&prmbuf[3], abs(utc_offset) % 100, 2);
- to_bcd(&prmbuf[4], utc_offset >= 0 ? 0 : 1, 2);
- retval = icom_transaction(rig, cmd, subcmd, prmbuf, 5, NULL, NULL);
-
- if (retval != RIG_OK)
- {
- rig_debug(RIG_DEBUG_ERR, "%s(%d): %s\b", __func__, __LINE__, rigerror(retval));
- }
- }
-
- return retval;
-}
-
-static int ic7610_get_clock(RIG *rig, int *year, int *month, int *day, int *hour,
- int *min, int *sec, double *msec, int *utc_offset)
-{
- int cmd = 0x1a;
- int subcmd = 0x05;
- int retval = RIG_OK;
- int resplen;
- unsigned char prmbuf[MAXFRAMELEN];
- unsigned char respbuf[MAXFRAMELEN];
-
- prmbuf[0] = 0x00;
- prmbuf[1] = 0x58;
- resplen = sizeof(respbuf);
- retval = icom_transaction(rig, cmd, subcmd, prmbuf, 2, respbuf, &resplen);
- *year = from_bcd(&respbuf[4], 2) * 100 + from_bcd(&respbuf[5], 2);
- *month = from_bcd(&respbuf[6], 2);
- *day = from_bcd(&respbuf[7], 2);
-
- if (hour != NULL)
- {
- prmbuf[0] = 0x00;
- prmbuf[1] = 0x59;
- retval = icom_transaction(rig, cmd, subcmd, prmbuf, 2, respbuf, &resplen);
-
- if (retval != RIG_OK)
- {
- return retval;
- }
-
- *hour = from_bcd(&respbuf[4], 2);
- *min = from_bcd(&respbuf[5], 2);
- *sec = 0;
- *msec = 0;
-
- prmbuf[0] = 0x00;
- prmbuf[1] = 0x62;
- retval = icom_transaction(rig, cmd, subcmd, prmbuf, 2, respbuf, &resplen);
-
- if (retval != RIG_OK)
- {
- return retval;
- }
-
- *utc_offset = from_bcd(&respbuf[4], 2) * 100;
- *utc_offset += from_bcd(&respbuf[5], 2);
-
- if (respbuf[6] != 0x00) { *utc_offset *= -1; }
-
- //rig_debug(RIG_DEBUG_VERBOSE,
- // "%s: %02d-%02d-%02dT%02d:%02d:%06.3lf%s%04d\n'",
- // __func__, *year, *month, *day, *hour, *min, *sec + *msec / 1000,
- // *utc_offset >= 0 ? "+" : "-", (unsigned)abs(*utc_offset));
- }
-
- return retval;
-}
-
struct rig_caps ic7610_caps =
{
RIG_MODEL(RIG_MODEL_IC7610),
@@ -619,7 +512,7 @@ struct rig_caps ic7610_caps =
.wait_morse = rig_wait_morse,
.send_voice_mem = icom_send_voice_mem,
.stop_voice_mem = icom_stop_voice_mem,
- .set_clock = ic7610_set_clock,
- .get_clock = ic7610_get_clock,
+ .set_clock = icom_set_clock,
+ .get_clock = icom_get_clock,
.hamlib_check_rig_caps = HAMLIB_CHECK_RIG_CAPS
};
-----------------------------------------------------------------------
Summary of changes:
NEWS | 14 ++++++
rigs/icom/ic7600.c | 129 +++++------------------------------------------------
rigs/icom/ic7610.c | 129 +++++------------------------------------------------
rigs/icom/ic7700.c | 127 +++++-----------------------------------------------
rigs/icom/ic7760.c | 127 +++++-----------------------------------------------
rigs/icom/icom.c | 8 ++--
6 files changed, 62 insertions(+), 472 deletions(-)
hooks/post-receive
--
Hamlib -- Ham radio control libraries
|
|
From: n0nb <n0...@us...> - 2026-04-22 20:07:32
|
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 7a64176bd06d5e618d3e4bc279fc0f2f6f9c7a15 (commit)
via 2f3d01728b2fac145717755ccc144da97d3bd5ef (commit)
via 147a233ed95d494a78908edb709bc6d2b6e72d8f (commit)
from 912cdd963df4807cb9a4736d7d9e226d157082d2 (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 7a64176bd06d5e618d3e4bc279fc0f2f6f9c7a15
Merge: 912cdd963 2f3d01728
Author: Nate Bargmann <n0...@n0...>
Date: Wed Apr 22 14:55:06 2026 -0500
Merge GitHub PR #2041
commit 2f3d01728b2fac145717755ccc144da97d3bd5ef
Author: George Baltz N3GB <Geo...@gm...>
Date: Wed Apr 22 06:05:51 2026 -0400
Remove all traces of FTDX3000DM
Per Yaesu Tech support, treat all FTDX-3000 models the same. See comments
in PR #2039.
While removing references to FTDX-3000DM, I happened across simft818.c.
It set a new low for simulators. It is completely wrong - it uses
new CAT protocol, while the rig uses the old 5-byte binary version.
If you want to simulate the FT-818, start over with simft817.c as
the basis, because this one is gone.
diff --git a/rigs/yaesu/ft1200.c b/rigs/yaesu/ft1200.c
index 135c726a0..1fe619e46 100644
--- a/rigs/yaesu/ft1200.c
+++ b/rigs/yaesu/ft1200.c
@@ -33,7 +33,7 @@
#include "ft1200.h"
#include "tones.h"
-// Shared with FTDX-3000/FTDX-3000dm
+// Shared with FTDX-3000
const struct newcat_width_info ftdx1200_cw_widths =
{
.count = 17,
diff --git a/rigs/yaesu/newcat.c b/rigs/yaesu/newcat.c
index d2cc92694..868bd02e1 100644
--- a/rigs/yaesu/newcat.c
+++ b/rigs/yaesu/newcat.c
@@ -69,8 +69,7 @@ typedef enum nc_rigid_e
NC_RIGID_FTDX9000Contest = 102,
NC_RIGID_FTDX9000MP = 103,
NC_RIGID_FTDX5000 = 362,
- NC_RIGID_FTDX3000 = 460,
- NC_RIGID_FTDX3000DM = 462, // an undocumented FT-DX3000DM 50W rig
+ NC_RIGID_FTDX3000 = 462,
NC_RIGID_FTDX101D = 681,
NC_RIGID_FTDX101MP = 682,
NC_RIGID_FT710 = 800,
@@ -185,11 +184,9 @@ static const rptr_offs_cmd_entry_t rptr_offs_cmd_table[] = {
{ NC_RIGID_FTDX1200, RPTR_BAND_10M, "EX087", RPTR_OFFS_STEP_1K },
{ NC_RIGID_FTDX1200, RPTR_BAND_6M, "EX088", RPTR_OFFS_STEP_1K },
- /* FTDX-3000/FTDX-3000DM */
+ /* FTDX-3000 */
{ NC_RIGID_FTDX3000, RPTR_BAND_10M, "EX086", RPTR_OFFS_STEP_1K },
{ NC_RIGID_FTDX3000, RPTR_BAND_6M, "EX087", RPTR_OFFS_STEP_1K },
- { NC_RIGID_FTDX3000DM, RPTR_BAND_10M, "EX086", RPTR_OFFS_STEP_1K },
- { NC_RIGID_FTDX3000DM, RPTR_BAND_6M, "EX087", RPTR_OFFS_STEP_1K },
/* FTDX-5000 */
{ NC_RIGID_FTDX5000, RPTR_BAND_10M, "EX081", RPTR_OFFS_STEP_1K },
@@ -238,9 +235,8 @@ static const antivox_cmd_entry_t antivox_cmd_table[] = {
/* FTDX-5000: EX176 */
{ NC_RIGID_FTDX5000, "EX176", NULL },
- /* FTDX-3000/3000DM, FTDX-1200: EX183 */
+ /* FTDX-3000, FTDX-1200: EX183 */
{ NC_RIGID_FTDX3000, "EX183", NULL },
- { NC_RIGID_FTDX3000DM,"EX183", NULL },
{ NC_RIGID_FTDX1200, "EX183", NULL },
/* FT-991/991A: EX145 for set, EX147 for get (different menu items) */
@@ -430,27 +426,6 @@ const cal_table_float_t yaesu_default_id_meter_cal =
}
};
-#if 0 // This cannot handle multiple rigs! (Think SO2R)
-// Easy reference to rig model -- it is set in newcat_valid_command
-static ncboolean is_ft450;
-static ncboolean is_ft710;
-static ncboolean is_ft891;
-static ncboolean is_ft897;
-static ncboolean is_ft897d;
-static ncboolean is_ft950;
-static ncboolean is_ft991;
-static ncboolean is_ft2000;
-static ncboolean is_ftdx9000;
-static ncboolean is_ftdx5000;
-static ncboolean is_ftdx1200;
-static ncboolean is_ftdx3000;
-static ncboolean is_ftdx3000dm;
-static ncboolean is_ftdx101d;
-static ncboolean is_ftdx101mp;
-static ncboolean is_ftdx10;
-static ncboolean is_ftx1;
-static ncboolean is_ftdx9000Old;
-#else
// These assume there is a 'rig' in scope
#define is_ft450 (RIG_MODEL_FT450==rig->caps->rig_model || RIG_MODEL_FT450D==rig->caps->rig_model)
#define is_ft710 (RIG_MODEL_FT710==rig->caps->rig_model)
@@ -465,13 +440,10 @@ static ncboolean is_ftdx9000Old;
#define is_ftdx101mp (RIG_MODEL_FTDX101MP==rig->caps->rig_model)
#define is_ftdx1200 (RIG_MODEL_FTDX1200==rig->caps->rig_model)
#define is_ftdx3000 (RIG_MODEL_FTDX3000==rig->caps->rig_model)
-// Only needed to distinguish between versions of the same model
-#define is_ftdx3000dm (NC_RIGID_FTDX3000DM==((struct newcat_priv_data *)(STATE(rig)->priv))->rig_id)
#define is_ftdx5000 (RIG_MODEL_FTDX5000==rig->caps->rig_model)
#define is_ftdx9000 (RIG_MODEL_FT9000==rig->caps->rig_model)
#define is_ftdx9000Old (RIG_MODEL_FTD000OLD==rig->caps->rig_model)
#define is_ftx1 (RIG_MODEL_FTX1==rig->caps->rig_model)
-#endif
/*
* Even though this table does make a handy reference, it could be deprecated as it is not really needed.
@@ -868,8 +840,7 @@ int newcat_open(RIG *rig)
|| priv->rig_id == NC_RIGID_FT991A
|| priv->rig_id == NC_RIGID_FT950
|| priv->rig_id == NC_RIGID_FTDX10
- || priv->rig_id == NC_RIGID_FTDX3000
- || priv->rig_id == NC_RIGID_FTDX3000DM)
+ || priv->rig_id == NC_RIGID_FTDX3000)
{
char *cmd = "EX0291;EX029;"; // FT2000/D
int retry_save;
@@ -883,8 +854,6 @@ int newcat_open(RIG *rig)
|| rig->caps->rig_model == RIG_MODEL_FT991) { cmd = "EX0321;EX032;"; }
else if (priv->rig_id == NC_RIGID_FTDX3000
|| rig->caps->rig_model == RIG_MODEL_FTDX3000) { cmd = "EX0391;"; set_only = 1; }
- else if (priv->rig_id == NC_RIGID_FTDX3000DM
- || rig->caps->rig_model == RIG_MODEL_FTDX3000) { cmd = "EX0391;"; set_only = 1; }
else if (priv->rig_id == NC_RIGID_FTDX5000
|| rig->caps->rig_model == RIG_MODEL_FTDX5000) { cmd = "EX0331;EX033"; }
else if (priv->rig_id == NC_RIGID_FTDX10
@@ -912,7 +881,7 @@ int newcat_open(RIG *rig)
}
}
- if (priv->rig_id == NC_RIGID_FTDX3000 || priv->rig_id == NC_RIGID_FTDX3000DM)
+ if (priv->rig_id == NC_RIGID_FTDX3000)
{
rig_s->disable_yaesu_bandselect = 1;
rig_debug(RIG_DEBUG_VERBOSE, "%s: disabling FTDX3000 band select\n", __func__);
@@ -1254,9 +1223,9 @@ int newcat_set_freq(RIG *rig, vfo_t vfo, freq_t freq)
//special_60m = newcat_is_rig(rig, RIG_MODEL_FTDX5000);
//special_60m |= newcat_is_rig(rig, RIG_MODEL_FT450);
rig_debug(RIG_DEBUG_TRACE,
- "%s: special_60m=%d, 60m freq=%d, is_ftdx3000=%d,is_ftdx3000dm=%d\n",
+ "%s: special_60m=%d, 60m freq=%d, is_ftdx3000=%d\n",
__func__, special_60m, freq >= 5300000
- && freq <= 5410000, is_ftdx3000, is_ftdx3000dm);
+ && freq <= 5410000, is_ftdx3000);
if (special_60m && (freq >= 5300000 && freq <= 5410000))
{
@@ -4135,14 +4104,7 @@ int newcat_set_level(RIG *rig, vfo_t vfo, setting_t level, value_t val)
RETURNFUNC(-RIG_ENAVAIL);
}
- if (is_ftdx3000dm) /* No separate rig->caps for this rig :-( */
- {
- fpf = (int)((val.f * 50.0f) + 0.5f);
- }
- else
- {
- fpf = (int)((val.f / level_info->step.f) + 0.5f);
- }
+ fpf = (int)((val.f / level_info->step.f) + 0.5f);
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "PC%03d%c", fpf, cat_term);
break;
@@ -10376,8 +10338,6 @@ int newcat_get_rigid(RIG *rig)
{
s += 2; /* ID0310, jump past ID */
priv->rig_id = atoi(s);
-
- //is_ftdx3000dm = priv->rig_id == NC_RIGID_FTDX3000DM;
}
rig_debug(RIG_DEBUG_TRACE, "rig_id = %d, idstr = %s\n", priv->rig_id,
@@ -10781,8 +10741,7 @@ int newcat_set_cmd_validate(RIG *rig)
{
strcpy(valcmd, "FA;");
- if (priv->rig_id == NC_RIGID_FTDX3000 || priv->rig_id == NC_RIGID_FTDX5000
- || priv->rig_id == NC_RIGID_FTDX3000DM)
+ if (priv->rig_id == NC_RIGID_FTDX3000 || priv->rig_id == NC_RIGID_FTDX5000)
{
strcpy(valcmd, "");
}
@@ -10791,8 +10750,7 @@ int newcat_set_cmd_validate(RIG *rig)
{
strcpy(valcmd, "FB;");
- if (priv->rig_id == NC_RIGID_FTDX3000 || priv->rig_id == NC_RIGID_FTDX5000
- || priv->rig_id == NC_RIGID_FTDX3000DM)
+ if (priv->rig_id == NC_RIGID_FTDX3000 || priv->rig_id == NC_RIGID_FTDX5000)
{
strcpy(valcmd, "");
}
diff --git a/simulators/Makefile.am b/simulators/Makefile.am
index a87f73f67..33f16c199 100644
--- a/simulators/Makefile.am
+++ b/simulators/Makefile.am
@@ -20,7 +20,6 @@ check_PROGRAMS = \
simft736 \
simft747gx \
simft817 \
- simft818 \
simft847 \
simft897 \
simft990 \
diff --git a/simulators/sim.h b/simulators/sim.h
index d4030bb7b..bfff8c3a2 100644
--- a/simulators/sim.h
+++ b/simulators/sim.h
@@ -22,8 +22,7 @@ typedef enum nc_rigid_e
NC_RIGID_FTDX9000Contest = 102,
NC_RIGID_FTDX9000MP = 103,
NC_RIGID_FTDX5000 = 362,
- NC_RIGID_FTDX3000 = 460,
- NC_RIGID_FTDX3000DM = 462, // an undocumented FT-DX3000DM 50W rig
+ NC_RIGID_FTDX3000 = 462,
NC_RIGID_FTDX101D = 681,
NC_RIGID_FTDX101MP = 682,
NC_RIGID_FT710 = 800,
diff --git a/simulators/simft818.c b/simulators/simft818.c
deleted file mode 100644
index 79813b509..000000000
--- a/simulators/simft818.c
+++ /dev/null
@@ -1,264 +0,0 @@
-// can run this using rigctl/rigctld and socat pty devices
-#define _XOPEN_SOURCE 700
-// since we are POSIX here we need this
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include "hamlib/rig.h"
-#include "misc.h"
-
-
-float freqA = 14074000;
-float freqB = 14074500;
-char tx_vfo = '0';
-char rx_vfo = '0';
-vfo_t curr_vfo = RIG_VFO_A;
-char modeA = '1';
-char modeB = '1';
-int width = 0;
-int ptt;
-
-
-#include "sim.h"
-
-
-int main(int argc, char *argv[])
-{
- char buf[BUFSIZE];
- char resp[256];
- char *pbuf;
- int n;
- int fd = openPort(argv[1]);
-
- while (1)
- {
- buf[0] = 0;
-
- if (getmyline(fd, buf))
- {
- printf("Cmd:%s\n", buf);
- }
-
- //else { return 0; }
-
- if (strcmp(buf, "RM5;") == 0)
- {
- printf("%s\n", buf);
- hl_usleep(50 * 1000);
- pbuf = "RM5100000;";
- n = write(fd, pbuf, strlen(pbuf));
- printf("n=%d\n", n);
-
- if (n <= 0) { perror("RM5"); }
- }
-
- if (strcmp(buf, "AN0;") == 0)
- {
- printf("%s\n", buf);
- hl_usleep(50 * 1000);
- pbuf = "AN030;";
- n = write(fd, pbuf, strlen(pbuf));
- printf("n=%d\n", n);
-
- if (n <= 0) { perror("AN"); }
- }
- else if (strcmp(buf, "FA;") == 0)
- {
- //SNPRINTF(resp, sizeof(resp), "FA%010.0f;", freqA);
- SNPRINTF(resp, sizeof(resp), "FA%08.0f;", freqA);
- freqA += 10;
- n = write(fd, resp, strlen(resp));
- }
- else if (strncmp(buf, "FA", 2) == 0)
- {
- sscanf(buf, "FA%f", &freqA);
- }
- else if (strcmp(buf, "FB;") == 0)
- {
- //SNPRINTF(resp, sizeof(resp), "FB%0010.0f;", freqB);
- SNPRINTF(resp, sizeof(resp), "FB%08.0f;", freqB);
- n = write(fd, resp, strlen(resp));
- }
- else if (strncmp(buf, "FB", 2) == 0)
- {
- sscanf(buf, "FB%f", &freqB);
- }
- else if (strcmp(buf, "IF;") == 0)
- {
- printf("%s\n", buf);
- hl_usleep(50 * 1000);
- //pbuf = "IF00107041000+000000200000;";
- pbuf = "IF00010138698 +00000000002000000 ;";
- n = write(fd, pbuf, strlen(pbuf));
- printf("n=%d\n", n);
-
- if (n <= 0) { perror("IF"); }
- }
- else if (strcmp(buf, "ID;") == 0)
- {
- printf("%s\n", buf);
- hl_usleep(50 * 1000);
- int id = NC_RIGID_FTDX3000DM;
- SNPRINTF(buf, sizeof(buf), "ID%03d;", id);
- n = write(fd, buf, strlen(buf));
- printf("n=%d\n", n);
-
- if (n <= 0) { perror("ID"); }
- }
- else if (strcmp(buf, "AI;") == 0)
- {
- printf("%s\n", buf);
- hl_usleep(50 * 1000);
- SNPRINTF(buf, sizeof(buf), "AI0;");
- n = write(fd, buf, strlen(buf));
- printf("n=%d\n", n);
-
- if (n <= 0) { perror("ID"); }
- }
- else if (strcmp(buf, "AI0;") == 0)
- {
- hl_usleep(50 * 1000);
- }
- else if (strcmp(buf, "AB;") == 0)
- {
- freqB = freqA;
- modeB = modeA;
- }
-
-#if 0
- else if (strncmp(buf, "AI", 2) == 0)
- {
- if (strcmp(buf, "AI;"))
- {
- printf("%s\n", buf);
- hl_usleep(50 * 1000);
- n = fprintf(fp, "%s", "AI0;");
- printf("n=%d\n", n);
-
- if (n <= 0) { perror("AI"); }
- }
- }
-
-#endif
- else if (strcmp(buf, "VS") == 0 && strlen(buf) > 3)
- {
- curr_vfo = buf[3] == '1' ? RIG_VFO_B : RIG_VFO_A;
- hl_usleep(50 * 1000);
- }
- else if (strcmp(buf, "VS;") == 0)
- {
- printf("%s\n", buf);
- hl_usleep(50 * 1000);
- pbuf = strdup("VS0;");
-
- if (curr_vfo == RIG_VFO_B || curr_vfo == RIG_VFO_SUB) { pbuf[2] = '1'; }
-
- n = write(fd, pbuf, strlen(pbuf));
- printf("%s\n", pbuf);
- free(pbuf);
-
- if (n < 0) { perror("VS"); }
- }
- else if (strcmp(buf, "FT;") == 0)
- {
- hl_usleep(50 * 1000);
- SNPRINTF(resp, sizeof(resp), "FT%c;", tx_vfo);
- printf(" FT response#1=%s, tx_vfo=%c\n", resp, tx_vfo);
- n = write(fd, resp, strlen(resp));
- printf(" FT response#2=%s\n", resp);
-
- if (n < 0) { perror("FT"); }
- }
- else if (strncmp(buf, "FT", 2) == 0)
- {
- tx_vfo = buf[2];
-
- if (tx_vfo == '3') { tx_vfo = '1'; }
- else if (tx_vfo == '2') { tx_vfo = '0'; }
- else { perror("Expected 2 or 3"); }
- }
- else if (strcmp(buf, "MD0;") == 0)
- {
- hl_usleep(50 * 1000);
- SNPRINTF(resp, sizeof(resp), "MD0%c;", modeA);
- n = write(fd, resp, strlen(resp));
-
- if (n < 0) { perror("MD0;"); }
- }
- else if (strncmp(buf, "MD0", 3) == 0)
- {
- modeA = buf[3];
- }
- else if (strcmp(buf, "MD1;") == 0)
- {
- hl_usleep(50 * 1000);
- SNPRINTF(resp, sizeof(resp), "MD1%c;", modeB);
- n = write(fd, resp, strlen(resp));
-
- if (n < 0) { perror("MD0;"); }
- }
- else if (strncmp(buf, "MD1", 3) == 0)
- {
- modeB = buf[3];
- }
- else if (strcmp(buf, "SM0;") == 0)
- {
- hl_usleep(50 * 1000);
- SNPRINTF(resp, sizeof(resp), "SM0111;");
- n = write(fd, resp, strlen(resp));
-
- if (n < 0) { perror("SM"); }
- }
- else if (strcmp(buf, "TX;") == 0)
- {
- hl_usleep(50 * 1000);
- SNPRINTF(resp, sizeof(resp), "TX%d;", ptt);
- n = write(fd, resp, strlen(resp));
-
- if (n < 0) { perror("TX"); }
- }
- else if (strncmp(buf, "TX", 2) == 0)
- {
- hl_usleep(50 * 1000);
- ptt = buf[2] == '0' ? 0 : 1;
- }
- else if (strcmp(buf, "EX032;") == 0)
- {
- static int ant = 0;
- ant = (ant + 1) % 3;
- printf("%s\n", buf);
- hl_usleep(50 * 1000);
- SNPRINTF(buf, sizeof(buf), "EX032%1d;", ant);
- n = write(fd, buf, strlen(buf));
- printf("n=%d\n", n);
-
- if (n < 0) { perror("EX032"); }
- }
- else if (strcmp(buf, "SH0;") == 0)
- {
- SNPRINTF(buf, sizeof(buf), "SH0%02d;", width);
- hl_usleep(50 * 1000);
- n = write(fd, buf, strlen(buf));
- printf("%s n=%d\n", buf, n);
- }
- else if (strcmp(buf, "NA0;") == 0)
- {
- SNPRINTF(buf, sizeof(buf), "NA00;");
- hl_usleep(50 * 1000);
- n = write(fd, buf, strlen(buf));
- printf("%s n=%d\n", buf, n);
- }
-
- else if (strlen(buf) > 0)
- {
- fprintf(stderr, "Unknown command: %s\n", buf);
- }
-
- if (n == 0) { fprintf(stderr, "Write error? n==0\n"); }
-
- }
-
- return 0;
-}
diff --git a/simulators/simftdx3000.c b/simulators/simftdx3000.c
index a554dca11..c54e3beee 100644
--- a/simulators/simftdx3000.c
+++ b/simulators/simftdx3000.c
@@ -29,7 +29,6 @@ int keyspd = 24;
#include "sim.h"
#define ID NC_RIGID_FTDX3000
-//#define ID NC_RIGID_FTDX3000DM
int main(int argc, char *argv[])
{
commit 147a233ed95d494a78908edb709bc6d2b6e72d8f
Author: George Baltz N3GB <Geo...@gm...>
Date: Tue Apr 21 19:12:10 2026 -0400
Add CWR to modes eligible for dsp filtering
Fix issue #2038
diff --git a/rigs/icom/icom.c b/rigs/icom/icom.c
index f68272f6f..be03ef97a 100644
--- a/rigs/icom/icom.c
+++ b/rigs/icom/icom.c
@@ -2107,8 +2107,8 @@ pbwidth_t icom_get_dsp_flt(RIG *rig, rmode_t mode)
return ((i + 1) * 200); /* All Icoms that we know of */
}
else if (mode &
- (RIG_MODE_CW | RIG_MODE_USB | RIG_MODE_LSB | RIG_MODE_RTTY |
- RIG_MODE_RTTYR | RIG_MODE_PKTUSB | RIG_MODE_PKTLSB))
+ (RIG_MODE_CW | RIG_MODE_CWR | RIG_MODE_USB | RIG_MODE_LSB |
+ RIG_MODE_RTTY | RIG_MODE_RTTYR | RIG_MODE_PKTUSB | RIG_MODE_PKTLSB))
{
rig_debug(RIG_DEBUG_TRACE, "%s: using filtericom width=%d\n", __func__, i);
@@ -2175,8 +2175,8 @@ int icom_set_dsp_flt(RIG *rig, vfo_t vfo, rmode_t mode, pbwidth_t width)
{
flt_idx = (width / 200) - 1; /* TBC: IC_7800? */
}
- else if (mode & (RIG_MODE_CW | RIG_MODE_USB | RIG_MODE_LSB | RIG_MODE_RTTY |
- RIG_MODE_RTTYR | RIG_MODE_PKTUSB | RIG_MODE_PKTLSB))
+ else if (mode & (RIG_MODE_CW | RIG_MODE_CWR | RIG_MODE_USB | RIG_MODE_LSB |
+ RIG_MODE_RTTY | RIG_MODE_RTTYR | RIG_MODE_PKTUSB | RIG_MODE_PKTLSB))
{
if (width == 0)
{
-----------------------------------------------------------------------
Summary of changes:
rigs/icom/icom.c | 8 +-
rigs/yaesu/ft1200.c | 2 +-
rigs/yaesu/newcat.c | 62 ++---------
simulators/Makefile.am | 1 -
simulators/sim.h | 3 +-
simulators/simft818.c | 264 -----------------------------------------------
simulators/simftdx3000.c | 1 -
7 files changed, 16 insertions(+), 325 deletions(-)
delete mode 100644 simulators/simft818.c
hooks/post-receive
--
Hamlib -- Ham radio control libraries
|
|
From: n0nb <n0...@us...> - 2026-04-22 19:34:50
|
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 912cdd963df4807cb9a4736d7d9e226d157082d2 (commit)
via ee0ddd02737612e614ac2d0f44b626057a2457b3 (commit)
via 99e63bf6414895b6d20ee70388bab44887349364 (commit)
from 9a53e8629720b45c2026fd1c761697f3ffb1ee8c (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 912cdd963df4807cb9a4736d7d9e226d157082d2
Author: George Baltz N3GB <Geo...@gm...>
Date: Wed Apr 22 11:57:32 2026 -0400
Fix IC-7610 clock commands
Values taken from previous code were wrong - new values from
IC-7610 CI-V REFERENCE GUIDE
diff --git a/rigs/icom/ic7610.c b/rigs/icom/ic7610.c
index 9a86204b3..7e5639340 100644
--- a/rigs/icom/ic7610.c
+++ b/rigs/icom/ic7610.c
@@ -150,7 +150,7 @@ static int ic7610_ext_tokens[] =
static const struct icom_clock_cmds ic7610_clock_cmds =
{
- .date_cmds = { 0x00, 0x58 }, .time_cmds = { 0x00, 0x59 }, .offset_cmds = { 0x00, 0x62 }
+ .date_cmds = { 0x01, 0x58 }, .time_cmds = { 0x01, 0x59 }, .offset_cmds = { 0x01, 0x62 }
};
/*
commit ee0ddd02737612e614ac2d0f44b626057a2457b3
Author: George Baltz N3GB <Geo...@gm...>
Date: Mon Apr 20 05:15:06 2026 -0400
Update the last of the Icom clocks
diff --git a/rigs/icom/ic7700.c b/rigs/icom/ic7700.c
index 095634f76..464285926 100644
--- a/rigs/icom/ic7700.c
+++ b/rigs/icom/ic7700.c
@@ -103,17 +103,22 @@
{ 241, 15.0f } \
} }
-struct cmdparams ic7700_extcmds[] =
+static struct cmdparams ic7700_extcmds[] =
{
{ {.s = RIG_LEVEL_VOXDELAY}, CMD_PARAM_TYPE_LEVEL, C_CTL_MEM, S_MEM_PARM, SC_MOD_RW, 2, {0x01, 0x82}, CMD_DAT_INT, 1 },
{ { 0 } }
};
-int ic7700_ext_tokens[] =
+static int ic7700_ext_tokens[] =
{
TOK_DRIVE_GAIN, TOK_DIGI_SEL_FUNC, TOK_DIGI_SEL_LEVEL, TOK_BACKEND_NONE
};
+static const struct icom_clock_cmds ic7700_clock_cmds =
+{
+ .date_cmds = { 0x00, 0x58 }, .time_cmds = { 0x00, 0x59 }, .offset_cmds = { 0x00, 0x61 }
+};
+
/*
* IC-7700 rig capabilities.
*/
@@ -140,120 +145,10 @@ static const struct icom_priv_caps ic7700_priv_caps =
.x1cx03_possibly = 1,
.x1ax03_supported = 1,
.mode_with_filter = 1,
- .data_mode_supported = 1
+ .data_mode_supported = 1,
+ .clock_cmds = &ic7700_clock_cmds
};
-// if hour < 0 then only date will be set
-static int ic7700_set_clock(RIG *rig, int year, int month, int day, int hour, int min,
- int sec, double msec, int utc_offset)
-{
- int cmd = 0x1a;
- int subcmd = 0x05;
- int retval = RIG_OK;
- unsigned char prmbuf[MAXFRAMELEN];
-
- if (year >= 0)
- {
- prmbuf[0] = 0x00;
- prmbuf[1] = 0x58;
- to_bcd(&prmbuf[2], year / 100, 2);
- to_bcd(&prmbuf[3], year % 100, 2);
- to_bcd(&prmbuf[4], month, 2);
- to_bcd(&prmbuf[5], day, 2);
- retval = icom_transaction(rig, cmd, subcmd, prmbuf, 6, NULL, NULL);
-
- if (retval != RIG_OK)
- {
- rig_debug(RIG_DEBUG_ERR, "%s(%d): %s\b", __func__, __LINE__, rigerror(retval));
- }
- }
-
- if (hour >= 0)
- {
- prmbuf[0] = 0x00;
- prmbuf[1] = 0x59;
- to_bcd(&prmbuf[2], hour, 2);
- to_bcd(&prmbuf[3], min, 2);
- retval = icom_transaction(rig, cmd, subcmd, prmbuf, 4, NULL, NULL);
-
- if (retval != RIG_OK)
- {
- rig_debug(RIG_DEBUG_ERR, "%s(%d): %s\b", __func__, __LINE__, rigerror(retval));
- }
-
- prmbuf[0] = 0x00;
- prmbuf[1] = 0x61;
- rig_debug(RIG_DEBUG_ERR, "%s: utc_offset=%d\n", __func__, utc_offset);
- to_bcd(&prmbuf[2], abs(utc_offset) / 100, 2);
- to_bcd(&prmbuf[3], abs(utc_offset) % 100, 2);
- to_bcd(&prmbuf[4], utc_offset >= 0 ? 0 : 1, 2);
- retval = icom_transaction(rig, cmd, subcmd, prmbuf, 5, NULL, NULL);
-
- if (retval != RIG_OK)
- {
- rig_debug(RIG_DEBUG_ERR, "%s(%d): %s\b", __func__, __LINE__, rigerror(retval));
- }
- }
-
- return retval;
-}
-
-static int ic7700_get_clock(RIG *rig, int *year, int *month, int *day, int *hour,
- int *min, int *sec, double *msec, int *utc_offset)
-{
- int cmd = 0x1a;
- int subcmd = 0x05;
- int retval = RIG_OK;
- int resplen;
- unsigned char prmbuf[MAXFRAMELEN];
- unsigned char respbuf[MAXFRAMELEN];
-
- prmbuf[0] = 0x00;
- prmbuf[1] = 0x58;
- resplen = sizeof(respbuf);
- retval = icom_transaction(rig, cmd, subcmd, prmbuf, 2, respbuf, &resplen);
- *year = from_bcd(&respbuf[4], 2) * 100 + from_bcd(&respbuf[5], 2);
- *month = from_bcd(&respbuf[6], 2);
- *day = from_bcd(&respbuf[7], 2);
-
- if (hour != NULL)
- {
- prmbuf[0] = 0x00;
- prmbuf[1] = 0x59;
- retval = icom_transaction(rig, cmd, subcmd, prmbuf, 2, respbuf, &resplen);
-
- if (retval != RIG_OK)
- {
- return retval;
- }
-
- *hour = from_bcd(&respbuf[4], 2);
- *min = from_bcd(&respbuf[5], 2);
- *sec = 0;
- *msec = 0;
-
- prmbuf[0] = 0x00;
- prmbuf[1] = 0x61;
- retval = icom_transaction(rig, cmd, subcmd, prmbuf, 2, respbuf, &resplen);
-
- if (retval != RIG_OK)
- {
- return retval;
- }
-
- *utc_offset = from_bcd(&respbuf[4], 2) * 100;
- *utc_offset += from_bcd(&respbuf[5], 2);
-
- if (respbuf[6] != 0x00) { *utc_offset *= -1; }
-
- //rig_debug(RIG_DEBUG_VERBOSE,
- // "%s: %02d-%02d-%02dT%02d:%02d:%06.3lf%s%04d\n'",
- // __func__, *year, *month, *day, *hour, *min, *sec + *msec / 1000,
- // *utc_offset >= 0 ? "+" : "-", (unsigned)abs(*utc_offset));
- }
-
- return retval;
-}
static int ic7700_rig_open(RIG *rig)
{
@@ -453,7 +348,7 @@ struct rig_caps ic7700_caps =
.send_morse = icom_send_morse,
.stop_morse = icom_stop_morse,
.wait_morse = rig_wait_morse,
- .set_clock = ic7700_set_clock,
- .get_clock = ic7700_get_clock,
+ .set_clock = icom_set_clock,
+ .get_clock = icom_get_clock,
.hamlib_check_rig_caps = HAMLIB_CHECK_RIG_CAPS
};
diff --git a/rigs/icom/ic7760.c b/rigs/icom/ic7760.c
index c57385517..7eac7d01d 100644
--- a/rigs/icom/ic7760.c
+++ b/rigs/icom/ic7760.c
@@ -102,17 +102,22 @@
{ 241, 15.0f } \
} }
-struct cmdparams ic7760_extcmds[] =
+static struct cmdparams ic7760_extcmds[] =
{
{ {.s = RIG_LEVEL_VOXDELAY}, CMD_PARAM_TYPE_LEVEL, C_CTL_MEM, S_MEM_PARM, SC_MOD_RW, 2, {0x01, 0x82}, CMD_DAT_INT, 1 },
{ { 0 } }
};
-int ic7760_ext_tokens[] =
+static int ic7760_ext_tokens[] =
{
TOK_DRIVE_GAIN, TOK_DIGI_SEL_FUNC, TOK_DIGI_SEL_LEVEL, TOK_BACKEND_NONE
};
+static const struct icom_clock_cmds ic7760_clock_cmds =
+{
+ .date_cmds = { 0x02, 0x00 }, .time_cmds = { 0x02, 0x01 }, .offset_cmds = { 0x02, 0x04 }
+};
+
/*
* IC-7760 rig capabilities.
*/
@@ -139,120 +144,10 @@ static const struct icom_priv_caps ic7760_priv_caps =
.x1cx03_possibly = 1,
.x1ax03_supported = 1,
.mode_with_filter = 1,
- .data_mode_supported = 1
+ .data_mode_supported = 1,
+ .clock_cmds = &ic7760_clock_cmds
};
-// if hour < 0 then only date will be set
-static int ic7760_set_clock(RIG *rig, int year, int month, int day, int hour, int min,
- int sec, double msec, int utc_offset)
-{
- int cmd = 0x1a;
- int subcmd = 0x05;
- int retval = RIG_OK;
- unsigned char prmbuf[MAXFRAMELEN];
-
- if (year >= 0)
- {
- prmbuf[0] = 0x02;
- prmbuf[1] = 0x05;
- to_bcd(&prmbuf[2], year / 100, 2);
- to_bcd(&prmbuf[3], year % 100, 2);
- to_bcd(&prmbuf[4], month, 2);
- to_bcd(&prmbuf[5], day, 2);
- retval = icom_transaction(rig, cmd, subcmd, prmbuf, 6, NULL, NULL);
-
- if (retval != RIG_OK)
- {
- rig_debug(RIG_DEBUG_ERR, "%s(%d): %s\b", __func__, __LINE__, rigerror(retval));
- }
- }
-
- if (hour >= 0)
- {
- prmbuf[0] = 0x02;
- prmbuf[1] = 0x06;
- to_bcd(&prmbuf[2], hour, 2);
- to_bcd(&prmbuf[3], min, 2);
- retval = icom_transaction(rig, cmd, subcmd, prmbuf, 4, NULL, NULL);
-
- if (retval != RIG_OK)
- {
- rig_debug(RIG_DEBUG_ERR, "%s(%d): %s\b", __func__, __LINE__, rigerror(retval));
- }
-
- prmbuf[0] = 0x02;
- prmbuf[1] = 0x04;
- rig_debug(RIG_DEBUG_ERR, "%s: utc_offset=%d\n", __func__, utc_offset);
- to_bcd(&prmbuf[2], abs(utc_offset) / 100, 2);
- to_bcd(&prmbuf[3], abs(utc_offset) % 100, 2);
- to_bcd(&prmbuf[4], utc_offset >= 0 ? 0 : 1, 2);
- retval = icom_transaction(rig, cmd, subcmd, prmbuf, 5, NULL, NULL);
-
- if (retval != RIG_OK)
- {
- rig_debug(RIG_DEBUG_ERR, "%s(%d): %s\b", __func__, __LINE__, rigerror(retval));
- }
- }
-
- return retval;
-}
-
-static int ic7760_get_clock(RIG *rig, int *year, int *month, int *day, int *hour,
- int *min, int *sec, double *msec, int *utc_offset)
-{
- int cmd = 0x1a;
- int subcmd = 0x05;
- int retval = RIG_OK;
- int resplen;
- unsigned char prmbuf[MAXFRAMELEN];
- unsigned char respbuf[MAXFRAMELEN];
-
- prmbuf[0] = 0x00;
- prmbuf[1] = 0x58;
- resplen = sizeof(respbuf);
- retval = icom_transaction(rig, cmd, subcmd, prmbuf, 2, respbuf, &resplen);
- *year = from_bcd(&respbuf[4], 2) * 100 + from_bcd(&respbuf[5], 2);
- *month = from_bcd(&respbuf[6], 2);
- *day = from_bcd(&respbuf[7], 2);
-
- if (hour != NULL)
- {
- prmbuf[0] = 0x00;
- prmbuf[1] = 0x59;
- retval = icom_transaction(rig, cmd, subcmd, prmbuf, 2, respbuf, &resplen);
-
- if (retval != RIG_OK)
- {
- return retval;
- }
-
- *hour = from_bcd(&respbuf[4], 2);
- *min = from_bcd(&respbuf[5], 2);
- *sec = 0;
- *msec = 0;
-
- prmbuf[0] = 0x00;
- prmbuf[1] = 0x61;
- retval = icom_transaction(rig, cmd, subcmd, prmbuf, 2, respbuf, &resplen);
-
- if (retval != RIG_OK)
- {
- return retval;
- }
-
- *utc_offset = from_bcd(&respbuf[4], 2) * 100;
- *utc_offset += from_bcd(&respbuf[5], 2);
-
- if (respbuf[6] != 0x00) { *utc_offset *= -1; }
-
- //rig_debug(RIG_DEBUG_VERBOSE,
- // "%s: %02d-%02d-%02dT%02d:%02d:%06.3lf%s%04d\n'",
- // __func__, *year, *month, *day, *hour, *min, *sec + *msec / 1000,
- // *utc_offset >= 0 ? "+" : "-", (unsigned)abs(*utc_offset));
- }
-
- return retval;
-}
static int ic7760_rig_open(RIG *rig)
{
@@ -450,7 +345,7 @@ struct rig_caps ic7760_caps =
.send_morse = icom_send_morse,
.stop_morse = icom_stop_morse,
.wait_morse = rig_wait_morse,
- .set_clock = ic7760_set_clock,
- .get_clock = ic7760_get_clock,
+ .set_clock = icom_set_clock,
+ .get_clock = icom_get_clock,
.hamlib_check_rig_caps = HAMLIB_CHECK_RIG_CAPS
};
commit 99e63bf6414895b6d20ee70388bab44887349364
Author: George Baltz N3GB <Geo...@gm...>
Date: Sun Apr 19 22:35:04 2026 -0400
Update clock routines for IC-7600 & IC-7610
Resturns rigs/icom/ic7600.c and rigs/icom/ic7610.c to data only.
diff --git a/rigs/icom/ic7600.c b/rigs/icom/ic7600.c
index b01c8c53e..0b4610bd7 100644
--- a/rigs/icom/ic7600.c
+++ b/rigs/icom/ic7600.c
@@ -127,7 +127,7 @@
{ 241, 25.0f } \
} }
-struct cmdparams ic7600_extcmds[] =
+static struct cmdparams ic7600_extcmds[] =
{
{ {.s = RIG_PARM_BEEP}, CMD_PARAM_TYPE_PARM, C_CTL_MEM, S_MEM_PARM, SC_MOD_RW, 2, {0x00, 0x59}, CMD_DAT_BOL, 1 },
{ {.s = RIG_PARM_BACKLIGHT}, CMD_PARAM_TYPE_PARM, C_CTL_MEM, S_MEM_PARM, SC_MOD_RW, 2, {0x00, 0x38}, CMD_DAT_LVL, 2 },
@@ -137,11 +137,16 @@ struct cmdparams ic7600_extcmds[] =
{ { 0 } }
};
-int ic7600_ext_tokens[] =
+static int ic7600_ext_tokens[] =
{
TOK_DRIVE_GAIN, TOK_BACKEND_NONE
};
+static const struct icom_clock_cmds ic7600_clock_cmds =
+{
+ .date_cmds = { 0x00, 0x53 }, .time_cmds = { 0x00, 0x54 }, .offset_cmds = { 0x00, 0x56 }
+};
+
/*
* IC-7600 rig capabilities.
*/
@@ -167,122 +172,10 @@ static const struct icom_priv_caps ic7600_priv_caps =
.x1cx03_possibly = 1,
.x1ax03_supported = 1,
.mode_with_filter = 1,
- .data_mode_supported = 1
+ .data_mode_supported = 1,
+ .clock_cmds = &ic7600_clock_cmds
};
-
-// if hour < 0 then only date will be set
-static int ic7600_set_clock(RIG *rig, int year, int month, int day, int hour, int min,
- int sec, double msec, int utc_offset)
-{
- int cmd = 0x1a;
- int subcmd = 0x05;
- int retval = RIG_OK;
- unsigned char prmbuf[MAXFRAMELEN];
-
- if (year >= 0)
- {
- prmbuf[0] = 0x00;
- prmbuf[1] = 0x53;
- to_bcd(&prmbuf[2], year / 100, 2);
- to_bcd(&prmbuf[3], year % 100, 2);
- to_bcd(&prmbuf[4], month, 2);
- to_bcd(&prmbuf[5], day, 2);
- retval = icom_transaction(rig, cmd, subcmd, prmbuf, 6, NULL, NULL);
-
- if (retval != RIG_OK)
- {
- rig_debug(RIG_DEBUG_ERR, "%s(%d): %s\b", __func__, __LINE__, rigerror(retval));
- }
- }
-
- if (hour >= 0)
- {
- prmbuf[0] = 0x00;
- prmbuf[1] = 0x54;
- to_bcd(&prmbuf[2], hour, 2);
- to_bcd(&prmbuf[3], min, 2);
- retval = icom_transaction(rig, cmd, subcmd, prmbuf, 4, NULL, NULL);
-
- if (retval != RIG_OK)
- {
- rig_debug(RIG_DEBUG_ERR, "%s(%d): %s\b", __func__, __LINE__, rigerror(retval));
- }
-
- prmbuf[0] = 0x00;
- prmbuf[1] = 0x56;
- rig_debug(RIG_DEBUG_ERR, "%s: utc_offset=%d\n", __func__, utc_offset);
- to_bcd(&prmbuf[2], abs(utc_offset) / 100, 2);
- to_bcd(&prmbuf[3], abs(utc_offset) % 100, 2);
- to_bcd(&prmbuf[4], utc_offset >= 0 ? 0 : 1, 2);
- retval = icom_transaction(rig, cmd, subcmd, prmbuf, 5, NULL, NULL);
-
- if (retval != RIG_OK)
- {
- rig_debug(RIG_DEBUG_ERR, "%s(%d): %s\b", __func__, __LINE__, rigerror(retval));
- }
- }
-
- return retval;
-}
-
-static int ic7600_get_clock(RIG *rig, int *year, int *month, int *day, int *hour,
- int *min, int *sec, double *msec, int *utc_offset)
-{
- int cmd = 0x1a;
- int subcmd = 0x05;
- int retval = RIG_OK;
- int resplen;
- unsigned char prmbuf[MAXFRAMELEN];
- unsigned char respbuf[MAXFRAMELEN];
-
- prmbuf[0] = 0x00;
- prmbuf[1] = 0x53;
- resplen = sizeof(respbuf);
- retval = icom_transaction(rig, cmd, subcmd, prmbuf, 2, respbuf, &resplen);
- *year = from_bcd(&respbuf[4], 2) * 100 + from_bcd(&respbuf[5], 2);
- *month = from_bcd(&respbuf[6], 2);
- *day = from_bcd(&respbuf[7], 2);
-
- if (hour != NULL)
- {
- prmbuf[0] = 0x00;
- prmbuf[1] = 0x54;
- retval = icom_transaction(rig, cmd, subcmd, prmbuf, 2, respbuf, &resplen);
-
- if (retval != RIG_OK)
- {
- return retval;
- }
-
- *hour = from_bcd(&respbuf[4], 2);
- *min = from_bcd(&respbuf[5], 2);
- *sec = 0;
- *msec = 0;
-
- prmbuf[0] = 0x00;
- prmbuf[1] = 0x56;
- retval = icom_transaction(rig, cmd, subcmd, prmbuf, 2, respbuf, &resplen);
-
- if (retval != RIG_OK)
- {
- return retval;
- }
-
- *utc_offset = from_bcd(&respbuf[4], 2) * 100;
- *utc_offset += from_bcd(&respbuf[5], 2);
-
- if (respbuf[6] != 0x00) { *utc_offset *= -1; }
-
- //rig_debug(RIG_DEBUG_VERBOSE,
- // "%s: %02d-%02d-%02dT%02d:%02d:%06.3lf%s%04d\n'",
- // __func__, *year, *month, *day, *hour, *min, *sec + *msec / 1000,
- // *utc_offset >= 0 ? "+" : "-", (unsigned)abs(*utc_offset));
- }
-
- return retval;
-}
-
struct rig_caps ic7600_caps =
{
RIG_MODEL(RIG_MODEL_IC7600),
@@ -478,7 +371,7 @@ struct rig_caps ic7600_caps =
.get_powerstat = icom_get_powerstat,
.send_morse = icom_send_morse,
.wait_morse = rig_wait_morse,
- .set_clock = ic7600_set_clock,
- .get_clock = ic7600_get_clock,
+ .set_clock = icom_set_clock,
+ .get_clock = icom_get_clock,
.hamlib_check_rig_caps = HAMLIB_CHECK_RIG_CAPS
};
diff --git a/rigs/icom/ic7610.c b/rigs/icom/ic7610.c
index 9f6e322fb..9a86204b3 100644
--- a/rigs/icom/ic7610.c
+++ b/rigs/icom/ic7610.c
@@ -128,7 +128,7 @@
{ 241, 30.0f } \
} }
-struct cmdparams ic7610_extcmds[] =
+static struct cmdparams ic7610_extcmds[] =
{
{ {.s = RIG_PARM_BEEP}, CMD_PARAM_TYPE_PARM, C_CTL_MEM, S_MEM_PARM, SC_MOD_RW, 2, {0x00, 0x24}, CMD_DAT_BOL, 1 },
{ {.s = RIG_PARM_BACKLIGHT}, CMD_PARAM_TYPE_PARM, C_CTL_MEM, S_MEM_PARM, SC_MOD_RW, 2, {0x01, 0x41}, CMD_DAT_LVL, 2 },
@@ -141,13 +141,18 @@ struct cmdparams ic7610_extcmds[] =
{ { 0 } }
};
-int ic7610_ext_tokens[] =
+static int ic7610_ext_tokens[] =
{
TOK_DRIVE_GAIN, TOK_DIGI_SEL_FUNC, TOK_DIGI_SEL_LEVEL,
TOK_SCOPE_MSS, TOK_SCOPE_SDS, TOK_SCOPE_STX, TOK_SCOPE_CFQ, TOK_SCOPE_EDG, TOK_SCOPE_VBW, TOK_SCOPE_RBW, TOK_SCOPE_MKP, TOK_IPP_FUNC, TOK_TX_INHIBIT_FUNC, TOK_DPP_FUNC, TOK_ICPW2_FUNC,
TOK_BACKEND_NONE
};
+static const struct icom_clock_cmds ic7610_clock_cmds =
+{
+ .date_cmds = { 0x00, 0x58 }, .time_cmds = { 0x00, 0x59 }, .offset_cmds = { 0x00, 0x62 }
+};
+
/*
* IC-7610 rig capabilities.
*/
@@ -248,122 +253,10 @@ static const struct icom_priv_caps ic7610_priv_caps =
.x1cx03_possibly = 1,
.x1ax03_supported = 1,
.mode_with_filter = 1,
- .data_mode_supported = 1
+ .data_mode_supported = 1,
+ .clock_cmds = &ic7610_clock_cmds
};
-
-// if hour < 0 then only date will be set
-static int ic7610_set_clock(RIG *rig, int year, int month, int day, int hour, int min,
- int sec, double msec, int utc_offset)
-{
- int cmd = 0x1a;
- int subcmd = 0x05;
- int retval = RIG_OK;
- unsigned char prmbuf[MAXFRAMELEN];
-
- if (year >= 0)
- {
- prmbuf[0] = 0x00;
- prmbuf[1] = 0x58;
- to_bcd(&prmbuf[2], year / 100, 2);
- to_bcd(&prmbuf[3], year % 100, 2);
- to_bcd(&prmbuf[4], month, 2);
- to_bcd(&prmbuf[5], day, 2);
- retval = icom_transaction(rig, cmd, subcmd, prmbuf, 6, NULL, NULL);
-
- if (retval != RIG_OK)
- {
- rig_debug(RIG_DEBUG_ERR, "%s(%d): %s\b", __func__, __LINE__, rigerror(retval));
- }
- }
-
- if (hour >= 0)
- {
- prmbuf[0] = 0x00;
- prmbuf[1] = 0x59;
- to_bcd(&prmbuf[2], hour, 2);
- to_bcd(&prmbuf[3], min, 2);
- retval = icom_transaction(rig, cmd, subcmd, prmbuf, 4, NULL, NULL);
-
- if (retval != RIG_OK)
- {
- rig_debug(RIG_DEBUG_ERR, "%s(%d): %s\b", __func__, __LINE__, rigerror(retval));
- }
-
- prmbuf[0] = 0x00;
- prmbuf[1] = 0x62;
- rig_debug(RIG_DEBUG_ERR, "%s: utc_offset=%d\n", __func__, utc_offset);
- to_bcd(&prmbuf[2], abs(utc_offset) / 100, 2);
- to_bcd(&prmbuf[3], abs(utc_offset) % 100, 2);
- to_bcd(&prmbuf[4], utc_offset >= 0 ? 0 : 1, 2);
- retval = icom_transaction(rig, cmd, subcmd, prmbuf, 5, NULL, NULL);
-
- if (retval != RIG_OK)
- {
- rig_debug(RIG_DEBUG_ERR, "%s(%d): %s\b", __func__, __LINE__, rigerror(retval));
- }
- }
-
- return retval;
-}
-
-static int ic7610_get_clock(RIG *rig, int *year, int *month, int *day, int *hour,
- int *min, int *sec, double *msec, int *utc_offset)
-{
- int cmd = 0x1a;
- int subcmd = 0x05;
- int retval = RIG_OK;
- int resplen;
- unsigned char prmbuf[MAXFRAMELEN];
- unsigned char respbuf[MAXFRAMELEN];
-
- prmbuf[0] = 0x00;
- prmbuf[1] = 0x58;
- resplen = sizeof(respbuf);
- retval = icom_transaction(rig, cmd, subcmd, prmbuf, 2, respbuf, &resplen);
- *year = from_bcd(&respbuf[4], 2) * 100 + from_bcd(&respbuf[5], 2);
- *month = from_bcd(&respbuf[6], 2);
- *day = from_bcd(&respbuf[7], 2);
-
- if (hour != NULL)
- {
- prmbuf[0] = 0x00;
- prmbuf[1] = 0x59;
- retval = icom_transaction(rig, cmd, subcmd, prmbuf, 2, respbuf, &resplen);
-
- if (retval != RIG_OK)
- {
- return retval;
- }
-
- *hour = from_bcd(&respbuf[4], 2);
- *min = from_bcd(&respbuf[5], 2);
- *sec = 0;
- *msec = 0;
-
- prmbuf[0] = 0x00;
- prmbuf[1] = 0x62;
- retval = icom_transaction(rig, cmd, subcmd, prmbuf, 2, respbuf, &resplen);
-
- if (retval != RIG_OK)
- {
- return retval;
- }
-
- *utc_offset = from_bcd(&respbuf[4], 2) * 100;
- *utc_offset += from_bcd(&respbuf[5], 2);
-
- if (respbuf[6] != 0x00) { *utc_offset *= -1; }
-
- //rig_debug(RIG_DEBUG_VERBOSE,
- // "%s: %02d-%02d-%02dT%02d:%02d:%06.3lf%s%04d\n'",
- // __func__, *year, *month, *day, *hour, *min, *sec + *msec / 1000,
- // *utc_offset >= 0 ? "+" : "-", (unsigned)abs(*utc_offset));
- }
-
- return retval;
-}
-
struct rig_caps ic7610_caps =
{
RIG_MODEL(RIG_MODEL_IC7610),
@@ -619,7 +512,7 @@ struct rig_caps ic7610_caps =
.wait_morse = rig_wait_morse,
.send_voice_mem = icom_send_voice_mem,
.stop_voice_mem = icom_stop_voice_mem,
- .set_clock = ic7610_set_clock,
- .get_clock = ic7610_get_clock,
+ .set_clock = icom_set_clock,
+ .get_clock = icom_get_clock,
.hamlib_check_rig_caps = HAMLIB_CHECK_RIG_CAPS
};
-----------------------------------------------------------------------
Summary of changes:
rigs/icom/ic7600.c | 129 +++++------------------------------------------------
rigs/icom/ic7610.c | 129 +++++------------------------------------------------
rigs/icom/ic7700.c | 127 +++++-----------------------------------------------
rigs/icom/ic7760.c | 127 +++++-----------------------------------------------
4 files changed, 44 insertions(+), 468 deletions(-)
hooks/post-receive
--
Hamlib -- Ham radio control libraries
|
|
From: n0nb <n0...@us...> - 2026-04-21 19:20:41
|
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 9a53e8629720b45c2026fd1c761697f3ffb1ee8c (commit)
via 7cfa437aae3f63efffa0295b0913c068d8c6b74d (commit)
via b84d3686d4ba60c3aabcb81ef34c68066a2008f4 (commit)
via cbf6aff25a4e107a1c105af20f485ff4940da4b6 (commit)
via bb451e5ce9fb60c9663db844ae69e307e66ef462 (commit)
via c375832f62d70467ff50454a5b6094c99cab2a14 (commit)
via 26e598c32a476ad115284cdcc5eb8ff0420926ba (commit)
via 3dec8fb59cd9910f7efe87b5c6f72c7ef516017e (commit)
via 4b9908f98169ec9c24ac74ee1c571cff139beb12 (commit)
via d18b9c8984f9bf3e9a0b25d186a2839b5d861cbd (commit)
via 78530515e5b55c466f226ccc2ca07862a283a7eb (commit)
via 1b5f492255f5f0f5d97e632a7163dd39b9b6d466 (commit)
via 2e2c8fbc968cb7a9b390a7b5b7027c0cdcbf5c73 (commit)
via 610e10af3f793dee3e6d64f290d36ad56fc720bf (commit)
via 4d0d37f251ac1f223d0d1f691bd94b923a344c0d (commit)
via 4f2b9b8a7eb1938595f4d54ece4f4a1bd9b9f6ba (commit)
via 58829e1221bbbc1533f6d621e0ec6b4f1d6b9978 (commit)
via c7688c776001f8ac75971f9729b8200ae9afed8f (commit)
via 06f35bae1089163ae1e493f460b584ec32394c20 (commit)
from 8a714a44b6147bdc56be5b31975a85674d4a76df (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 9a53e8629720b45c2026fd1c761697f3ffb1ee8c
Author: George Baltz N3GB <Geo...@gm...>
Date: Sun Apr 19 17:20:42 2026 -0400
Update newcat version, comments, NEWS and ReleaseNotes_5.0.md
diff --git a/NEWS b/NEWS
index e204ec4fd..c1c81def8 100644
--- a/NEWS
+++ b/NEWS
@@ -14,6 +14,8 @@ Version 5.x -- future
* Change FT1000MP Mark V model names to align with FT1000MP
* Internal data structures moved out of rig_struct to individual
heap buffers - Github issues #487 & #1445 (n3gb)
+ * Update bandwidth handling in rigs/yaesu/newcat.c to use data in
+ priv_caps. Moves lots of hard-coded data into tables. (n3gb)
Version 4.7.0
* 2026-02-15
diff --git a/ReleaseNotes_5.0.md b/ReleaseNotes_5.0.md
index ccacfc8eb..9cdde4552 100644
--- a/ReleaseNotes_5.0.md
+++ b/ReleaseNotes_5.0.md
@@ -12,6 +12,9 @@ changes to the Application Binary Interface(ABI).
- shortfreq_t changed to int32? (may not happen)
- Functions rig_get_conf(), rot_get_conf() and amp_get_conf() have been removed.
See [issue #924](https://github.com/Hamlib/Hamlib/issues/924).
+- Clean up bandwidth handling in newcat.c. Move data from code to priv_caps.
+- Convert ncboolean (in newcat.h) to real `bool` typedef. Clean up previous
+ pseudo-boolean code.
## Build changes
- C compiler needs at least c11 capability.
diff --git a/rigs/yaesu/newcat.h b/rigs/yaesu/newcat.h
index e3da57bfb..6e55c5c89 100644
--- a/rigs/yaesu/newcat.h
+++ b/rigs/yaesu/newcat.h
@@ -54,7 +54,7 @@
typedef bool ncboolean;
/* shared function version */
-#define NEWCAT_VER "20241118"
+#define NEWCAT_VER "20260419"
/* Hopefully large enough for future use, 128 chars plus '\0' */
#define NEWCAT_DATA_LEN 129
@@ -109,8 +109,9 @@ struct newcat_roofing_filter
struct newcat_width_info
{
+ // New entries should go here
short count; // Max value + 1
- uint16_t widths[]; // Must have values for all indices from 0 to max
+ uint16_t widths[]; // Must have values for all indices from 0 to max and must be last in struct
};
struct newcat_priv_caps
commit 7cfa437aae3f63efffa0295b0913c068d8c6b74d
Author: George Baltz N3GB <Geo...@gm...>
Date: Sun Apr 19 16:00:53 2026 -0400
Add ftx1 to entabulated width rig list.
diff --git a/rigs/yaesu/ftx1/ftx1.c b/rigs/yaesu/ftx1/ftx1.c
index c8806b934..74705f653 100644
--- a/rigs/yaesu/ftx1/ftx1.c
+++ b/rigs/yaesu/ftx1/ftx1.c
@@ -51,8 +51,20 @@
#include "ftx1_menu.h"
/* Private caps for newcat framework */
+static const struct newcat_width_info ftx1_ssb_widths =
+{
+ // Bandwidth table per FTX-1 CAT Operation Reference Manual Table 5
+ // (doc 2508-C). Differs from the FT-710/FTDX10 table at SSB codes
+ // 12/13/14 (2250/2400/2450 Hz vs 2200/2300/2400), so do not merge.
+ .count = 24,
+ .widths = { 0, 300, 400, 600, 850, 1100, 1200, 1500, 1650, 1800, 1950, 2100, 2250,
+ 2400, 2450, 2500, 2600, 2700, 2800, 2900, 3000, 3200, 3500, 4000 }
+};
+
static const struct newcat_priv_caps ftx1_priv_caps = {
.roofing_filter_count = 0,
+ .cw_widths = &ftdx101_cw_widths,
+ .ssb_widths = &ftx1_ssb_widths,
};
/* Extern declarations for group-specific functions (add more as groups are implemented) */
diff --git a/rigs/yaesu/newcat.c b/rigs/yaesu/newcat.c
index 0eb0e5bd6..d2cc92694 100644
--- a/rigs/yaesu/newcat.c
+++ b/rigs/yaesu/newcat.c
@@ -9141,9 +9141,6 @@ int newcat_set_rx_bandwidth(RIG *rig, vfo_t vfo, rmode_t mode, pbwidth_t width)
} // end is_ftdx101d || is_ftdx101mp || is_ftdx10 || is_ft710
else if (is_ftx1)
{
- // Bandwidth table per FTX-1 CAT Operation Reference Manual Table 5
- // (doc 2508-C). Differs from the FT-710/FTDX10 table at SSB codes
- // 12/13/14 (2250/2400/2450 Hz vs 2200/2300/2400), so do not merge.
switch (mode)
{
case RIG_MODE_PKTUSB:
@@ -9153,58 +9150,14 @@ int newcat_set_rx_bandwidth(RIG *rig, vfo_t vfo, rmode_t mode, pbwidth_t width)
case RIG_MODE_CW:
case RIG_MODE_CWR:
case RIG_MODE_PSK:
- 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; }
- else if (width <= 200) { w = 4; }
- else if (width <= 250) { w = 5; }
- else if (width <= 300) { w = 6; }
- else if (width <= 350) { w = 7; }
- else if (width <= 400) { w = 8; }
- else if (width <= 450) { w = 9; }
- else if (width <= 500) { w = 10; }
- else if (width <= 600) { w = 11; }
- else if (width <= 800) { w = 12; }
- else if (width <= 1200) { w = 13; }
- else if (width <= 1400) { w = 14; }
- else if (width <= 1700) { w = 15; }
- else if (width <= 2000) { w = 16; }
- else if (width <= 2400) { w = 17; }
- else if (width <= 3000) { w = 18; }
- else if (width <= 3200) { w = 19; }
- else if (width <= 3500) { w = 20; }
- else { w = 21; } // 4000 Hz
-
+ w = newcat_get_index_from_width(width, priv_caps->cw_widths);
+ if (w < 0) { RETURNFUNC(w); } // Out of bounds
break;
case RIG_MODE_LSB:
case RIG_MODE_USB:
- 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; }
- else if (width <= 850) { w = 4; }
- else if (width <= 1100) { w = 5; }
- else if (width <= 1200) { w = 6; }
- else if (width <= 1500) { w = 7; }
- else if (width <= 1650) { w = 8; }
- else if (width <= 1800) { w = 9; }
- else if (width <= 1950) { w = 10; }
- else if (width <= 2100) { w = 11; }
- else if (width <= 2250) { w = 12; }
- else if (width <= 2400) { w = 13; }
- else if (width <= 2450) { w = 14; }
- else if (width <= 2500) { w = 15; }
- else if (width <= 2600) { w = 16; }
- else if (width <= 2700) { w = 17; }
- else if (width <= 2800) { w = 18; }
- else if (width <= 2900) { w = 19; }
- else if (width <= 3000) { w = 20; }
- else if (width <= 3200) { w = 21; }
- else if (width <= 3500) { w = 22; }
- else { w = 23; } // 4000 Hz
-
+ w = newcat_get_index_from_width(width, priv_caps->ssb_widths);
+ if (w < 0) { RETURNFUNC(w); }
break;
case RIG_MODE_AM:
@@ -9224,14 +9177,8 @@ int newcat_set_rx_bandwidth(RIG *rig, vfo_t vfo, rmode_t mode, pbwidth_t width)
case RIG_MODE_AM:
case RIG_MODE_FM:
case RIG_MODE_PKTFM:
- if (width > 0 && width < rig_passband_normal(rig, mode))
- {
- err = newcat_set_narrow(rig, vfo, TRUE);
- }
- else
- {
- err = newcat_set_narrow(rig, vfo, FALSE);
- }
+ is_narrow = width > 0 && width < rig_passband_normal(rig, mode);
+ err = newcat_set_narrow(rig, vfo, is_narrow);
RETURNFUNC(err);
@@ -10121,8 +10068,6 @@ int newcat_get_rx_bandwidth(RIG *rig, vfo_t vfo, rmode_t mode, pbwidth_t *width)
} /* end if is_ftdx101d || is_ftdx101mp || is_ftdx10 || is_ft710 */
else if (is_ftx1)
{
- // Bandwidth table per FTX-1 CAT Operation Reference Manual Table 5
- // (doc 2508-C). Differs from FT-710/FTDX10 at SSB codes 12/13/14.
rig_debug(RIG_DEBUG_TRACE, "%s: is_ftx1 w=%d, mode=%s\n", __func__, w,
rig_strrmode(mode));
@@ -10140,114 +10085,29 @@ int newcat_get_rx_bandwidth(RIG *rig, vfo_t vfo, rmode_t mode, pbwidth_t *width)
case RIG_MODE_CW:
case RIG_MODE_CWR:
case RIG_MODE_PSK:
- switch (w)
+ if (w > 0 && w < priv_caps->cw_widths->count)
{
- case 0: break; /* default */
-
- case 1: *width = 50; break;
-
- case 2: *width = 100; break;
-
- case 3: *width = 150; break;
-
- case 4: *width = 200; break;
-
- case 5: *width = 250; break;
-
- case 6: *width = 300; break;
-
- case 7: *width = 350; break;
-
- case 8: *width = 400; break;
-
- case 9: *width = 450; break;
-
- case 10: *width = 500; break;
-
- case 11: *width = 600; break;
-
- case 12: *width = 800; break;
-
- case 13: *width = 1200; break;
-
- case 14: *width = 1400; break;
-
- case 15: *width = 1700; break;
-
- case 16: *width = 2000; break;
-
- case 17: *width = 2400; break;
-
- case 18: *width = 3000; break;
-
- case 19: *width = 3200; break;
-
- case 20: *width = 3500; break;
-
- case 21: *width = 4000; break;
-
- default:
- RETURNFUNC(-RIG_EINVAL);
+ *width = priv_caps->cw_widths->widths[w];
+ }
+ else if (w == 0)
+ {
+ break; // use the roofing/default width
}
+ else {RETURNFUNC(-RIG_EPROTO);} // Should not happen
break;
case RIG_MODE_LSB:
case RIG_MODE_USB:
- switch (w)
+ if (w > 0 && w < priv_caps->ssb_widths->count)
{
- case 0: break; /* default */
-
- case 1: *width = 300; break;
-
- case 2: *width = 400; break;
-
- case 3: *width = 600; break;
-
- case 4: *width = 850; break;
-
- case 5: *width = 1100; break;
-
- case 6: *width = 1200; break;
-
- case 7: *width = 1500; break;
-
- case 8: *width = 1650; break;
-
- case 9: *width = 1800; break;
-
- case 10: *width = 1950; break;
-
- case 11: *width = 2100; break;
-
- case 12: *width = 2250; break;
-
- case 13: *width = 2400; break;
-
- case 14: *width = 2450; break;
-
- case 15: *width = 2500; break;
-
- case 16: *width = 2600; break;
-
- case 17: *width = 2700; break;
-
- case 18: *width = 2800; break;
-
- case 19: *width = 2900; break;
-
- case 20: *width = 3000; break;
-
- case 21: *width = 3200; break;
-
- case 22: *width = 3500; break;
-
- case 23: *width = 4000; break;
-
- default:
- rig_debug(RIG_DEBUG_ERR, "%s: unknown width=%d\n", __func__, w);
- RETURNFUNC(-RIG_EINVAL);
+ *width = priv_caps->ssb_widths->widths[w];
}
+ else if (w == 0)
+ {
+ break; // Use the roofing/default value
+ }
+ else {RETURNFUNC(-RIG_EPROTO);}
break;
commit b84d3686d4ba60c3aabcb81ef34c68066a2008f4
Author: George Baltz N3GB <Geo...@gm...>
Date: Sun Apr 19 15:15:45 2026 -0400
Convert FTDX-5000 to new bandwidth code.
diff --git a/rigs/yaesu/ft5000.c b/rigs/yaesu/ft5000.c
index aec321907..6a53dc633 100644
--- a/rigs/yaesu/ft5000.c
+++ b/rigs/yaesu/ft5000.c
@@ -32,6 +32,14 @@
#include "ft5000.h"
#include "tones.h"
+/* FTDX-5000 CAT Operation Reference says index 14 not defined - 2400 duplicated as filler */
+static const struct newcat_width_info ftdx5000_ssb_widths =
+{
+ .count = 26,
+ .widths = { 0, 200, 400, 600, 850, 1100, 1350, 1500, 1650, 1800, 1950, 2100, 2250, 2400,
+ 2400, 2500, 2600, 2700, 2800, 2900, 3000, 3200, 3400, 3600, 3800, 4000 }
+};
+
const struct newcat_priv_caps ftdx5000_priv_caps =
{
.roofing_filter_count = 11,
@@ -50,6 +58,8 @@ const struct newcat_priv_caps ftdx5000_priv_caps =
{ .index = 9, .set_value = 0, .get_value = '9', .width = 600, .optional = 0 },
{ .index = 10, .set_value = 0, .get_value = 'A', .width = 300, .optional = 0 },
},
+ .cw_widths = &ftdx1200_cw_widths,
+ .ssb_widths = &ftdx5000_ssb_widths,
};
const struct confparams ftdx5000_ext_levels[] =
diff --git a/rigs/yaesu/newcat.c b/rigs/yaesu/newcat.c
index 5fb5502cb..0eb0e5bd6 100644
--- a/rigs/yaesu/newcat.c
+++ b/rigs/yaesu/newcat.c
@@ -9034,23 +9034,8 @@ int newcat_set_rx_bandwidth(RIG *rig, vfo_t vfo, rmode_t mode, pbwidth_t width)
RETURNFUNC(err);
}
- 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; }
- else if (width <= 200) { w = 4; }
- else if (width <= 250) { w = 5; }
- else if (width <= 300) { w = 6; }
- else if (width <= 350) { w = 7; }
- else if (width <= 400) { w = 8; }
- else if (width <= 450) { w = 9; }
- else if (width <= 500) { w = 10; }
- else if (width <= 800) { w = 11; }
- else if (width <= 1200) { w = 12; }
- else if (width <= 1400) { w = 13; }
- else if (width <= 1700) { w = 14; }
- else if (width <= 2000) { w = 15; }
- else { w = 16; } // 2400 Hz
+ w = newcat_get_index_from_width(width, priv_caps->cw_widths);
+ if (w < 0) { RETURNFUNC(w); }
break;
@@ -9064,31 +9049,8 @@ int newcat_set_rx_bandwidth(RIG *rig, vfo_t vfo, rmode_t mode, pbwidth_t width)
RETURNFUNC(err);
}
- if (width == RIG_PASSBAND_NORMAL) { w = 0; }
- else if (width <= 200) { w = 1; }
- else if (width <= 400) { w = 2; }
- else if (width <= 600) { w = 3; }
- else if (width <= 850) { w = 4; }
- else if (width <= 1100) { w = 5; }
- else if (width <= 1350) { w = 6; }
- else if (width <= 1500) { w = 7; }
- else if (width <= 1650) { w = 8; }
- else if (width <= 1800) { w = 9; }
- else if (width <= 1950) { w = 10; }
- else if (width <= 2100) { w = 11; }
- else if (width <= 2250) { w = 12; }
- else if (width <= 2400) { w = 13; }
- else if (width <= 2500) { w = 15; }
- else if (width <= 2600) { w = 16; }
- else if (width <= 2700) { w = 17; }
- else if (width <= 2800) { w = 18; }
- else if (width <= 2900) { w = 19; }
- else if (width <= 3000) { w = 20; }
- else if (width <= 3200) { w = 21; }
- else if (width <= 3400) { w = 22; }
- else if (width <= 3600) { w = 23; }
- else if (width <= 3800) { w = 24; }
- else { w = 25; } // 4000 Hz
+ w = newcat_get_index_from_width(width, priv_caps->ssb_widths);
+ if (w < 0) { RETURNFUNC(w); }
break;
@@ -10027,109 +9989,34 @@ int newcat_get_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:
- switch (w)
+ if (w > 0 && w < priv_caps->cw_widths->count)
+ {
+ *width = priv_caps->cw_widths->widths[w];
+ }
+ else if (w == 0)
{
- case 0:
*width = narrow ? 500 : 2400;
- break;
-
- case 1: *width = 50; break;
-
- case 2: *width = 100; break;
-
- case 3: *width = 150; break;
-
- case 4: *width = 200; break;
-
- case 5: *width = 250; break;
-
- case 6: *width = 300; break;
-
- case 7: *width = 350; break;
-
- case 8: *width = 400; break;
-
- case 9: *width = 450; break;
-
- case 10: *width = 500; break;
-
- case 11: *width = 800; break;
-
- case 12: *width = 1200; break;
-
- case 13: *width = 1400; break;
-
- case 14: *width = 1700; break;
-
- case 15: *width = 2000; break;
-
- case 16: *width = 2400; break;
-
- default: RETURNFUNC(-RIG_EINVAL);
+ }
+ else
+ {
+ RETURNFUNC(-RIG_EINVAL);
}
break;
case RIG_MODE_LSB:
case RIG_MODE_USB:
- switch (w)
+ if (w > 0 && w < priv_caps->ssb_widths->count)
+ {
+ *width = priv_caps->ssb_widths->widths[w];
+ }
+ else if (w == 0)
{
- case 0:
*width = narrow ? 1500 : 2400;
- break;
-
- case 1: *width = 200; break;
-
- case 2: *width = 400; break;
-
- case 3: *width = 600; break;
-
- case 4: *width = 850; break;
-
- case 5: *width = 1100; break;
-
- case 6: *width = 1350; break;
-
- case 7: *width = 1500; break;
-
- case 8: *width = 1650; break;
-
- case 9: *width = 1800; break;
-
- case 10: *width = 1950; break;
-
- case 11: *width = 2100; break;
-
- case 12: *width = 2250; break;
-
- case 13: *width = 2400; break;
-
- // 14 is not defined for FTDX 5000, but leaving here for completeness
- case 14: *width = 2400; break;
-
- case 15: *width = 2500; break;
-
- case 16: *width = 2600; break;
-
- case 17: *width = 2700; break;
-
- case 18: *width = 2800; break;
-
- case 19: *width = 2900; break;
-
- case 20: *width = 3000; break;
-
- case 21: *width = 3200; break;
-
- case 22: *width = 3400; break;
-
- case 23: *width = 3600; break;
-
- case 24: *width = 3800; break;
-
- case 25: *width = 4000; break;
-
- default: RETURNFUNC(-RIG_EINVAL);
+ }
+ else
+ {
+ RETURNFUNC(-RIG_EINVAL);
}
break;
commit cbf6aff25a4e107a1c105af20f485ff4940da4b6
Author: George Baltz N3GB <Geo...@gm...>
Date: Sun Apr 19 14:44:58 2026 -0400
One more simulator limps across the starting line.
Just enough hacking to get it going.
diff --git a/simulators/simftdx5000.c b/simulators/simftdx5000.c
index 121542f4c..387d83622 100644
--- a/simulators/simftdx5000.c
+++ b/simulators/simftdx5000.c
@@ -5,9 +5,8 @@
#include <string.h>
#include <unistd.h>
-#include "hamlib/rig.h"
-#include "misc.h"
-
+// Borrowed from misc.h
+int hl_usleep(unsigned long usec);
float freqA = 14074000;
float freqB = 14074500;
@@ -26,6 +25,7 @@ int ex103 = 0;
#include "sim.h"
+#define ID NC_RIGID_FTDX5000
int main(int argc, char *argv[])
{
@@ -77,8 +77,7 @@ int main(int argc, char *argv[])
{
printf("%s\n", buf);
hl_usleep(50 * 1000);
- int id = NC_RIGID_FTDX3000;
- SNPRINTF(buf, sizeof(buf), "ID%03d;", id);
+ snprintf(buf, sizeof(buf), "ID%04d;", ID);
n = write(fd, buf, strlen(buf));
printf("n=%d\n", n);
@@ -90,7 +89,7 @@ int main(int argc, char *argv[])
ant = (ant + 1) % 3;
printf("%s\n", buf);
hl_usleep(50 * 1000);
- SNPRINTF(buf, sizeof(buf), "EX032%1d;", ant);
+ snprintf(buf, sizeof(buf), "EX032%1d;", ant);
n = write(fd, buf, strlen(buf));
printf("n=%d\n", n);
@@ -99,7 +98,7 @@ int main(int argc, char *argv[])
else if (strcmp(buf, "FA;") == 0)
{
- SNPRINTF(buf, sizeof(buf), "FA%08.0f;", freqA);
+ snprintf(buf, sizeof(buf), "FA%08.0f;", freqA);
n = write(fd, buf, strlen(buf));
}
else if (strncmp(buf, "FA", 2) == 0)
@@ -108,7 +107,7 @@ int main(int argc, char *argv[])
}
else if (strcmp(buf, "FB;") == 0)
{
- SNPRINTF(buf, sizeof(buf), "FB%08.0f;", freqB);
+ snprintf(buf, sizeof(buf), "FB%08.0f;", freqB);
n = write(fd, buf, strlen(buf));
}
else if (strncmp(buf, "FB", 2) == 0)
@@ -117,7 +116,7 @@ int main(int argc, char *argv[])
}
else if (strcmp(buf, "FT;") == 0)
{
- SNPRINTF(buf, sizeof(buf), "FT%d;", ft);
+ snprintf(buf, sizeof(buf), "FT%d;", ft);
n = write(fd, buf, strlen(buf));
}
else if (strncmp(buf, "FT", 2) == 0)
@@ -131,7 +130,7 @@ int main(int argc, char *argv[])
}
else if (strcmp(buf, "MD0;") == 0)
{
- SNPRINTF(buf, sizeof(buf), "MD0%d;", md0);
+ snprintf(buf, sizeof(buf), "MD0%d;", md0);
n = write(fd, buf, strlen(buf));
}
else if (strncmp(buf, "MD0", 2) == 0)
@@ -140,7 +139,7 @@ int main(int argc, char *argv[])
}
else if (strcmp(buf, "MD1;") == 0)
{
- SNPRINTF(buf, sizeof(buf), "MD1%d;", md1);
+ snprintf(buf, sizeof(buf), "MD1%d;", md1);
n = write(fd, buf, strlen(buf));
}
else if (strncmp(buf, "MD1", 2) == 0)
@@ -149,7 +148,7 @@ int main(int argc, char *argv[])
}
else if (strcmp(buf, "VS;") == 0)
{
- SNPRINTF(buf, sizeof(buf), "VS%d;", vs);
+ snprintf(buf, sizeof(buf), "VS%d;", vs);
n = write(fd, buf, strlen(buf));
}
else if (strncmp(buf, "VS", 2) == 0)
@@ -158,7 +157,7 @@ int main(int argc, char *argv[])
}
else if (strcmp(buf, "TX;") == 0)
{
- SNPRINTF(buf, sizeof(buf), "TX%d;", tx);
+ snprintf(buf, sizeof(buf), "TX%d;", tx);
n = write(fd, buf, strlen(buf));
}
else if (strncmp(buf, "TX", 2) == 0)
@@ -167,7 +166,7 @@ int main(int argc, char *argv[])
}
else if (strcmp(buf, "AI;") == 0)
{
- SNPRINTF(buf, sizeof(buf), "AI%d;", ai);
+ snprintf(buf, sizeof(buf), "AI%d;", ai);
n = write(fd, buf, strlen(buf));
}
else if (strncmp(buf, "AI", 2) == 0)
@@ -176,7 +175,7 @@ int main(int argc, char *argv[])
}
else if (strcmp(buf, "SH0;") == 0)
{
- SNPRINTF(buf, sizeof(buf), "SH0%d;", sh);
+ snprintf(buf, sizeof(buf), "SH0%02d;", sh);
n = write(fd, buf, strlen(buf));
}
else if (strncmp(buf, "SH0", 3) == 0)
@@ -185,7 +184,7 @@ int main(int argc, char *argv[])
}
else if (strcmp(buf, "NA0;") == 0)
{
- SNPRINTF(buf, sizeof(buf), "NA0%d;", na);
+ snprintf(buf, sizeof(buf), "NA0%d;", na);
n = write(fd, buf, strlen(buf));
}
else if (strncmp(buf, "NA0", 3) == 0)
@@ -194,7 +193,7 @@ int main(int argc, char *argv[])
}
else if (strcmp(buf, "EX039;") == 0)
{
- SNPRINTF(buf, sizeof(buf), "EX039%d;", ex039);
+ snprintf(buf, sizeof(buf), "EX039%d;", ex039);
n = write(fd, buf, strlen(buf));
}
else if (strncmp(buf, "EX039", 5) == 0)
@@ -203,7 +202,7 @@ int main(int argc, char *argv[])
}
else if (strcmp(buf, "EX103;") == 0)
{
- SNPRINTF(buf, sizeof(buf), "EX103%d;", ex103);
+ snprintf(buf, sizeof(buf), "EX103%d;", ex103);
n = write(fd, buf, strlen(buf));
}
else if (strncmp(buf, "EX103", 3) == 0)
@@ -212,7 +211,7 @@ int main(int argc, char *argv[])
}
else if (strcmp(buf, "PS;") == 0)
{
- SNPRINTF(buf, sizeof(buf), "PS1;");
+ snprintf(buf, sizeof(buf), "PS1;");
n = write(fd, buf, strlen(buf));
}
else if (strlen(buf) > 0)
commit bb451e5ce9fb60c9663db844ae69e307e66ef462
Author: George Baltz N3GB <Geo...@gm...>
Date: Sun Apr 19 05:55:53 2026 -0400
Convert FTDX-1200 and FTDX-3000 to new bandwidth code
And some minor cleanups
diff --git a/rigs/yaesu/ft1200.c b/rigs/yaesu/ft1200.c
index f850a74e4..135c726a0 100644
--- a/rigs/yaesu/ft1200.c
+++ b/rigs/yaesu/ft1200.c
@@ -33,6 +33,20 @@
#include "ft1200.h"
#include "tones.h"
+// Shared with FTDX-3000/FTDX-3000dm
+const struct newcat_width_info ftdx1200_cw_widths =
+{
+ .count = 17,
+ .widths = { 0, 50, 100, 150, 200, 250, 300, 350, 400, 450, 500, 800, 1200, 1400,
+ 1700, 2000, 2400 }
+};
+const struct newcat_width_info ftdx1200_ssb_widths =
+{
+ .count = 26,
+ .widths = { 0, 200, 400, 600, 850, 1100, 1350, 1500, 1650, 1800, 1950, 2100, 2200, 2300,
+ 2400, 2500, 2600, 2700, 2800, 2900, 3000, 3200, 3400, 3600, 3800, 4000 }
+};
+
const struct newcat_priv_caps ftdx1200_priv_caps =
{
.roofing_filter_count = 7,
@@ -46,7 +60,9 @@ const struct newcat_priv_caps ftdx1200_priv_caps =
{ .index = 4, .set_value = 0, .get_value = '4', .width = 15000, .optional = 0 },
{ .index = 5, .set_value = 0, .get_value = '5', .width = 6000, .optional = 0 },
{ .index = 6, .set_value = 0, .get_value = '6', .width = 3000, .optional = 0 },
- }
+ },
+ .cw_widths = &ftdx1200_cw_widths,
+ .ssb_widths = &ftdx1200_ssb_widths
};
const struct confparams ftdx1200_ext_levels[] =
diff --git a/rigs/yaesu/ft3000.c b/rigs/yaesu/ft3000.c
index f166bb4d5..a6ff8215a 100644
--- a/rigs/yaesu/ft3000.c
+++ b/rigs/yaesu/ft3000.c
@@ -53,7 +53,9 @@ const struct newcat_priv_caps ftdx3000_priv_caps =
{ .index = 8, .set_value = 0, .get_value = '6', .width = 3000, .optional = 0 },
{ .index = 9, .set_value = 0, .get_value = '9', .width = 600, .optional = 0 },
{ .index = 10, .set_value = 0, .get_value = 'A', .width = 300, .optional = 0 },
- }
+ },
+ .cw_widths = &ftdx1200_cw_widths,
+ .ssb_widths = &ftdx1200_ssb_widths
};
const struct confparams ftdx3000_ext_levels[] =
diff --git a/rigs/yaesu/newcat.c b/rigs/yaesu/newcat.c
index a6c8e2016..5fb5502cb 100644
--- a/rigs/yaesu/newcat.c
+++ b/rigs/yaesu/newcat.c
@@ -8601,7 +8601,7 @@ int newcat_set_narrow(RIG *rig, vfo_t vfo, ncboolean narrow)
main_sub_vfo = (RIG_VFO_B == vfo || RIG_VFO_SUB == vfo) ? '1' : '0';
}
- if (narrow == TRUE)
+ if (narrow)
{
c = '1';
}
@@ -8966,23 +8966,8 @@ int newcat_set_rx_bandwidth(RIG *rig, vfo_t vfo, rmode_t mode, pbwidth_t width)
RETURNFUNC(err);
}
- 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; }
- else if (width <= 200) { w = 4; }
- else if (width <= 250) { w = 5; }
- else if (width <= 300) { w = 6; }
- else if (width <= 350) { w = 7; }
- else if (width <= 400) { w = 8; }
- else if (width <= 450) { w = 9; }
- else if (width <= 500) { w = 10; }
- else if (width <= 800) { w = 11; }
- else if (width <= 1200) { w = 12; }
- else if (width <= 1400) { w = 13; }
- else if (width <= 1700) { w = 14; }
- else if (width <= 2000) { w = 15; }
- else { w = 16; } // 2400 Hz
+ w = newcat_get_index_from_width(width, priv_caps->cw_widths);
+ if (w < 0) { RETURNFUNC(w); }
break;
@@ -8996,32 +8981,8 @@ int newcat_set_rx_bandwidth(RIG *rig, vfo_t vfo, rmode_t mode, pbwidth_t width)
RETURNFUNC(err);
}
- if (width == RIG_PASSBAND_NORMAL) { w = 0; }
- else if (width <= 200) { w = 1; }
- else if (width <= 400) { w = 2; }
- else if (width <= 600) { w = 3; }
- else if (width <= 850) { w = 4; }
- else if (width <= 1100) { w = 5; }
- else if (width <= 1350) { w = 6; }
- else if (width <= 1500) { w = 7; }
- else if (width <= 1650) { w = 8; }
- else if (width <= 1800) { w = 9; }
- else if (width <= 1950) { w = 10; }
- else if (width <= 2100) { w = 11; }
- else if (width <= 2200) { w = 12; }
- else if (width <= 2300) { w = 13; }
- else if (width <= 2400) { w = 14; }
- else if (width <= 2500) { w = 15; }
- else if (width <= 2600) { w = 16; }
- else if (width <= 2700) { w = 17; }
- else if (width <= 2800) { w = 18; }
- else if (width <= 2900) { w = 19; }
- else if (width <= 3000) { w = 20; }
- else if (width <= 3200) { w = 21; }
- else if (width <= 3400) { w = 22; }
- else if (width <= 3600) { w = 23; }
- else if (width <= 3800) { w = 24; }
- else { w = 25; } // 4000 Hz
+ w = newcat_get_index_from_width(width, priv_caps->ssb_widths);
+ if (w < 0) { RETURNFUNC(w); }
break;
@@ -9193,7 +9154,7 @@ int newcat_set_rx_bandwidth(RIG *rig, vfo_t vfo, rmode_t mode, pbwidth_t width)
RETURNFUNC(-RIG_EINVAL);
} // end switch(mode)
- if (((struct newcat_priv_caps *)rig->caps->priv)->roofing_filter_count > 0)
+ if (priv_caps->roofing_filter_count > 0)
{
if ((err = set_roofing_filter_for_width(rig, vfo, width)) != RIG_OK)
{
@@ -9997,108 +9958,34 @@ int newcat_get_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:
- switch (w)
+ if (w > 0 && w < priv_caps->cw_widths->count)
+ {
+ *width = priv_caps->cw_widths->widths[w];
+ }
+ else if (w == 0)
{
- case 0:
*width = narrow ? 500 : 2400;
- break;
-
- case 1: *width = 50; break;
-
- case 2: *width = 100; break;
-
- case 3: *width = 150; break;
-
- case 4: *width = 200; break;
-
- case 5: *width = 250; break;
-
- case 6: *width = 300; break;
-
- case 7: *width = 350; break;
-
- case 8: *width = 400; break;
-
- case 9: *width = 450; break;
-
- case 10: *width = 500; break;
-
- case 11: *width = 800; break;
-
- case 12: *width = 1200; break;
-
- case 13: *width = 1400; break;
-
- case 14: *width = 1700; break;
-
- case 15: *width = 2000; break;
-
- case 16: *width = 2400; break;
-
- default: RETURNFUNC(-RIG_EINVAL);
+ }
+ else
+ {
+ RETURNFUNC(-RIG_EPROTO);
}
break;
case RIG_MODE_LSB:
case RIG_MODE_USB:
- switch (w)
+ if (w > 0 && w < priv_caps->ssb_widths->count)
+ {
+ *width = priv_caps->ssb_widths->widths[w];
+ }
+ else if (w == 0)
{
- case 0:
*width = narrow ? 1500 : 2400;
- break;
-
- case 1: *width = 200; break;
-
- case 2: *width = 400; break;
-
- case 3: *width = 600; break;
-
- case 4: *width = 850; break;
-
- case 5: *width = 1100; break;
-
- case 6: *width = 1350; break;
-
- case 7: *width = 1500; break;
-
- case 8: *width = 1650; break;
-
- case 9: *width = 1800; break;
-
- case 10: *width = 1950; break;
-
- case 11: *width = 2100; break;
-
- case 12: *width = 2250; break;
-
- case 13: *width = 2400; break;
-
- case 14: *width = 2450; break;
-
- case 15: *width = 2500; break;
-
- case 16: *width = 2600; break;
-
- case 17: *width = 2700; break;
-
- case 18: *width = 2800; break;
-
- case 19: *width = 2900; break;
-
- case 20: *width = 3000; break;
-
- case 21: *width = 3200; break;
-
- case 22: *width = 3400; break;
-
- case 23: *width = 3600; break;
-
- case 24: *width = 3800; break;
-
- case 25: *width = 4000; break;
-
- default: RETURNFUNC(-RIG_EINVAL);
+ }
+ else
+ {
+ RETURNFUNC(-RIG_EPROTO);
}
break;
diff --git a/rigs/yaesu/newcat.h b/rigs/yaesu/newcat.h
index 40481d28a..e3da57bfb 100644
--- a/rigs/yaesu/newcat.h
+++ b/rigs/yaesu/newcat.h
@@ -274,6 +274,7 @@ int newcat_scan(RIG *rig, vfo_t vfo, scan_t scan, int ch);
*/
extern const struct newcat_width_info ft991_cw_widths, ft991_ssb_widths;
extern const struct newcat_width_info ftdx101_cw_widths, ftdx101_ssb_widths;
+extern const struct newcat_width_info ftdx1200_cw_widths, ftdx1200_ssb_widths;
#define TOKEN_BACKEND(t) (t)
commit c375832f62d70467ff50454a5b6094c99cab2a14
Author: George Baltz N3GB <Geo...@gm...>
Date: Sat Apr 18 21:58:11 2026 -0400
Make a couple more simulators barely functional
Allow simftdx1200.c and simftdx3000.c to at least start, go
through the initial setup/open, have mode and width do something.
Fix field lengths, missing commands, incorrect data, etc.
simftdx3000.c shows an interesting problem - the FTDX3000 CAT manual
says the rig should return 0462 for the ID command - hamlib thinks
that is a FTDX-3000DM, the low power version. Maybe they're backwards??
Does anybody have a real one to find out?
diff --git a/simulators/simftdx1200.c b/simulators/simftdx1200.c
index f6b56820f..e5fda730e 100644
--- a/simulators/simftdx1200.c
+++ b/simulators/simftdx1200.c
@@ -5,9 +5,7 @@
#include <string.h>
#include <unistd.h>
-#include "hamlib/rig.h"
-#include "misc.h"
-
+int hl_usleep(unsigned long usec);
float freqA = 14074000;
float freqB = 14074500;
@@ -22,9 +20,9 @@ int na = 0;
int ex039 = 0;
int keyspd = 20;
-
#include "sim.h"
+#define ID NC_RIGID_FTDX1200
int main(int argc, char *argv[])
{
@@ -74,10 +72,8 @@ int main(int argc, char *argv[])
}
else if (strcmp(buf, "ID;") == 0)
{
- printf("%s\n", buf);
hl_usleep(50 * 1000);
- int id = NC_RIGID_FTDX3000;
- SNPRINTF(buf, sizeof(buf), "ID%03d;", id);
+ snprintf(buf, sizeof(buf), "ID%04d;", ID);
n = write(fd, buf, strlen(buf));
printf("n=%d\n", n);
@@ -105,7 +101,7 @@ int main(int argc, char *argv[])
ant = (ant + 1) % 3;
printf("%s\n", buf);
hl_usleep(50 * 1000);
- SNPRINTF(buf, sizeof(buf), "EX032%1d;", ant);
+ snprintf(buf, sizeof(buf), "EX032%1d;", ant);
n = write(fd, buf, strlen(buf));
printf("n=%d\n", n);
@@ -114,7 +110,7 @@ int main(int argc, char *argv[])
else if (strcmp(buf, "FA;") == 0)
{
- SNPRINTF(buf, sizeof(buf), "FA%08.0f;", freqA);
+ snprintf(buf, sizeof(buf), "FA%08.0f;", freqA);
n = write(fd, buf, strlen(buf));
}
else if (strncmp(buf, "FA", 2) == 0)
@@ -123,7 +119,7 @@ int main(int argc, char *argv[])
}
else if (strcmp(buf, "FB;") == 0)
{
- SNPRINTF(buf, sizeof(buf), "FB%08.0f;", freqB);
+ snprintf(buf, sizeof(buf), "FB%08.0f;", freqB);
n = write(fd, buf, strlen(buf));
}
else if (strncmp(buf, "FB", 2) == 0)
@@ -132,17 +128,21 @@ int main(int argc, char *argv[])
}
else if (strcmp(buf, "FT;") == 0)
{
- SNPRINTF(buf, sizeof(buf), "FT%d;", ft);
+ snprintf(buf, sizeof(buf), "FT%d;", ft);
n = write(fd, buf, strlen(buf));
}
else if (strcmp(buf, "MD0;") == 0)
{
- SNPRINTF(buf, sizeof(buf), "MD0%d;", md);
+ snprintf(buf, sizeof(buf), "MD0%d;", md);
n = write(fd, buf, strlen(buf));
}
+ else if (strncmp(buf, "MD0", 3) == 0)
+ {
+ sscanf(buf, "MD0%d", &md);
+ }
else if (strcmp(buf, "VS;") == 0)
{
- SNPRINTF(buf, sizeof(buf), "VS%c;", vfo == 0 ? '0' : '1');
+ snprintf(buf, sizeof(buf), "VS%c;", vfo == 0 ? '0' : '1');
n = write(fd, buf, strlen(buf));
}
else if (strncmp(buf, "VS", 2) == 0)
@@ -151,7 +151,7 @@ int main(int argc, char *argv[])
}
else if (strcmp(buf, "TX;") == 0)
{
- SNPRINTF(buf, sizeof(buf), "TX%d;", tx);
+ snprintf(buf, sizeof(buf), "TX%d;", tx);
n = write(fd, buf, strlen(buf));
}
else if (strncmp(buf, "TX", 2) == 0)
@@ -160,7 +160,7 @@ int main(int argc, char *argv[])
}
else if (strcmp(buf, "AI;") == 0)
{
- SNPRINTF(buf, sizeof(buf), "AI%d;", ai);
+ snprintf(buf, sizeof(buf), "AI%d;", ai);
n = write(fd, buf, strlen(buf));
}
else if (strncmp(buf, "AI", 2) == 0)
@@ -169,7 +169,7 @@ int main(int argc, char *argv[])
}
else if (strcmp(buf, "SH0;") == 0)
{
- SNPRINTF(buf, sizeof(buf), "SH0%d;", sh);
+ snprintf(buf, sizeof(buf), "SH0%02d;", sh);
n = write(fd, buf, strlen(buf));
}
else if (strncmp(buf, "SH0", 3) == 0)
@@ -178,7 +178,7 @@ int main(int argc, char *argv[])
}
else if (strcmp(buf, "NA0;") == 0)
{
- SNPRINTF(buf, sizeof(buf), "NA0%d;", na);
+ snprintf(buf, sizeof(buf), "NA0%d;", na);
n = write(fd, buf, strlen(buf));
}
else if (strncmp(buf, "NA0", 3) == 0)
@@ -187,7 +187,7 @@ int main(int argc, char *argv[])
}
else if (strcmp(buf, "EX039;") == 0)
{
- SNPRINTF(buf, sizeof(buf), "EX039%d;", ex039);
+ snprintf(buf, sizeof(buf), "EX039%d;", ex039);
n = write(fd, buf, strlen(buf));
}
else if (strncmp(buf, "EX039", 5) == 0)
@@ -196,7 +196,7 @@ int main(int argc, char *argv[])
}
else if (strcmp(buf, "PS;") == 0)
{
- SNPRINTF(buf, sizeof(buf), "PS1;");
+ snprintf(buf, sizeof(buf), "PS1;");
n = write(fd, buf, strlen(buf));
}
else if (strncmp(buf, "KS;", 3) == 0)
diff --git a/simulators/simftdx3000.c b/simulators/simftdx3000.c
index d4cd4f851..a554dca11 100644
--- a/simulators/simftdx3000.c
+++ b/simulators/simftdx3000.c
@@ -5,9 +5,12 @@
#include <string.h>
#include <unistd.h>
+#if 0
#include "hamlib/rig.h"
#include "misc.h"
-
+#else
+int hl_usleep(unsigned long usec);
+#endif
float freqA = 14074000;
float freqB = 14074500;
@@ -20,10 +23,13 @@ int ai = 0;
int sh = 25;
int na = 0;
int ex039 = 0;
+int keyspd = 24;
#include "sim.h"
+#define ID NC_RIGID_FTDX3000
+//#define ID NC_RIGID_FTDX3000DM
int main(int argc, char *argv[])
{
@@ -75,8 +81,7 @@ int main(int argc, char *argv[])
{
printf("%s\n", buf);
hl_usleep(50 * 1000);
- int id = NC_RIGID_FTDX3000;
- SNPRINTF(buf, sizeof(buf), "ID%03d;", id);
+ snprintf(buf, sizeof(buf), "ID%04d;", ID);
n = write(fd, buf, strlen(buf));
printf("n=%d\n", n);
@@ -89,7 +94,7 @@ int main(int argc, char *argv[])
ant = (ant + 1) % 3;
printf("%s\n", buf);
hl_usleep(50 * 1000);
- SNPRINTF(buf, sizeof(buf), "EX032%1d;", ant);
+ snprintf(buf, sizeof(buf), "EX032%1d;", ant);
n = write(fd, buf, strlen(buf));
printf("n=%d\n", n);
@@ -98,7 +103,7 @@ int main(int argc, char *argv[])
else if (strcmp(buf, "FA;") == 0)
{
- SNPRINTF(buf, sizeof(buf), "FA%08.0f;", freqA);
+ snprintf(buf, sizeof(buf), "FA%08.0f;", freqA);
n = write(fd, buf, strlen(buf));
}
else if (strncmp(buf, "FA", 2) == 0)
@@ -107,7 +112,7 @@ int main(int argc, char *argv[])
}
else if (strcmp(buf, "FB;") == 0)
{
- SNPRINTF(buf, sizeof(buf), "FB%08.0f;", freqB);
+ snprintf(buf, sizeof(buf), "FB%08.0f;", freqB);
n = write(fd, buf, strlen(buf));
}
else if (strncmp(buf, "FB", 2) == 0)
@@ -121,7 +126,7 @@ int main(int argc, char *argv[])
if (ft == 2) { val = 0; }
else if (ft == 3) { val = 1; }
- SNPRINTF(buf, sizeof(buf), "FT%d;", val);
+ snprintf(buf, sizeof(buf), "FT%d;", val);
n = write(fd, buf, strlen(buf));
}
else if (strncmp(buf, "FT", 2) == 0)
@@ -130,7 +135,7 @@ int main(int argc, char *argv[])
}
else if (strcmp(buf, "MD0;") == 0)
{
- SNPRINTF(buf, sizeof(buf), "MD0%d;", md);
+ snprintf(buf, sizeof(buf), "MD0%d;", md);
n = write(fd, buf, strlen(buf));
}
else if (strncmp(buf, "MD0", 3) == 0)
@@ -139,12 +144,12 @@ int main(int argc, char *argv[])
}
else if (strcmp(buf, "PS;") == 0)
{
- SNPRINTF(buf, sizeof(buf), "PS1;");
+ snprintf(buf, sizeof(buf), "PS1;");
n = write(fd, buf, strlen(buf));
}
else if (strcmp(buf, "VS;") == 0)
{
- SNPRINTF(buf, sizeof(buf), "VS%d;", vs);
+ snprintf(buf, sizeof(buf), "VS%d;", vs);
n = write(fd, buf, strlen(buf));
}
else if (strncmp(buf, "VS", 2) == 0)
@@ -153,7 +158,7 @@ int main(int argc, char *argv[])
}
else if (strcmp(buf, "TX;") == 0)
{
- SNPRINTF(buf, sizeof(buf), "TX%d;", tx);
+ snprintf(buf, sizeof(buf), "TX%d;", tx);
n = write(fd, buf, strlen(buf));
}
else if (strncmp(buf, "TX", 2) == 0)
@@ -162,7 +167,7 @@ int main(int argc, char *argv[])
}
else if (strcmp(buf, "AI;") == 0)
{
- SNPRINTF(buf, sizeof(buf), "AI%d;", ai);
+ snprintf(buf, sizeof(buf), "AI%d;", ai);
n = write(fd, buf, strlen(buf));
}
else if (strncmp(buf, "AI", 2) == 0)
@@ -171,7 +176,7 @@ int main(int argc, char *argv[])
}
else if (strcmp(buf, "SH0;") == 0)
{
- SNPRINTF(buf, sizeof(buf), "SH0%d;", sh);
+ snprintf(buf, sizeof(buf), "SH0%02d;", sh);
n = write(fd, buf, strlen(buf));
}
else if (strncmp(buf, "SH0", 3) == 0)
@@ -180,7 +185,7 @@ int main(int argc, char *argv[])
}
else if (strcmp(buf, "NA0;") == 0)
{
- SNPRINTF(buf, sizeof(buf), "NA0%d;", na);
+ snprintf(buf, sizeof(buf), "NA0%d;", na);
n = write(fd, buf, strlen(buf));
}
else if (strncmp(buf, "NA0", 3) == 0)
@@ -189,13 +194,22 @@ int main(int argc, char *argv[])
}
else if (strcmp(buf, "EX039;") == 0)
{
- SNPRINTF(buf, sizeof(buf), "EX039%d;", ex039);
+ snprintf(buf, sizeof(buf), "EX039%d;", ex039);
n = write(fd, buf, strlen(buf));
}
else if (strncmp(buf, "EX039", 5) == 0)
{
sscanf(buf, "EX039%d", &ex039);
}
+ else if (strncmp(buf, "KS;", 3) == 0)
+ {
+ sprintf(buf, "KS%d;", keyspd);
+ n = write(fd, buf, strlen(buf));
+ }
+ else if (strncmp(buf, "KS", 2) == 0)
+ {
+ sscanf(buf, "KS%03d", &keyspd);
+ }
else if (strlen(buf) > 0)
{
fprintf(stderr, "Unknown command: %s\n", buf);
commit 26e598c32a476ad115284cdcc5eb8ff0420926ba
Author: George Baltz N3GB <Geo...@gm...>
Date: Fri Apr 17 22:12:47 2026 -0400
Change FT-891 to use new width structures
Use the same info as the FT991.
diff --git a/rigs/yaesu/ft891.c b/rigs/yaesu/ft891.c
index 28cb9385a..e46a6ffb4 100644
--- a/rigs/yaesu/ft891.c
+++ b/rigs/yaesu/ft891.c
@@ -123,6 +123,12 @@ int ft891_ext_tokens[] =
TOK_BACKEND_NONE
};
+static const struct newcat_priv_caps ft891_priv_caps =
+{
+ .cw_widths = &ft991_cw_widths,
+ .ssb_widths = &ft991_ssb_widths
+};
+
/*
* FT-891 rig capabilities
*/
@@ -286,7 +292,7 @@ struct rig_caps ft891_caps =
.ext_tokens = ft891_ext_tokens,
.extlevels = ft891_ext_levels,
- .priv = NULL, /* private data FIXME: */
+ .priv = &ft891_priv_caps,
.rig_init = ft891_init,
.rig_cleanup = newcat_cleanup,
diff --git a/rigs/yaesu/ft991.c b/rigs/yaesu/ft991.c
index fd197cf8b..703016352 100644
--- a/rigs/yaesu/ft991.c
+++ b/rigs/yaesu/ft991.c
@@ -169,15 +169,13 @@ int ft991_ext_tokens[] =
TOK_BACKEND_NONE
};
-/*
- * Rig unique data
- */
-static const struct newcat_width_info ft991_cw_widths = {
+// Shared with FT-891
+const struct newcat_width_info ft991_cw_widths = {
.count = 18,
.widths = { 0, 50, 100, 150, 200, 250, 300, 350, 400, 450, 500, 800, 1200, 1400, 1700,
2000, 2400, 3000 }
};
-static const struct newcat_width_info ft991_ssb_widths = {
+const struct newcat_width_info ft991_ssb_widths = {
.count = 22,
.widths = { 0, 200, 400, 600, 850, 1100, 1350, 1500, 1650, 1800, 1950, 2100, 2200, 2300,
2400, 2500, 2600, 2700, 2800, 2900, 3000, 3200 }
diff --git a/rigs/yaesu/newcat.c b/rigs/yaesu/newcat.c
index 38a26da0c..a6c8e2016 100644
--- a/rigs/yaesu/newcat.c
+++ b/rigs/yaesu/newcat.c
@@ -759,8 +759,7 @@ int newcat_init(RIG *rig)
STATE(rig)->priv = (struct newcat_priv_data *) calloc(1,
sizeof(struct newcat_priv_data));
- if (!STATE(
- rig)->priv) /* whoops! memory shortage! */
+ if (!STATE(rig)->priv) /* whoops! memory shortage! */
{
RETURNFUNC(-RIG_ENOMEM);
}
@@ -774,34 +773,6 @@ int newcat_init(RIG *rig)
priv->current_mem = NC_MEM_CHANNEL_NONE;
priv->fast_set_commands = FALSE;
- /*
- * Determine the type of rig from the model number. Note it is
- * possible for several model variants to exist; i.e., all the
- * FT-9000 variants.
- */
-
-#if 0
- is_ft450 = newcat_is_rig(rig, RIG_MODEL_FT450);
- is_ft450 |= newcat_is_rig(rig, RIG_MODEL_FT450D);
- is_ft891 = newcat_is_rig(rig, RIG_MODEL_FT891);
- is_ft897 = newcat_is_rig(rig, RIG_MODEL_FT897);
- is_ft897d = newcat_is_rig(rig, RIG_MODEL_FT897D);
- is_ft950 = newcat_is_rig(rig, RIG_MODEL_FT950);
- is_ft991 = newcat_is_rig(rig, RIG_MODEL_FT991);
- is_ft2000 = newcat_is_rig(rig, RIG_MODEL_FT2000);
- is_ftdx9000 = newcat_is_rig(rig, RIG_MODEL_FT9000);
- is_ftdx9000Old = newcat_is_rig(rig, RIG_MODEL_FT9000OLD);
- is_ftdx5000 = newcat_is_rig(rig, RIG_MODEL_FTDX5000);
- is_ftdx1200 = newcat_is_rig(rig, RIG_MODEL_FTDX1200);
- is_ftdx3000 = newcat_is_rig(rig, RIG_MODEL_FTDX3000);
- is_ftdx3000dm = FALSE; // Detected dynamically
- is_ftdx101d = newcat_is_rig(rig, RIG_MODEL_FTDX101D);
- is_ftdx101mp = newcat_is_rig(rig, RIG_MODEL_FTDX101MP);
- is_ftdx10 = newcat_is_rig(rig, RIG_MODEL_FTDX10);
- is_ft710 = newcat_is_rig(rig, RIG_MODEL_FT710);
- is_ftx1 = newcat_is_rig(rig, RIG_MODEL_FTX1);
-#endif
-
RETURNFUNC(RIG_OK);
}
@@ -8845,24 +8816,8 @@ int newcat_set_rx_bandwidth(RIG *rig, vfo_t vfo, rmode_t mode, pbwidth_t width)
RETURNFUNC(err);
}
- 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; }
- else if (width <= 200) { w = 4; }
- else if (width <= 250) { w = 5; }
- else if (width <= 300) { w = 6; }
- else if (width <= 350) { w = 7; }
- else if (width <= 400) { w = 8; }
- else if (width <= 450) { w = 9; }
- else if (width <= 500) { w = 10; }
- else if (width <= 800) { w = 11; }
- else if (width <= 1200) { w = 12; }
- else if (width <= 1400) { w = 13; }
- else if (width <= 1700) { w = 14; }
- else if (width <= 2000) { w = 15; }
- else if (width <= 2400) { w = 16; }
- else { w = 17; } // 3000 Hz
+ w = newcat_get_index_from_width(width, priv_caps->cw_widths);
+ if (w < 0) { RETURNFUNC(w); }
break;
@@ -8876,28 +8831,8 @@ int newcat_set_rx_bandwidth(RIG *rig, vfo_t vfo, rmode_t mode, pbwidth_t width)
RETURNFUNC(err);
}
- if (width == RIG_PASSBAND_NORMAL) { w = 0; }
- else if (width <= 200) { w = 1; }
- else if (width <= 400) { w = 2; }
- else if (width <= 600) { w = 3; }
- else if (width <= 850) { w = 4; }
- else if (width <= 1100) { w = 5; }
- else if (width <= 1350) { w = 6; }
- else if (width <= 1500) { w = 7; }
- else if (width <= 1650) { w = 8; }
- else if (width <= 1800) { w = 9; }
- else if (width <= 1950) { w = 10; }
- else if (width <= 2100) { w = 11; }
- else if (width <= 2200) { w = 12; }
- else if (width <= 2300) { w = 13; }
- else if (width <= 2400) { w = 14; }
- else if (width <= 2500) { w = 15; }
- else if (width <= 2600) { w = 16; }
- else if (width <= 2700) { w = 17; }
- else if (width <= 2800) { w = 18; }
- else if (width <= 2900) { w = 19; }
- else if (width <= 3000) { w = 20; }
- else { w = 21; } // 3000 Hz
+ w = newcat_get_index_from_width(width, priv_caps->ssb_widths);
+ if (w < 0) { RETURNFUNC(w); }
break;
@@ -9908,9 +9843,12 @@ int newcat_get_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:
- switch (w)
+ if (w > 0 && w < priv_caps->cw_widths->count)
+ {
+ *width = priv_caps->cw_widths->widths[w];
+ }
+ else if (w == 0)
{
- case 0:
if (mode == RIG_MODE_CW || mode == RIG_MODE_CWR)
{
*width = narrow ? 500 : 2400;
@@ -9919,44 +9857,9 @@ int newcat_get_rx_bandwidth(RIG *rig, vfo_t vfo, rmode_t mode, pbwidth_t *width)
{
*width = narrow ? 300 : 500;
}
-
- break;
-
- case 1: *width = 50; break;
-
- case 2: *width = 100; break;
-
- case 3: *width = 150; break;
-
- case 4: *width = 200; break;
-
- case 5: *width = 250; break;
-
- case 6: *width = 300; break;
-
- case 7: *width = 350; break;
-
- case 8: *width = 400; break;
-
- case 9: *width = 450; break;
-
- case 10: *width = 500; break;
-
- case 11: *width = 800; break;
-
- case 12: *width = 1200; break;
-
- case 13: *width = 1400; break;
-
- case 14: *width = 1700; break;
-
- case 15: *width = 2000; break;
-
- case 16: *width = 2400; break;
-
- case 17: *width = 3000; break;
-
- default:
+ }
+ else
+ {
rig_debug(RIG_DEBUG_ERR, "%s: unknown w=%d\n", __func__, w);
RETURNFUNC(-RIG_EINVAL);
}
@@ -9965,53 +9868,16 @@ int newcat_get_rx_bandwidth(RIG *rig, vfo_t vfo, rmode_t mode, pbwidth_t *width)
case RIG_MODE_LSB:
case RIG_MODE_USB:
- switch (w)
+ if (w > 0 && w < priv_caps->ssb_widths->count)
+ {
+ *width = priv_caps->ssb_widths->widths[w];
+ }
+ else if (w == 0)
+ {
+ *width = narrow ? 1500 : 2400;
+ }
+ else
{
- case 0: *width = narrow ? 1500 : 2400; break;
-
- case 1: *width = 200; break;
-
- case 2: *width = 400; break;
-
- case 3: *width = 600; break;
-
- case 4: *width = 850; break;
-
- case 5: *width = 1100; break;
-
- case 6: *width = 1350; break;
-
- case 7: *width = 1500; break;
-
- case 8: *width = 1650; break;
-
- case 9: *width = 1800; break;
-
- case 10: *width = 1950; break;
-
- case 11: *width = 2100; break;
-
- case 12: *width = 2200; break;
-
- case 13: *width = 2300; break;
-
- case 14: *width = 2400; break;
-
- case 15: *width = 2500; break;
-
- case 16: *width = 2600; break;
-
- case 17: *width = 2700; break;
-
- case 18: *width = 2800; break;
-
- case 19: *width = 2900; break;
-
- case 20: *width = 3000; break;
-
- case 21: *width = 3200; break;
-
- default:
rig_debug(RIG_DEBUG_ERR, "%s: unknown mode=%s\n", __func__, rig_strrmode(mode));
RETURNFUNC(-RIG_EINVAL);
}
@@ -10087,7 +9953,7 @@ int newcat_get_rx_bandwidth(RIG *rig, vfo_t vfo, rmode_t mode, pbwidth_t *width)
}
else if (w == 0)
{
- *width = narrow ? 1500 : 2400; break;
+ *width = narrow ? 1500 : 2400;
}
else
{
diff --git a/rigs/yaesu/newcat.h b/rigs/yaesu/newcat.h
index 75fbaf70a..40481d28a 100644
--- a/rigs/yaesu/newcat.h
+++ b/rigs/yaesu/newcat.h
@@ -272,6 +272,7 @@ int newcat_scan(RIG *rig, vfo_t vfo, scan_t scan, int ch);
/*
* Shared data structures
*/
+extern const struct newcat_width_info ft991_cw_widths, ft991_ssb_widths;
extern const struct newcat_width_info ftdx101_cw_widths, ftdx101_ssb_widths;
#define TOKEN_BACKEND(t) (t)
commit 3dec8fb59cd9910f7efe87b5c6f72c7ef516017e
Author: George Baltz N3GB <Geo...@gm...>
Date: Fri Apr 17 05:38:28 2026 -0400
Convert FT-991/FT-991A
Re-arrange some if() statements so most likely case is first.
diff --git a/rigs/yaesu/ft991.c b/rigs/yaesu/ft991.c
index 4f6d19922..fd197cf8b 100644
--- a/rigs/yaesu/ft991.c
+++ b/rigs/yaesu/ft991.c
@@ -169,6 +169,25 @@ int ft991_ext_tokens[] =
TOK_BACKEND_NONE
};
+/*
+ * Rig unique data
+ */
+static const struct newcat_width_info ft991_cw_widths = {
+ .count = 18,
+ .widths = { 0, 50, 100, 150, 200, 250, 300, 350, 400, 450, 500, 800, 1200, 1400, 1700,
+ 2000, 2400, 3000 }
+};
+static const struct newcat_width_info ft991_ssb_widths = {
+ .count = 22,
+ .widths = { 0, 200, 400, 600, 850, 1100, 1350, 1500, 1650, 1800, 1950, 2100, 2200, 2300,
+ 2400, 2500, 2600, 2700, 2800, 2900, 3000, 3200 }
+};
+
+static const struct newcat_priv_caps ft991_priv_caps = {
+ .cw_widths = &ft991_cw_widths,
+ .ssb_widths = &ft991_ssb_widths
+};
+
/*
* FT-991 rig capabilities
*/
@@ -347,7 +366,7 @@ struct rig_caps ft991_caps =
.ext_tokens = ft991_ext_tokens,
.extlevels = ft991_ext_levels,
- .priv = NULL, /* private data FIXME: */
+ .priv = &ft991_priv_caps,
.rig_init = ft991_init,
.rig_cleanup = newcat_cleanup,
diff --git a/rigs/yaesu/newcat.c b/rigs/yaesu/newcat.c
index fa0ac4920..38a26da0c 100644
--- a/rigs/yaesu/newcat.c
+++ b/rigs/yaesu/newcat.c
@@ -8934,24 +8934,8 @@ int newcat_set_rx_bandwidth(RIG *rig, vfo_t vfo, rmode_t mode, pbwidth_t width)
RETURNFUNC(err);
}
- 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; }
- else if (width <= 200) { w = 4; }
- else if (width <= 250) { w = 5; }
- else if (width <= 300) { w = 6; }
- else if (width <= 350) { w = 7; }
- else if (width <= 400) { w = 8; }
- else if (width <= 450) { w = 9; }
- else if (width <= 500) { w = 10; }
- else if (width <= 800) { w = 11; }
- else if (width <= 1200) { w = 12; }
- else if (width <= 1400) { w = 13; }
- else if (width <= 1700) { w = 14; }
- else if (width <= 2000) { w = 15; }
- else if (width <= 2400) { w = 16; }
- else { w = 17; } // 3000 Hz
+ w = newcat_get_index_from_width(width, priv_caps->cw_widths);
+ if (w < 0) { RETURNFUNC(w); }
break;
@@ -8965,28 +8949,8 @@ int newcat_set_rx_bandwidth(RIG *rig, vfo_t vfo, rmode_t mode, pbwidth_t width)
RETURNFUNC(err);
}
- if (width == RIG_PASSBAND_NORMAL) { w = 0; }
- else if (width <= 200) { w = 1; }
- else if (width <= 400) { w = 2; }
- else if (width <= 600) { w = 3; }
- else if (width <= 850) { w = 4; }
- else if (width <= 1100) { w = 5; }
- else if (width <= 1350) { w = 6; }
- else if (width <= 1500) { w = 7; }
- else if (width <= 1650) { w = 8; }
- else if (width <= 1800) { w = 9; }
- else if (width <= 1950) { w = 10; }
- else if (width <= 2100) { w = 11; }
- else if (width <= 2200) { w = 12; }
- else if (width <= 2300) { w = 13; }
- else if (width <= 2400) { w = 14; }
- else if (width <= 2500) { w = 15; }
- else if (width <= 2600) { w = 16; }
- else if (width <= 2700) { w = 17; }
- else if (width <= 2800) { w = 18; }
- else if (width <= 2900) { w = 19; }
- else if (width <= 3000) { w = 20; }
- else { w = 21; } // 3200 Hz
+ w = newcat_get_index_from_width(width, priv_caps->ssb_widths);
+ if (w < 0) { RETURNFUNC(w); }
break;
@@ -9877,34 +9841,34 @@ int newcat_get_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 (w == 0)
+ if (w > 0 && w < priv_caps->cw_widths->count)
{
- ...
[truncated message content] |
|
From: n0nb <n0...@us...> - 2026-04-19 17:45:42
|
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, Hamlib-4.7 has been updated
via bd551aad73d207d2a00a7f5ea21f710b7ca4c304 (commit)
via 65905f201d29aa710e01ac1fadf47cd15d382a59 (commit)
via 88b4efda04e2a1a9187b7531a12ab9981b216fa8 (commit)
via 893a10f2e380034425878d85a42a1ad5daa3b632 (commit)
via 2bbd6699af0d87a75ecf251ee58fd4691baf14c2 (commit)
via c9ca4c4688349a5fcd9768c63be2ca73dfb6cd4c (commit)
via 25d2db438da02eb239287fab1ed530d9280764ad (commit)
from d042479a9f8095ba1a8e103a977c3614d7233cb2 (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 bd551aad73d207d2a00a7f5ea21f710b7ca4c304
Author: KJ5HST <kj...@de...>
Date: Sun Apr 19 10:40:45 2026 -0400
ftx1: use bounded %.*s in snprintf to silence GCC -Wformat-truncation
Replace "%s" with "%.*s" and explicit precision (sizeof(dst) - 1)
in the four ret_data snapshot sites. Reported by N0NB on Debian 13
(GCC 14); clang and MinGW GCC did not trigger the warning.
(cherry picked from commit 8a714a44b6147bdc56be5b31975a85674d4a76df)
diff --git a/rigs/yaesu/ftx1/ftx1_mem.c b/rigs/yaesu/ftx1/ftx1_mem.c
index e3f64e501..857ed0616 100644
--- a/rigs/yaesu/ftx1/ftx1_mem.c
+++ b/rigs/yaesu/ftx1/ftx1_mem.c
@@ -242,12 +242,14 @@ int ftx1_set_channel(RIG *rig, vfo_t vfo, const channel_t *chan)
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "FB;");
if (newcat_get_cmd(rig) == RIG_OK)
{
- snprintf(saved_fb, sizeof(saved_fb), "%s", priv->ret_data);
+ snprintf(saved_fb, sizeof(saved_fb), "%.*s",
+ (int)sizeof(saved_fb) - 1, priv->ret_data);
}
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "MD1;");
if (newcat_get_cmd(rig) == RIG_OK)
{
- snprintf(saved_md1, sizeof(saved_md1), "%s", priv->ret_data);
+ snprintf(saved_md1, sizeof(saved_md1), "%.*s",
+ (int)sizeof(saved_md1) - 1, priv->ret_data);
}
/* 1. Point the Sub-side MC cursor at the target slot. The MC SET
@@ -456,12 +458,14 @@ static void ftx1_read_channel_tone_state(RIG *rig, int ch, int mr_p8,
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "VM0;");
if (newcat_get_cmd(rig) == RIG_OK)
{
- snprintf(saved_vm, sizeof(saved_vm), "%s", priv->ret_data);
+ snprintf(saved_vm, sizeof(saved_vm), "%.*s",
+ (int)sizeof(saved_vm) - 1, priv->ret_data);
}
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "MC0;");
if (newcat_get_cmd(rig) == RIG_OK)
{
- snprintf(saved_mc, sizeof(saved_mc), "%s", priv->ret_data);
+ snprintf(saved_mc, sizeof(saved_mc), "%.*s",
+ (int)sizeof(saved_mc) - 1, priv->ret_data);
}
/* Select the target memory channel. */
commit 65905f201d29aa710e01ac1fadf47cd15d382a59
Author: KJ5HST <kj...@de...>
Date: Sat Apr 18 21:39:31 2026 -0400
ftx1: silence GCC strncpy warnings, target Sub cursor in set_channel
Two fixes in preparation for resubmitting PR #2035:
1. Replace four strncpy(dst, src, sizeof(dst) - 1) calls with
snprintf(dst, sizeof(dst), "%s", src). GCC on Debian 13 flagged
these as -Wstringop-truncation because priv->ret_data (128 bytes)
is larger than the destination and strncpy doesn't guarantee NUL
termination. snprintf always NUL-terminates, which GCC recognises
as safe. Clang does not emit the warning either way.
Reported by N0NB. Sites: saved_fb / saved_md1 in ftx1_set_channel,
and saved_vm / saved_mc in ftx1_read_channel_tone_state.
2. Change the cursor step in ftx1_set_channel from MC%06d; to
MC1%05d;. Hardware probing (2026-04-18, fw v1.12) established that
the MC SET command takes a VFO digit followed by a 5-digit channel:
MC0NNNNN targets Main, MC1NNNNN targets Sub. Both sides maintain
independent memory-mode state and can be parked in memory mode
simultaneously (VM011 + VM111). BM commits VFO-B to the Sub side's
last-selected memory, so the cursor-positioning step should target
Sub. The previous MC%06d; form produced MC0NNNNN for channels
1..99, silently flipping Main's front-panel channel to the write
target on every ftx1_set_channel call.
Also rewrites the MC comment block at the top of ftx1_mem.c to
document the VFO digit in both SET and READ forms, replacing the
prior (incorrect) claim that the SET form is VFO-less.
(cherry picked from commit 2b28d2e0ad064b717c8180da139ec0f0f8c2b8f0)
diff --git a/rigs/yaesu/ftx1/ftx1_mem.c b/rigs/yaesu/ftx1/ftx1_mem.c
index 9b818a9f7..e3f64e501 100644
--- a/rigs/yaesu/ftx1/ftx1_mem.c
+++ b/rigs/yaesu/ftx1/ftx1_mem.c
@@ -8,10 +8,20 @@
* All memory commands use DIFFERENT FORMATS than documented in the spec!
*
* MC (Memory Channel Select):
- * Query: MC0 (MAIN VFO) or MC1 (SUB VFO)
- * Response: MCNNNNNN (6-digit channel, e.g., MC000001)
- * Set: MCNNNNNN (6-digit channel)
- * Returns '?' if channel doesn't exist (not programmed)
+ * Both the query and the set form take a VFO digit followed by a
+ * 5-digit channel. The VFO digit is 0 (Main) or 1 (Sub); the two
+ * sides have independent memory-mode state and can both be parked
+ * in memory mode simultaneously (VM011 + VM111).
+ * Query: MC0; returns MC0NNNNN (Main's channel)
+ * MC1; returns MC1NNNNN (Sub's channel)
+ * Set: MC0NNNNN; tunes Main to channel NNNNN
+ * MC1NNNNN; tunes Sub to channel NNNNN
+ * The radio's active VFO (VS) does NOT influence which side the SET
+ * applies to — the first digit of the parameter does. MC%06d; with
+ * a channel in 1..99 happens to produce MC0NNNNN, so it targets
+ * Main. Hardware-verified 2026-04-18 against fw v1.12.
+ * Returns '?' if channel doesn't exist (not programmed), but the
+ * cursor still updates for a subsequent BM commit.
*
* MR (Memory Read): 5-digit format
* Query: MR00001 (not MR001 or MR0001)
@@ -232,17 +242,22 @@ int ftx1_set_channel(RIG *rig, vfo_t vfo, const channel_t *chan)
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "FB;");
if (newcat_get_cmd(rig) == RIG_OK)
{
- strncpy(saved_fb, priv->ret_data, sizeof(saved_fb) - 1);
+ snprintf(saved_fb, sizeof(saved_fb), "%s", priv->ret_data);
}
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "MD1;");
if (newcat_get_cmd(rig) == RIG_OK)
{
- strncpy(saved_md1, priv->ret_data, sizeof(saved_md1) - 1);
+ snprintf(saved_md1, sizeof(saved_md1), "%s", priv->ret_data);
}
- /* 1. Point the MC cursor at the target slot. Returns '?;' when the
- * slot is unprogrammed, but the cursor still updates for BM. */
- SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "MC%06d;",
+ /* 1. Point the Sub-side MC cursor at the target slot. The MC SET
+ * form takes a VFO digit followed by a 5-digit channel
+ * (MC0NNNNN = Main, MC1NNNNN = Sub); BM commits VFO-B to the
+ * last-selected memory on the Sub side, so targeting Sub here
+ * keeps Main's front-panel channel from silently flipping.
+ * Returns '?;' when the slot is unprogrammed, but the cursor
+ * still updates for the subsequent BM. */
+ SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "MC1%05d;",
chan->channel_num);
(void)newcat_set_cmd(rig);
@@ -441,12 +456,12 @@ static void ftx1_read_channel_tone_state(RIG *rig, int ch, int mr_p8,
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "VM0;");
if (newcat_get_cmd(rig) == RIG_OK)
{
- strncpy(saved_vm, priv->ret_data, sizeof(saved_vm) - 1);
+ snprintf(saved_vm, sizeof(saved_vm), "%s", priv->ret_data);
}
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "MC0;");
if (newcat_get_cmd(rig) == RIG_OK)
{
- strncpy(saved_mc, priv->ret_data, sizeof(saved_mc) - 1);
+ snprintf(saved_mc, sizeof(saved_mc), "%s", priv->ret_data);
}
/* Select the target memory channel. */
commit 88b4efda04e2a1a9187b7531a12ab9981b216fa8
Author: KJ5HST <kj...@de...>
Date: Wed Apr 15 16:17:12 2026 -0400
ftx1: auto-exit Memory mode before VFO-state setters (#2034)
Commands that set VFO-side state on the Main side behave poorly when
the radio is in Memory mode (VM011):
FA main-freq set: rejected outright with '?;'
OS repeater shift: rejected outright with '?;'
MD main-mode set: accepted but treated as a transient memory-tune
overlay — the change does not persist when the
user leaves the channel
CT main-CTCSS mode: transient overlay (same pattern)
CN main-tone/DCS: transient overlay (same pattern)
Hamlib had no awareness of this: a caller doing rig_set_mem() followed
by rig_set_freq() would silently fail (FA rejected), and rig_set_mode()
would appear to succeed but the mode change would vanish on the next
MC recall.
Add a simple memory-mode tracking flag to the shared newcat_priv_data
(ftx1_in_memory_mode), set to 1 inside ftx1_set_mem after a successful
MC command. Introduce ftx1_ensure_vfo_mode() in ftx1.c that checks the
flag and, if set, sends VM000; and clears the flag. Call it at the top
of every VFO-state setter that is actually affected by Memory mode:
ftx1_set_freq (Main-VFO branch only — FB on Sub is unaffected)
ftx1_set_rptr_shift (OS)
ftx1_set_ctcss_mode (CT Main)
ftx1_set_ctcss_tone (CN00 Main)
ftx1_set_dcs_code (CN01 Main)
Sub-targeted CN commands (CN10/CN11 in set_ctcss_sql / set_dcs_sql) are
deliberately left alone — the Sub side is never in Memory mode on this
firmware, and an injection there would needlessly clobber a user who
has intentionally parked Main in Memory mode while tuning Sub.
Add a new ftx1_set_mode wrapper in ftx1_mode.c that calls
ftx1_ensure_vfo_mode() and delegates to newcat_set_mode. Wire it up in
rig_caps (replacing the direct newcat_set_mode pointer).
Also flip priv->ftx1_in_memory_mode = 0 at the end of ftx1_set_channel
because the BM commit path always ends with the Main side in VFO mode,
regardless of the caller's prior position.
Verified end-to-end against fw v1.12:
$ rigctl -m 1051 -r ... E 1
Rig command: F 7050000
Rig command: f
7050000
(radio is now in VFO mode at 7.050 MHz — without the fix the F would
have been rejected and the radio would still be in Memory mode)
$ rigctl -m 1051 -r ... E 1
Rig command: M USB 2700
Rig command: m
Mode: USB
Passband: 2700
(VFO mode USB — without the fix the MD set would have been a
transient overlay that vanished on next MC recall)
The tracking flag avoids paying for a VM000 CAT round trip on every
setter call; it only fires when the driver actually knows the radio
entered Memory mode via set_mem.
(cherry picked from commit 370dca238ac3f7eeb7c70b41110b6ab08ab2f26a)
diff --git a/rigs/yaesu/ftx1/ftx1.c b/rigs/yaesu/ftx1/ftx1.c
index a2bb45cc4..c8806b934 100644
--- a/rigs/yaesu/ftx1/ftx1.c
+++ b/rigs/yaesu/ftx1/ftx1.c
@@ -72,6 +72,7 @@ extern int ftx1_set_att_helper(RIG *rig, vfo_t vfo, value_t val);
extern int ftx1_get_att_helper(RIG *rig, vfo_t vfo, value_t *val);
/* Wrappers from ftx1_func.c for rig caps */
+extern int ftx1_set_mode(RIG *rig, vfo_t vfo, rmode_t mode, pbwidth_t width);
extern int ftx1_set_ptt_func(RIG *rig, vfo_t vfo, ptt_t ptt);
extern int ftx1_get_ptt_func(RIG *rig, vfo_t vfo, ptt_t *ptt);
extern int ftx1_set_powerstat_func(RIG *rig, powerstat_t status);
@@ -862,6 +863,43 @@ static int ftx1_close(RIG *rig)
return newcat_close(rig);
}
+/*
+ * ftx1_ensure_vfo_mode - exit Memory mode if the driver last saw MC enter it
+ *
+ * FTX-1 firmware rejects FA/OS sets when the Main side is in Memory mode
+ * (VM011) and silently discards CT/CN/MD sets as transient memory-tune
+ * overlays. Callers that set VFO-side state should call this first so the
+ * operation actually lands.
+ *
+ * We track memory-mode entry in priv->ftx1_in_memory_mode (set by
+ * ftx1_set_mem after a successful MC). If the flag is clear, this is a
+ * no-op — we don't spam the rig with VM000 on every VFO-state set.
+ *
+ * Best-effort: on failure the flag is cleared unconditionally so we
+ * don't loop.
+ */
+void ftx1_ensure_vfo_mode(RIG *rig)
+{
+ struct newcat_priv_data *priv;
+
+ if (!rig)
+ {
+ return;
+ }
+
+ priv = STATE(rig)->priv;
+ if (!priv || !priv->ftx1_in_memory_mode)
+ {
+ return;
+ }
+
+ rig_debug(RIG_DEBUG_VERBOSE, "%s: exiting memory mode via VM000;\n",
+ __func__);
+ SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "VM000;");
+ (void)newcat_set_cmd(rig);
+ priv->ftx1_in_memory_mode = 0;
+}
+
/*
* ftx1_has_spa1 - Check if Optima/SPA-1 amplifier is present
*
@@ -1157,7 +1195,7 @@ struct rig_caps ftx1_caps = {
.rig_close = ftx1_close, /* FTX-1 specific close - resets detection state */
.set_freq = ftx1_set_freq,
.get_freq = ftx1_get_freq,
- .set_mode = newcat_set_mode,
+ .set_mode = ftx1_set_mode,
.get_mode = newcat_get_mode,
.set_vfo = ftx1_set_vfo,
.get_vfo = ftx1_get_vfo,
diff --git a/rigs/yaesu/ftx1/ftx1.h b/rigs/yaesu/ftx1/ftx1.h
index 33da645ee..ee88a6e5c 100644
--- a/rigs/yaesu/ftx1/ftx1.h
+++ b/rigs/yaesu/ftx1/ftx1.h
@@ -219,6 +219,14 @@ static inline int ftx1_vfo_to_p1(RIG *rig, vfo_t vfo)
extern int ftx1_has_spa1(RIG *rig);
extern int ftx1_get_head_type(RIG *rig);
+/*
+ * ftx1_ensure_vfo_mode - force the radio out of Memory mode if the driver
+ * knows it entered via a prior set_mem. Call at the top of any VFO-state
+ * setter that would otherwise fail or behave transiently in Memory mode.
+ * See ftx1.c for full rationale.
+ */
+extern void ftx1_ensure_vfo_mode(RIG *rig);
+
/*
* FTX-1 band select functions (defined in ftx1_scan.c)
*/
diff --git a/rigs/yaesu/ftx1/ftx1_ctcss.c b/rigs/yaesu/ftx1/ftx1_ctcss.c
index fd0210114..faf608a55 100644
--- a/rigs/yaesu/ftx1/ftx1_ctcss.c
+++ b/rigs/yaesu/ftx1/ftx1_ctcss.c
@@ -101,6 +101,10 @@ int ftx1_set_ctcss_mode(RIG *rig, tone_t mode)
rig_debug(RIG_DEBUG_VERBOSE, "%s: mode=%u\n", __func__, mode);
+ /* CT sets are transient overlays in Memory mode — accepted but not
+ * persisted. Exit memory mode so the change actually sticks. */
+ ftx1_ensure_vfo_mode(rig);
+
/* CT P1 P2; where P1=VFO (0=Main), P2=mode */
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "CT0%d;", (int)mode);
return newcat_set_cmd(rig);
@@ -168,6 +172,9 @@ int ftx1_set_ctcss_tone(RIG *rig, vfo_t vfo, tone_t tone)
rig_debug(RIG_DEBUG_VERBOSE, "%s: tone=%u tone_num=%d\n", __func__, tone,
tone_num);
+ /* CN on Main is a transient overlay in Memory mode — exit first. */
+ ftx1_ensure_vfo_mode(rig);
+
/* P1=0 for TX tone, P2P3P4 is 3-digit tone number */
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "CN00%03d;", tone_num);
return newcat_set_cmd(rig);
@@ -225,7 +232,9 @@ int ftx1_set_ctcss_sql(RIG *rig, vfo_t vfo, tone_t tone)
rig_debug(RIG_DEBUG_VERBOSE, "%s: tone=%u tone_num=%d\n", __func__, tone,
tone_num);
- /* P1=1 for RX tone, P2P3P4 is 3-digit tone number */
+ /* P1=1 for RX tone, P2P3P4 is 3-digit tone number. CN10 targets
+ * Sub VFO, which is not affected by Main's Memory mode, so no
+ * VM000 injection is needed here. */
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "CN10%03d;", tone_num);
return newcat_set_cmd(rig);
}
@@ -280,6 +289,9 @@ int ftx1_set_dcs_code(RIG *rig, vfo_t vfo, tone_t code)
rig_debug(RIG_DEBUG_VERBOSE, "%s: code=%u\n", __func__, code);
+ /* CN on Main is a transient overlay in Memory mode — exit first. */
+ ftx1_ensure_vfo_mode(rig);
+
/* CN01XXX: Main VFO (0), DCS (1), code index */
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "CN01%03u;", code);
return newcat_set_cmd(rig);
diff --git a/rigs/yaesu/ftx1/ftx1_freq.c b/rigs/yaesu/ftx1/ftx1_freq.c
index ede4a269d..07308f43e 100644
--- a/rigs/yaesu/ftx1/ftx1_freq.c
+++ b/rigs/yaesu/ftx1/ftx1_freq.c
@@ -16,6 +16,7 @@
#include "misc.h"
#include "yaesu.h"
#include "newcat.h"
+#include "ftx1.h"
// FTX-1 uses 9-digit Hz format for frequency
#define FTX1_FREQ_DIGITS 9
@@ -42,6 +43,10 @@ int ftx1_set_freq(RIG *rig, vfo_t vfo, freq_t freq)
case RIG_VFO_MAIN:
case RIG_VFO_CURR:
cmd = 'A';
+ /* FA set is rejected with ?; while the Main side is in Memory
+ * mode. Force an exit before sending the command. FB (sub) is
+ * unaffected and does not need this. */
+ ftx1_ensure_vfo_mode(rig);
break;
case RIG_VFO_B:
@@ -175,6 +180,9 @@ int ftx1_set_rptr_shift(RIG *rig, vfo_t vfo, rptr_shift_t shift)
rig_debug(RIG_DEBUG_VERBOSE, "%s: vfo=%s shift=%d\n",
__func__, rig_strvfo(vfo), shift);
+ /* OS Main is rejected with ?; in Memory mode. Exit before sending. */
+ ftx1_ensure_vfo_mode(rig);
+
/* Determine VFO */
switch (vfo)
{
diff --git a/rigs/yaesu/ftx1/ftx1_mem.c b/rigs/yaesu/ftx1/ftx1_mem.c
index 853ac4d4c..9b818a9f7 100644
--- a/rigs/yaesu/ftx1/ftx1_mem.c
+++ b/rigs/yaesu/ftx1/ftx1_mem.c
@@ -67,6 +67,7 @@ static int ftx1_get_vfo_mem_mode_internal(RIG *rig, vfo_t *vfo);
int ftx1_set_mem(RIG *rig, vfo_t vfo, int ch)
{
struct newcat_priv_data *priv = STATE(rig)->priv;
+ int ret;
(void)vfo; /* VFO not used in MC command */
@@ -80,7 +81,15 @@ int ftx1_set_mem(RIG *rig, vfo_t vfo, int ch)
/* Format: MCNNNNNN (6-digit channel) */
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "MC%06d;", ch);
- return newcat_set_cmd(rig);
+ ret = newcat_set_cmd(rig);
+ if (ret == RIG_OK)
+ {
+ /* MC on a programmed channel enters Memory mode on the Main
+ * side. Track this so the next VFO-state setter can force an
+ * exit via VM000 before issuing FA/OS/CT/CN/MD. */
+ priv->ftx1_in_memory_mode = 1;
+ }
+ return ret;
}
/*
@@ -388,6 +397,11 @@ restore:
(void)newcat_set_cmd(rig);
}
+ /* BM always ends with the Main side in VFO mode regardless of the
+ * caller's prior position, so clear the memory-mode tracking flag
+ * to keep ftx1_ensure_vfo_mode() accurate for subsequent setters. */
+ priv->ftx1_in_memory_mode = 0;
+
return err;
}
diff --git a/rigs/yaesu/ftx1/ftx1_mode.c b/rigs/yaesu/ftx1/ftx1_mode.c
index 292795e60..fd7bba3bd 100644
--- a/rigs/yaesu/ftx1/ftx1_mode.c
+++ b/rigs/yaesu/ftx1/ftx1_mode.c
@@ -2,8 +2,12 @@
* Hamlib Yaesu backend - FTX-1 Mode Commands
* Copyright (c) 2025 by Terrell Deppe (KJ5HST)
*
- * Mode commands are handled by newcat_set_mode/newcat_get_mode.
- * This file documents the FTX-1 specific mode codes for reference.
+ * Mode commands are mostly handled by newcat_set_mode/newcat_get_mode.
+ * This file adds an FTX-1 set_mode wrapper that forces the radio out
+ * of Memory mode before delegating to newcat, because Memory-mode MD
+ * sets on the Main side are accepted by firmware but treated as a
+ * transient memory-tune overlay that does not persist when the user
+ * leaves the channel.
*
* CAT Commands:
* MD P1 P2; - Operating Mode (P1=VFO 0/1, P2=mode code)
@@ -17,4 +21,15 @@
* NA (Notch Auto) - handled via ftx1_noise.c
*/
-/* No FTX-1 specific mode functions needed - newcat handles MD command */
+#include <hamlib/rig.h>
+#include "newcat.h"
+#include "ftx1.h"
+
+int ftx1_set_mode(RIG *rig, vfo_t vfo, rmode_t mode, pbwidth_t width)
+{
+ /* Memory-mode MD sets on Main are accepted but do not persist —
+ * they act as a transient memory-tune overlay. Force an exit so
+ * the user's mode change actually sticks. */
+ ftx1_ensure_vfo_mode(rig);
+ return newcat_set_mode(rig, vfo, mode, width);
+}
diff --git a/rigs/yaesu/newcat.h b/rigs/yaesu/newcat.h
index 2e0372777..a02acab7f 100644
--- a/rigs/yaesu/newcat.h
+++ b/rigs/yaesu/newcat.h
@@ -142,6 +142,7 @@ struct newcat_priv_data
int ftx1_clar_cached; /* 1 if RX/TX CLAR states have been cached */
char ftx1_rx_clar_on; /* Cached RX CLAR enable: '0' or '1' */
char ftx1_tx_clar_on; /* Cached TX CLAR enable: '0' or '1' */
+ int ftx1_in_memory_mode; /* 1 if driver knows the Main-side is in Memory mode (VM011) */
};
/*
commit 893a10f2e380034425878d85a42a1ad5daa3b632
Author: KJ5HST <kj...@de...>
Date: Wed Apr 15 15:43:29 2026 -0400
ftx1: populate CTCSS/DCS fields in get_channel
ftx1_get_channel has historically parsed the P8 byte from the MR
response and then discarded it with a (void) cast, so rig_get_channel
always returned chan->ctcss_tone == 0 regardless of what was actually
programmed in the channel. An FM memory channel with a CTCSS tone or
DCS code read back as "no tone" — silently misleading for callers.
MR itself does not carry the tone number, only the mode (P8).
Verified by byte-level comparison of MR responses across "no tone"
and "CTCSS ENC tone 12" writes on fw v1.12 — only byte 23 differs.
The tone number lives in CN, which is only queryable against an
operating VFO.
Add ftx1_read_channel_tone_state(), a static helper that:
1. Snapshots current VM and MC state via queries
2. Selects the target memory channel via MC<ch>; (enters mem mode)
3. Queries CN00 (CTCSS) or CN01 (DCS) to get the stored number
4. Populates chan->ctcss_tone / ctcss_sql / dcs_code using
ftx1_tone_num_to_freq() for CTCSS
5. Restores the caller's prior state — if originally in VFO mode
send VM000, if originally in memory mode on another channel
send MC<original>
The helper applies the MW/MR P8 swap encoding (P8=1 is TSQ, P8=2
is ENC, P8=3 is DCS) and sets ctcss_sql only for the TSQ case.
Intrusiveness: get_channel now briefly switches the radio to memory
mode on the target channel, which causes a momentary front-panel
display change. State is restored before the function returns so the
operator's net position is unchanged. The intrusion is only triggered
when P8 indicates a tone is present — no-tone channels skip the CN
query entirely.
Also exposes ftx1_tone_num_to_freq() via ftx1.h (previously file-
static in ftx1_ctcss.c) so ftx1_mem.c can reuse the existing tone
table instead of duplicating it.
Verified end-to-end via rigctl H/h against fw v1.12:
ENC: H 1 ... 1000 0 -> h 1: CTCSS: 100.0Hz, CTCSSsql: 0.0Hz
TSQ: H 1 ... 1000 1000 -> h 1: CTCSS: 100.0Hz, CTCSSsql: 100.0Hz
OFF: H 1 ... 0 0 -> h 1: CTCSS: 0.0Hz, CTCSSsql: 0.0Hz
After each read, VFO state and channel 1 MR response are byte-for-
byte identical to the pre-test snapshot.
DCS is supported in the readback path but currently unverifiable on
the available hardware — the firmware does not appear to persist DCS
state into memory channels via the BM write path, so no DCS channel
exists to read back. The code handles P8=3 correctly should a
front-panel-programmed DCS channel produce that byte value.
(cherry picked from commit 130d733be2c447faabcb69f53ae3f571bba34978)
diff --git a/rigs/yaesu/ftx1/ftx1.h b/rigs/yaesu/ftx1/ftx1.h
index 8bedd84bd..33da645ee 100644
--- a/rigs/yaesu/ftx1/ftx1.h
+++ b/rigs/yaesu/ftx1/ftx1.h
@@ -229,5 +229,6 @@ extern int ftx1_get_band_select(RIG *rig, vfo_t vfo, int *band);
* FTX-1 CTCSS helpers (defined in ftx1_ctcss.c)
*/
extern int ftx1_freq_to_tone_num(unsigned int freq);
+extern unsigned int ftx1_tone_num_to_freq(int num);
#endif /* _FTX1_H */
diff --git a/rigs/yaesu/ftx1/ftx1_ctcss.c b/rigs/yaesu/ftx1/ftx1_ctcss.c
index 5152c4322..fd0210114 100644
--- a/rigs/yaesu/ftx1/ftx1_ctcss.c
+++ b/rigs/yaesu/ftx1/ftx1_ctcss.c
@@ -62,7 +62,7 @@ int ftx1_freq_to_tone_num(unsigned int freq)
}
/* Convert tone number (0-based per spec) to frequency (in 0.1 Hz) */
-static unsigned int ftx1_tone_num_to_freq(int num)
+unsigned int ftx1_tone_num_to_freq(int num)
{
if (num < FTX1_CTCSS_MIN || num > FTX1_CTCSS_MAX)
{
diff --git a/rigs/yaesu/ftx1/ftx1_mem.c b/rigs/yaesu/ftx1/ftx1_mem.c
index 945e853d7..853ac4d4c 100644
--- a/rigs/yaesu/ftx1/ftx1_mem.c
+++ b/rigs/yaesu/ftx1/ftx1_mem.c
@@ -391,6 +391,100 @@ restore:
return err;
}
+/*
+ * ftx1_read_channel_tone_state — read a channel's CTCSS tone / DCS code.
+ *
+ * The MR response carries only the tone MODE (P8), not the actual tone
+ * number or DCS code. To retrieve those we have to select the memory
+ * channel via MC, query CN (which reflects the stored channel state in
+ * memory mode), then restore the caller's prior VM/MC position.
+ *
+ * Intrusiveness note: this briefly switches the radio to memory mode
+ * on the target channel. The visible side effect is a momentary front-
+ * panel display change. State is restored at the end — if the caller
+ * was previously in VFO mode we return via VM000, if they were already
+ * in memory mode on another channel we MC back to that channel.
+ *
+ * mr_p8 is the raw stored P8 byte from MR, encoded per the firmware's
+ * MW/MR swap (different from CT encoding):
+ * 1 = TSQ (tone squelch — TX+RX CTCSS tone)
+ * 2 = ENC (TX CTCSS tone only)
+ * 3 = DCS
+ *
+ * Returns void: best-effort. On any CAT failure the tone fields are
+ * simply left at whatever the caller passed in, and the restore step
+ * still runs.
+ */
+static void ftx1_read_channel_tone_state(RIG *rig, int ch, int mr_p8,
+ channel_t *chan)
+{
+ struct newcat_priv_data *priv = STATE(rig)->priv;
+ char saved_vm[16] = {0};
+ char saved_mc[16] = {0};
+ int p1p2, val;
+
+ /* Snapshot current VM and MC so we can restore them. */
+ SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "VM0;");
+ if (newcat_get_cmd(rig) == RIG_OK)
+ {
+ strncpy(saved_vm, priv->ret_data, sizeof(saved_vm) - 1);
+ }
+ SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "MC0;");
+ if (newcat_get_cmd(rig) == RIG_OK)
+ {
+ strncpy(saved_mc, priv->ret_data, sizeof(saved_mc) - 1);
+ }
+
+ /* Select the target memory channel. */
+ SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "MC%06d;", ch);
+ if (newcat_set_cmd(rig) != RIG_OK)
+ {
+ goto restore;
+ }
+
+ if (mr_p8 == 3)
+ {
+ /* DCS: query main-side DCS code via CN01. */
+ SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "CN01;");
+ if (newcat_get_cmd(rig) == RIG_OK
+ && sscanf(priv->ret_data + 2, "%2d%3d", &p1p2, &val) == 2)
+ {
+ chan->dcs_code = (tone_t)val;
+ }
+ }
+ else
+ {
+ /* CTCSS: query main-side tone index via CN00. */
+ SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "CN00;");
+ if (newcat_get_cmd(rig) == RIG_OK
+ && sscanf(priv->ret_data + 2, "%2d%3d", &p1p2, &val) == 2)
+ {
+ tone_t tone = (tone_t)ftx1_tone_num_to_freq(val);
+ chan->ctcss_tone = tone;
+ /* MW/MR P8=1 is TSQ (encode and decode tones both active);
+ * P8=2 is ENC only. */
+ if (mr_p8 == 1)
+ {
+ chan->ctcss_sql = tone;
+ }
+ }
+ }
+
+restore:
+ /* Return to the caller's prior position. Memory mode on some other
+ * channel is restored via MC; otherwise fall back to VFO mode. */
+ if (strstr(saved_vm, "VM011;") != NULL && saved_mc[0] != '\0')
+ {
+ SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "%s", saved_mc);
+ (void)newcat_set_cmd(rig);
+ }
+ else
+ {
+ SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "VM000;");
+ (void)newcat_set_cmd(rig);
+ }
+}
+
/*
* Memory Read (MR) - read memory channel data
* FIRMWARE FORMAT: MR P1P2P2P2P2 (5-digit: bank + 4-digit channel)
@@ -405,10 +499,14 @@ restore:
* 20 P5 TX CLAR on/off (0/1)
* 21 P6 Mode code (1-E)
* 22 P7 VFO/Memory (0/1)
- * 23 P8 CTCSS mode (0-3)
+ * 23 P8 CTCSS mode (0-3, MW/MR swap encoding)
* 24-25 P9 Reserved "00"
* 26 P10 Shift (0=simplex, 1=+, 2=-)
* Returns '?' if channel doesn't exist (not programmed)
+ *
+ * P8 does NOT carry the actual tone number or DCS code — those have
+ * to be fetched separately via CN, which requires briefly selecting
+ * the channel via MC. See ftx1_read_channel_tone_state().
*/
int ftx1_get_channel(RIG *rig, vfo_t vfo, channel_t *chan, int read_only)
{
@@ -518,11 +616,12 @@ int ftx1_get_channel(RIG *rig, vfo_t vfo, channel_t *chan, int read_only)
/* Skip VFO/Memory indicator (1 char) */
p++;
- /* Parse CTCSS mode (1 char) */
+ /* Parse CTCSS mode (1 char). This is the MW/MR stored encoding,
+ * which is swapped relative to CT:
+ * 0 = OFF, 1 = TSQ, 2 = ENC, 3 = DCS
+ * The actual tone number or DCS code is fetched below via the
+ * ftx1_read_channel_tone_state helper — MR does not carry it. */
ctcss_mode = *p++ - '0';
- /* Note: Actual tone frequencies require separate CN/QN queries */
- /* Here we just record the mode for reference */
- (void)ctcss_mode;
/* Skip reserved "00" (2 chars) */
p += 2;
@@ -538,6 +637,13 @@ int ftx1_get_channel(RIG *rig, vfo_t vfo, channel_t *chan, int read_only)
/* Set width to default (not stored in memory response) */
chan->width = RIG_PASSBAND_NORMAL;
+ /* If the channel has a tone, fetch the actual number or DCS code
+ * via CN (intrusive — briefly selects the channel and restores). */
+ if (ctcss_mode > 0 && ctcss_mode <= 3)
+ {
+ ftx1_read_channel_tone_state(rig, ch, ctcss_mode, chan);
+ }
+
rig_debug(RIG_DEBUG_VERBOSE,
"%s: ch=%d freq=%.0f mode=%s rit=%ld xit=%ld shift=%d\n",
__func__, ch, chan->freq, rig_strrmode(chan->mode),
commit 2bbd6699af0d87a75ecf251ee58fd4691baf14c2
Author: KJ5HST <kj...@de...>
Date: Wed Apr 15 14:52:50 2026 -0400
ftx1: add clarifier support and document firmware limits in set_channel
Empirically verified three BM-propagation unknowns against fw v1.12:
- Clarifier: the CF command series (11-char form, P3=0 for the
RX/TX toggles and P3=1 for the offset) is captured by BM. MR
readback shows the stored channel with the programmed clarifier
offset and the RX CLAR flag. Add CF programming to the rewrite
so rig_set_channel now persists chan->rit into the memory slot.
- TX CLAR flag (XIT): the offset and RX flag propagate but the TX
CLAR on/off toggle is silently dropped by BM. The stored channel
always reads back with TX CLAR off, regardless of what CF100.3
was set to on VFO-B before the commit. We emit the command
anyway for forward compatibility with a firmware fix.
- DCS: CT13 (CT mode = DCS) and CN11<code> program VFO-B correctly
and readback of VFO-B shows both values, but BM does not copy
either to the memory channel. The stored MR response is
byte-identical to a no-tone write, across DCS codes ranging from
023 to 103. DCS channels cannot be programmed via CAT on this
firmware and must be set up from the front panel. We still emit
CT13 + CN11 so the code path survives a later firmware fix.
Also tighten the cleanup path: the function now explicitly clears
VFO-B's clarifier state (and CT state for FM-family writes) on exit
in addition to restoring FB/MD1 from the entry snapshot. This avoids
leaking intermediate state when rig_set_channel returns.
Verified end-to-end via rigctl H 1 with rit=200 Hz — channel 1 MR
readback shows clar=+0200 rx=1 as expected, and both VFOs survive
the round trip.
(cherry picked from commit c1a259406ace8e3c4c801f2b7cb64424efc28914)
diff --git a/rigs/yaesu/ftx1/ftx1_mem.c b/rigs/yaesu/ftx1/ftx1_mem.c
index b210b1ac9..945e853d7 100644
--- a/rigs/yaesu/ftx1/ftx1_mem.c
+++ b/rigs/yaesu/ftx1/ftx1_mem.c
@@ -141,21 +141,34 @@ int ftx1_get_mem(RIG *rig, vfo_t vfo, int *ch)
* target slot. Ignore '?' if the slot is currently
* unprogrammed — the cursor still updates for BM.
* 2. VM000; Force VFO mode in case MC entered memory mode.
- * 3. FB / MD1 / CT1 / CN10 / CN11 / OS1 Program VFO-B.
- * CT/CN/OS only work in FM, so tone/shift are only
- * emitted for FM-family channel modes.
+ * 3. FB / MD1 / CT1 / CN10 / OS1 / CF1 Program VFO-B.
+ * CT/CN/OS only work in FM, so tone and shift are only
+ * emitted for FM-family channel modes. Clarifier (CF)
+ * is programmed for all modes.
* 4. BM; Copy VFO-B to the last-selected memory channel.
*
* VFO-B is used rather than VFO-A so the operator's primary RX VFO
* is not disturbed. VFO-B's frequency and mode are snapshotted at
* entry and best-effort restored on exit (including error paths).
- * Advanced VFO-B state (CT/CN/OS/CF) may still be clobbered for
- * callers that relied on it.
+ * VFO-B's clarifier and CT state are cleared during cleanup — any
+ * caller that relied on those aspects of VFO-B's state will need to
+ * reprogram them after rig_set_channel.
*
- * Clarifier/RIT/XIT persistence into the memory slot is not yet
- * supported — BM's handling of clarifier state has not been
- * empirically verified. This is a potential follow-up if users
- * report it missing.
+ * Firmware limitations verified empirically on fw v1.12: the BM
+ * command does NOT propagate two kinds of state to the memory slot,
+ * even though the CAT commands to set them on VFO-B succeed:
+ *
+ * - DCS: CT13 (DCS mode) + CN11<code> program VFO-B correctly, but
+ * the stored memory channel reads back with CTCSS mode OFF. DCS
+ * channels cannot be programmed via CAT and must be set up from
+ * the front panel. We still emit the CT/CN commands so that if
+ * firmware is fixed later, the code path works.
+ *
+ * - XIT (TX clarifier flag): the clarifier offset frequency and
+ * the RX clarifier on/off flag both propagate correctly, but the
+ * TX CLAR on/off flag is dropped by BM and always reads back as
+ * OFF in the stored channel. We set it anyway for forward
+ * compatibility.
*/
int ftx1_set_channel(RIG *rig, vfo_t vfo, const channel_t *chan)
{
@@ -295,14 +308,75 @@ int ftx1_set_channel(RIG *rig, vfo_t vfo, const channel_t *chan)
(void)newcat_set_cmd(rig);
}
+ /* 3d. Clarifier (RIT/XIT). The FTX-1 uses one shared offset with
+ * independent RX/TX on-off toggles via the 11-char CF command:
+ * CF P1 P2 P3 P4 P5P5P5P5 ; where P3=0 sets RX/TX on/off
+ * (P4: 0=RX OFF, 1=RX ON, 2=TX OFF, 3=TX ON) and P3=1 sets the
+ * offset frequency (P4=+/-, P5P5P5P5 = offset Hz).
+ *
+ * If both rit and xit are set, rit's offset wins (matches the
+ * pre-#2034 behavior of the broken MW path). Note that the TX
+ * CLAR flag is silently dropped by BM (firmware limitation);
+ * we still emit it for forward compatibility. */
+ if (chan->rit != 0 || chan->xit != 0)
+ {
+ int off;
+ char dir;
+
+ if (chan->rit != 0)
+ {
+ dir = (chan->rit >= 0) ? '+' : '-';
+ off = (int)labs(chan->rit);
+ }
+ else
+ {
+ dir = (chan->xit >= 0) ? '+' : '-';
+ off = (int)labs(chan->xit);
+ }
+ if (off > 9999) off = 9999;
+
+ SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str),
+ "CF100%d0000;", (chan->rit != 0) ? 1 : 0);
+ (void)newcat_set_cmd(rig);
+
+ SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str),
+ "CF100%d0000;", (chan->xit != 0) ? 3 : 2);
+ (void)newcat_set_cmd(rig);
+
+ SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str),
+ "CF101%c%04d;", dir, off);
+ (void)newcat_set_cmd(rig);
+ }
+ else
+ {
+ /* Explicitly clear VFO-B clarifier state so it doesn't leak
+ * from a previous write or the operator's prior VFO-B. */
+ SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "CF10000000;");
+ (void)newcat_set_cmd(rig);
+ SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "CF10020000;");
+ (void)newcat_set_cmd(rig);
+ }
+
/* 4. Commit VFO-B to the last-selected memory channel. */
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "BM;");
err = newcat_set_cmd(rig);
restore:
- /* Best-effort restore of VFO-B state. Restore failures are not
- * surfaced — the caller cares about the write's status, not the
+ /* Best-effort restore of VFO-B. Clarifier and CT state that we may
+ * have touched are cleared unconditionally — we don't snapshot
+ * them because CF has no reliable read form. FB and MD1 are
+ * replayed from the entry snapshot. Restore failures are not
+ * surfaced: the caller cares about the write's status, not the
* side-effect cleanup. */
+ SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "CF10000000;");
+ (void)newcat_set_cmd(rig);
+ SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "CF10020000;");
+ (void)newcat_set_cmd(rig);
+ if (is_fm_family)
+ {
+ SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "CT10;");
+ (void)newcat_set_cmd(rig);
+ }
if (saved_fb[0] != '\0')
{
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "%s", saved_fb);
commit c9ca4c4688349a5fcd9768c63be2ca73dfb6cd4c
Author: KJ5HST <kj...@de...>
Date: Wed Apr 15 14:06:45 2026 -0400
ftx1: rewrite set_channel using VFO-B + BM (firmware MW bug) (#2034)
The FTX-1 MW (Memory Write) CAT command is firmware-broken on v1.08+
and always returns '?;' regardless of channel or parameters. The
previous ftx1_set_channel built a 30-char MW command and relied on it
succeeding, so rig_set_channel on an FTX-1 failed on every call --
no memory channel ever got written.
Replace the MW path with the sequence the firmware actually supports:
1. MC<ch>; point the "last-selected channel" cursor at the target.
The radio returns '?;' for unprogrammed slots, but the
cursor still updates for the subsequent BM commit.
2. VM000; force VFO mode in case MC entered memory mode.
3. FB / MD1 / CT1 / CN10 / CN11 / OS1 program VFO-B to the target
state. CT/CN/OS only function in FM, so tone and shift
are only emitted for FM-family channel modes. DCS goes
through CN with P2=1 because the DC command is also
firmware-broken.
4. BM; copy VFO-B to the last-selected memory channel.
VFO-B is used rather than VFO-A so the operator's primary RX VFO is
not disturbed. VFO-B's frequency and mode are snapshotted at entry and
best-effort restored on exit (including the error path), so a caller
that was using VFO-B sees minimal side effects.
Clarifier/RIT/XIT state is not yet programmed into the channel -- BM's
handling of clarifier has not been empirically verified, and getting
it wrong silently is worse than dropping it for now. Left as a
potential follow-up if users report it missing.
Verified end-to-end on a live FTX-1 field head + Optima/SPA-1 running
firmware MAIN v1.12 at 115200 bps: rigctl -m 1051 H 1 round-trips
channel 1 between 7.000 MHz LSB and 7.050 MHz LSB, and VFO-A
(144.260 FM) and VFO-B (28.074 USB) are both preserved across the
operation.
Exposes ftx1_freq_to_tone_num() in ftx1.h (previously file-static in
ftx1_ctcss.c) so ftx1_mem.c can reuse the existing CTCSS frequency
lookup instead of duplicating the table.
(cherry picked from commit 4024cd5d0d6ca3ae959ce7da1cf193438144c20a)
diff --git a/rigs/yaesu/ftx1/ftx1.h b/rigs/yaesu/ftx1/ftx1.h
index d09da4d57..8bedd84bd 100644
--- a/rigs/yaesu/ftx1/ftx1.h
+++ b/rigs/yaesu/ftx1/ftx1.h
@@ -225,4 +225,9 @@ extern int ftx1_get_head_type(RIG *rig);
extern int ftx1_set_band_select(RIG *rig, vfo_t vfo, int band);
extern int ftx1_get_band_select(RIG *rig, vfo_t vfo, int *band);
+/*
+ * FTX-1 CTCSS helpers (defined in ftx1_ctcss.c)
+ */
+extern int ftx1_freq_to_tone_num(unsigned int freq);
+
#endif /* _FTX1_H */
diff --git a/rigs/yaesu/ftx1/ftx1_ctcss.c b/rigs/yaesu/ftx1/ftx1_ctcss.c
index a2f47fb13..5152c4322 100644
--- a/rigs/yaesu/ftx1/ftx1_ctcss.c
+++ b/rigs/yaesu/ftx1/ftx1_ctcss.c
@@ -46,7 +46,7 @@ static const unsigned int ftx1_ctcss_tones[] = {
};
/* Convert CTCSS frequency (in 0.1 Hz) to tone number (0-based per spec) */
-static int ftx1_freq_to_tone_num(unsigned int freq)
+int ftx1_freq_to_tone_num(unsigned int freq)
{
int i;
diff --git a/rigs/yaesu/ftx1/ftx1_mem.c b/rigs/yaesu/ftx1/ftx1_mem.c
index 07827632c..b210b1ac9 100644
--- a/rigs/yaesu/ftx1/ftx1_mem.c
+++ b/rigs/yaesu/ftx1/ftx1_mem.c
@@ -129,121 +129,192 @@ int ftx1_get_mem(RIG *rig, vfo_t vfo, int *ch)
}
/*
- * Memory Write (MW) - write channel data to memory
- * CAT Format: MW P1P1P1P1P1 P2P2P2P2P2P2P2P2P2 P3P3P3P3P3 P4 P5 P6 P7 P8 P9P9 P10;
- * P1 (5 bytes): Channel number (00001-00999 or P-01L-P-50U for PMS)
- * P2 (9 bytes): VFO Frequency in Hz
- * P3 (5 bytes): Clarifier direction (+/-) + offset (0000-9990 Hz)
- * P4 (1 byte): RX CLAR (0=OFF, 1=ON)
- * P5 (1 byte): TX CLAR (0=OFF, 1=ON)
- * P6 (1 byte): Mode code (1=LSB, 2=USB, 3=CW-U, 4=FM, 5=AM, 6=RTTY-L,
- * 7=CW-L, 8=DATA-L, 9=RTTY-U, A=DATA-FM, B=FM-N,
- * C=DATA-U, D=AM-N, E=PSK, F=DATA-FM-N)
- * P7 (1 byte): VFO/Memory mode (0=VFO, 1=Memory, 2=Memory Tune, 3=QMB, 5=PMS)
- * P8 (1 byte): CTCSS mode (0=OFF, 1=ENC/DEC, 2=ENC, 3=DCS, 4=PR FREQ, 5=REV TONE)
- * P9 (2 bytes): Fixed "00"
- * P10 (1 byte): Shift (0=Simplex, 1=Plus, 2=Minus)
+ * Memory Write — VFO-B + BM workaround (issue #2034)
+ *
+ * The FTX-1 MW command is firmware-broken: the radio returns '?;' for
+ * every MW write on every channel, regardless of parameters (verified
+ * against fw v1.12). We therefore implement rig_set_channel by
+ * programming VFO-B to the target state and committing it to the
+ * target memory slot via the BM command:
+ *
+ * 1. MC<ch>; Point the "last-selected channel" cursor at the
+ * target slot. Ignore '?' if the slot is currently
+ * unprogrammed — the cursor still updates for BM.
+ * 2. VM000; Force VFO mode in case MC entered memory mode.
+ * 3. FB / MD1 / CT1 / CN10 / CN11 / OS1 Program VFO-B.
+ * CT/CN/OS only work in FM, so tone/shift are only
+ * emitted for FM-family channel modes.
+ * 4. BM; Copy VFO-B to the last-selected memory channel.
+ *
+ * VFO-B is used rather than VFO-A so the operator's primary RX VFO
+ * is not disturbed. VFO-B's frequency and mode are snapshotted at
+ * entry and best-effort restored on exit (including error paths).
+ * Advanced VFO-B state (CT/CN/OS/CF) may still be clobbered for
+ * callers that relied on it.
+ *
+ * Clarifier/RIT/XIT persistence into the memory slot is not yet
+ * supported — BM's handling of clarifier state has not been
+ * empirically verified. This is a potential follow-up if users
+ * report it missing.
*/
int ftx1_set_channel(RIG *rig, vfo_t vfo, const channel_t *chan)
{
struct newcat_priv_data *priv = STATE(rig)->priv;
+ char saved_fb[32] = {0};
+ char saved_md1[16] = {0};
char mode_char;
- char clar_dir;
- int clar_offset;
- int p7_vfo_mem;
- int p8_ctcss;
- int p10_shift;
+ int err;
+ int is_fm_family;
(void)vfo;
- rig_debug(RIG_DEBUG_VERBOSE, "%s: ch=%d freq=%.0f mode=%d\n", __func__,
- chan->channel_num, chan->freq, (int)chan->mode);
+ rig_debug(RIG_DEBUG_VERBOSE, "%s: ch=%d freq=%.0f mode=%s\n", __func__,
+ chan->channel_num, chan->freq, rig_strrmode(chan->mode));
- /* Validate channel number */
- if (chan->channel_num < FTX1_MEM_MIN || chan->channel_num > FTX1_MEM_MAX) {
+ if (chan->channel_num < FTX1_MEM_MIN || chan->channel_num > FTX1_MEM_MAX)
+ {
rig_debug(RIG_DEBUG_ERR, "%s: channel %d out of range %d-%d\n",
__func__, chan->channel_num, FTX1_MEM_MIN, FTX1_MEM_MAX);
return -RIG_EINVAL;
}
- /* Convert Hamlib mode to FTX-1 mode code */
- switch (chan->mode) {
- case RIG_MODE_LSB: mode_char = '1'; break;
- case RIG_MODE_USB: mode_char = '2'; break;
- case RIG_MODE_CW: mode_char = '3'; break; /* CW-U */
- case RIG_MODE_FM: mode_char = '4'; break;
- case RIG_MODE_AM: mode_char = '5'; break;
- case RIG_MODE_RTTYR: mode_char = '6'; break; /* RTTY-L */
- case RIG_MODE_CWR: mode_char = '7'; break; /* CW-L */
- case RIG_MODE_PKTLSB: mode_char = '8'; break; /* DATA-L */
- case RIG_MODE_RTTY: mode_char = '9'; break; /* RTTY-U */
- case RIG_MODE_PKTFM: mode_char = 'A'; break; /* DATA-FM */
- case RIG_MODE_FMN: mode_char = 'B'; break; /* FM-N */
- case RIG_MODE_PKTUSB: mode_char = 'C'; break; /* DATA-U */
- case RIG_MODE_AMN: mode_char = 'D'; break; /* AM-N */
- case RIG_MODE_PSK: mode_char = 'E'; break; /* PSK */
- default: mode_char = '2'; break; /* Default to USB */
+ switch (chan->mode)
+ {
+ case RIG_MODE_LSB: mode_char = '1'; break;
+ case RIG_MODE_USB: mode_char = '2'; break;
+ case RIG_MODE_CW: mode_char = '3'; break; /* CW-U */
+ case RIG_MODE_FM: mode_char = '4'; break;
+ case RIG_MODE_AM: mode_char = '5'; break;
+ case RIG_MODE_RTTYR: mode_char = '6'; break; /* RTTY-L */
+ case RIG_MODE_CWR: mode_char = '7'; break; /* CW-L */
+ case RIG_MODE_PKTLSB: mode_char = '8'; break; /* DATA-L */
+ case RIG_MODE_RTTY: mode_char = '9'; break; /* RTTY-U */
+ case RIG_MODE_PKTFM: mode_char = 'A'; break; /* DATA-FM */
+ case RIG_MODE_FMN: mode_char = 'B'; break; /* FM-N */
+ case RIG_MODE_PKTUSB: mode_char = 'C'; break; /* DATA-U */
+ case RIG_MODE_AMN: mode_char = 'D'; break; /* AM-N */
+ case RIG_MODE_PSK: mode_char = 'E'; break; /* PSK */
+ default:
+ rig_debug(RIG_DEBUG_ERR, "%s: unsupported mode %s\n",
+ __func__, rig_strrmode(chan->mode));
+ return -RIG_EINVAL;
}
- /* Clarifier direction and offset */
- if (chan->rit != 0) {
- clar_dir = (chan->rit >= 0) ? '+' : '-';
- clar_offset = labs(chan->rit);
- if (clar_offset > 9990) clar_offset = 9990;
- } else if (chan->xit != 0) {
- clar_dir = (chan->xit >= 0) ? '+' : '-';
- clar_offset = labs(chan->xit);
- if (clar_offset > 9990) clar_offset = 9990;
- } else {
- clar_dir = '+';
- clar_offset = 0;
+ is_fm_family = (chan->mode == RIG_MODE_FM || chan->mode == RIG_MODE_FMN
+ || chan->mode == RIG_MODE_PKTFM || chan->mode == RIG_MODE_PKTFMN);
+
+ /* Snapshot VFO-B state for best-effort restore on exit. Responses
+ * (FB%09d; and MD1%c;) are already valid set commands and can be
+ * replayed verbatim. If the query fails, the saved_* buffer stays
+ * empty and restore is skipped. */
+ SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "FB;");
+ if (newcat_get_cmd(rig) == RIG_OK)
+ {
+ strncpy(saved_fb, priv->ret_data, sizeof(saved_fb) - 1);
+ }
+ SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "MD1;");
+ if (newcat_get_cmd(rig) == RIG_OK)
+ {
+ strncpy(saved_md1, priv->ret_data, sizeof(saved_md1) - 1);
}
- /* P7: VFO/Memory mode - default to Memory (1) when writing to channel */
- p7_vfo_mem = 1;
+ /* 1. Point the MC cursor at the target slot. Returns '?;' when the
+ * slot is unprogrammed, but the cursor still updates for BM. */
+ SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "MC%06d;",
+ chan->channel_num);
+ (void)newcat_set_cmd(rig);
+
+ /* 2. Force VFO mode. Must be the 6-char form — extra digits are
+ * rejected by firmware. */
+ SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "VM000;");
+ (void)newcat_set_cmd(rig);
+
+ /* 3a. Program VFO-B frequency. */
+ SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "FB%09.0f;", chan->freq);
+ err = newcat_set_cmd(rig);
+ if (err != RIG_OK) goto restore;
+
+ /* 3b. Program VFO-B mode. */
+ SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "MD1%c;", mode_char);
+ err = newcat_set_cmd(rig);
+ if (err != RIG_OK) goto restore;
+
+ /* 3c. FM-family channels: program CTCSS/DCS and repeater shift.
+ * CT, CN (P2=1), and OS commands only function in FM mode, so
+ * non-FM channels skip this block entirely. */
+ if (is_fm_family)
+ {
+ int os_mode;
+
+ if (chan->dcs_code != 0)
+ {
+ /* DCS: select CT mode 3, then program code via CN P2=1.
+ * (The DC command is firmware-broken — use CN instead.) */
+ SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "CT13;");
+ (void)newcat_set_cmd(rig);
+
+ SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "CN11%03u;",
+ chan->dcs_code);
+ (void)newcat_set_cmd(rig);
+ }
+ else if (chan->ctcss_tone != 0)
+ {
+ /* CTCSS: TSQ when both encode and squelch tones are set,
+ * else ENC only. CN P2=0 programs the tone index. */
+ int ct_mode = (chan->ctcss_sql != 0)
+ ? FTX1_CTCSS_MODE_TSQ
+ : FTX1_CTCSS_MODE_ENC;
+ int tone_num = ftx1_freq_to_tone_num(chan->ctcss_tone);
+
+ SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str),
+ "CT1%d;", ct_mode);
+ (void)newcat_set_cmd(rig);
+
+ if (tone_num >= 0)
+ {
+ SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str),
+ "CN10%03d;", tone_num);
+ (void)newcat_set_cmd(rig);
+ }
+ }
+ else
+ {
+ /* Explicit CT OFF in case VFO-B was previously configured
+ * with a tone. */
+ SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "CT10;");
+ (void)newcat_set_cmd(rig);
+ }
- /* P8: CTCSS mode from channel flags */
- p8_ctcss = 0; /* Default OFF */
- if (chan->flags & RIG_CHFLAG_SKIP) {
- /* Use flags for tone squelch indication if available */
- }
- /* Check tone settings */
- if (chan->ctcss_tone != 0 && chan->ctcss_sql != 0) {
- p8_ctcss = 1; /* CTCSS ENC/DEC */
- } else if (chan->ctcss_tone != 0) {
- p8_ctcss = 2; /* CTCSS ENC only */
- } else if (chan->dcs_code != 0) {
- p8_ctcss = 3; /* DCS */
+ switch (chan->rptr_shift)
+ {
+ case RIG_RPT_SHIFT_PLUS: os_mode = 1; break;
+ case RIG_RPT_SHIFT_MINUS: os_mode = 2; break;
+ default: os_mode = 0; break; /* simplex */
+ }
+ SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "OS1%d;", os_mode);
+ (void)newcat_set_cmd(rig);
}
- /* P10: Repeater shift */
- switch (chan->rptr_shift) {
- case RIG_RPT_SHIFT_PLUS: p10_shift = 1; break;
- case RIG_RPT_SHIFT_MINUS: p10_shift = 2; break;
- default: p10_shift = 0; break; /* Simplex */
+ /* 4. Commit VFO-B to the last-selected memory channel. */
+ SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "BM;");
+ err = newcat_set_cmd(rig);
+
+restore:
+ /* Best-effort restore of VFO-B state. Restore failures are not
+ * surfaced — the caller cares about the write's status, not the
+ * side-effect cleanup. */
+ if (saved_fb[0] != '\0')
+ {
+ SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "%s", saved_fb);
+ (void)newcat_set_cmd(rig);
+ }
+ if (saved_md1[0] != '\0')
+ {
+ SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "%s", saved_md1);
+ (void)newcat_set_cmd(rig);
}
- /* Build MW command string:
- * MW P1P1P1P1P1 P2P2P2P2P2P2P2P2P2 P3P3P3P3P3 P4 P5 P6 P7 P8 P9P9 P10;
- * Total: 2 + 5 + 9 + 5 + 1 + 1 + 1 + 1 + 1 + 2 + 1 + 1 = 30 chars
- */
- SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str),
- "MW%05d%09.0f%c%04d%d%d%c%d%d00%d;",
- chan->channel_num, /* P1: 5-digit channel */
- chan->freq, /* P2: 9-digit frequency in Hz */
- clar_dir, /* P3: clarifier direction */
- clar_offset, /* P3: clarifier offset */
- (chan->rit != 0) ? 1 : 0, /* P4: RX CLAR on/off */
- (chan->xit != 0) ? 1 : 0, /* P5: TX CLAR on/off */
- mode_char, /* P6: mode code */
- p7_vfo_mem, /* P7: VFO/Memory mode */
- p8_ctcss, /* P8: CTCSS mode */
- /* P9: "00" (fixed) */
- p10_shift); /* P10: shift */
-
- rig_debug(RIG_DEBUG_VERBOSE, "%s: cmd='%s'\n", __func__, priv->cmd_str);
-
- return newcat_set_cmd(rig);
+ return err;
}
/*
commit 25d2db438da02eb239287fab1ed530d9280764ad
Author: Nate Bargmann <n0...@n0...>
Date: Sun Apr 19 12:09:54 2026 -0500
Advance to 4.7.2~rc
diff --git a/configure.ac b/configure.ac
index 26614d46d..7468ac678 100644
--- a/configure.ac
+++ b/configure.ac
@@ -14,7 +14,7 @@ dnl Please do not use '-' in the version number, as package managers will fail,
dnl however, the use of '~' should be fine as apt (others?) will treat
dnl it as an earlier version than the actual release. TNX KA6MAL
dnl PACKAGE_NAME + " " + PACKAGE_VERSION must not exceed 20 chars!
-AC_INIT([Hamlib],[4.7.1],[ham...@li...],[hamlib],[http://www.hamlib.org])
+AC_INIT([Hamlib],[4.7.2~rc],[ham...@li...],[hamlib],[http://www.hamlib.org])
#AC_INIT([PRODUCT_NAME], [Hamlib])
#AC_DEFINE([Hamlib], [PRODUCT_VERSION_RESOURCE])
@@ -78,7 +78,7 @@ dnl See README.release on setting these values
# Set them here to keep c++/Makefile and src/Makefile in sync.
ABI_VERSION=4
ABI_REVISION=7
-ABI_PATCH=1
+ABI_PATCH=2
ABI_AGE=0
AC_DEFINE_UNQUOTED([ABI_VERSION], [$ABI_VERSION], [Frontend ABI version])
-----------------------------------------------------------------------
Summary of changes:
configure.ac | 4 +-
rigs/yaesu/ftx1/ftx1.c | 40 +++-
rigs/yaesu/ftx1/ftx1.h | 14 ++
rigs/yaesu/ftx1/ftx1_ctcss.c | 18 +-
rigs/yaesu/ftx1/ftx1_freq.c | 8 +
rigs/yaesu/ftx1/ftx1_mem.c | 504 +++++++++++++++++++++++++++++++++----------
rigs/yaesu/ftx1/ftx1_mode.c | 21 +-
rigs/yaesu/newcat.h | 1 +
8 files changed, 491 insertions(+), 119 deletions(-)
hooks/post-receive
--
Hamlib -- Ham radio control libraries
|
|
From: n0nb <n0...@us...> - 2026-04-19 17:07: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 8a714a44b6147bdc56be5b31975a85674d4a76df (commit)
via 2b28d2e0ad064b717c8180da139ec0f0f8c2b8f0 (commit)
via 370dca238ac3f7eeb7c70b41110b6ab08ab2f26a (commit)
via 130d733be2c447faabcb69f53ae3f571bba34978 (commit)
via c1a259406ace8e3c4c801f2b7cb64424efc28914 (commit)
via 4024cd5d0d6ca3ae959ce7da1cf193438144c20a (commit)
from 9de702a452e4607b1834acd1e45baa624c3f5a9f (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 8a714a44b6147bdc56be5b31975a85674d4a76df
Author: KJ5HST <kj...@de...>
Date: Sun Apr 19 10:40:45 2026 -0400
ftx1: use bounded %.*s in snprintf to silence GCC -Wformat-truncation
Replace "%s" with "%.*s" and explicit precision (sizeof(dst) - 1)
in the four ret_data snapshot sites. Reported by N0NB on Debian 13
(GCC 14); clang and MinGW GCC did not trigger the warning.
diff --git a/rigs/yaesu/ftx1/ftx1_mem.c b/rigs/yaesu/ftx1/ftx1_mem.c
index e3f64e501..857ed0616 100644
--- a/rigs/yaesu/ftx1/ftx1_mem.c
+++ b/rigs/yaesu/ftx1/ftx1_mem.c
@@ -242,12 +242,14 @@ int ftx1_set_channel(RIG *rig, vfo_t vfo, const channel_t *chan)
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "FB;");
if (newcat_get_cmd(rig) == RIG_OK)
{
- snprintf(saved_fb, sizeof(saved_fb), "%s", priv->ret_data);
+ snprintf(saved_fb, sizeof(saved_fb), "%.*s",
+ (int)sizeof(saved_fb) - 1, priv->ret_data);
}
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "MD1;");
if (newcat_get_cmd(rig) == RIG_OK)
{
- snprintf(saved_md1, sizeof(saved_md1), "%s", priv->ret_data);
+ snprintf(saved_md1, sizeof(saved_md1), "%.*s",
+ (int)sizeof(saved_md1) - 1, priv->ret_data);
}
/* 1. Point the Sub-side MC cursor at the target slot. The MC SET
@@ -456,12 +458,14 @@ static void ftx1_read_channel_tone_state(RIG *rig, int ch, int mr_p8,
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "VM0;");
if (newcat_get_cmd(rig) == RIG_OK)
{
- snprintf(saved_vm, sizeof(saved_vm), "%s", priv->ret_data);
+ snprintf(saved_vm, sizeof(saved_vm), "%.*s",
+ (int)sizeof(saved_vm) - 1, priv->ret_data);
}
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "MC0;");
if (newcat_get_cmd(rig) == RIG_OK)
{
- snprintf(saved_mc, sizeof(saved_mc), "%s", priv->ret_data);
+ snprintf(saved_mc, sizeof(saved_mc), "%.*s",
+ (int)sizeof(saved_mc) - 1, priv->ret_data);
}
/* Select the target memory channel. */
commit 2b28d2e0ad064b717c8180da139ec0f0f8c2b8f0
Author: KJ5HST <kj...@de...>
Date: Sat Apr 18 21:39:31 2026 -0400
ftx1: silence GCC strncpy warnings, target Sub cursor in set_channel
Two fixes in preparation for resubmitting PR #2035:
1. Replace four strncpy(dst, src, sizeof(dst) - 1) calls with
snprintf(dst, sizeof(dst), "%s", src). GCC on Debian 13 flagged
these as -Wstringop-truncation because priv->ret_data (128 bytes)
is larger than the destination and strncpy doesn't guarantee NUL
termination. snprintf always NUL-terminates, which GCC recognises
as safe. Clang does not emit the warning either way.
Reported by N0NB. Sites: saved_fb / saved_md1 in ftx1_set_channel,
and saved_vm / saved_mc in ftx1_read_channel_tone_state.
2. Change the cursor step in ftx1_set_channel from MC%06d; to
MC1%05d;. Hardware probing (2026-04-18, fw v1.12) established that
the MC SET command takes a VFO digit followed by a 5-digit channel:
MC0NNNNN targets Main, MC1NNNNN targets Sub. Both sides maintain
independent memory-mode state and can be parked in memory mode
simultaneously (VM011 + VM111). BM commits VFO-B to the Sub side's
last-selected memory, so the cursor-positioning step should target
Sub. The previous MC%06d; form produced MC0NNNNN for channels
1..99, silently flipping Main's front-panel channel to the write
target on every ftx1_set_channel call.
Also rewrites the MC comment block at the top of ftx1_mem.c to
document the VFO digit in both SET and READ forms, replacing the
prior (incorrect) claim that the SET form is VFO-less.
diff --git a/rigs/yaesu/ftx1/ftx1_mem.c b/rigs/yaesu/ftx1/ftx1_mem.c
index 9b818a9f7..e3f64e501 100644
--- a/rigs/yaesu/ftx1/ftx1_mem.c
+++ b/rigs/yaesu/ftx1/ftx1_mem.c
@@ -8,10 +8,20 @@
* All memory commands use DIFFERENT FORMATS than documented in the spec!
*
* MC (Memory Channel Select):
- * Query: MC0 (MAIN VFO) or MC1 (SUB VFO)
- * Response: MCNNNNNN (6-digit channel, e.g., MC000001)
- * Set: MCNNNNNN (6-digit channel)
- * Returns '?' if channel doesn't exist (not programmed)
+ * Both the query and the set form take a VFO digit followed by a
+ * 5-digit channel. The VFO digit is 0 (Main) or 1 (Sub); the two
+ * sides have independent memory-mode state and can both be parked
+ * in memory mode simultaneously (VM011 + VM111).
+ * Query: MC0; returns MC0NNNNN (Main's channel)
+ * MC1; returns MC1NNNNN (Sub's channel)
+ * Set: MC0NNNNN; tunes Main to channel NNNNN
+ * MC1NNNNN; tunes Sub to channel NNNNN
+ * The radio's active VFO (VS) does NOT influence which side the SET
+ * applies to — the first digit of the parameter does. MC%06d; with
+ * a channel in 1..99 happens to produce MC0NNNNN, so it targets
+ * Main. Hardware-verified 2026-04-18 against fw v1.12.
+ * Returns '?' if channel doesn't exist (not programmed), but the
+ * cursor still updates for a subsequent BM commit.
*
* MR (Memory Read): 5-digit format
* Query: MR00001 (not MR001 or MR0001)
@@ -232,17 +242,22 @@ int ftx1_set_channel(RIG *rig, vfo_t vfo, const channel_t *chan)
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "FB;");
if (newcat_get_cmd(rig) == RIG_OK)
{
- strncpy(saved_fb, priv->ret_data, sizeof(saved_fb) - 1);
+ snprintf(saved_fb, sizeof(saved_fb), "%s", priv->ret_data);
}
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "MD1;");
if (newcat_get_cmd(rig) == RIG_OK)
{
- strncpy(saved_md1, priv->ret_data, sizeof(saved_md1) - 1);
+ snprintf(saved_md1, sizeof(saved_md1), "%s", priv->ret_data);
}
- /* 1. Point the MC cursor at the target slot. Returns '?;' when the
- * slot is unprogrammed, but the cursor still updates for BM. */
- SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "MC%06d;",
+ /* 1. Point the Sub-side MC cursor at the target slot. The MC SET
+ * form takes a VFO digit followed by a 5-digit channel
+ * (MC0NNNNN = Main, MC1NNNNN = Sub); BM commits VFO-B to the
+ * last-selected memory on the Sub side, so targeting Sub here
+ * keeps Main's front-panel channel from silently flipping.
+ * Returns '?;' when the slot is unprogrammed, but the cursor
+ * still updates for the subsequent BM. */
+ SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "MC1%05d;",
chan->channel_num);
(void)newcat_set_cmd(rig);
@@ -441,12 +456,12 @@ static void ftx1_read_channel_tone_state(RIG *rig, int ch, int mr_p8,
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "VM0;");
if (newcat_get_cmd(rig) == RIG_OK)
{
- strncpy(saved_vm, priv->ret_data, sizeof(saved_vm) - 1);
+ snprintf(saved_vm, sizeof(saved_vm), "%s", priv->ret_data);
}
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "MC0;");
if (newcat_get_cmd(rig) == RIG_OK)
{
- strncpy(saved_mc, priv->ret_data, sizeof(saved_mc) - 1);
+ snprintf(saved_mc, sizeof(saved_mc), "%s", priv->ret_data);
}
/* Select the target memory channel. */
commit 370dca238ac3f7eeb7c70b41110b6ab08ab2f26a
Author: KJ5HST <kj...@de...>
Date: Wed Apr 15 16:17:12 2026 -0400
ftx1: auto-exit Memory mode before VFO-state setters (#2034)
Commands that set VFO-side state on the Main side behave poorly when
the radio is in Memory mode (VM011):
FA main-freq set: rejected outright with '?;'
OS repeater shift: rejected outright with '?;'
MD main-mode set: accepted but treated as a transient memory-tune
overlay — the change does not persist when the
user leaves the channel
CT main-CTCSS mode: transient overlay (same pattern)
CN main-tone/DCS: transient overlay (same pattern)
Hamlib had no awareness of this: a caller doing rig_set_mem() followed
by rig_set_freq() would silently fail (FA rejected), and rig_set_mode()
would appear to succeed but the mode change would vanish on the next
MC recall.
Add a simple memory-mode tracking flag to the shared newcat_priv_data
(ftx1_in_memory_mode), set to 1 inside ftx1_set_mem after a successful
MC command. Introduce ftx1_ensure_vfo_mode() in ftx1.c that checks the
flag and, if set, sends VM000; and clears the flag. Call it at the top
of every VFO-state setter that is actually affected by Memory mode:
ftx1_set_freq (Main-VFO branch only — FB on Sub is unaffected)
ftx1_set_rptr_shift (OS)
ftx1_set_ctcss_mode (CT Main)
ftx1_set_ctcss_tone (CN00 Main)
ftx1_set_dcs_code (CN01 Main)
Sub-targeted CN commands (CN10/CN11 in set_ctcss_sql / set_dcs_sql) are
deliberately left alone — the Sub side is never in Memory mode on this
firmware, and an injection there would needlessly clobber a user who
has intentionally parked Main in Memory mode while tuning Sub.
Add a new ftx1_set_mode wrapper in ftx1_mode.c that calls
ftx1_ensure_vfo_mode() and delegates to newcat_set_mode. Wire it up in
rig_caps (replacing the direct newcat_set_mode pointer).
Also flip priv->ftx1_in_memory_mode = 0 at the end of ftx1_set_channel
because the BM commit path always ends with the Main side in VFO mode,
regardless of the caller's prior position.
Verified end-to-end against fw v1.12:
$ rigctl -m 1051 -r ... E 1
Rig command: F 7050000
Rig command: f
7050000
(radio is now in VFO mode at 7.050 MHz — without the fix the F would
have been rejected and the radio would still be in Memory mode)
$ rigctl -m 1051 -r ... E 1
Rig command: M USB 2700
Rig command: m
Mode: USB
Passband: 2700
(VFO mode USB — without the fix the MD set would have been a
transient overlay that vanished on next MC recall)
The tracking flag avoids paying for a VM000 CAT round trip on every
setter call; it only fires when the driver actually knows the radio
entered Memory mode via set_mem.
diff --git a/rigs/yaesu/ftx1/ftx1.c b/rigs/yaesu/ftx1/ftx1.c
index a2bb45cc4..c8806b934 100644
--- a/rigs/yaesu/ftx1/ftx1.c
+++ b/rigs/yaesu/ftx1/ftx1.c
@@ -72,6 +72,7 @@ extern int ftx1_set_att_helper(RIG *rig, vfo_t vfo, value_t val);
extern int ftx1_get_att_helper(RIG *rig, vfo_t vfo, value_t *val);
/* Wrappers from ftx1_func.c for rig caps */
+extern int ftx1_set_mode(RIG *rig, vfo_t vfo, rmode_t mode, pbwidth_t width);
extern int ftx1_set_ptt_func(RIG *rig, vfo_t vfo, ptt_t ptt);
extern int ftx1_get_ptt_func(RIG *rig, vfo_t vfo, ptt_t *ptt);
extern int ftx1_set_powerstat_func(RIG *rig, powerstat_t status);
@@ -862,6 +863,43 @@ static int ftx1_close(RIG *rig)
return newcat_close(rig);
}
+/*
+ * ftx1_ensure_vfo_mode - exit Memory mode if the driver last saw MC enter it
+ *
+ * FTX-1 firmware rejects FA/OS sets when the Main side is in Memory mode
+ * (VM011) and silently discards CT/CN/MD sets as transient memory-tune
+ * overlays. Callers that set VFO-side state should call this first so the
+ * operation actually lands.
+ *
+ * We track memory-mode entry in priv->ftx1_in_memory_mode (set by
+ * ftx1_set_mem after a successful MC). If the flag is clear, this is a
+ * no-op — we don't spam the rig with VM000 on every VFO-state set.
+ *
+ * Best-effort: on failure the flag is cleared unconditionally so we
+ * don't loop.
+ */
+void ftx1_ensure_vfo_mode(RIG *rig)
+{
+ struct newcat_priv_data *priv;
+
+ if (!rig)
+ {
+ return;
+ }
+
+ priv = STATE(rig)->priv;
+ if (!priv || !priv->ftx1_in_memory_mode)
+ {
+ return;
+ }
+
+ rig_debug(RIG_DEBUG_VERBOSE, "%s: exiting memory mode via VM000;\n",
+ __func__);
+ SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "VM000;");
+ (void)newcat_set_cmd(rig);
+ priv->ftx1_in_memory_mode = 0;
+}
+
/*
* ftx1_has_spa1 - Check if Optima/SPA-1 amplifier is present
*
@@ -1157,7 +1195,7 @@ struct rig_caps ftx1_caps = {
.rig_close = ftx1_close, /* FTX-1 specific close - resets detection state */
.set_freq = ftx1_set_freq,
.get_freq = ftx1_get_freq,
- .set_mode = newcat_set_mode,
+ .set_mode = ftx1_set_mode,
.get_mode = newcat_get_mode,
.set_vfo = ftx1_set_vfo,
.get_vfo = ftx1_get_vfo,
diff --git a/rigs/yaesu/ftx1/ftx1.h b/rigs/yaesu/ftx1/ftx1.h
index 5099263fc..65e131928 100644
--- a/rigs/yaesu/ftx1/ftx1.h
+++ b/rigs/yaesu/ftx1/ftx1.h
@@ -221,6 +221,14 @@ static inline int ftx1_vfo_to_p1(RIG *rig, vfo_t vfo)
extern int ftx1_has_spa1(RIG *rig);
extern int ftx1_get_head_type(RIG *rig);
+/*
+ * ftx1_ensure_vfo_mode - force the radio out of Memory mode if the driver
+ * knows it entered via a prior set_mem. Call at the top of any VFO-state
+ * setter that would otherwise fail or behave transiently in Memory mode.
+ * See ftx1.c for full rationale.
+ */
+extern void ftx1_ensure_vfo_mode(RIG *rig);
+
/*
* FTX-1 band select functions (defined in ftx1_scan.c)
*/
diff --git a/rigs/yaesu/ftx1/ftx1_ctcss.c b/rigs/yaesu/ftx1/ftx1_ctcss.c
index fd0210114..faf608a55 100644
--- a/rigs/yaesu/ftx1/ftx1_ctcss.c
+++ b/rigs/yaesu/ftx1/ftx1_ctcss.c
@@ -101,6 +101,10 @@ int ftx1_set_ctcss_mode(RIG *rig, tone_t mode)
rig_debug(RIG_DEBUG_VERBOSE, "%s: mode=%u\n", __func__, mode);
+ /* CT sets are transient overlays in Memory mode — accepted but not
+ * persisted. Exit memory mode so the change actually sticks. */
+ ftx1_ensure_vfo_mode(rig);
+
/* CT P1 P2; where P1=VFO (0=Main), P2=mode */
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "CT0%d;", (int)mode);
return newcat_set_cmd(rig);
@@ -168,6 +172,9 @@ int ftx1_set_ctcss_tone(RIG *rig, vfo_t vfo, tone_t tone)
rig_debug(RIG_DEBUG_VERBOSE, "%s: tone=%u tone_num=%d\n", __func__, tone,
tone_num);
+ /* CN on Main is a transient overlay in Memory mode — exit first. */
+ ftx1_ensure_vfo_mode(rig);
+
/* P1=0 for TX tone, P2P3P4 is 3-digit tone number */
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "CN00%03d;", tone_num);
return newcat_set_cmd(rig);
@@ -225,7 +232,9 @@ int ftx1_set_ctcss_sql(RIG *rig, vfo_t vfo, tone_t tone)
rig_debug(RIG_DEBUG_VERBOSE, "%s: tone=%u tone_num=%d\n", __func__, tone,
tone_num);
- /* P1=1 for RX tone, P2P3P4 is 3-digit tone number */
+ /* P1=1 for RX tone, P2P3P4 is 3-digit tone number. CN10 targets
+ * Sub VFO, which is not affected by Main's Memory mode, so no
+ * VM000 injection is needed here. */
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "CN10%03d;", tone_num);
return newcat_set_cmd(rig);
}
@@ -280,6 +289,9 @@ int ftx1_set_dcs_code(RIG *rig, vfo_t vfo, tone_t code)
rig_debug(RIG_DEBUG_VERBOSE, "%s: code=%u\n", __func__, code);
+ /* CN on Main is a transient overlay in Memory mode — exit first. */
+ ftx1_ensure_vfo_mode(rig);
+
/* CN01XXX: Main VFO (0), DCS (1), code index */
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "CN01%03u;", code);
return newcat_set_cmd(rig);
diff --git a/rigs/yaesu/ftx1/ftx1_freq.c b/rigs/yaesu/ftx1/ftx1_freq.c
index 7668ef917..bfcf5f82a 100644
--- a/rigs/yaesu/ftx1/ftx1_freq.c
+++ b/rigs/yaesu/ftx1/ftx1_freq.c
@@ -17,6 +17,7 @@
#include "misc.h"
#include "yaesu.h"
#include "newcat.h"
+#include "ftx1.h"
// FTX-1 uses 9-digit Hz format for frequency
#define FTX1_FREQ_DIGITS 9
@@ -43,6 +44,10 @@ int ftx1_set_freq(RIG *rig, vfo_t vfo, freq_t freq)
case RIG_VFO_MAIN:
case RIG_VFO_CURR:
cmd = 'A';
+ /* FA set is rejected with ?; while the Main side is in Memory
+ * mode. Force an exit before sending the command. FB (sub) is
+ * unaffected and does not need this. */
+ ftx1_ensure_vfo_mode(rig);
break;
case RIG_VFO_B:
@@ -176,6 +181,9 @@ int ftx1_set_rptr_shift(RIG *rig, vfo_t vfo, rptr_shift_t shift)
rig_debug(RIG_DEBUG_VERBOSE, "%s: vfo=%s shift=%d\n",
__func__, rig_strvfo(vfo), shift);
+ /* OS Main is rejected with ?; in Memory mode. Exit before sending. */
+ ftx1_ensure_vfo_mode(rig);
+
/* Determine VFO */
switch (vfo)
{
diff --git a/rigs/yaesu/ftx1/ftx1_mem.c b/rigs/yaesu/ftx1/ftx1_mem.c
index 853ac4d4c..9b818a9f7 100644
--- a/rigs/yaesu/ftx1/ftx1_mem.c
+++ b/rigs/yaesu/ftx1/ftx1_mem.c
@@ -67,6 +67,7 @@ static int ftx1_get_vfo_mem_mode_internal(RIG *rig, vfo_t *vfo);
int ftx1_set_mem(RIG *rig, vfo_t vfo, int ch)
{
struct newcat_priv_data *priv = STATE(rig)->priv;
+ int ret;
(void)vfo; /* VFO not used in MC command */
@@ -80,7 +81,15 @@ int ftx1_set_mem(RIG *rig, vfo_t vfo, int ch)
/* Format: MCNNNNNN (6-digit channel) */
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "MC%06d;", ch);
- return newcat_set_cmd(rig);
+ ret = newcat_set_cmd(rig);
+ if (ret == RIG_OK)
+ {
+ /* MC on a programmed channel enters Memory mode on the Main
+ * side. Track this so the next VFO-state setter can force an
+ * exit via VM000 before issuing FA/OS/CT/CN/MD. */
+ priv->ftx1_in_memory_mode = 1;
+ }
+ return ret;
}
/*
@@ -388,6 +397,11 @@ restore:
(void)newcat_set_cmd(rig);
}
+ /* BM always ends with the Main side in VFO mode regardless of the
+ * caller's prior position, so clear the memory-mode tracking flag
+ * to keep ftx1_ensure_vfo_mode() accurate for subsequent setters. */
+ priv->ftx1_in_memory_mode = 0;
+
return err;
}
diff --git a/rigs/yaesu/ftx1/ftx1_mode.c b/rigs/yaesu/ftx1/ftx1_mode.c
index 292795e60..fd7bba3bd 100644
--- a/rigs/yaesu/ftx1/ftx1_mode.c
+++ b/rigs/yaesu/ftx1/ftx1_mode.c
@@ -2,8 +2,12 @@
* Hamlib Yaesu backend - FTX-1 Mode Commands
* Copyright (c) 2025 by Terrell Deppe (KJ5HST)
*
- * Mode commands are handled by newcat_set_mode/newcat_get_mode.
- * This file documents the FTX-1 specific mode codes for reference.
+ * Mode commands are mostly handled by newcat_set_mode/newcat_get_mode.
+ * This file adds an FTX-1 set_mode wrapper that forces the radio out
+ * of Memory mode before delegating to newcat, because Memory-mode MD
+ * sets on the Main side are accepted by firmware but treated as a
+ * transient memory-tune overlay that does not persist when the user
+ * leaves the channel.
*
* CAT Commands:
* MD P1 P2; - Operating Mode (P1=VFO 0/1, P2=mode code)
@@ -17,4 +21,15 @@
* NA (Notch Auto) - handled via ftx1_noise.c
*/
-/* No FTX-1 specific mode functions needed - newcat handles MD command */
+#include <hamlib/rig.h>
+#include "newcat.h"
+#include "ftx1.h"
+
+int ftx1_set_mode(RIG *rig, vfo_t vfo, rmode_t mode, pbwidth_t width)
+{
+ /* Memory-mode MD sets on Main are accepted but do not persist —
+ * they act as a transient memory-tune overlay. Force an exit so
+ * the user's mode change actually sticks. */
+ ftx1_ensure_vfo_mode(rig);
+ return newcat_set_mode(rig, vfo, mode, width);
+}
diff --git a/rigs/yaesu/newcat.h b/rigs/yaesu/newcat.h
index 2e0372777..a02acab7f 100644
--- a/rigs/yaesu/newcat.h
+++ b/rigs/yaesu/newcat.h
@@ -142,6 +142,7 @@ struct newcat_priv_data
int ftx1_clar_cached; /* 1 if RX/TX CLAR states have been cached */
char ftx1_rx_clar_on; /* Cached RX CLAR enable: '0' or '1' */
char ftx1_tx_clar_on; /* Cached TX CLAR enable: '0' or '1' */
+ int ftx1_in_memory_mode; /* 1 if driver knows the Main-side is in Memory mode (VM011) */
};
/*
commit 130d733be2c447faabcb69f53ae3f571bba34978
Author: KJ5HST <kj...@de...>
Date: Wed Apr 15 15:43:29 2026 -0400
ftx1: populate CTCSS/DCS fields in get_channel
ftx1_get_channel has historically parsed the P8 byte from the MR
response and then discarded it with a (void) cast, so rig_get_channel
always returned chan->ctcss_tone == 0 regardless of what was actually
programmed in the channel. An FM memory channel with a CTCSS tone or
DCS code read back as "no tone" — silently misleading for callers.
MR itself does not carry the tone number, only the mode (P8).
Verified by byte-level comparison of MR responses across "no tone"
and "CTCSS ENC tone 12" writes on fw v1.12 — only byte 23 differs.
The tone number lives in CN, which is only queryable against an
operating VFO.
Add ftx1_read_channel_tone_state(), a static helper that:
1. Snapshots current VM and MC state via queries
2. Selects the target memory channel via MC<ch>; (enters mem mode)
3. Queries CN00 (CTCSS) or CN01 (DCS) to get the stored number
4. Populates chan->ctcss_tone / ctcss_sql / dcs_code using
ftx1_tone_num_to_freq() for CTCSS
5. Restores the caller's prior state — if originally in VFO mode
send VM000, if originally in memory mode on another channel
send MC<original>
The helper applies the MW/MR P8 swap encoding (P8=1 is TSQ, P8=2
is ENC, P8=3 is DCS) and sets ctcss_sql only for the TSQ case.
Intrusiveness: get_channel now briefly switches the radio to memory
mode on the target channel, which causes a momentary front-panel
display change. State is restored before the function returns so the
operator's net position is unchanged. The intrusion is only triggered
when P8 indicates a tone is present — no-tone channels skip the CN
query entirely.
Also exposes ftx1_tone_num_to_freq() via ftx1.h (previously file-
static in ftx1_ctcss.c) so ftx1_mem.c can reuse the existing tone
table instead of duplicating it.
Verified end-to-end via rigctl H/h against fw v1.12:
ENC: H 1 ... 1000 0 -> h 1: CTCSS: 100.0Hz, CTCSSsql: 0.0Hz
TSQ: H 1 ... 1000 1000 -> h 1: CTCSS: 100.0Hz, CTCSSsql: 100.0Hz
OFF: H 1 ... 0 0 -> h 1: CTCSS: 0.0Hz, CTCSSsql: 0.0Hz
After each read, VFO state and channel 1 MR response are byte-for-
byte identical to the pre-test snapshot.
DCS is supported in the readback path but currently unverifiable on
the available hardware — the firmware does not appear to persist DCS
state into memory channels via the BM write path, so no DCS channel
exists to read back. The code handles P8=3 correctly should a
front-panel-programmed DCS channel produce that byte value.
diff --git a/rigs/yaesu/ftx1/ftx1.h b/rigs/yaesu/ftx1/ftx1.h
index 75956c010..5099263fc 100644
--- a/rigs/yaesu/ftx1/ftx1.h
+++ b/rigs/yaesu/ftx1/ftx1.h
@@ -231,5 +231,6 @@ extern int ftx1_get_band_select(RIG *rig, vfo_t vfo, int *band);
* FTX-1 CTCSS helpers (defined in ftx1_ctcss.c)
*/
extern int ftx1_freq_to_tone_num(unsigned int freq);
+extern unsigned int ftx1_tone_num_to_freq(int num);
#endif /* _FTX1_H */
diff --git a/rigs/yaesu/ftx1/ftx1_ctcss.c b/rigs/yaesu/ftx1/ftx1_ctcss.c
index 5152c4322..fd0210114 100644
--- a/rigs/yaesu/ftx1/ftx1_ctcss.c
+++ b/rigs/yaesu/ftx1/ftx1_ctcss.c
@@ -62,7 +62,7 @@ int ftx1_freq_to_tone_num(unsigned int freq)
}
/* Convert tone number (0-based per spec) to frequency (in 0.1 Hz) */
-static unsigned int ftx1_tone_num_to_freq(int num)
+unsigned int ftx1_tone_num_to_freq(int num)
{
if (num < FTX1_CTCSS_MIN || num > FTX1_CTCSS_MAX)
{
diff --git a/rigs/yaesu/ftx1/ftx1_mem.c b/rigs/yaesu/ftx1/ftx1_mem.c
index 945e853d7..853ac4d4c 100644
--- a/rigs/yaesu/ftx1/ftx1_mem.c
+++ b/rigs/yaesu/ftx1/ftx1_mem.c
@@ -391,6 +391,100 @@ restore:
return err;
}
+/*
+ * ftx1_read_channel_tone_state — read a channel's CTCSS tone / DCS code.
+ *
+ * The MR response carries only the tone MODE (P8), not the actual tone
+ * number or DCS code. To retrieve those we have to select the memory
+ * channel via MC, query CN (which reflects the stored channel state in
+ * memory mode), then restore the caller's prior VM/MC position.
+ *
+ * Intrusiveness note: this briefly switches the radio to memory mode
+ * on the target channel. The visible side effect is a momentary front-
+ * panel display change. State is restored at the end — if the caller
+ * was previously in VFO mode we return via VM000, if they were already
+ * in memory mode on another channel we MC back to that channel.
+ *
+ * mr_p8 is the raw stored P8 byte from MR, encoded per the firmware's
+ * MW/MR swap (different from CT encoding):
+ * 1 = TSQ (tone squelch — TX+RX CTCSS tone)
+ * 2 = ENC (TX CTCSS tone only)
+ * 3 = DCS
+ *
+ * Returns void: best-effort. On any CAT failure the tone fields are
+ * simply left at whatever the caller passed in, and the restore step
+ * still runs.
+ */
+static void ftx1_read_channel_tone_state(RIG *rig, int ch, int mr_p8,
+ channel_t *chan)
+{
+ struct newcat_priv_data *priv = STATE(rig)->priv;
+ char saved_vm[16] = {0};
+ char saved_mc[16] = {0};
+ int p1p2, val;
+
+ /* Snapshot current VM and MC so we can restore them. */
+ SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "VM0;");
+ if (newcat_get_cmd(rig) == RIG_OK)
+ {
+ strncpy(saved_vm, priv->ret_data, sizeof(saved_vm) - 1);
+ }
+ SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "MC0;");
+ if (newcat_get_cmd(rig) == RIG_OK)
+ {
+ strncpy(saved_mc, priv->ret_data, sizeof(saved_mc) - 1);
+ }
+
+ /* Select the target memory channel. */
+ SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "MC%06d;", ch);
+ if (newcat_set_cmd(rig) != RIG_OK)
+ {
+ goto restore;
+ }
+
+ if (mr_p8 == 3)
+ {
+ /* DCS: query main-side DCS code via CN01. */
+ SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "CN01;");
+ if (newcat_get_cmd(rig) == RIG_OK
+ && sscanf(priv->ret_data + 2, "%2d%3d", &p1p2, &val) == 2)
+ {
+ chan->dcs_code = (tone_t)val;
+ }
+ }
+ else
+ {
+ /* CTCSS: query main-side tone index via CN00. */
+ SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "CN00;");
+ if (newcat_get_cmd(rig) == RIG_OK
+ && sscanf(priv->ret_data + 2, "%2d%3d", &p1p2, &val) == 2)
+ {
+ tone_t tone = (tone_t)ftx1_tone_num_to_freq(val);
+ chan->ctcss_tone = tone;
+ /* MW/MR P8=1 is TSQ (encode and decode tones both active);
+ * P8=2 is ENC only. */
+ if (mr_p8 == 1)
+ {
+ chan->ctcss_sql = tone;
+ }
+ }
+ }
+
+restore:
+ /* Return to the caller's prior position. Memory mode on some other
+ * channel is restored via MC; otherwise fall back to VFO mode. */
+ if (strstr(saved_vm, "VM011;") != NULL && saved_mc[0] != '\0')
+ {
+ SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "%s", saved_mc);
+ (void)newcat_set_cmd(rig);
+ }
+ else
+ {
+ SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "VM000;");
+ (void)newcat_set_cmd(rig);
+ }
+}
+
/*
* Memory Read (MR) - read memory channel data
* FIRMWARE FORMAT: MR P1P2P2P2P2 (5-digit: bank + 4-digit channel)
@@ -405,10 +499,14 @@ restore:
* 20 P5 TX CLAR on/off (0/1)
* 21 P6 Mode code (1-E)
* 22 P7 VFO/Memory (0/1)
- * 23 P8 CTCSS mode (0-3)
+ * 23 P8 CTCSS mode (0-3, MW/MR swap encoding)
* 24-25 P9 Reserved "00"
* 26 P10 Shift (0=simplex, 1=+, 2=-)
* Returns '?' if channel doesn't exist (not programmed)
+ *
+ * P8 does NOT carry the actual tone number or DCS code — those have
+ * to be fetched separately via CN, which requires briefly selecting
+ * the channel via MC. See ftx1_read_channel_tone_state().
*/
int ftx1_get_channel(RIG *rig, vfo_t vfo, channel_t *chan, int read_only)
{
@@ -518,11 +616,12 @@ int ftx1_get_channel(RIG *rig, vfo_t vfo, channel_t *chan, int read_only)
/* Skip VFO/Memory indicator (1 char) */
p++;
- /* Parse CTCSS mode (1 char) */
+ /* Parse CTCSS mode (1 char). This is the MW/MR stored encoding,
+ * which is swapped relative to CT:
+ * 0 = OFF, 1 = TSQ, 2 = ENC, 3 = DCS
+ * The actual tone number or DCS code is fetched below via the
+ * ftx1_read_channel_tone_state helper — MR does not carry it. */
ctcss_mode = *p++ - '0';
- /* Note: Actual tone frequencies require separate CN/QN queries */
- /* Here we just record the mode for reference */
- (void)ctcss_mode;
/* Skip reserved "00" (2 chars) */
p += 2;
@@ -538,6 +637,13 @@ int ftx1_get_channel(RIG *rig, vfo_t vfo, channel_t *chan, int read_only)
/* Set width to default (not stored in memory response) */
chan->width = RIG_PASSBAND_NORMAL;
+ /* If the channel has a tone, fetch the actual number or DCS code
+ * via CN (intrusive — briefly selects the channel and restores). */
+ if (ctcss_mode > 0 && ctcss_mode <= 3)
+ {
+ ftx1_read_channel_tone_state(rig, ch, ctcss_mode, chan);
+ }
+
rig_debug(RIG_DEBUG_VERBOSE,
"%s: ch=%d freq=%.0f mode=%s rit=%ld xit=%ld shift=%d\n",
__func__, ch, chan->freq, rig_strrmode(chan->mode),
commit c1a259406ace8e3c4c801f2b7cb64424efc28914
Author: KJ5HST <kj...@de...>
Date: Wed Apr 15 14:52:50 2026 -0400
ftx1: add clarifier support and document firmware limits in set_channel
Empirically verified three BM-propagation unknowns against fw v1.12:
- Clarifier: the CF command series (11-char form, P3=0 for the
RX/TX toggles and P3=1 for the offset) is captured by BM. MR
readback shows the stored channel with the programmed clarifier
offset and the RX CLAR flag. Add CF programming to the rewrite
so rig_set_channel now persists chan->rit into the memory slot.
- TX CLAR flag (XIT): the offset and RX flag propagate but the TX
CLAR on/off toggle is silently dropped by BM. The stored channel
always reads back with TX CLAR off, regardless of what CF100.3
was set to on VFO-B before the commit. We emit the command
anyway for forward compatibility with a firmware fix.
- DCS: CT13 (CT mode = DCS) and CN11<code> program VFO-B correctly
and readback of VFO-B shows both values, but BM does not copy
either to the memory channel. The stored MR response is
byte-identical to a no-tone write, across DCS codes ranging from
023 to 103. DCS channels cannot be programmed via CAT on this
firmware and must be set up from the front panel. We still emit
CT13 + CN11 so the code path survives a later firmware fix.
Also tighten the cleanup path: the function now explicitly clears
VFO-B's clarifier state (and CT state for FM-family writes) on exit
in addition to restoring FB/MD1 from the entry snapshot. This avoids
leaking intermediate state when rig_set_channel returns.
Verified end-to-end via rigctl H 1 with rit=200 Hz — channel 1 MR
readback shows clar=+0200 rx=1 as expected, and both VFOs survive
the round trip.
diff --git a/rigs/yaesu/ftx1/ftx1_mem.c b/rigs/yaesu/ftx1/ftx1_mem.c
index b210b1ac9..945e853d7 100644
--- a/rigs/yaesu/ftx1/ftx1_mem.c
+++ b/rigs/yaesu/ftx1/ftx1_mem.c
@@ -141,21 +141,34 @@ int ftx1_get_mem(RIG *rig, vfo_t vfo, int *ch)
* target slot. Ignore '?' if the slot is currently
* unprogrammed — the cursor still updates for BM.
* 2. VM000; Force VFO mode in case MC entered memory mode.
- * 3. FB / MD1 / CT1 / CN10 / CN11 / OS1 Program VFO-B.
- * CT/CN/OS only work in FM, so tone/shift are only
- * emitted for FM-family channel modes.
+ * 3. FB / MD1 / CT1 / CN10 / OS1 / CF1 Program VFO-B.
+ * CT/CN/OS only work in FM, so tone and shift are only
+ * emitted for FM-family channel modes. Clarifier (CF)
+ * is programmed for all modes.
* 4. BM; Copy VFO-B to the last-selected memory channel.
*
* VFO-B is used rather than VFO-A so the operator's primary RX VFO
* is not disturbed. VFO-B's frequency and mode are snapshotted at
* entry and best-effort restored on exit (including error paths).
- * Advanced VFO-B state (CT/CN/OS/CF) may still be clobbered for
- * callers that relied on it.
+ * VFO-B's clarifier and CT state are cleared during cleanup — any
+ * caller that relied on those aspects of VFO-B's state will need to
+ * reprogram them after rig_set_channel.
*
- * Clarifier/RIT/XIT persistence into the memory slot is not yet
- * supported — BM's handling of clarifier state has not been
- * empirically verified. This is a potential follow-up if users
- * report it missing.
+ * Firmware limitations verified empirically on fw v1.12: the BM
+ * command does NOT propagate two kinds of state to the memory slot,
+ * even though the CAT commands to set them on VFO-B succeed:
+ *
+ * - DCS: CT13 (DCS mode) + CN11<code> program VFO-B correctly, but
+ * the stored memory channel reads back with CTCSS mode OFF. DCS
+ * channels cannot be programmed via CAT and must be set up from
+ * the front panel. We still emit the CT/CN commands so that if
+ * firmware is fixed later, the code path works.
+ *
+ * - XIT (TX clarifier flag): the clarifier offset frequency and
+ * the RX clarifier on/off flag both propagate correctly, but the
+ * TX CLAR on/off flag is dropped by BM and always reads back as
+ * OFF in the stored channel. We set it anyway for forward
+ * compatibility.
*/
int ftx1_set_channel(RIG *rig, vfo_t vfo, const channel_t *chan)
{
@@ -295,14 +308,75 @@ int ftx1_set_channel(RIG *rig, vfo_t vfo, const channel_t *chan)
(void)newcat_set_cmd(rig);
}
+ /* 3d. Clarifier (RIT/XIT). The FTX-1 uses one shared offset with
+ * independent RX/TX on-off toggles via the 11-char CF command:
+ * CF P1 P2 P3 P4 P5P5P5P5 ; where P3=0 sets RX/TX on/off
+ * (P4: 0=RX OFF, 1=RX ON, 2=TX OFF, 3=TX ON) and P3=1 sets the
+ * offset frequency (P4=+/-, P5P5P5P5 = offset Hz).
+ *
+ * If both rit and xit are set, rit's offset wins (matches the
+ * pre-#2034 behavior of the broken MW path). Note that the TX
+ * CLAR flag is silently dropped by BM (firmware limitation);
+ * we still emit it for forward compatibility. */
+ if (chan->rit != 0 || chan->xit != 0)
+ {
+ int off;
+ char dir;
+
+ if (chan->rit != 0)
+ {
+ dir = (chan->rit >= 0) ? '+' : '-';
+ off = (int)labs(chan->rit);
+ }
+ else
+ {
+ dir = (chan->xit >= 0) ? '+' : '-';
+ off = (int)labs(chan->xit);
+ }
+ if (off > 9999) off = 9999;
+
+ SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str),
+ "CF100%d0000;", (chan->rit != 0) ? 1 : 0);
+ (void)newcat_set_cmd(rig);
+
+ SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str),
+ "CF100%d0000;", (chan->xit != 0) ? 3 : 2);
+ (void)newcat_set_cmd(rig);
+
+ SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str),
+ "CF101%c%04d;", dir, off);
+ (void)newcat_set_cmd(rig);
+ }
+ else
+ {
+ /* Explicitly clear VFO-B clarifier state so it doesn't leak
+ * from a previous write or the operator's prior VFO-B. */
+ SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "CF10000000;");
+ (void)newcat_set_cmd(rig);
+ SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "CF10020000;");
+ (void)newcat_set_cmd(rig);
+ }
+
/* 4. Commit VFO-B to the last-selected memory channel. */
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "BM;");
err = newcat_set_cmd(rig);
restore:
- /* Best-effort restore of VFO-B state. Restore failures are not
- * surfaced — the caller cares about the write's status, not the
+ /* Best-effort restore of VFO-B. Clarifier and CT state that we may
+ * have touched are cleared unconditionally — we don't snapshot
+ * them because CF has no reliable read form. FB and MD1 are
+ * replayed from the entry snapshot. Restore failures are not
+ * surfaced: the caller cares about the write's status, not the
* side-effect cleanup. */
+ SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "CF10000000;");
+ (void)newcat_set_cmd(rig);
+ SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "CF10020000;");
+ (void)newcat_set_cmd(rig);
+ if (is_fm_family)
+ {
+ SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "CT10;");
+ (void)newcat_set_cmd(rig);
+ }
if (saved_fb[0] != '\0')
{
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "%s", saved_fb);
commit 4024cd5d0d6ca3ae959ce7da1cf193438144c20a
Author: KJ5HST <kj...@de...>
Date: Wed Apr 15 14:06:45 2026 -0400
ftx1: rewrite set_channel using VFO-B + BM (firmware MW bug) (#2034)
The FTX-1 MW (Memory Write) CAT command is firmware-broken on v1.08+
and always returns '?;' regardless of channel or parameters. The
previous ftx1_set_channel built a 30-char MW command and relied on it
succeeding, so rig_set_channel on an FTX-1 failed on every call --
no memory channel ever got written.
Replace the MW path with the sequence the firmware actually supports:
1. MC<ch>; point the "last-selected channel" cursor at the target.
The radio returns '?;' for unprogrammed slots, but the
cursor still updates for the subsequent BM commit.
2. VM000; force VFO mode in case MC entered memory mode.
3. FB / MD1 / CT1 / CN10 / CN11 / OS1 program VFO-B to the target
state. CT/CN/OS only function in FM, so tone and shift
are only emitted for FM-family channel modes. DCS goes
through CN with P2=1 because the DC command is also
firmware-broken.
4. BM; copy VFO-B to the last-selected memory channel.
VFO-B is used rather than VFO-A so the operator's primary RX VFO is
not disturbed. VFO-B's frequency and mode are snapshotted at entry and
best-effort restored on exit (including the error path), so a caller
that was using VFO-B sees minimal side effects.
Clarifier/RIT/XIT state is not yet programmed into the channel -- BM's
handling of clarifier has not been empirically verified, and getting
it wrong silently is worse than dropping it for now. Left as a
potential follow-up if users report it missing.
Verified end-to-end on a live FTX-1 field head + Optima/SPA-1 running
firmware MAIN v1.12 at 115200 bps: rigctl -m 1051 H 1 round-trips
channel 1 between 7.000 MHz LSB and 7.050 MHz LSB, and VFO-A
(144.260 FM) and VFO-B (28.074 USB) are both preserved across the
operation.
Exposes ftx1_freq_to_tone_num() in ftx1.h (previously file-static in
ftx1_ctcss.c) so ftx1_mem.c can reuse the existing CTCSS frequency
lookup instead of duplicating the table.
diff --git a/rigs/yaesu/ftx1/ftx1.h b/rigs/yaesu/ftx1/ftx1.h
index dae62f59b..75956c010 100644
--- a/rigs/yaesu/ftx1/ftx1.h
+++ b/rigs/yaesu/ftx1/ftx1.h
@@ -227,4 +227,9 @@ extern int ftx1_get_head_type(RIG *rig);
extern int ftx1_set_band_select(RIG *rig, vfo_t vfo, int band);
extern int ftx1_get_band_select(RIG *rig, vfo_t vfo, int *band);
+/*
+ * FTX-1 CTCSS helpers (defined in ftx1_ctcss.c)
+ */
+extern int ftx1_freq_to_tone_num(unsigned int freq);
+
#endif /* _FTX1_H */
diff --git a/rigs/yaesu/ftx1/ftx1_ctcss.c b/rigs/yaesu/ftx1/ftx1_ctcss.c
index a2f47fb13..5152c4322 100644
--- a/rigs/yaesu/ftx1/ftx1_ctcss.c
+++ b/rigs/yaesu/ftx1/ftx1_ctcss.c
@@ -46,7 +46,7 @@ static const unsigned int ftx1_ctcss_tones[] = {
};
/* Convert CTCSS frequency (in 0.1 Hz) to tone number (0-based per spec) */
-static int ftx1_freq_to_tone_num(unsigned int freq)
+int ftx1_freq_to_tone_num(unsigned int freq)
{
int i;
diff --git a/rigs/yaesu/ftx1/ftx1_mem.c b/rigs/yaesu/ftx1/ftx1_mem.c
index 07827632c..b210b1ac9 100644
--- a/rigs/yaesu/ftx1/ftx1_mem.c
+++ b/rigs/yaesu/ftx1/ftx1_mem.c
@@ -129,121 +129,192 @@ int ftx1_get_mem(RIG *rig, vfo_t vfo, int *ch)
}
/*
- * Memory Write (MW) - write channel data to memory
- * CAT Format: MW P1P1P1P1P1 P2P2P2P2P2P2P2P2P2 P3P3P3P3P3 P4 P5 P6 P7 P8 P9P9 P10;
- * P1 (5 bytes): Channel number (00001-00999 or P-01L-P-50U for PMS)
- * P2 (9 bytes): VFO Frequency in Hz
- * P3 (5 bytes): Clarifier direction (+/-) + offset (0000-9990 Hz)
- * P4 (1 byte): RX CLAR (0=OFF, 1=ON)
- * P5 (1 byte): TX CLAR (0=OFF, 1=ON)
- * P6 (1 byte): Mode code (1=LSB, 2=USB, 3=CW-U, 4=FM, 5=AM, 6=RTTY-L,
- * 7=CW-L, 8=DATA-L, 9=RTTY-U, A=DATA-FM, B=FM-N,
- * C=DATA-U, D=AM-N, E=PSK, F=DATA-FM-N)
- * P7 (1 byte): VFO/Memory mode (0=VFO, 1=Memory, 2=Memory Tune, 3=QMB, 5=PMS)
- * P8 (1 byte): CTCSS mode (0=OFF, 1=ENC/DEC, 2=ENC, 3=DCS, 4=PR FREQ, 5=REV TONE)
- * P9 (2 bytes): Fixed "00"
- * P10 (1 byte): Shift (0=Simplex, 1=Plus, 2=Minus)
+ * Memory Write — VFO-B + BM workaround (issue #2034)
+ *
+ * The FTX-1 MW command is firmware-broken: the radio returns '?;' for
+ * every MW write on every channel, regardless of parameters (verified
+ * against fw v1.12). We therefore implement rig_set_channel by
+ * programming VFO-B to the target state and committing it to the
+ * target memory slot via the BM command:
+ *
+ * 1. MC<ch>; Point the "last-selected channel" cursor at the
+ * target slot. Ignore '?' if the slot is currently
+ * unprogrammed — the cursor still updates for BM.
+ * 2. VM000; Force VFO mode in case MC entered memory mode.
+ * 3. FB / MD1 / CT1 / CN10 / CN11 / OS1 Program VFO-B.
+ * CT/CN/OS only work in FM, so tone/shift are only
+ * emitted for FM-family channel modes.
+ * 4. BM; Copy VFO-B to the last-selected memory channel.
+ *
+ * VFO-B is used rather than VFO-A so the operator's primary RX VFO
+ * is not disturbed. VFO-B's frequency and mode are snapshotted at
+ * entry and best-effort restored on exit (including error paths).
+ * Advanced VFO-B state (CT/CN/OS/CF) may still be clobbered for
+ * callers that relied on it.
+ *
+ * Clarifier/RIT/XIT persistence into the memory slot is not yet
+ * supported — BM's handling of clarifier state has not been
+ * empirically verified. This is a potential follow-up if users
+ * report it missing.
*/
int ftx1_set_channel(RIG *rig, vfo_t vfo, const channel_t *chan)
{
struct newcat_priv_data *priv = STATE(rig)->priv;
+ char saved_fb[32] = {0};
+ char saved_md1[16] = {0};
char mode_char;
- char clar_dir;
- int clar_offset;
- int p7_vfo_mem;
- int p8_ctcss;
- int p10_shift;
+ int err;
+ int is_fm_family;
(void)vfo;
- rig_debug(RIG_DEBUG_VERBOSE, "%s: ch=%d freq=%.0f mode=%d\n", __func__,
- chan->channel_num, chan->freq, (int)chan->mode);
+ rig_debug(RIG_DEBUG_VERBOSE, "%s: ch=%d freq=%.0f mode=%s\n", __func__,
+ chan->channel_num, chan->freq, rig_strrmode(chan->mode));
- /* Validate channel number */
- if (chan->channel_num < FTX1_MEM_MIN || chan->channel_num > FTX1_MEM_MAX) {
+ if (chan->channel_num < FTX1_MEM_MIN || chan->channel_num > FTX1_MEM_MAX)
+ {
rig_debug(RIG_DEBUG_ERR, "%s: channel %d out of range %d-%d\n",
__func__, chan->channel_num, FTX1_MEM_MIN, FTX1_MEM_MAX);
return -RIG_EINVAL;
}
- /* Convert Hamlib mode to FTX-1 mode code */
- switch (chan->mode) {
- case RIG_MODE_LSB: mode_char = '1'; break;
- case RIG_MODE_USB: mode_char = '2'; break;
- case RIG_MODE_CW: mode_char = '3'; break; /* CW-U */
- case RIG_MODE_FM: mode_char = '4'; break;
- case RIG_MODE_AM: mode_char = '5'; break;
- case RIG_MODE_RTTYR: mode_char = '6'; break; /* RTTY-L */
- case RIG_MODE_CWR: mode_char = '7'; break; /* CW-L */
- case RIG_MODE_PKTLSB: mode_char = '8'; break; /* DATA-L */
- case RIG_MODE_RTTY: mode_char = '9'; break; /* RTTY-U */
- case RIG_MODE_PKTFM: mode_char = 'A'; break; /* DATA-FM */
- case RIG_MODE_FMN: mode_char = 'B'; break; /* FM-N */
- case RIG_MODE_PKTUSB: mode_char = 'C'; break; /* DATA-U */
- case RIG_MODE_AMN: mode_char = 'D'; break; /* AM-N */
- case RIG_MODE_PSK: mode_char = 'E'; break; /* PSK */
- default: mode_char = '2'; break; /* Default to USB */
+ switch (chan->mode)
+ {
+ case RIG_MODE_LSB: mode_char = '1'; break;
+ case RIG_MODE_USB: mode_char = '2'; break;
+ case RIG_MODE_CW: mode_char = '3'; break; /* CW-U */
+ case RIG_MODE_FM: mode_char = '4'; break;
+ case RIG_MODE_AM: mode_char = '5'; break;
+ case RIG_MODE_RTTYR: mode_char = '6'; break; /* RTTY-L */
+ case RIG_MODE_CWR: mode_char = '7'; break; /* CW-L */
+ case RIG_MODE_PKTLSB: mode_char = '8'; break; /* DATA-L */
+ case RIG_MODE_RTTY: mode_char = '9'; break; /* RTTY-U */
+ case RIG_MODE_PKTFM: mode_char = 'A'; break; /* DATA-FM */
+ case RIG_MODE_FMN: mode_char = 'B'; break; /* FM-N */
+ case RIG_MODE_PKTUSB: mode_char = 'C'; break; /* DATA-U */
+ case RIG_MODE_AMN: mode_char = 'D'; break; /* AM-N */
+ case RIG_MODE_PSK: mode_char = 'E'; break; /* PSK */
+ default:
+ rig_debug(RIG_DEBUG_ERR, "%s: unsupported mode %s\n",
+ __func__, rig_strrmode(chan->mode));
+ return -RIG_EINVAL;
}
- /* Clarifier direction and offset */
- if (chan->rit != 0) {
- clar_dir = (chan->rit >= 0) ? '+' : '-';
- clar_offset = labs(chan->rit);
- if (clar_offset > 9990) clar_offset = 9990;
- } else if (chan->xit != 0) {
- clar_dir = (chan->xit >= 0) ? '+' : '-';
- clar_offset = labs(chan->xit);
- if (clar_offset > 9990) clar_offset = 9990;
- } else {
- clar_dir = '+';
- clar_offset = 0;
+ is_fm_family = (chan->mode == RIG_MODE_FM || chan->mode == RIG_MODE_FMN
+ || chan->mode == RIG_MODE_PKTFM || chan->mode == RIG_MODE_PKTFMN);
+
+ /* Snapshot VFO-B state for best-effort restore on exit. Responses
+ * (FB%09d; and MD1%c;) are already valid set commands and can be
+ * replayed verbatim. If the query fails, the saved_* buffer stays
+ * empty and restore is skipped. */
+ SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "FB;");
+ if (newcat_get_cmd(rig) == RIG_OK)
+ {
+ strncpy(saved_fb, priv->ret_data, sizeof(saved_fb) - 1);
+ }
+ SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "MD1;");
+ if (newcat_get_cmd(rig) == RIG_OK)
+ {
+ strncpy(saved_md1, priv->ret_data, sizeof(saved_md1) - 1);
}
- /* P7: VFO/Memory mode - default to Memory (1) when writing to channel */
- p7_vfo_mem = 1;
+ /* 1. Point the MC cursor at the target slot. Returns '?;' when the
+ * slot is unprogrammed, but the cursor still updates for BM. */
+ SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "MC%06d;",
+ chan->channel_num);
+ (void)newcat_set_cmd(rig);
+
+ /* 2. Force VFO mode. Must be the 6-char form — extra digits are
+ * rejected by firmware. */
+ SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "VM000;");
+ (void)newcat_set_cmd(rig);
+
+ /* 3a. Program VFO-B frequency. */
+ SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "FB%09.0f;", chan->freq);
+ err = newcat_set_cmd(rig);
+ if (err != RIG_OK) goto restore;
+
+ /* 3b. Program VFO-B mode. */
+ SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "MD1%c;", mode_char);
+ err = newcat_set_cmd(rig);
+ if (err != RIG_OK) goto restore;
+
+ /* 3c. FM-family channels: program CTCSS/DCS and repeater shift.
+ * CT, CN (P2=1), and OS commands only function in FM mode, so
+ * non-FM channels skip this block entirely. */
+ if (is_fm_family)
+ {
+ int os_mode;
+
+ if (chan->dcs_code != 0)
+ {
+ /* DCS: select CT mode 3, then program code via CN P2=1.
+ * (The DC command is firmware-broken — use CN instead.) */
+ SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "CT13;");
+ (void)newcat_set_cmd(rig);
+
+ SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "CN11%03u;",
+ chan->dcs_code);
+ (void)newcat_set_cmd(rig);
+ }
+ else if (chan->ctcss_tone != 0)
+ {
+ /* CTCSS: TSQ when both encode and squelch tones are set,
+ * else ENC only. CN P2=0 programs the tone index. */
+ int ct_mode = (chan->ctcss_sql != 0)
+ ? FTX1_CTCSS_MODE_TSQ
+ : FTX1_CTCSS_MODE_ENC;
+ int tone_num = ftx1_freq_to_tone_num(chan->ctcss_tone);
+
+ SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str),
+ "CT1%d;", ct_mode);
+ (void)newcat_set_cmd(rig);
+
+ if (tone_num >= 0)
+ {
+ SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str),
+ "CN10%03d;", tone_num);
+ (void)newcat_set_cmd(rig);
+ }
+ }
+ else
+ {
+ /* Explicit CT OFF in case VFO-B was previously configured
+ * with a tone. */
+ SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "CT10;");
+ (void)newcat_set_cmd(rig);
+ }
- /* P8: CTCSS mode from channel flags */
- p8_ctcss = 0; /* Default OFF */
- if (chan->flags & RIG_CHFLAG_SKIP) {
- /* Use flags for tone squelch indication if available */
- }
- /* Check tone settings */
- if (chan->ctcss_tone != 0 && chan->ctcss_sql != 0) {
- p8_ctcss = 1; /* CTCSS ENC/DEC */
- } else if (chan->ctcss_tone != 0) {
- p8_ctcss = 2; /* CTCSS ENC only */
- } else if (chan->dcs_code != 0) {
- p8_ctcss = 3; /* DCS */
+ switch (chan->rptr_shift)
+ {
+ case RIG_RPT_SHIFT_PLUS: os_mode = 1; break;
+ case RIG_RPT_SHIFT_MINUS: os_mode = 2; break;
+ default: os_mode = 0; break; /* simplex */
+ }
+ SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "OS1%d;", os_mode);
+ (void)newcat_set_cmd(rig);
}
- /* P10: Repeater shift */
- switch (chan->rptr_shift) {
- case RIG_RPT_SHIFT_PLUS: p10_shift = 1; break;
- case RIG_RPT_SHIFT_MINUS: p10_shift = 2; break;
- default: p10_shift = 0; break; /* Simplex */
+ /* 4. Commit VFO-B to the last-selected memory channel. */
+ SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "BM;");
+ err = newcat_set_cmd(rig);
+
+restore:
+ /* Best-effort restore of VFO-B state. Restore failures are not
+ * surfaced — the caller cares about the write's status, not the
+ * side-effect cleanup. */
+ if (saved_fb[0] != '\0')
+ {
+ SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "%s", saved_fb);
+ (void)newcat_set_cmd(rig);
+ }
+ if (saved_md1[0] != '\0')
+ {
+ SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "%s", saved_md1);
+ (void)newcat_set_cmd(rig);
}
- /* Build MW command string:
- * MW P1P1P1P1P1 P2P2P2P2P2P2P2P2P2 P3P3P3P3P3 P4 P5 P6 P7 P8 P9P9 P10;
- * Total: 2 + 5 + 9 + 5 + 1 + 1 + 1 + 1 + 1 + 2 + 1 + 1 = 30 chars
- */
- SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str),
- "MW%05d%09.0f%c%04d%d%d%c%d%d00%d;",
- chan->channel_num, /* P1: 5-digit channel */
- chan->freq, /* P2: 9-digit frequency in Hz */
- clar_dir, /* P3: clarifier direction */
- clar_offset, /* P3: clarifier offset */
- (chan->rit != 0) ? 1 : 0, /* P4: RX CLAR on/off */
- (chan->xit != 0) ? 1 : 0, /* P5: TX CLAR on/off */
- mode_char, /* P6: mode code */
- p7_vfo_mem, /* P7: VFO/Memory mode */
- p8_ctcss, /* P8: CTCSS mode */
- /* P9: "00" (fixed) */
- p10_shift); /* P10: shift */
-
- rig_debug(RIG_DEBUG_VERBOSE, "%s: cmd='%s'\n", __func__, priv->cmd_str);
-
- return newcat_set_cmd(rig);
+ return err;
}
/*
-----------------------------------------------------------------------
Summary of changes:
rigs/yaesu/ftx1/ftx1.c | 40 +++-
rigs/yaesu/ftx1/ftx1.h | 14 ++
rigs/yaesu/ftx1/ftx1_ctcss.c | 18 +-
rigs/yaesu/ftx1/ftx1_freq.c | 8 +
rigs/yaesu/ftx1/ftx1_mem.c | 504 +++++++++++++++++++++++++++++++++----------
rigs/yaesu/ftx1/ftx1_mode.c | 21 +-
rigs/yaesu/newcat.h | 1 +
7 files changed, 489 insertions(+), 117 deletions(-)
hooks/post-receive
--
Hamlib -- Ham radio control libraries
|
|
From: n0nb <n0...@us...> - 2026-04-15 20:34:29
|
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 annotated tag, 4.7.1 has been created
at a0f5ce64de6ecd9e45fbc59ce93ba9f8f5882766 (tag)
tagging d042479a9f8095ba1a8e103a977c3614d7233cb2 (commit)
replaces 4.7.0
tagged by Nate Bargmann
on Wed Apr 15 15:31:21 2026 -0500
- Log -----------------------------------------------------------------
Hamlib 4.7.1 release
-----BEGIN PGP SIGNATURE-----
iF0EABECAB0WIQSC1k9rDmfNQfaJu6b7LFEw1VqIGQUCad/1pQAKCRD7LFEw1VqI
Gbe/AKCXLcPo4/EJRR+iyo+c72pFe6DPewCeLPJs4imUYEBb/ffeDztjhZiJ4PA=
=YSe9
-----END PGP SIGNATURE-----
Bradford D. Boyle (1):
Fix various unknown type compilation errors
Dhiru Kholia (1):
Add support for rigs using the 'Simple CAT' protocol
Elisamuel Resto (1):
kenwood: add get_split_vfo to TS-850 backend
George Baltz N3GB (16):
Add support text from release email to RelNotes
Include Release Notes in tarball
Rel notes update
Avoid warnings from gcc-16
Add generalized routines for Icom clock handling
First uses of icom_[gs]et_clock
Fixes for IC-705 and IC-905
Tidy up more Icom rigs.
Clean up IC-7000, IC-7100, and IC-9100
Update IC-9700
Fix attenuator limit in level_gran_yaesu.h
Fix some obvious errors in newcat.c
Make sure simft710.c rejects RF command
Use the correct SH command in newcat_set_rx_bandwidth() and simft710.c
Fix FT-710 newcat_get_rx_bandwidth()
Fix compiler warning
KJ5HST (15):
fix: correct RM meter command codes for FTX-1 driver (Bug 1.2)
fix: correct CTCSS tone table missing 4 tones and shifted indices (Bug 1.1)
fix: apply calibration to STRENGTH level instead of returning raw value (Bug 2.3)
fix: convert VOXDELAY between Hamlib tenths-of-seconds and VD codes (Bug 2.1)
fix: convert BKINDL between Hamlib tenths-of-dots and SD codes (Bug 2.2)
fix: correct FBKIN/SBKIN break-in mode detection and control (Bug 1.3)
fix: restore VD_METER and ID_METER to FTX-1 rig caps
fix: add RFPOWER_METER, RFPOWER_METER_WATTS, and COMP_METER to FTX-1 rig caps
fix: close 4 Hamlib coverage gaps in FTX-1 driver
fix: correct NR level range and SH width documentation per CAT manual
fix: correct MS meter switch mapping for FTX-1
fix: add meter calibration tables for SWR, ALC, COMP, VD, and ID meters
fix: use calibration tables for SWR and ALC meter scaling
fix: eliminate clarifier read-then-write race condition (Bug 3.1)
ftx1: wire SH bandwidth command into set_mode/get_mode (#2027)
Matthias Moeller (1):
Initialize rp->timeout in rig_init
Nate Bargmann (23):
Advance to 4.7.1~rc
Merge GitHub PR #1995
Update NEWS--type error fix
Update NEWS for rig port fix
Update NEWS for updated ReleaseNotes*.md
Update NEWS for FTX-1 fixes
Update NEWS for Flrig power off & GCC 16 warning
Add RIG_LEVEL_SWR to K3_LEVEL_ALL
Update NEWS for K3/K4 added SWR level support
Update NEWS for adding TS-850 get_split_vfo
Quell warning from MinGW; update NEWS for simplecat
Update NEWS for Icom and Yaesu fixes
Fixes to PR #2028
Update NEWS to add new rig model PRC-138
Add RIG_MODEL_PRC138 to test_Hamlib_class.py
Update NEWS for FT-710 fixes
Fix RF Power output reading in low power mode
Update NEWS for K3/K3S low power calculation fix
Update NEWS for FTX-1 bandwisth fixes
Quell clang warning on Debian Stable
Update NEWS for quelling clang warning
Update NEWS for additional warning fix
Hamlib 4.7.1 release
Phil GM3ZZA (1):
Add Power Off to Flrig backend
Rega57 (4):
Add support for Harris PRC-138
Update harris.c
Initial comment with GPL added
Warning fixed long long
-----------------------------------------------------------------------
hooks/post-receive
--
Hamlib -- Ham radio control libraries
|
|
From: n0nb <n0...@us...> - 2026-04-15 20:33:27
|
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, Hamlib-4.7 has been updated
via d042479a9f8095ba1a8e103a977c3614d7233cb2 (commit)
from b173cab3bc3cbe9afe264beca620d4fab0c6a43c (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 d042479a9f8095ba1a8e103a977c3614d7233cb2
Author: Nate Bargmann <n0...@n0...>
Date: Wed Apr 15 15:20:01 2026 -0500
Hamlib 4.7.1 release
diff --git a/configure.ac b/configure.ac
index 8432154e1..26614d46d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -14,7 +14,7 @@ dnl Please do not use '-' in the version number, as package managers will fail,
dnl however, the use of '~' should be fine as apt (others?) will treat
dnl it as an earlier version than the actual release. TNX KA6MAL
dnl PACKAGE_NAME + " " + PACKAGE_VERSION must not exceed 20 chars!
-AC_INIT([Hamlib],[4.7.1~rc],[ham...@li...],[hamlib],[http://www.hamlib.org])
+AC_INIT([Hamlib],[4.7.1],[ham...@li...],[hamlib],[http://www.hamlib.org])
#AC_INIT([PRODUCT_NAME], [Hamlib])
#AC_DEFINE([Hamlib], [PRODUCT_VERSION_RESOURCE])
-----------------------------------------------------------------------
Summary of changes:
configure.ac | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
hooks/post-receive
--
Hamlib -- Ham radio control libraries
|
|
From: n0nb <n0...@us...> - 2026-04-15 03:21:31
|
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, Hamlib-4.7 has been updated
via b173cab3bc3cbe9afe264beca620d4fab0c6a43c (commit)
via d4b0eb2df80dcdac623e8f8a3cc41cc59c117caf (commit)
from 228e9461e2052315031d3ec412a54a78e495deb6 (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 b173cab3bc3cbe9afe264beca620d4fab0c6a43c
Author: Nate Bargmann <n0...@n0...>
Date: Tue Apr 14 22:19:47 2026 -0500
Update NEWS for additional warning fix
diff --git a/NEWS b/NEWS
index 87b214d8e..0b4490662 100644
--- a/NEWS
+++ b/NEWS
@@ -33,7 +33,8 @@ Version 4.7.1
Ensure FT-710 simulator rejects RF command. (TNX George Baltz)
* Fix low power calculation for K3/K3S. (N0NB)
* Fix FTX-1 SH bandwidth command in set/get_mode. (TNX Terrell Deppe)
- * Quell initializer overrides prior initialzation clang warning. (TNX George Baltz)
+ * Quell initializer overrides prior initialzation clang warning in ftx1.c
+ and fix compiler warning in hd1780.c. (TNX George Baltz)
Version 4.7.0
* 2026-02-15
commit d4b0eb2df80dcdac623e8f8a3cc41cc59c117caf
Author: George Baltz N3GB <Geo...@gm...>
Date: Tue Apr 14 14:31:51 2026 -0400
Fix compiler warning
(cherry picked from commit 1236b6991bbcb691aa0e3039396dd8e2ba4b5aff)
diff --git a/rotators/heathkit/hd1780.c b/rotators/heathkit/hd1780.c
index 3256b10c3..150a8cf51 100644
--- a/rotators/heathkit/hd1780.c
+++ b/rotators/heathkit/hd1780.c
@@ -169,7 +169,8 @@ static int hd1780_rot_set_position(ROT *rot, azimuth_t azimuth,
elevation_t elevation)
{
char cmdstr[8];
- const char execstr[5] = "\r", ok[3];
+ const char execstr[5] = "\r";
+ char ok[3];
int err;
rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
-----------------------------------------------------------------------
Summary of changes:
NEWS | 3 ++-
rotators/heathkit/hd1780.c | 3 ++-
2 files changed, 4 insertions(+), 2 deletions(-)
hooks/post-receive
--
Hamlib -- Ham radio control libraries
|
|
From: n0nb <n0...@us...> - 2026-04-15 03:16:41
|
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 9de702a452e4607b1834acd1e45baa624c3f5a9f (commit)
via 1236b6991bbcb691aa0e3039396dd8e2ba4b5aff (commit)
from 0a2b7f06dde00fda7344054ee23d92b942b19141 (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 9de702a452e4607b1834acd1e45baa624c3f5a9f
Merge: 0a2b7f06d 1236b6991
Author: Nate Bargmann <n0...@n0...>
Date: Tue Apr 14 21:04:46 2026 -0500
Merge GitHub PR 2033
commit 1236b6991bbcb691aa0e3039396dd8e2ba4b5aff
Author: George Baltz N3GB <Geo...@gm...>
Date: Tue Apr 14 14:31:51 2026 -0400
Fix compiler warning
diff --git a/rotators/heathkit/hd1780.c b/rotators/heathkit/hd1780.c
index 3256b10c3..150a8cf51 100644
--- a/rotators/heathkit/hd1780.c
+++ b/rotators/heathkit/hd1780.c
@@ -169,7 +169,8 @@ static int hd1780_rot_set_position(ROT *rot, azimuth_t azimuth,
elevation_t elevation)
{
char cmdstr[8];
- const char execstr[5] = "\r", ok[3];
+ const char execstr[5] = "\r";
+ char ok[3];
int err;
rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
-----------------------------------------------------------------------
Summary of changes:
rotators/heathkit/hd1780.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
hooks/post-receive
--
Hamlib -- Ham radio control libraries
|
|
From: n0nb <n0...@us...> - 2026-04-14 19:00: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, Hamlib-4.7 has been updated
via 228e9461e2052315031d3ec412a54a78e495deb6 (commit)
from 2fbcd70a04a48c8b2d6f1e8c0fe25c8a973da5d3 (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 228e9461e2052315031d3ec412a54a78e495deb6
Author: Nate Bargmann <n0...@n0...>
Date: Tue Apr 14 13:59:17 2026 -0500
Update NEWS for quelling clang warning
diff --git a/NEWS b/NEWS
index 67083b300..87b214d8e 100644
--- a/NEWS
+++ b/NEWS
@@ -33,6 +33,7 @@ Version 4.7.1
Ensure FT-710 simulator rejects RF command. (TNX George Baltz)
* Fix low power calculation for K3/K3S. (N0NB)
* Fix FTX-1 SH bandwidth command in set/get_mode. (TNX Terrell Deppe)
+ * Quell initializer overrides prior initialzation clang warning. (TNX George Baltz)
Version 4.7.0
* 2026-02-15
-----------------------------------------------------------------------
Summary of changes:
NEWS | 1 +
1 file changed, 1 insertion(+)
hooks/post-receive
--
Hamlib -- Ham radio control libraries
|
|
From: n0nb <n0...@us...> - 2026-04-14 18:55:11
|
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 0a2b7f06dde00fda7344054ee23d92b942b19141 (commit)
from b429b2a35b76ef7bdbae4ca12a44ec5289720f20 (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 0a2b7f06dde00fda7344054ee23d92b942b19141
Author: Nate Bargmann <n0...@n0...>
Date: Tue Apr 14 13:42:09 2026 -0500
Quell clang warning on Debian Stable
The clang compiler generated the following warning on Debian Stable
(13):
CC ftx1/ftx1.lo
../../../hamlib/rigs/yaesu/ftx1/ftx1.c:1020:24: warning: initializer overrides prior initialization of this subobject [-Winitializer-overrides]
1020 | [LVL_KEYSPD] = { .min = { .i = 4 }, .max = { .i = 60 }, .step = { .i = 1 } },
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
../../../hamlib/rigs/yaesu/level_gran_yaesu.h:12:25: note: previous initialization is here
12 | [LVL_KEYSPD] = { .min = { .i = 4 }, .max = { .i = 60 }, .step = { .i = 1 } },
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1 warning generated.
Per George Baltz this should have generated a warning with GCC but did
not. Commenting for now "just in case".
(cherry picked from commit 2fbcd70a04a48c8b2d6f1e8c0fe25c8a973da5d3)
diff --git a/rigs/yaesu/ftx1/ftx1.c b/rigs/yaesu/ftx1/ftx1.c
index 176847dd6..a2bb45cc4 100644
--- a/rigs/yaesu/ftx1/ftx1.c
+++ b/rigs/yaesu/ftx1/ftx1.c
@@ -1017,7 +1017,7 @@ struct rig_caps ftx1_caps = {
/* CW pitch: FTX-1 KP command sets pitch 300-1050 Hz in 10Hz steps */
[LVL_CWPITCH] = { .min = { .i = 300 }, .max = { .i = 1050 }, .step = { .i = 10 } },
/* Key speed: FTX-1 uses 4-60 WPM */
- [LVL_KEYSPD] = { .min = { .i = 4 }, .max = { .i = 60 }, .step = { .i = 1 } },
+// [LVL_KEYSPD] = { .min = { .i = 4 }, .max = { .i = 60 }, .step = { .i = 1 } },
/* Break-in delay: Hamlib tenths-of-dots, range matches standard Yaesu gran */
[LVL_BKINDL] = { .min = { .i = 30 }, .max = { .i = 3000 }, .step = { .i = 1 } },
/* VOX delay: Hamlib uses tenths of seconds (0=0.0s to 300=30.0s) */
@@ -1222,4 +1222,4 @@ struct rig_caps ftx1_caps = {
.mW2power = newcat_mW2power,
.morse_qsize = 50,
.hamlib_check_rig_caps = HAMLIB_CHECK_RIG_CAPS
-};
\ No newline at end of file
+};
-----------------------------------------------------------------------
Summary of changes:
rigs/yaesu/ftx1/ftx1.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
hooks/post-receive
--
Hamlib -- Ham radio control libraries
|
|
From: n0nb <n0...@us...> - 2026-04-14 18:46:30
|
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, Hamlib-4.7 has been updated
via 2fbcd70a04a48c8b2d6f1e8c0fe25c8a973da5d3 (commit)
from b234d789d18a938b4801a4aa9969522011ddf21c (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 2fbcd70a04a48c8b2d6f1e8c0fe25c8a973da5d3
Author: Nate Bargmann <n0...@n0...>
Date: Tue Apr 14 13:42:09 2026 -0500
Quell clang warning on Debian Stable
The clang compiler generated the following warning on Debian Stable
(13):
CC ftx1/ftx1.lo
../../../hamlib/rigs/yaesu/ftx1/ftx1.c:1020:24: warning: initializer overrides prior initialization of this subobject [-Winitializer-overrides]
1020 | [LVL_KEYSPD] = { .min = { .i = 4 }, .max = { .i = 60 }, .step = { .i = 1 } },
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
../../../hamlib/rigs/yaesu/level_gran_yaesu.h:12:25: note: previous initialization is here
12 | [LVL_KEYSPD] = { .min = { .i = 4 }, .max = { .i = 60 }, .step = { .i = 1 } },
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1 warning generated.
Per George Baltz this should have generated a warning with GCC but did
not. Commenting for now "just in case".
diff --git a/rigs/yaesu/ftx1/ftx1.c b/rigs/yaesu/ftx1/ftx1.c
index 176847dd6..a2bb45cc4 100644
--- a/rigs/yaesu/ftx1/ftx1.c
+++ b/rigs/yaesu/ftx1/ftx1.c
@@ -1017,7 +1017,7 @@ struct rig_caps ftx1_caps = {
/* CW pitch: FTX-1 KP command sets pitch 300-1050 Hz in 10Hz steps */
[LVL_CWPITCH] = { .min = { .i = 300 }, .max = { .i = 1050 }, .step = { .i = 10 } },
/* Key speed: FTX-1 uses 4-60 WPM */
- [LVL_KEYSPD] = { .min = { .i = 4 }, .max = { .i = 60 }, .step = { .i = 1 } },
+// [LVL_KEYSPD] = { .min = { .i = 4 }, .max = { .i = 60 }, .step = { .i = 1 } },
/* Break-in delay: Hamlib tenths-of-dots, range matches standard Yaesu gran */
[LVL_BKINDL] = { .min = { .i = 30 }, .max = { .i = 3000 }, .step = { .i = 1 } },
/* VOX delay: Hamlib uses tenths of seconds (0=0.0s to 300=30.0s) */
@@ -1222,4 +1222,4 @@ struct rig_caps ftx1_caps = {
.mW2power = newcat_mW2power,
.morse_qsize = 50,
.hamlib_check_rig_caps = HAMLIB_CHECK_RIG_CAPS
-};
\ No newline at end of file
+};
-----------------------------------------------------------------------
Summary of changes:
rigs/yaesu/ftx1/ftx1.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
hooks/post-receive
--
Hamlib -- Ham radio control libraries
|
|
From: n0nb <n0...@us...> - 2026-04-14 01:51:44
|
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, Hamlib-4.7 has been updated
via b234d789d18a938b4801a4aa9969522011ddf21c (commit)
via 7932d4b59e893e20814c099f960d81dac44240df (commit)
from 037a3e232e5cd1425d4ea5a2539072010a44df36 (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 b234d789d18a938b4801a4aa9969522011ddf21c
Author: Nate Bargmann <n0...@n0...>
Date: Mon Apr 13 20:50:44 2026 -0500
Update NEWS for FTX-1 bandwisth fixes
diff --git a/NEWS b/NEWS
index c989f7997..67083b300 100644
--- a/NEWS
+++ b/NEWS
@@ -32,6 +32,7 @@ Version 4.7.1
* Various FT-710 fixes, eespecially handling SH format and RX bandwidth.
Ensure FT-710 simulator rejects RF command. (TNX George Baltz)
* Fix low power calculation for K3/K3S. (N0NB)
+ * Fix FTX-1 SH bandwidth command in set/get_mode. (TNX Terrell Deppe)
Version 4.7.0
* 2026-02-15
commit 7932d4b59e893e20814c099f960d81dac44240df
Author: KJ5HST <kj...@de...>
Date: Mon Apr 13 10:02:46 2026 -0400
ftx1: wire SH bandwidth command into set_mode/get_mode (#2027)
The FTX-1 driver delegates mode handling to newcat_set_mode /
newcat_get_mode, which previously had no FTX-1 branch in the
bandwidth helpers. Effects:
* rig_get_mode always returned passband=0 for the FTX-1
* rig_set_mode silently dropped the width argument
Add dedicated is_ftx1 branches to newcat_set_rx_bandwidth and
newcat_get_rx_bandwidth, and extend the SH command-string builder
to emit the 7-char SH00NN; form for FTX-1.
The bandwidth table is per FTX-1 CAT Operation Reference Manual
Table 5 (doc 2508-C). It is deliberately kept separate from the
FT-710 / FTDX10 branch because the SSB column diverges at codes
12/13/14: FTX-1 uses 2250/2400/2450 Hz where FT-710 uses
2200/2300/2400 Hz. Sharing the branch would silently misreport
2400 Hz on the FTX-1 -- exactly the canonical SSB filter.
PSK is included in the CW/DATA/RTTY case group because Table 5
groups it there, and live probing of firmware v1.12 confirmed PSK
mode defaults to SH code 19 (the DATA default) rather than an SSB
code.
Verified end-to-end against a live FTX-1 (fw v1.12) at 115200 bps:
USB 2400/2700/2250/2450/3000, CW 500/2400, PKTUSB 3000, AM 9000,
FM 16000 all round-trip correctly through rig_set_mode /
rig_get_mode, with raw-CAT SH reads confirming the corrected code
mapping (2250->SH12, 2400->SH13, 2450->SH14).
(cherry picked from commit b429b2a35b76ef7bdbae4ca12a44ec5289720f20)
diff --git a/rigs/yaesu/newcat.c b/rigs/yaesu/newcat.c
index 10d040324..b86bc5232 100644
--- a/rigs/yaesu/newcat.c
+++ b/rigs/yaesu/newcat.c
@@ -9411,6 +9411,107 @@ int newcat_set_rx_bandwidth(RIG *rig, vfo_t vfo, rmode_t mode, pbwidth_t width)
RETURNFUNC(RIG_OK);
}
} // end is_ftdx101d || is_ftdx101mp || is_ftdx10 || is_ft710
+ else if (is_ftx1)
+ {
+ // Bandwidth table per FTX-1 CAT Operation Reference Manual Table 5
+ // (doc 2508-C). Differs from the FT-710/FTDX10 table at SSB codes
+ // 12/13/14 (2250/2400/2450 Hz vs 2200/2300/2400), so do not merge.
+ switch (mode)
+ {
+ case RIG_MODE_PKTUSB:
+ case RIG_MODE_PKTLSB:
+ case RIG_MODE_RTTY:
+ case RIG_MODE_RTTYR:
+ case RIG_MODE_CW:
+ case RIG_MODE_CWR:
+ case RIG_MODE_PSK:
+ 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; }
+ else if (width <= 200) { w = 4; }
+ else if (width <= 250) { w = 5; }
+ else if (width <= 300) { w = 6; }
+ else if (width <= 350) { w = 7; }
+ else if (width <= 400) { w = 8; }
+ else if (width <= 450) { w = 9; }
+ else if (width <= 500) { w = 10; }
+ else if (width <= 600) { w = 11; }
+ else if (width <= 800) { w = 12; }
+ else if (width <= 1200) { w = 13; }
+ else if (width <= 1400) { w = 14; }
+ else if (width <= 1700) { w = 15; }
+ else if (width <= 2000) { w = 16; }
+ else if (width <= 2400) { w = 17; }
+ else if (width <= 3000) { w = 18; }
+ else if (width <= 3200) { w = 19; }
+ else if (width <= 3500) { w = 20; }
+ else { w = 21; } // 4000 Hz
+
+ break;
+
+ case RIG_MODE_LSB:
+ case RIG_MODE_USB:
+ 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; }
+ else if (width <= 850) { w = 4; }
+ else if (width <= 1100) { w = 5; }
+ else if (width <= 1200) { w = 6; }
+ else if (width <= 1500) { w = 7; }
+ else if (width <= 1650) { w = 8; }
+ else if (width <= 1800) { w = 9; }
+ else if (width <= 1950) { w = 10; }
+ else if (width <= 2100) { w = 11; }
+ else if (width <= 2250) { w = 12; }
+ else if (width <= 2400) { w = 13; }
+ else if (width <= 2450) { w = 14; }
+ else if (width <= 2500) { w = 15; }
+ else if (width <= 2600) { w = 16; }
+ else if (width <= 2700) { w = 17; }
+ else if (width <= 2800) { w = 18; }
+ else if (width <= 2900) { w = 19; }
+ else if (width <= 3000) { w = 20; }
+ else if (width <= 3200) { w = 21; }
+ else if (width <= 3500) { w = 22; }
+ else { w = 23; } // 4000 Hz
+
+ break;
+
+ case RIG_MODE_AM:
+ case RIG_MODE_AMN:
+ case RIG_MODE_FM:
+ case RIG_MODE_PKTFM:
+ case RIG_MODE_FMN:
+ // Fixed-width per Table 5; handled by narrow-mode toggle below.
+ break;
+
+ default:
+ RETURNFUNC(-RIG_EINVAL);
+ } // end switch(mode)
+
+ switch (mode)
+ {
+ case RIG_MODE_AM:
+ case RIG_MODE_FM:
+ case RIG_MODE_PKTFM:
+ if (width > 0 && width < rig_passband_normal(rig, mode))
+ {
+ err = newcat_set_narrow(rig, vfo, TRUE);
+ }
+ else
+ {
+ err = newcat_set_narrow(rig, vfo, FALSE);
+ }
+
+ RETURNFUNC(err);
+
+ case RIG_MODE_AMN:
+ case RIG_MODE_FMN:
+ RETURNFUNC(RIG_OK);
+ }
+ } // end is_ftx1
else if (is_ft2000)
{
// We need details on the widths here, manuals lack information.
@@ -9565,7 +9666,7 @@ int newcat_set_rx_bandwidth(RIG *rig, vfo_t vfo, rmode_t mode, pbwidth_t width)
{
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "SH0%02d;", w);
}
- else if (is_ftdx10 || is_ft710)
+ else if (is_ftdx10 || is_ft710 || is_ftx1)
{
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "SH00%02d;", w);
}
@@ -10727,6 +10828,160 @@ int newcat_get_rx_bandwidth(RIG *rig, vfo_t vfo, rmode_t mode, pbwidth_t *width)
rig_debug(RIG_DEBUG_TRACE, "%s: end if FTDX101D\n", __func__);
} /* end if is_ftdx101d || is_ftdx101mp || is_ftdx10 || is_ft710 */
+ else if (is_ftx1)
+ {
+ // Bandwidth table per FTX-1 CAT Operation Reference Manual Table 5
+ // (doc 2508-C). Differs from FT-710/FTDX10 at SSB codes 12/13/14.
+ rig_debug(RIG_DEBUG_TRACE, "%s: is_ftx1 w=%d, mode=%s\n", __func__, w,
+ rig_strrmode(mode));
+
+ if (w == 0) // default: fall back to the mode's normal passband
+ {
+ *width = rig_passband_normal(rig, mode);
+ }
+
+ switch (mode)
+ {
+ case RIG_MODE_PKTUSB:
+ case RIG_MODE_PKTLSB:
+ case RIG_MODE_RTTY:
+ case RIG_MODE_RTTYR:
+ case RIG_MODE_CW:
+ case RIG_MODE_CWR:
+ case RIG_MODE_PSK:
+ switch (w)
+ {
+ case 0: break; /* default */
+
+ case 1: *width = 50; break;
+
+ case 2: *width = 100; break;
+
+ case 3: *width = 150; break;
+
+ case 4: *width = 200; break;
+
+ case 5: *width = 250; break;
+
+ case 6: *width = 300; break;
+
+ case 7: *width = 350; break;
+
+ case 8: *width = 400; break;
+
+ case 9: *width = 450; break;
+
+ case 10: *width = 500; break;
+
+ case 11: *width = 600; break;
+
+ case 12: *width = 800; break;
+
+ case 13: *width = 1200; break;
+
+ case 14: *width = 1400; break;
+
+ case 15: *width = 1700; break;
+
+ case 16: *width = 2000; break;
+
+ case 17: *width = 2400; break;
+
+ case 18: *width = 3000; break;
+
+ case 19: *width = 3200; break;
+
+ case 20: *width = 3500; break;
+
+ case 21: *width = 4000; break;
+
+ default:
+ RETURNFUNC(-RIG_EINVAL);
+ }
+
+ break;
+
+ case RIG_MODE_LSB:
+ case RIG_MODE_USB:
+ switch (w)
+ {
+ case 0: break; /* default */
+
+ case 1: *width = 300; break;
+
+ case 2: *width = 400; break;
+
+ case 3: *width = 600; break;
+
+ case 4: *width = 850; break;
+
+ case 5: *width = 1100; break;
+
+ case 6: *width = 1200; break;
+
+ case 7: *width = 1500; break;
+
+ case 8: *width = 1650; break;
+
+ case 9: *width = 1800; break;
+
+ case 10: *width = 1950; break;
+
+ case 11: *width = 2100; break;
+
+ case 12: *width = 2250; break;
+
+ case 13: *width = 2400; break;
+
+ case 14: *width = 2450; break;
+
+ case 15: *width = 2500; break;
+
+ case 16: *width = 2600; break;
+
+ case 17: *width = 2700; break;
+
+ case 18: *width = 2800; break;
+
+ case 19: *width = 2900; break;
+
+ case 20: *width = 3000; break;
+
+ case 21: *width = 3200; break;
+
+ case 22: *width = 3500; break;
+
+ case 23: *width = 4000; break;
+
+ default:
+ rig_debug(RIG_DEBUG_ERR, "%s: unknown width=%d\n", __func__, w);
+ RETURNFUNC(-RIG_EINVAL);
+ }
+
+ break;
+
+ case RIG_MODE_AM:
+ case RIG_MODE_FMN:
+ case RIG_MODE_PKTFMN:
+ *width = 9000;
+ break;
+
+ case RIG_MODE_AMN:
+ *width = 6000;
+ break;
+
+ case RIG_MODE_FM:
+ case RIG_MODE_PKTFM:
+ *width = 16000;
+ break;
+
+ default:
+ rig_debug(RIG_DEBUG_TRACE, "%s: bad mode\n", __func__);
+ RETURNFUNC(-RIG_EINVAL);
+ } /* end switch(mode) */
+
+ rig_debug(RIG_DEBUG_TRACE, "%s: end if is_ftx1\n", __func__);
+ } /* end if is_ftx1 */
else if (is_ft2000)
{
if ((narrow = get_narrow(rig, RIG_VFO_MAIN)) < 0)
-----------------------------------------------------------------------
Summary of changes:
NEWS | 1 +
rigs/yaesu/newcat.c | 257 +++++++++++++++++++++++++++++++++++++++++++++++++++-
2 files changed, 257 insertions(+), 1 deletion(-)
hooks/post-receive
--
Hamlib -- Ham radio control libraries
|
|
From: n0nb <n0...@us...> - 2026-04-14 01:16:40
|
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 b429b2a35b76ef7bdbae4ca12a44ec5289720f20 (commit)
from 01494a0c0d9011457d5e61c586d364ecf7d85e73 (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 b429b2a35b76ef7bdbae4ca12a44ec5289720f20
Author: KJ5HST <kj...@de...>
Date: Mon Apr 13 10:02:46 2026 -0400
ftx1: wire SH bandwidth command into set_mode/get_mode (#2027)
The FTX-1 driver delegates mode handling to newcat_set_mode /
newcat_get_mode, which previously had no FTX-1 branch in the
bandwidth helpers. Effects:
* rig_get_mode always returned passband=0 for the FTX-1
* rig_set_mode silently dropped the width argument
Add dedicated is_ftx1 branches to newcat_set_rx_bandwidth and
newcat_get_rx_bandwidth, and extend the SH command-string builder
to emit the 7-char SH00NN; form for FTX-1.
The bandwidth table is per FTX-1 CAT Operation Reference Manual
Table 5 (doc 2508-C). It is deliberately kept separate from the
FT-710 / FTDX10 branch because the SSB column diverges at codes
12/13/14: FTX-1 uses 2250/2400/2450 Hz where FT-710 uses
2200/2300/2400 Hz. Sharing the branch would silently misreport
2400 Hz on the FTX-1 -- exactly the canonical SSB filter.
PSK is included in the CW/DATA/RTTY case group because Table 5
groups it there, and live probing of firmware v1.12 confirmed PSK
mode defaults to SH code 19 (the DATA default) rather than an SSB
code.
Verified end-to-end against a live FTX-1 (fw v1.12) at 115200 bps:
USB 2400/2700/2250/2450/3000, CW 500/2400, PKTUSB 3000, AM 9000,
FM 16000 all round-trip correctly through rig_set_mode /
rig_get_mode, with raw-CAT SH reads confirming the corrected code
mapping (2250->SH12, 2400->SH13, 2450->SH14).
diff --git a/rigs/yaesu/newcat.c b/rigs/yaesu/newcat.c
index f73512195..68e3f4adb 100644
--- a/rigs/yaesu/newcat.c
+++ b/rigs/yaesu/newcat.c
@@ -9413,6 +9413,107 @@ int newcat_set_rx_bandwidth(RIG *rig, vfo_t vfo, rmode_t mode, pbwidth_t width)
RETURNFUNC(RIG_OK);
}
} // end is_ftdx101d || is_ftdx101mp || is_ftdx10 || is_ft710
+ else if (is_ftx1)
+ {
+ // Bandwidth table per FTX-1 CAT Operation Reference Manual Table 5
+ // (doc 2508-C). Differs from the FT-710/FTDX10 table at SSB codes
+ // 12/13/14 (2250/2400/2450 Hz vs 2200/2300/2400), so do not merge.
+ switch (mode)
+ {
+ case RIG_MODE_PKTUSB:
+ case RIG_MODE_PKTLSB:
+ case RIG_MODE_RTTY:
+ case RIG_MODE_RTTYR:
+ case RIG_MODE_CW:
+ case RIG_MODE_CWR:
+ case RIG_MODE_PSK:
+ 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; }
+ else if (width <= 200) { w = 4; }
+ else if (width <= 250) { w = 5; }
+ else if (width <= 300) { w = 6; }
+ else if (width <= 350) { w = 7; }
+ else if (width <= 400) { w = 8; }
+ else if (width <= 450) { w = 9; }
+ else if (width <= 500) { w = 10; }
+ else if (width <= 600) { w = 11; }
+ else if (width <= 800) { w = 12; }
+ else if (width <= 1200) { w = 13; }
+ else if (width <= 1400) { w = 14; }
+ else if (width <= 1700) { w = 15; }
+ else if (width <= 2000) { w = 16; }
+ else if (width <= 2400) { w = 17; }
+ else if (width <= 3000) { w = 18; }
+ else if (width <= 3200) { w = 19; }
+ else if (width <= 3500) { w = 20; }
+ else { w = 21; } // 4000 Hz
+
+ break;
+
+ case RIG_MODE_LSB:
+ case RIG_MODE_USB:
+ 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; }
+ else if (width <= 850) { w = 4; }
+ else if (width <= 1100) { w = 5; }
+ else if (width <= 1200) { w = 6; }
+ else if (width <= 1500) { w = 7; }
+ else if (width <= 1650) { w = 8; }
+ else if (width <= 1800) { w = 9; }
+ else if (width <= 1950) { w = 10; }
+ else if (width <= 2100) { w = 11; }
+ else if (width <= 2250) { w = 12; }
+ else if (width <= 2400) { w = 13; }
+ else if (width <= 2450) { w = 14; }
+ else if (width <= 2500) { w = 15; }
+ else if (width <= 2600) { w = 16; }
+ else if (width <= 2700) { w = 17; }
+ else if (width <= 2800) { w = 18; }
+ else if (width <= 2900) { w = 19; }
+ else if (width <= 3000) { w = 20; }
+ else if (width <= 3200) { w = 21; }
+ else if (width <= 3500) { w = 22; }
+ else { w = 23; } // 4000 Hz
+
+ break;
+
+ case RIG_MODE_AM:
+ case RIG_MODE_AMN:
+ case RIG_MODE_FM:
+ case RIG_MODE_PKTFM:
+ case RIG_MODE_FMN:
+ // Fixed-width per Table 5; handled by narrow-mode toggle below.
+ break;
+
+ default:
+ RETURNFUNC(-RIG_EINVAL);
+ } // end switch(mode)
+
+ switch (mode)
+ {
+ case RIG_MODE_AM:
+ case RIG_MODE_FM:
+ case RIG_MODE_PKTFM:
+ if (width > 0 && width < rig_passband_normal(rig, mode))
+ {
+ err = newcat_set_narrow(rig, vfo, TRUE);
+ }
+ else
+ {
+ err = newcat_set_narrow(rig, vfo, FALSE);
+ }
+
+ RETURNFUNC(err);
+
+ case RIG_MODE_AMN:
+ case RIG_MODE_FMN:
+ RETURNFUNC(RIG_OK);
+ }
+ } // end is_ftx1
else if (is_ft2000)
{
// We need details on the widths here, manuals lack information.
@@ -9567,7 +9668,7 @@ int newcat_set_rx_bandwidth(RIG *rig, vfo_t vfo, rmode_t mode, pbwidth_t width)
{
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "SH0%02d;", w);
}
- else if (is_ftdx10 || is_ft710)
+ else if (is_ftdx10 || is_ft710 || is_ftx1)
{
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "SH00%02d;", w);
}
@@ -10729,6 +10830,160 @@ int newcat_get_rx_bandwidth(RIG *rig, vfo_t vfo, rmode_t mode, pbwidth_t *width)
rig_debug(RIG_DEBUG_TRACE, "%s: end if FTDX101D\n", __func__);
} /* end if is_ftdx101d || is_ftdx101mp || is_ftdx10 || is_ft710 */
+ else if (is_ftx1)
+ {
+ // Bandwidth table per FTX-1 CAT Operation Reference Manual Table 5
+ // (doc 2508-C). Differs from FT-710/FTDX10 at SSB codes 12/13/14.
+ rig_debug(RIG_DEBUG_TRACE, "%s: is_ftx1 w=%d, mode=%s\n", __func__, w,
+ rig_strrmode(mode));
+
+ if (w == 0) // default: fall back to the mode's normal passband
+ {
+ *width = rig_passband_normal(rig, mode);
+ }
+
+ switch (mode)
+ {
+ case RIG_MODE_PKTUSB:
+ case RIG_MODE_PKTLSB:
+ case RIG_MODE_RTTY:
+ case RIG_MODE_RTTYR:
+ case RIG_MODE_CW:
+ case RIG_MODE_CWR:
+ case RIG_MODE_PSK:
+ switch (w)
+ {
+ case 0: break; /* default */
+
+ case 1: *width = 50; break;
+
+ case 2: *width = 100; break;
+
+ case 3: *width = 150; break;
+
+ case 4: *width = 200; break;
+
+ case 5: *width = 250; break;
+
+ case 6: *width = 300; break;
+
+ case 7: *width = 350; break;
+
+ case 8: *width = 400; break;
+
+ case 9: *width = 450; break;
+
+ case 10: *width = 500; break;
+
+ case 11: *width = 600; break;
+
+ case 12: *width = 800; break;
+
+ case 13: *width = 1200; break;
+
+ case 14: *width = 1400; break;
+
+ case 15: *width = 1700; break;
+
+ case 16: *width = 2000; break;
+
+ case 17: *width = 2400; break;
+
+ case 18: *width = 3000; break;
+
+ case 19: *width = 3200; break;
+
+ case 20: *width = 3500; break;
+
+ case 21: *width = 4000; break;
+
+ default:
+ RETURNFUNC(-RIG_EINVAL);
+ }
+
+ break;
+
+ case RIG_MODE_LSB:
+ case RIG_MODE_USB:
+ switch (w)
+ {
+ case 0: break; /* default */
+
+ case 1: *width = 300; break;
+
+ case 2: *width = 400; break;
+
+ case 3: *width = 600; break;
+
+ case 4: *width = 850; break;
+
+ case 5: *width = 1100; break;
+
+ case 6: *width = 1200; break;
+
+ case 7: *width = 1500; break;
+
+ case 8: *width = 1650; break;
+
+ case 9: *width = 1800; break;
+
+ case 10: *width = 1950; break;
+
+ case 11: *width = 2100; break;
+
+ case 12: *width = 2250; break;
+
+ case 13: *width = 2400; break;
+
+ case 14: *width = 2450; break;
+
+ case 15: *width = 2500; break;
+
+ case 16: *width = 2600; break;
+
+ case 17: *width = 2700; break;
+
+ case 18: *width = 2800; break;
+
+ case 19: *width = 2900; break;
+
+ case 20: *width = 3000; break;
+
+ case 21: *width = 3200; break;
+
+ case 22: *width = 3500; break;
+
+ case 23: *width = 4000; break;
+
+ default:
+ rig_debug(RIG_DEBUG_ERR, "%s: unknown width=%d\n", __func__, w);
+ RETURNFUNC(-RIG_EINVAL);
+ }
+
+ break;
+
+ case RIG_MODE_AM:
+ case RIG_MODE_FMN:
+ case RIG_MODE_PKTFMN:
+ *width = 9000;
+ break;
+
+ case RIG_MODE_AMN:
+ *width = 6000;
+ break;
+
+ case RIG_MODE_FM:
+ case RIG_MODE_PKTFM:
+ *width = 16000;
+ break;
+
+ default:
+ rig_debug(RIG_DEBUG_TRACE, "%s: bad mode\n", __func__);
+ RETURNFUNC(-RIG_EINVAL);
+ } /* end switch(mode) */
+
+ rig_debug(RIG_DEBUG_TRACE, "%s: end if is_ftx1\n", __func__);
+ } /* end if is_ftx1 */
else if (is_ft2000)
{
if ((narrow = get_narrow(rig, RIG_VFO_MAIN)) < 0)
-----------------------------------------------------------------------
Summary of changes:
rigs/yaesu/newcat.c | 257 +++++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 256 insertions(+), 1 deletion(-)
hooks/post-receive
--
Hamlib -- Ham radio control libraries
|
|
From: n0nb <n0...@us...> - 2026-04-12 02:27:35
|
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 01494a0c0d9011457d5e61c586d364ecf7d85e73 (commit)
from 374c2d1183cb2daccee72e807e51c0c5e4f046e2 (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 01494a0c0d9011457d5e61c586d364ecf7d85e73
Author: Nate Bargmann <n0...@n0...>
Date: Sat Apr 11 18:18:10 2026 -0500
Fix RF Power output reading in low power mode
As reported by Tom, W2YF:
https://sourceforge.net/p/hamlib/mailman/message/59309943/
In low power mode, <= 12 Watts, the power was incorrectly reported too
high by a factor of 10.
Also use a lower value of divisor to achieve a reported power level
closer to the actual value.
(cherry picked from commit 8ba5fd2f3c4cb9de6482818c99c595d0a7b36d6f)
diff --git a/rigs/kenwood/k3.c b/rigs/kenwood/k3.c
index 19c3dd094..1ddcf1628 100644
--- a/rigs/kenwood/k3.c
+++ b/rigs/kenwood/k3.c
@@ -2761,6 +2761,7 @@ static int k3_get_bar_graph_level(RIG *rig, float *smeter, float *pwr, float *al
int *mode_tx)
{
char levelbuf[16];
+ char pwr_buf[16];
int retval;
int tm_raw;
int bg_raw;
@@ -2828,7 +2829,22 @@ static int k3_get_bar_graph_level(RIG *rig, float *smeter, float *pwr, float *al
// PWR: nn is 00 - 12
if (pwr != NULL)
{
- *pwr = (float) bg_raw / 12.0f;
+ retval = kenwood_transaction(rig, "PC", pwr_buf, sizeof(pwr_buf));
+
+ if (retval != RIG_OK)
+ {
+ return retval;
+ }
+
+ // extended K22 format PCnnnx where x == 0=.1W units and 1=1W units
+ if (6 == strlen(pwr_buf) && '0' == pwr_buf[5])
+ {
+ *pwr = (float) bg_raw / 100.0f;
+ }
+ else
+ {
+ *pwr = (float) bg_raw / 10.0f;
+ }
}
if (alc != NULL)
-----------------------------------------------------------------------
Summary of changes:
rigs/kenwood/k3.c | 18 +++++++++++++++++-
1 file changed, 17 insertions(+), 1 deletion(-)
hooks/post-receive
--
Hamlib -- Ham radio control libraries
|
|
From: n0nb <n0...@us...> - 2026-04-12 02:24:13
|
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, Hamlib-4.7 has been updated
via 037a3e232e5cd1425d4ea5a2539072010a44df36 (commit)
via 8ba5fd2f3c4cb9de6482818c99c595d0a7b36d6f (commit)
from fda9092c89aee2b3a78534a8b01154aa933045bf (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 037a3e232e5cd1425d4ea5a2539072010a44df36
Author: Nate Bargmann <n0...@n0...>
Date: Sat Apr 11 21:22:40 2026 -0500
Update NEWS for K3/K3S low power calculation fix
diff --git a/NEWS b/NEWS
index 333b8a1a1..c989f7997 100644
--- a/NEWS
+++ b/NEWS
@@ -31,6 +31,7 @@ Version 4.7.1
* Add new rig model Harris PRC-138. (TNX Antonio Regazzoni)
* Various FT-710 fixes, eespecially handling SH format and RX bandwidth.
Ensure FT-710 simulator rejects RF command. (TNX George Baltz)
+ * Fix low power calculation for K3/K3S. (N0NB)
Version 4.7.0
* 2026-02-15
commit 8ba5fd2f3c4cb9de6482818c99c595d0a7b36d6f
Author: Nate Bargmann <n0...@n0...>
Date: Sat Apr 11 18:18:10 2026 -0500
Fix RF Power output reading in low power mode
As reported by Tom, W2YF:
https://sourceforge.net/p/hamlib/mailman/message/59309943/
In low power mode, <= 12 Watts, the power was incorrectly reported too
high by a factor of 10.
Also use a lower value of divisor to achieve a reported power level
closer to the actual value.
diff --git a/rigs/kenwood/k3.c b/rigs/kenwood/k3.c
index aef12f35d..58c54b902 100644
--- a/rigs/kenwood/k3.c
+++ b/rigs/kenwood/k3.c
@@ -2764,6 +2764,7 @@ static int k3_get_bar_graph_level(RIG *rig, float *smeter, float *pwr, float *al
int *mode_tx)
{
char levelbuf[16];
+ char pwr_buf[16];
int retval;
int tm_raw;
int bg_raw;
@@ -2831,7 +2832,22 @@ static int k3_get_bar_graph_level(RIG *rig, float *smeter, float *pwr, float *al
// PWR: nn is 00 - 12
if (pwr != NULL)
{
- *pwr = (float) bg_raw / 12.0f;
+ retval = kenwood_transaction(rig, "PC", pwr_buf, sizeof(pwr_buf));
+
+ if (retval != RIG_OK)
+ {
+ return retval;
+ }
+
+ // extended K22 format PCnnnx where x == 0=.1W units and 1=1W units
+ if (6 == strlen(pwr_buf) && '0' == pwr_buf[5])
+ {
+ *pwr = (float) bg_raw / 100.0f;
+ }
+ else
+ {
+ *pwr = (float) bg_raw / 10.0f;
+ }
}
if (alc != NULL)
-----------------------------------------------------------------------
Summary of changes:
NEWS | 1 +
rigs/kenwood/k3.c | 18 +++++++++++++++++-
2 files changed, 18 insertions(+), 1 deletion(-)
hooks/post-receive
--
Hamlib -- Ham radio control libraries
|
|
From: n0nb <n0...@us...> - 2026-04-11 15:02:31
|
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, Hamlib-4.7 has been updated
via fda9092c89aee2b3a78534a8b01154aa933045bf (commit)
via 40a8c82967a9cbdf31478fc2f2a52b1c15a37805 (commit)
via 7fef4c3933d1f72b8373c514449be08998a29a75 (commit)
via 6eff8d01a5c01d27f27ea63a6ff29cefa15d4889 (commit)
via e8430e9943644b4a1b972e959d56d471f2b29a39 (commit)
from 8cde902c7cabe6c9e08e006edb2276894e71c5de (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 fda9092c89aee2b3a78534a8b01154aa933045bf
Author: Nate Bargmann <n0...@n0...>
Date: Sat Apr 11 10:01:18 2026 -0500
Update NEWS for FT-710 fixes
diff --git a/NEWS b/NEWS
index 6600a9ad4..333b8a1a1 100644
--- a/NEWS
+++ b/NEWS
@@ -29,6 +29,8 @@ Version 4.7.1
* Fix and generalize clock handling for Icom radios. (TNX George Baltz)
* Fix Yaesu attenuator levels and LVL_KEYSPD reinitialization. (TNX George Baltz)
* Add new rig model Harris PRC-138. (TNX Antonio Regazzoni)
+ * Various FT-710 fixes, eespecially handling SH format and RX bandwidth.
+ Ensure FT-710 simulator rejects RF command. (TNX George Baltz)
Version 4.7.0
* 2026-02-15
commit 40a8c82967a9cbdf31478fc2f2a52b1c15a37805
Author: George Baltz N3GB <Geo...@gm...>
Date: Fri Apr 10 13:05:06 2026 -0400
Fix FT-710 newcat_get_rx_bandwidth()
Found after fixing set (issue #2021)
Also fix typo in FT-950 code.
(cherry picked from commit 506c3ea77022e5ced78ddb8d53aefe17ffbf637f)
diff --git a/rigs/yaesu/newcat.c b/rigs/yaesu/newcat.c
index 09b74db97..10d040324 100644
--- a/rigs/yaesu/newcat.c
+++ b/rigs/yaesu/newcat.c
@@ -9895,7 +9895,7 @@ int newcat_get_rx_bandwidth(RIG *rig, vfo_t vfo, rmode_t mode, pbwidth_t *width)
case 6: *width = 400; break;
- case 7: *width = 5000; break;
+ case 7: *width = 500; break;
case 8: *width = 800; break;
@@ -10565,7 +10565,7 @@ int newcat_get_rx_bandwidth(RIG *rig, vfo_t vfo, rmode_t mode, pbwidth_t *width)
} /* end switch(mode) */
} /* end if is_ftdx5000 */
- else if (is_ftdx101d || is_ftdx101mp || is_ftdx10)
+ else if (is_ftdx101d || is_ftdx101mp || is_ftdx10 || is_ft710)
{
rig_debug(RIG_DEBUG_TRACE, "%s: is_ftdx101 w=%d, mode=%s\n", __func__, w,
rig_strrmode(mode));
@@ -10579,6 +10579,10 @@ int newcat_get_rx_bandwidth(RIG *rig, vfo_t vfo, rmode_t mode, pbwidth_t *width)
{
*width = roofing_filter->width;
}
+ else
+ {
+ *width = rig_passband_normal(rig, mode); // The best we can do
+ }
}
switch (mode)
@@ -10722,7 +10726,7 @@ int newcat_get_rx_bandwidth(RIG *rig, vfo_t vfo, rmode_t mode, pbwidth_t *width)
} /* end switch(mode) */
rig_debug(RIG_DEBUG_TRACE, "%s: end if FTDX101D\n", __func__);
- } /* end if is_ftdx101 */
+ } /* end if is_ftdx101d || is_ftdx101mp || is_ftdx10 || is_ft710 */
else if (is_ft2000)
{
if ((narrow = get_narrow(rig, RIG_VFO_MAIN)) < 0)
commit 7fef4c3933d1f72b8373c514449be08998a29a75
Author: George Baltz N3GB <Geo...@gm...>
Date: Fri Apr 3 21:13:51 2026 -0400
Use the correct SH command in newcat_set_rx_bandwidth() and simft710.c
FT-710 CAT Operations Manual says the FT-710 has 2 leading zeroes (P1
& P2), not just 1.
Fix missing "== 0"
(cherry picked from commit bf5bea401268b28cce611a6ed7509b2dada74f5c)
diff --git a/rigs/yaesu/newcat.c b/rigs/yaesu/newcat.c
index 5108cea34..09b74db97 100644
--- a/rigs/yaesu/newcat.c
+++ b/rigs/yaesu/newcat.c
@@ -9565,7 +9565,7 @@ int newcat_set_rx_bandwidth(RIG *rig, vfo_t vfo, rmode_t mode, pbwidth_t width)
{
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "SH0%02d;", w);
}
- else if (is_ftdx10)
+ else if (is_ftdx10 || is_ft710)
{
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "SH00%02d;", w);
}
diff --git a/simulators/simft710.c b/simulators/simft710.c
index 7fd48a4c5..877a6880a 100644
--- a/simulators/simft710.c
+++ b/simulators/simft710.c
@@ -480,12 +480,12 @@ int main(int argc, char *argv[])
}
else if (strncmp(buf, "SH0;", 4) == 0)
{
- sprintf(buf, "SH0%02d;", width);
+ sprintf(buf, "SH00%02d;", width);
n = write(fd, buf, strlen(buf));
}
else if (strncmp(buf, "SH0", 3) == 0)
{
- sscanf(buf, "SH0%02d", &width);
+ sscanf(buf, "SH00%02d", &width);
}
else if (strncmp(buf, "NA0;", 4) == 0)
{
@@ -532,7 +532,7 @@ int main(int argc, char *argv[])
sprintf(buf, "ST%d;", st);
n = write(fd, buf, strlen(buf));
}
- else if (strncmp(buf, "RF", 2)) // Not defined for FT-710
+ else if (strncmp(buf, "RF", 2) == 0) // Not defined for FT-710
{
n = write(fd, "?;", 2);
}
commit 6eff8d01a5c01d27f27ea63a6ff29cefa15d4889
Author: George Baltz N3GB <Geo...@gm...>
Date: Fri Apr 3 16:45:08 2026 -0400
Make sure simft710.c rejects RF command
No roofing filters on this rig.
Clean out includes of rig.h and misc.c
(cherry picked from commit 31d1635cf3fdb561fb1144df3e74733c7986a10d)
diff --git a/simulators/simft710.c b/simulators/simft710.c
index 525f49bbb..7fd48a4c5 100644
--- a/simulators/simft710.c
+++ b/simulators/simft710.c
@@ -5,9 +5,12 @@
#include <string.h>
#include <unistd.h>
+#if 0
#include "hamlib/rig.h"
#include "misc.h"
-
+#else
+int hl_usleep(unsigned long usec);
+#endif
float freqA = 14074000;
float freqB = 14074500;
@@ -108,7 +111,7 @@ int main(int argc, char *argv[])
}
else if (strcmp(buf, "FA;") == 0)
{
- SNPRINTF(buf, sizeof(buf), "FA%08.0f;", freqA);
+ snprintf(buf, sizeof(buf), "FA%08.0f;", freqA);
n = write(fd, buf, strlen(buf));
}
else if (strncmp(buf, "FA", 2) == 0)
@@ -117,7 +120,7 @@ int main(int argc, char *argv[])
}
else if (strcmp(buf, "FB;") == 0)
{
- SNPRINTF(buf, sizeof(buf), "FB%08.0f;", freqB);
+ snprintf(buf, sizeof(buf), "FB%08.0f;", freqB);
n = write(fd, buf, strlen(buf));
}
else if (strncmp(buf, "FB", 2) == 0)
@@ -128,20 +131,20 @@ int main(int argc, char *argv[])
{
hl_usleep(50 * 1000);
int id = NC_RIGID_FT710;
- SNPRINTF(buf, sizeof(buf), "ID%03d;", id);
+ snprintf(buf, sizeof(buf), "ID%03d;", id);
n = write(fd, buf, strlen(buf));
if (n <= 0) { perror("ID"); }
}
else if (strcmp(buf, "PS;") == 0)
{
- SNPRINTF(buf, sizeof(buf), "PS1;");
+ snprintf(buf, sizeof(buf), "PS1;");
n = write(fd, buf, strlen(buf));
}
else if (strcmp(buf, "AI;") == 0)
{
hl_usleep(50 * 1000);
- SNPRINTF(buf, sizeof(buf), "AI0;");
+ snprintf(buf, sizeof(buf), "AI0;");
n = write(fd, buf, strlen(buf));
if (n <= 0) { perror("ID"); }
@@ -153,7 +156,7 @@ int main(int argc, char *argv[])
else if (strcmp(buf, "FT;") == 0)
{
hl_usleep(50 * 1000);
- SNPRINTF(buf, sizeof(buf), "FT%c;", tx_vfo);
+ snprintf(buf, sizeof(buf), "FT%c;", tx_vfo);
n = write(fd, buf, strlen(buf));
if (n < 0) { perror("FT"); }
@@ -166,7 +169,7 @@ int main(int argc, char *argv[])
{
printf("MD=%s\n", buf);
hl_usleep(50 * 1000);
- SNPRINTF(buf, sizeof(buf), "MD0%c;", modeA);
+ snprintf(buf, sizeof(buf), "MD0%c;", modeA);
n = write(fd, buf, strlen(buf));
if (n < 0) { perror("MD0;"); }
@@ -178,7 +181,7 @@ int main(int argc, char *argv[])
else if (strcmp(buf, "MD1;") == 0)
{
hl_usleep(50 * 1000);
- SNPRINTF(buf, sizeof(buf), "MD1%c;", modeB);
+ snprintf(buf, sizeof(buf), "MD1%c;", modeB);
n = write(fd, buf, strlen(buf));
if (n < 0) { perror("MD0;"); }
@@ -206,7 +209,7 @@ int main(int argc, char *argv[])
else if (strcmp(buf, "VS;") == 0)
{
hl_usleep(50 * 1000);
- SNPRINTF(buf, sizeof(buf), "VS%d;", vs);
+ snprintf(buf, sizeof(buf), "VS%d;", vs);
n = write(fd, buf, strlen(buf));
if (n < 0) { perror("VS"); }
@@ -218,7 +221,7 @@ int main(int argc, char *argv[])
else if (strcmp(buf, "KR;") == 0)
{
hl_usleep(50 * 1000);
- SNPRINTF(buf, sizeof(buf), "KR%d;", kr);
+ snprintf(buf, sizeof(buf), "KR%d;", kr);
n = write(fd, buf, strlen(buf));
if (n < 0) { perror("KR"); }
@@ -230,7 +233,7 @@ int main(int argc, char *argv[])
else if (strcmp(buf, "BI;") == 0)
{
hl_usleep(50 * 1000);
- SNPRINTF(buf, sizeof(buf), "BI%d;", bi);
+ snprintf(buf, sizeof(buf), "BI%d;", bi);
n = write(fd, buf, strlen(buf));
if (n < 0) { perror("BI"); }
@@ -242,7 +245,7 @@ int main(int argc, char *argv[])
else if (strcmp(buf, "VX;") == 0)
{
hl_usleep(50 * 1000);
- SNPRINTF(buf, sizeof(buf), "VX%d;", vx);
+ snprintf(buf, sizeof(buf), "VX%d;", vx);
n = write(fd, buf, strlen(buf));
if (n < 0) { perror("VX"); }
@@ -255,7 +258,7 @@ int main(int argc, char *argv[])
else if (strcmp(buf, "PA;") == 0)
{
hl_usleep(50 * 1000);
- SNPRINTF(buf, sizeof(buf), "PA%d;", pa);
+ snprintf(buf, sizeof(buf), "PA%d;", pa);
n = write(fd, buf, strlen(buf));
if (n < 0) { perror("PA"); }
@@ -267,7 +270,7 @@ int main(int argc, char *argv[])
else if (strcmp(buf, "RA;") == 0)
{
hl_usleep(50 * 1000);
- SNPRINTF(buf, sizeof(buf), "RA%d;", ra);
+ snprintf(buf, sizeof(buf), "RA%d;", ra);
n = write(fd, buf, strlen(buf));
if (n < 0) { perror("RA"); }
@@ -279,7 +282,7 @@ int main(int argc, char *argv[])
else if (strcmp(buf, "AG;") == 0)
{
hl_usleep(50 * 1000);
- SNPRINTF(buf, sizeof(buf), "AG%d;", ag);
+ snprintf(buf, sizeof(buf), "AG%d;", ag);
n = write(fd, buf, strlen(buf));
if (n < 0) { perror("AG"); }
@@ -291,7 +294,7 @@ int main(int argc, char *argv[])
else if (strcmp(buf, "PC;") == 0)
{
hl_usleep(50 * 1000);
- SNPRINTF(buf, sizeof(buf), "PC%03d;", pc);
+ snprintf(buf, sizeof(buf), "PC%03d;", pc);
n = write(fd, buf, strlen(buf));
if (n < 0) { perror("PC"); }
@@ -303,7 +306,7 @@ int main(int argc, char *argv[])
else if (strcmp(buf, "VG;") == 0)
{
hl_usleep(50 * 1000);
- SNPRINTF(buf, sizeof(buf), "VG%03d;", vg);
+ snprintf(buf, sizeof(buf), "VG%03d;", vg);
n = write(fd, buf, strlen(buf));
if (n < 0) { perror("VG"); }
@@ -315,7 +318,7 @@ int main(int argc, char *argv[])
else if (strcmp(buf, "RG0;") == 0)
{
hl_usleep(50 * 1000);
- SNPRINTF(buf, sizeof(buf), "RG0%03d;", rg);
+ snprintf(buf, sizeof(buf), "RG0%03d;", rg);
n = write(fd, buf, strlen(buf));
if (n < 0) { perror("RG"); }
@@ -327,7 +330,7 @@ int main(int argc, char *argv[])
else if (strcmp(buf, "GT0;") == 0)
{
hl_usleep(50 * 1000);
- SNPRINTF(buf, sizeof(buf), "GT0%0d;", gt);
+ snprintf(buf, sizeof(buf), "GT0%0d;", gt);
n = write(fd, buf, strlen(buf));
if (n < 0) { perror("GT"); }
@@ -339,7 +342,7 @@ int main(int argc, char *argv[])
else if (strcmp(buf, "TX;") == 0)
{
hl_usleep(50 * 1000);
- SNPRINTF(buf, sizeof(buf), "TX+%04d;", tx);
+ snprintf(buf, sizeof(buf), "TX+%04d;", tx);
n = write(fd, buf, strlen(buf));
if (n < 0) { perror("TX"); }
@@ -351,7 +354,7 @@ int main(int argc, char *argv[])
else if (strcmp(buf, "IS;") == 0)
{
hl_usleep(50 * 1000);
- SNPRINTF(buf, sizeof(buf), "IS+%04d;", is);
+ snprintf(buf, sizeof(buf), "IS+%04d;", is);
n = write(fd, buf, strlen(buf));
if (n < 0) { perror("IS"); }
@@ -363,7 +366,7 @@ int main(int argc, char *argv[])
else if (strcmp(buf, "RL0;") == 0)
{
hl_usleep(50 * 1000);
- SNPRINTF(buf, sizeof(buf), "RL0%d;", rl);
+ snprintf(buf, sizeof(buf), "RL0%d;", rl);
n = write(fd, buf, strlen(buf));
if (n < 0) { perror("RL"); }
@@ -375,7 +378,7 @@ int main(int argc, char *argv[])
else if (strcmp(buf, "BP00;") == 0)
{
hl_usleep(50 * 1000);
- SNPRINTF(buf, sizeof(buf), "BP0%d;", bp_on);
+ snprintf(buf, sizeof(buf), "BP0%d;", bp_on);
n = write(fd, buf, strlen(buf));
if (n < 0) { perror("BP"); }
@@ -387,7 +390,7 @@ int main(int argc, char *argv[])
else if (strcmp(buf, "BP01;") == 0)
{
hl_usleep(50 * 1000);
- SNPRINTF(buf, sizeof(buf), "BP0%d;", bp_pos);
+ snprintf(buf, sizeof(buf), "BP0%d;", bp_pos);
n = write(fd, buf, strlen(buf));
if (n < 0) { perror("BP"); }
@@ -399,7 +402,7 @@ int main(int argc, char *argv[])
else if (strcmp(buf, "NB0;") == 0)
{
hl_usleep(50 * 1000);
- SNPRINTF(buf, sizeof(buf), "NB0%d;", nb);
+ snprintf(buf, sizeof(buf), "NB0%d;", nb);
n = write(fd, buf, strlen(buf));
if (n < 0) { perror("NB"); }
@@ -411,7 +414,7 @@ int main(int argc, char *argv[])
else if (strcmp(buf, "NR0;") == 0)
{
hl_usleep(50 * 1000);
- SNPRINTF(buf, sizeof(buf), "NR0%d;", nr);
+ snprintf(buf, sizeof(buf), "NR0%d;", nr);
n = write(fd, buf, strlen(buf));
if (n < 0) { perror("NR"); }
@@ -427,7 +430,7 @@ int main(int argc, char *argv[])
static int ant = 0;
ant = (ant + 1) % 3;
hl_usleep(50 * 1000);
- SNPRINTF(buf, sizeof(buf), "EX032%1d;", ant);
+ snprintf(buf, sizeof(buf), "EX032%1d;", ant);
n = write(fd, buf, strlen(buf));
if (n < 0) { perror("EX032"); }
@@ -435,7 +438,7 @@ int main(int argc, char *argv[])
else if (strcmp(buf, "EX016;") == 0)
{
hl_usleep(50 * 1000);
- SNPRINTF(buf, sizeof(buf), "EX016%04d;", ex016);
+ snprintf(buf, sizeof(buf), "EX016%04d;", ex016);
n = write(fd, buf, strlen(buf));
if (n < 0) { perror("EX016"); }
@@ -443,7 +446,7 @@ int main(int argc, char *argv[])
else if (strcmp(buf, "EX020;") == 0)
{
hl_usleep(50 * 1000);
- SNPRINTF(buf, sizeof(buf), "EX020%04d;", ex020);
+ snprintf(buf, sizeof(buf), "EX020%04d;", ex020);
n = write(fd, buf, strlen(buf));
if (n < 0) { perror("EX016"); }
@@ -529,6 +532,10 @@ int main(int argc, char *argv[])
sprintf(buf, "ST%d;", st);
n = write(fd, buf, strlen(buf));
}
+ else if (strncmp(buf, "RF", 2)) // Not defined for FT-710
+ {
+ n = write(fd, "?;", 2);
+ }
else if (strlen(buf) > 0)
{
fprintf(stderr, "Unknown command: %s\n", buf);
commit e8430e9943644b4a1b972e959d56d471f2b29a39
Author: George Baltz N3GB <Geo...@gm...>
Date: Wed Apr 1 16:53:58 2026 -0400
Fix some obvious errors in newcat.c
Try a few shots in the dark for issues #2021 & #2024
Acknowledge that the FT-710 does NOT have an "RF" command.
Don't call newcat_set_roofing_filter_for_width() if there are
no roofing filters available.
Fix runaway search for matching roofing filters; use count as there
are no end entries the filter table.
I really can't test these(no hardware), but just looking at the code
and the traces from the issues above it's evident that these things
are broken. This may not fix everything, and may even break in new ways,
but it may make the actual problems a bit easier to find.
(cherry picked from commit 1fa3444884eb76e63c879d09c6527b479b175f8d)
diff --git a/rigs/yaesu/newcat.c b/rigs/yaesu/newcat.c
index 5f248a302..5108cea34 100644
--- a/rigs/yaesu/newcat.c
+++ b/rigs/yaesu/newcat.c
@@ -547,7 +547,7 @@ static const yaesu_newcat_commands_t valid_commands[] =
{"RA", TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE },
{"RC", TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE },
{"RD", TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE },
- {"RF", FALSE, TRUE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE },
+ {"RF", FALSE, TRUE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, TRUE },
{"RG", TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE },
{"RI", TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE },
{"RL", TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE },
@@ -9382,9 +9382,12 @@ int newcat_set_rx_bandwidth(RIG *rig, vfo_t vfo, rmode_t mode, pbwidth_t width)
RETURNFUNC(-RIG_EINVAL);
} // end switch(mode)
- if ((err = set_roofing_filter_for_width(rig, vfo, width)) != RIG_OK)
+ if (((struct newcat_priv_caps *)rig->caps->priv)->roofing_filter_count > 0)
{
- RETURNFUNC(err);
+ if ((err = set_roofing_filter_for_width(rig, vfo, width)) != RIG_OK)
+ {
+ RETURNFUNC(err);
+ }
}
switch (mode)
@@ -9407,7 +9410,7 @@ int newcat_set_rx_bandwidth(RIG *rig, vfo_t vfo, rmode_t mode, pbwidth_t width)
case RIG_MODE_FMN:
RETURNFUNC(RIG_OK);
}
- } // end is_ftdx101
+ } // end is_ftdx101d || is_ftdx101mp || is_ftdx10 || is_ft710
else if (is_ft2000)
{
// We need details on the widths here, manuals lack information.
@@ -9606,7 +9609,7 @@ static int set_roofing_filter(RIG *rig, vfo_t vfo, int index)
RETURNFUNC(-RIG_ENAVAIL);
}
- for (i = 0; roofing_filters[i].index >= 0; i++)
+ for (i = 0; i < priv_caps->roofing_filter_count; i++)
{
const struct newcat_roofing_filter *current_filter = &roofing_filters[i];
char set_value = current_filter->set_value;
-----------------------------------------------------------------------
Summary of changes:
NEWS | 2 ++
rigs/yaesu/newcat.c | 25 +++++++++++-------
simulators/simft710.c | 71 ++++++++++++++++++++++++++++-----------------------
3 files changed, 57 insertions(+), 41 deletions(-)
hooks/post-receive
--
Hamlib -- Ham radio control libraries
|
|
From: n0nb <n0...@us...> - 2026-04-11 14:57:07
|
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 374c2d1183cb2daccee72e807e51c0c5e4f046e2 (commit)
via 506c3ea77022e5ced78ddb8d53aefe17ffbf637f (commit)
from d784cc49d9fa682511e2e39528cb9ea59e8aa655 (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 374c2d1183cb2daccee72e807e51c0c5e4f046e2
Merge: d784cc49d 506c3ea77
Author: Nate Bargmann <n0...@n0...>
Date: Sat Apr 11 09:46:19 2026 -0500
Merge PR #2029
commit 506c3ea77022e5ced78ddb8d53aefe17ffbf637f
Author: George Baltz N3GB <Geo...@gm...>
Date: Fri Apr 10 13:05:06 2026 -0400
Fix FT-710 newcat_get_rx_bandwidth()
Found after fixing set (issue #2021)
Also fix typo in FT-950 code.
diff --git a/rigs/yaesu/newcat.c b/rigs/yaesu/newcat.c
index 917538e23..f73512195 100644
--- a/rigs/yaesu/newcat.c
+++ b/rigs/yaesu/newcat.c
@@ -9897,7 +9897,7 @@ int newcat_get_rx_bandwidth(RIG *rig, vfo_t vfo, rmode_t mode, pbwidth_t *width)
case 6: *width = 400; break;
- case 7: *width = 5000; break;
+ case 7: *width = 500; break;
case 8: *width = 800; break;
@@ -10567,7 +10567,7 @@ int newcat_get_rx_bandwidth(RIG *rig, vfo_t vfo, rmode_t mode, pbwidth_t *width)
} /* end switch(mode) */
} /* end if is_ftdx5000 */
- else if (is_ftdx101d || is_ftdx101mp || is_ftdx10)
+ else if (is_ftdx101d || is_ftdx101mp || is_ftdx10 || is_ft710)
{
rig_debug(RIG_DEBUG_TRACE, "%s: is_ftdx101 w=%d, mode=%s\n", __func__, w,
rig_strrmode(mode));
@@ -10581,6 +10581,10 @@ int newcat_get_rx_bandwidth(RIG *rig, vfo_t vfo, rmode_t mode, pbwidth_t *width)
{
*width = roofing_filter->width;
}
+ else
+ {
+ *width = rig_passband_normal(rig, mode); // The best we can do
+ }
}
switch (mode)
@@ -10724,7 +10728,7 @@ int newcat_get_rx_bandwidth(RIG *rig, vfo_t vfo, rmode_t mode, pbwidth_t *width)
} /* end switch(mode) */
rig_debug(RIG_DEBUG_TRACE, "%s: end if FTDX101D\n", __func__);
- } /* end if is_ftdx101 */
+ } /* end if is_ftdx101d || is_ftdx101mp || is_ftdx10 || is_ft710 */
else if (is_ft2000)
{
if ((narrow = get_narrow(rig, RIG_VFO_MAIN)) < 0)
-----------------------------------------------------------------------
Summary of changes:
rigs/yaesu/newcat.c | 10 +++++++---
1 file changed, 7 insertions(+), 3 deletions(-)
hooks/post-receive
--
Hamlib -- Ham radio control libraries
|
|
From: n0nb <n0...@us...> - 2026-04-11 13:17:43
|
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 d784cc49d9fa682511e2e39528cb9ea59e8aa655 (commit)
via d800469dff9c0e5176fe13066909049aa797fdfe (commit)
from 452544e08ce14b51bb266645c92f1ba90de2d0d6 (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 d784cc49d9fa682511e2e39528cb9ea59e8aa655
Author: Nate Bargmann <n0...@n0...>
Date: Sat Apr 11 08:10:16 2026 -0500
Add RIG_MODEL_PRC138 to test_Hamlib_class.py
Reported by Walter Fey:
https://github.com/Hamlib/Hamlib/commit/4f4507fa8c8bb05040cd36ae7bb5866183b2a306#commitcomment-182142320
(cherry picked from commit 8cde902c7cabe6c9e08e006edb2276894e71c5de)
diff --git a/bindings/python/test_Hamlib_class.py b/bindings/python/test_Hamlib_class.py
index cab020e2d..950a6d6db 100755
--- a/bindings/python/test_Hamlib_class.py
+++ b/bindings/python/test_Hamlib_class.py
@@ -818,6 +818,7 @@ class TestClass:
'RIG_MODEL_PMR171',
'RIG_MODEL_PMSDR',
'RIG_MODEL_POWERSDR',
+'RIG_MODEL_PRC138',
'RIG_MODEL_PRM8060',
'RIG_MODEL_PRM8070',
'RIG_MODEL_PRO2052',
commit d800469dff9c0e5176fe13066909049aa797fdfe
Author: Nate Bargmann <n0...@n0...>
Date: Sat Apr 11 08:15:06 2026 -0500
Add missing Doxygen close tag in riglist.h
diff --git a/include/hamlib/riglist.h b/include/hamlib/riglist.h
index 9eb036263..eb523e28f 100644
--- a/include/hamlib/riglist.h
+++ b/include/hamlib/riglist.h
@@ -1138,6 +1138,7 @@
///@{
/// Model of the `RIG_SIMPLECAT` backend family.
#define RIG_MODEL_SIMPLECAT RIG_MAKE_MODEL(RIG_SIMPLECAT, 1)
+///@}
/*
* HARRIS
-----------------------------------------------------------------------
Summary of changes:
bindings/python/test_Hamlib_class.py | 1 +
include/hamlib/riglist.h | 1 +
2 files changed, 2 insertions(+)
hooks/post-receive
--
Hamlib -- Ham radio control libraries
|
|
From: n0nb <n0...@us...> - 2026-04-11 13:13:08
|
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, Hamlib-4.7 has been updated
via 8cde902c7cabe6c9e08e006edb2276894e71c5de (commit)
from c13e11530e372d1b3f76e730d8e502c99eb448ae (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 8cde902c7cabe6c9e08e006edb2276894e71c5de
Author: Nate Bargmann <n0...@n0...>
Date: Sat Apr 11 08:10:16 2026 -0500
Add RIG_MODEL_PRC138 to test_Hamlib_class.py
Reported by Walter Fey:
https://github.com/Hamlib/Hamlib/commit/4f4507fa8c8bb05040cd36ae7bb5866183b2a306#commitcomment-182142320
diff --git a/bindings/python/test_Hamlib_class.py b/bindings/python/test_Hamlib_class.py
index 2911df0fa..6b0deff43 100755
--- a/bindings/python/test_Hamlib_class.py
+++ b/bindings/python/test_Hamlib_class.py
@@ -807,6 +807,7 @@ class TestClass:
'RIG_MODEL_PMR171',
'RIG_MODEL_PMSDR',
'RIG_MODEL_POWERSDR',
+'RIG_MODEL_PRC138',
'RIG_MODEL_PRM8060',
'RIG_MODEL_PRM8070',
'RIG_MODEL_PRO2052',
-----------------------------------------------------------------------
Summary of changes:
bindings/python/test_Hamlib_class.py | 1 +
1 file changed, 1 insertion(+)
hooks/post-receive
--
Hamlib -- Ham radio control libraries
|
|
From: n0nb <n0...@us...> - 2026-04-11 02:55:47
|
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, Hamlib-4.7 has been updated
via c13e11530e372d1b3f76e730d8e502c99eb448ae (commit)
via fff7810f0a3763cd67888442c850d295532fc2dc (commit)
via ad3e839acf98293da1d70247e4b325e81616684e (commit)
via 489fe24d2a3519038d64d2910b6b6b2b53aba42a (commit)
via fb2d24e3c62e1239539cec77a912b41261944d07 (commit)
via 2df512825143b4a98e361b5e0f4507c9a4082bc0 (commit)
from 459023b2bb7227a9721a7a94ec8bd7e455aae79b (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 c13e11530e372d1b3f76e730d8e502c99eb448ae
Author: Nate Bargmann <n0...@n0...>
Date: Fri Apr 10 21:53:43 2026 -0500
Update NEWS to add new rig model PRC-138
diff --git a/NEWS b/NEWS
index 0312a5b69..6600a9ad4 100644
--- a/NEWS
+++ b/NEWS
@@ -28,6 +28,7 @@ Version 4.7.1
* New simplecat backend. Supports Bunzee Labs DDX. (TNX Dhiru Kholia)
* Fix and generalize clock handling for Icom radios. (TNX George Baltz)
* Fix Yaesu attenuator levels and LVL_KEYSPD reinitialization. (TNX George Baltz)
+ * Add new rig model Harris PRC-138. (TNX Antonio Regazzoni)
Version 4.7.0
* 2026-02-15
commit fff7810f0a3763cd67888442c850d295532fc2dc
Author: Nate Bargmann <n0...@n0...>
Date: Fri Apr 10 18:21:00 2026 -0500
Fixes to PR #2028
Add Android.mk.
Add header files to Makefile.am
Replace .rig_model member with RIG_MODEL() macro in prc138_caps
structure.
(cherry picked from commit 452544e08ce14b51bb266645c92f1ba90de2d0d6)
diff --git a/rigs/harris/Android.mk b/rigs/harris/Android.mk
new file mode 100644
index 000000000..e0226e1e1
--- /dev/null
+++ b/rigs/harris/Android.mk
@@ -0,0 +1,12 @@
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := harris.c prc138.c
+LOCAL_MODULE := harris
+
+LOCAL_CFLAGS :=
+LOCAL_C_INCLUDES := android include src
+LOCAL_LDLIBS := -lhamlib -Lobj/local/$(TARGET_ARCH_ABI)
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/rigs/harris/Makefile.am b/rigs/harris/Makefile.am
index 0264bc37a..2f3636240 100644
--- a/rigs/harris/Makefile.am
+++ b/rigs/harris/Makefile.am
@@ -1,4 +1,4 @@
-HARRISSRC = harris.c prc138.c
+HARRISSRC = harris.c harris.h prc138.c prc138.h
noinst_LTLIBRARIES = libhamlib-harris.la
libhamlib_harris_la_SOURCES = $(HARRISSRC)
diff --git a/rigs/harris/prc138.c b/rigs/harris/prc138.c
index e45fe7834..2e27599a6 100644
--- a/rigs/harris/prc138.c
+++ b/rigs/harris/prc138.c
@@ -31,7 +31,7 @@
* Harris PRC-138 Capabilities
*/
struct rig_caps prc138_caps = {
- .rig_model = RIG_MODEL_PRC138,
+ RIG_MODEL(RIG_MODEL_PRC138),
.model_name = "PRC-138",
.mfg_name = "Harris",
.version = "1.0.6",
commit ad3e839acf98293da1d70247e4b325e81616684e
Author: Rega57 <ant...@bl...>
Date: Sat Apr 4 20:45:26 2026 +0200
Warning fixed long long
Line 353 debug long long function
(cherry picked from commit a27c1a22fda37081ebd371dacc1fbbdaf786df8f)
diff --git a/rigs/harris/harris.c b/rigs/harris/harris.c
index b5e7e8345..d2dd7bcc2 100644
--- a/rigs/harris/harris.c
+++ b/rigs/harris/harris.c
@@ -350,7 +350,7 @@ int harris_set_func(RIG *rig, vfo_t vfo, setting_t func, int status)
/* Only Squelch is supported in this function */
if (func != RIG_FUNC_SQL) {
- rig_debug(RIG_DEBUG_TRACE, "%s: function %lu not supported\n", __func__, func);
+ rig_debug(RIG_DEBUG_TRACE, "%s: function %llu not supported\n", __func__, (unsigned long long)func);
return -RIG_EINVAL;
}
commit 489fe24d2a3519038d64d2910b6b6b2b53aba42a
Author: Rega57 <ant...@bl...>
Date: Sat Apr 4 17:00:20 2026 +0200
Initial comment with GPL added
Initial comment with GPL added
(cherry picked from commit c7c45f2997a3cc7527bc69a36eea32e6d8cb9e7c)
diff --git a/rigs/harris/harris.c b/rigs/harris/harris.c
index 742b36fc1..b5e7e8345 100644
--- a/rigs/harris/harris.c
+++ b/rigs/harris/harris.c
@@ -1,3 +1,29 @@
+/*
+ * Harris PRC-138 support developed by Antonio Regazzoni - HB9RBS
+ * Tested with three different PRC138 versions with following motherboard
+ * Firmware (module 01A) : 8211A, 8214D, 8214F.
+ * 04 april 2026
+ *
+ *
+ * Copyright (c) 2004-2010 by Stephane Fillod
+ *
+ *
+ * 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 <ctype.h>
#include <unistd.h>
#include <stdio.h>
diff --git a/rigs/harris/harris.h b/rigs/harris/harris.h
index 1697628a9..070e2a97f 100644
--- a/rigs/harris/harris.h
+++ b/rigs/harris/harris.h
@@ -1,3 +1,29 @@
+/*
+ * Harris PRC-138 support developed by Antonio Regazzoni - HB9RBS
+ * Tested with three different PRC138 versions with following motherboard
+ * Firmware (module 01A) : 8211A, 8214D, 8214F.
+ * 04 april 2026
+ *
+ *
+ * Copyright (c) 2004-2010 by Stephane Fillod
+ *
+ *
+ * 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 _HARRIS_H
#define _HARRIS_H
diff --git a/rigs/harris/prc138.c b/rigs/harris/prc138.c
index d0eacb52e..e45fe7834 100644
--- a/rigs/harris/prc138.c
+++ b/rigs/harris/prc138.c
@@ -1,3 +1,29 @@
+/*
+ * Harris PRC-138 support developed by Antonio Regazzoni - HB9RBS
+ * Tested with three different PRC138 versions with following motherboard
+ * Firmware (module 01A) : 8211A, 8214D, 8214F.
+ * 04 april 2026
+ *
+ *
+ * Copyright (c) 2004-2010 by Stephane Fillod
+ *
+ *
+ * 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 "harris.h"
#include "prc138.h"
diff --git a/rigs/harris/prc138.h b/rigs/harris/prc138.h
index 17142bbc6..2c2ceeeb5 100644
--- a/rigs/harris/prc138.h
+++ b/rigs/harris/prc138.h
@@ -1,3 +1,29 @@
+/*
+ * Harris PRC-138 support developed by Antonio Regazzoni - HB9RBS
+ * Tested with three different PRC138 versions with following motherboard
+ * Firmware (module 01A) : 8211A, 8214D, 8214F.
+ * 04 april 2026
+ *
+ *
+ * Copyright (c) 2004-2010 by Stephane Fillod
+ *
+ *
+ * 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 _PRC138_H
#define _PRC138_H
commit fb2d24e3c62e1239539cec77a912b41261944d07
Author: Rega57 <ant...@bl...>
Date: Sat Apr 4 15:19:18 2026 +0200
Update harris.c
Replaced italian comments and logs with english text.
(cherry picked from commit c3df0fc251e0f66c7586b9bb2f0a5095f48990d5)
diff --git a/rigs/harris/harris.c b/rigs/harris/harris.c
index ccea2f6b3..742b36fc1 100644
--- a/rigs/harris/harris.c
+++ b/rigs/harris/harris.c
@@ -23,15 +23,15 @@ static int harris_transaction(RIG *rig, const char *cmd, char *resp, int resp_le
target_buf[0] = '\0';
- /* 1. Pulizia fisica del buffer */
+ /* 1. Physical buffer flush */
rig_flush(RIGPORT(rig));
- /* 2. Invio del comando */
+ /* 2. Send command */
if (write_block(RIGPORT(rig), (unsigned char *)cmd, strlen(cmd)) < 0) {
return -RIG_EIO;
}
- /* 3. Loop di accumulo */
+ /* 3. Accumulation loop */
while (retry > 0) {
usleep(10000); //150000
@@ -41,7 +41,7 @@ static int harris_transaction(RIG *rig, const char *cmd, char *resp, int resp_le
if (buf[0] != '\0') {
strncat(target_buf, (char *)buf, target_len - strlen(target_buf) - 1);
- /* Se troviamo il prompt con lo spazio, abbiamo finito */
+ /* If we find the prompt with space, we are done */
if (strstr(target_buf, "SSB> ")) {
return RIG_OK;
}
@@ -55,18 +55,18 @@ int harris_set_freq(RIG *rig, vfo_t vfo, freq_t freq)
{
char cmd[64];
- rig_debug(RIG_DEBUG_VERBOSE, "%s: impostazione frequenza a %.0f Hz\n", __func__, freq);
+ rig_debug(RIG_DEBUG_VERBOSE, "%s: setting frequency to %.0f Hz\n", __func__, freq);
- /* Il formato %08.0f è CRUCIALE:
- - 0 significa 'riempi con zeri'
- - 8 significa 'lunghezza totale di 8 caratteri'
- - .0f significa 'numero reale senza decimali'
- Esempio: 7000000 diventa 07000000 */
+ /* The %08.0f format is CRITICAL:
+ - 0 means 'pad with zeros'
+ - 8 means 'total length of 8 characters'
+ - .0f means 'real number without decimals'
+ Example: 7000000 becomes 07000000 */
snprintf(cmd, sizeof(cmd), "FR %08.0f\r", freq);
- /* Usiamo la nostra fidata harris_transaction */
+ /* Use our trusted harris_transaction */
if (harris_transaction(rig, cmd, NULL, 0) != RIG_OK) {
- rig_debug(RIG_DEBUG_ERR, "%s: errore nella transazione FR\n", __func__);
+ rig_debug(RIG_DEBUG_ERR, "%s: error in FR transaction\n", __func__);
return -RIG_EIO;
}
@@ -78,54 +78,54 @@ int harris_get_freq(RIG *rig, vfo_t vfo, freq_t *freq)
char buf[512];
char *p;
- rig_debug(RIG_DEBUG_VERBOSE, "%s: richiesta frequenza\n", __func__);
+ rig_debug(RIG_DEBUG_VERBOSE, "%s: frequency request\n", __func__);
- /* 1. Eseguiamo la transazione completa */
+ /* 1. Perform complete transaction */
if (harris_transaction(rig, "FR\r", buf, sizeof(buf)) != RIG_OK) {
- rig_debug(RIG_DEBUG_ERR, "%s: errore nella transazione FR\n", __func__);
+ rig_debug(RIG_DEBUG_ERR, "%s: error in FR transaction\n", __func__);
return -RIG_EIO;
}
- /* 2. Cerchiamo la riga della frequenza di ricezione "RxFr " */
+ /* 2. Look for the Rx frequency line "RxFr " */
p = strstr(buf, "RxFr ");
if (p) {
- /* Saltiamo "RxFr " (5 caratteri) e leggiamo il numero */
- /* sscanf è più robusto di atof per stringhe che terminano con caratteri speciali */
+ /* Skip "RxFr " (5 characters) and read the number */
+ /* sscanf is more robust than atof for strings ending with special characters */
if (sscanf(p + 5, "%lf", freq) != 1) {
- rig_debug(RIG_DEBUG_ERR, "%s: formato frequenza non riconosciuto in [%s]\n", __func__, p);
+ rig_debug(RIG_DEBUG_ERR, "%s: frequency format not recognized in [%s]\n", __func__, p);
return -RIG_EPROTO;
}
- rig_debug(RIG_DEBUG_VERBOSE, "%s: frequenza letta: %.0f Hz\n", __func__, *freq);
+ rig_debug(RIG_DEBUG_VERBOSE, "%s: frequency read: %.0f Hz\n", __func__, *freq);
return RIG_OK;
}
- rig_debug(RIG_DEBUG_ERR, "%s: stringa RxFr non trovata nella risposta\n", __func__);
+ rig_debug(RIG_DEBUG_ERR, "%s: RxFr string not found in response\n", __func__);
return -RIG_EPROTO;
}
int harris_open(RIG *rig)
{
- rig_debug(RIG_DEBUG_VERBOSE, "%s: Apertura e sincronizzazione prompt\n", __func__);
+ rig_debug(RIG_DEBUG_VERBOSE, "%s: Opening and prompt synchronization\n", __func__);
- /* Inviamo un semplice ritorno a capo per sollecitare il prompt */
- /* Passiamo NULL come buffer di risposta perché ci interessa solo l'esito (RIG_OK) */
+ /* Send a simple carriage return to solicit the prompt */
+ /* Pass NULL as response buffer because we only care about the result (RIG_OK) */
if (harris_transaction(rig, "\r", NULL, 0) != RIG_OK) {
- rig_debug(RIG_DEBUG_ERR, "%s: La radio non risponde al prompt iniziale\n", __func__);
+ rig_debug(RIG_DEBUG_ERR, "%s: Radio not responding to initial prompt\n", __func__);
return -RIG_EIO;
}
- rig_debug(RIG_DEBUG_VERBOSE, "%s: Connessione stabilita con successo\n", __func__);
+ rig_debug(RIG_DEBUG_VERBOSE, "%s: Connection successfully established\n", __func__);
return RIG_OK;
}
static float find_closest_bandwidth(float target, const float *list) {
float closest = list[0];
- float min_diff = 99.0; // Valore iniziale alto
+ float min_diff = 99.0; // High initial value
for (int i = 0; list[i] != 0; i++) {
float diff = target - list[i];
- if (diff < 0) diff = -diff; // Valore assoluto
+ if (diff < 0) diff = -diff; // Absolute value
if (diff < min_diff) {
min_diff = diff;
@@ -142,14 +142,14 @@ int harris_set_pb_width(RIG *rig, vfo_t vfo, pbwidth_t width)
pbwidth_t current_width;
const float *bw_list;
- rig_debug(RIG_DEBUG_VERBOSE, "%s: richiesta variazione larghezza banda a %ld Hz\n", __func__, width);
+ rig_debug(RIG_DEBUG_VERBOSE, "%s: bandwidth change request to %ld Hz\n", __func__, width);
- /* 1. Recuperiamo il modo attuale per sapere quale tabella usare */
+ /* 1. Retrieve current mode to determine which table to use */
if (harris_get_mode(rig, vfo, ¤t_mode, ¤t_width) != RIG_OK) {
return -RIG_EIO;
}
- /* 2. Selezioniamo la tabella corretta */
+ /* 2. Select the correct table */
switch (current_mode) {
case RIG_MODE_USB:
case RIG_MODE_LSB: bw_list = bw_ssb; break;
@@ -158,7 +158,7 @@ int harris_set_pb_width(RIG *rig, vfo_t vfo, pbwidth_t width)
default: bw_list = bw_ssb; // Fallback
}
- /* 3. Approssimazione e invio */
+ /* 3. Approximation and sending */
float target_khz = (float)width / 1000.0;
float final_khz = find_closest_bandwidth(target_khz, bw_list);
@@ -179,11 +179,11 @@ int harris_set_mode(RIG *rig, vfo_t vfo, rmode_t mode, pbwidth_t width)
default: return -RIG_EINVAL;
}
- /* 1. Cambia il Modo */
+ /* 1. Change Mode */
snprintf(cmd, sizeof(cmd), "MODE %s\r", mstr);
if (harris_transaction(rig, cmd, NULL, 0) != RIG_OK) return -RIG_EIO;
- /* 2. Cambia la banda usando la nuova funzione (se width > 0) */
+ /* 2. Change bandwidth using the new function (if width > 0) */
if (width > 0 && width != RIG_PASSBAND_NORMAL) {
return harris_set_pb_width(rig, vfo, width);
}
@@ -198,7 +198,7 @@ int harris_get_mode(RIG *rig, vfo_t vfo, rmode_t *mode, pbwidth_t *width)
if (harris_transaction(rig, "MODE\r", buf, sizeof(buf)) != RIG_OK) return -RIG_EIO;
- /* Parsing Modo */
+ /* Mode Parsing */
p = strstr(buf, "MODE ");
if (p) {
p += 5;
@@ -208,7 +208,7 @@ int harris_get_mode(RIG *rig, vfo_t vfo, rmode_t *mode, pbwidth_t *width)
else if (strncmp(p, "AME", 3) == 0 || strncmp(p, "AM", 2) == 0) *mode = RIG_MODE_AM;
}
- /* Parsing Banda (Filtro) */
+ /* Band Parsing (Filter) */
p = strstr(buf, "BAND ");
if (p) {
*width = (pbwidth_t)(atof(p + 5) * 1000.0);
@@ -221,7 +221,7 @@ int harris_get_level(RIG *rig, vfo_t vfo, setting_t level, value_t *val)
{
char buf[2048];
- /* Caso speciale per il Preamp: il comando SH non lo mostra nel dump */
+ /* Special case for Preamp: SH command doesn't show it in dump */
if (level == RIG_LEVEL_PREAMP) {
if (harris_transaction(rig, "PRE\r", buf, sizeof(buf)) != RIG_OK) {
return -RIG_EIO;
@@ -230,7 +230,7 @@ int harris_get_level(RIG *rig, vfo_t vfo, setting_t level, value_t *val)
return RIG_OK;
}
- /* Per tutti gli altri livelli usiamo il dump SH */
+ /* For all other levels we use the SH dump */
if (harris_transaction(rig, "SH\r", buf, sizeof(buf)) != RIG_OK) {
return -RIG_EIO;
}
@@ -298,7 +298,7 @@ int harris_set_level(RIG *rig, vfo_t vfo, setting_t level, value_t val)
else if (val.i == RIG_AGC_MEDIUM) p_str = "MED";
else if (val.i == RIG_AGC_FAST) p_str = "FAST";
else p_str = "SLOW";
- snprintf(cmd, sizeof(cmd), "AGC %s\r", p_str); // Usiamo AGC esteso
+ snprintf(cmd, sizeof(cmd), "AGC %s\r", p_str); // Use extended AGC
break;
case RIG_LEVEL_RF:
@@ -306,7 +306,7 @@ int harris_set_level(RIG *rig, vfo_t vfo, setting_t level, value_t val)
break;
case RIG_LEVEL_PREAMP:
- // Cruciale: Solo "ENA" e "BYP" funzionano davvero
+ // Crucial: Only "ENA" and "BYP" actually work
snprintf(cmd, sizeof(cmd), "PRE %s\r", (val.i > 0) ? "ENA" : "BYP");
break;
@@ -322,20 +322,20 @@ int harris_set_func(RIG *rig, vfo_t vfo, setting_t func, int status)
{
char cmd[64];
- /* Supportiamo solo lo Squelch in questa funzione */
+ /* Only Squelch is supported in this function */
if (func != RIG_FUNC_SQL) {
- rig_debug(RIG_DEBUG_TRACE, "%s: funzione %lu non supportata\n", __func__, func);
+ rig_debug(RIG_DEBUG_TRACE, "%s: function %lu not supported\n", __func__, func);
return -RIG_EINVAL;
}
- /* Comando Harris: SQ ON per attivare, SQ OF per disattivare */
- /* Nota: Usiamo 'OF' con una sola F come da logica dei tuoi test precedenti */
+ /* Harris Command: SQ ON to activate, SQ OF to deactivate */
+ /* Note: Using 'OF' with single F as per previous test logic */
snprintf(cmd, sizeof(cmd), "SQ %s\r", status ? "ON" : "OF");
- rig_debug(RIG_DEBUG_VERBOSE, "%s: impostazione Squelch status %d [%s]\n",
+ rig_debug(RIG_DEBUG_VERBOSE, "%s: setting Squelch status %d [%s]\n",
__func__, status, cmd);
- /* Usiamo la transazione centralizzata per attendere il prompt SSB> */
+ /* Use centralized transaction to wait for SSB> prompt */
return harris_transaction(rig, cmd, NULL, 0);
}
@@ -343,21 +343,21 @@ int harris_get_ptt(RIG *rig, vfo_t vfo, ptt_t *ptt)
{
char buf[512];
- rig_debug(RIG_DEBUG_VERBOSE, "%s: query stato PTT\n", __func__);
+ rig_debug(RIG_DEBUG_VERBOSE, "%s: PTT status query\n", __func__);
- /* Usiamo la transazione centralizzata inviando solo 'K' */
+ /* Use centralized transaction by sending only 'K' */
if (harris_transaction(rig, "K\r", buf, sizeof(buf)) != RIG_OK) {
return -RIG_EIO;
}
- /* Analisi della risposta nel buffer */
- /* La radio tipicamente risponde con "KEY ON", "KEY MIC" o "KEY OFF" */
+ /* Response analysis in buffer */
+ /* Radio typically responds with "KEY ON", "KEY MIC" or "KEY OFF" */
if (strstr(buf, "KEY ON") || strstr(buf, "KEY MIC")) {
*ptt = RIG_PTT_ON;
} else if (strstr(buf, "KEY OFF")) {
*ptt = RIG_PTT_OFF;
} else {
- /* Fallback di sicurezza basato su stringhe parziali */
+ /* Safety fallback based on partial strings */
if (strstr(buf, "ON")) {
*ptt = RIG_PTT_ON;
} else {
@@ -365,7 +365,7 @@ int harris_get_ptt(RIG *rig, vfo_t vfo, ptt_t *ptt)
}
}
- rig_debug(RIG_DEBUG_TRACE, "%s: PTT rilevato: %s\n",
+ rig_debug(RIG_DEBUG_TRACE, "%s: PTT detected: %s\n",
__func__, (*ptt == RIG_PTT_ON) ? "ON" : "OFF");
return RIG_OK;
@@ -375,13 +375,13 @@ int harris_set_ptt(RIG *rig, vfo_t vfo, ptt_t ptt)
{
char cmd[16];
- /* Costruiamo il comando: K ON per attivare, K OF per disattivare */
- /* Nota: mantengo 'OF' con una sola F come da tua implementazione originale */
+ /* Build command: K ON to activate, K OF to deactivate */
+ /* Note: maintaining 'OF' with single F as per original implementation */
snprintf(cmd, sizeof(cmd), "K %s\r", (ptt == RIG_PTT_ON) ? "ON" : "OF");
- rig_debug(RIG_DEBUG_VERBOSE, "%s: impostazione PTT [%s]\n", __func__, cmd);
+ rig_debug(RIG_DEBUG_VERBOSE, "%s: setting PTT [%s]\n", __func__, cmd);
- /* Invio tramite transazione (ignora la risposta testuale, cerca solo il prompt) */
+ /* Send via transaction (ignore text response, just look for prompt) */
return harris_transaction(rig, cmd, NULL, 0);
}
commit 2df512825143b4a98e361b5e0f4507c9a4082bc0
Author: Rega57 <ant...@bl...>
Date: Sun Mar 29 17:28:25 2026 +0200
Add support for Harris PRC-138
This is the first implementation of basic funtionality of Harris PRC-138.
(cherry picked from commit f880cac0ad19c8da13d82428dbfbf562e093921f)
diff --git a/configure.ac b/configure.ac
index 9a2f56998..8432154e1 100644
--- a/configure.ac
+++ b/configure.ac
@@ -66,7 +66,7 @@ dnl added to AC_CONFIG_FILES near the end of this file. See README.developer
dnl Beware of duplication should a backend directory include both rig and
dnl rotor definitions, e.g. "dummy". Optional backends will not be listed
dnl here but will be added later, e.g. "winradio".
-RIG_BACKEND_LIST="rigs/adat rigs/alinco rigs/aor rigs/barrett rigs/codan rigs/dorji rigs/drake rigs/dummy rigs/elad rigs/flexradio rigs/icom rigs/icmarine rigs/jrc rigs/kachina rigs/kenwood rigs/kit rigs/lowe rigs/pcr rigs/prm80 rigs/racal rigs/rft rigs/rs rigs/simplecat rigs/skanti rigs/tapr rigs/tentec rigs/tuner rigs/uniden rigs/wj rigs/yaesu rigs/gomspace rigs/mds rigs/anytone rigs/motorola rigs/commradio rigs/guohetec"
+RIG_BACKEND_LIST="rigs/adat rigs/alinco rigs/aor rigs/barrett rigs/codan rigs/dorji rigs/drake rigs/dummy rigs/elad rigs/flexradio rigs/icom rigs/icmarine rigs/jrc rigs/kachina rigs/kenwood rigs/kit rigs/lowe rigs/pcr rigs/prm80 rigs/racal rigs/rft rigs/rs rigs/simplecat rigs/skanti rigs/tapr rigs/tentec rigs/tuner rigs/uniden rigs/wj rigs/yaesu rigs/gomspace rigs/mds rigs/anytone rigs/motorola rigs/commradio rigs/guohetec rigs/harris"
RIG_BACKEND_OPTIONAL_LIST=""
ROT_BACKEND_LIST="rotators/amsat rotators/apex rotators/ars rotators/celestron rotators/cnctrk rotators/grbltrk rotators/easycomm rotators/ether6 rotators/flir rotators/fodtrack rotators/gs232a rotators/heathkit rotators/m2 rotators/meade rotators/rotorez rotators/sartek rotators/saebrtrack rotators/spid rotators/ts7400 rotators/prosistel rotators/ioptron rotators/satel rotators/skywatcher rotators/radant"
ROT_BACKEND_OPTIONAL_LIST=""
@@ -931,6 +931,7 @@ rigs/drake/Makefile
rigs/dummy/Makefile
rigs/elad/Makefile
rigs/flexradio/Makefile
+rigs/harris/Makefile
rigs/icmarine/Makefile
rigs/icom/Makefile
rigs/jrc/Makefile
diff --git a/include/hamlib/riglist.h b/include/hamlib/riglist.h
index b2cd832df..7c6d683fe 100644
--- a/include/hamlib/riglist.h
+++ b/include/hamlib/riglist.h
@@ -1140,6 +1140,23 @@
#define RIG_MODEL_SIMPLECAT RIG_MAKE_MODEL(RIG_SIMPLECAT, 1)
///@}
+/*
+ * HARRIS
+ */
+/** The `HARRIS` family. */
+#define RIG_HARRIS 42
+/** Used in register.c for the `be_name`. */
+#define RIG_BACKEND_HARRIS "harris"
+
+/**
+ * \name HARRIS
+ * HARRIS models.
+ */
+///@{
+/// Model of the `RIG_HARRIS` backend family.
+#define RIG_MODEL_PRC138 RIG_MAKE_MODEL(RIG_HARRIS, 1)
+///@}
+
/** Convenience type definition for rig model. */
typedef uint32_t rig_model_t;
diff --git a/rigs/harris/Makefile.am b/rigs/harris/Makefile.am
new file mode 100644
index 000000000..0264bc37a
--- /dev/null
+++ b/rigs/harris/Makefile.am
@@ -0,0 +1,6 @@
+HARRISSRC = harris.c prc138.c
+
+noinst_LTLIBRARIES = libhamlib-harris.la
+libhamlib_harris_la_SOURCES = $(HARRISSRC)
+
+EXTRA_DIST = Android.mk
diff --git a/rigs/harris/harris.c b/rigs/harris/harris.c
new file mode 100644
index 000000000..ccea2f6b3
--- /dev/null
+++ b/rigs/harris/harris.c
@@ -0,0 +1,416 @@
+#include <ctype.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "hamlib/rig.h"
+#include "register.h"
+#include "iofunc.h"
+#include "harris.h"
+#include "prc138.h"
+
+static const float bw_ssb[] = {1.5, 2.0, 2.4, 2.7, 3.0, 0};
+static const float bw_cw[] = {0.35, 0.68, 1.0, 1.5, 0};
+static const float bw_am[] = {3.0, 4.0, 5.0, 6.0, 0};
+
+static int harris_transaction(RIG *rig, const char *cmd, char *resp, int resp_len)
+{
+ unsigned char buf[128];
+ char local_buf[512];
+ char *target_buf = resp ? resp : local_buf;
+ int target_len = resp ? resp_len : sizeof(local_buf);
+ int retry = 15;
+
+ target_buf[0] = '\0';
+
+ /* 1. Pulizia fisica del buffer */
+ rig_flush(RIGPORT(rig));
+
+ /* 2. Invio del comando */
+ if (write_block(RIGPORT(rig), (unsigned char *)cmd, strlen(cmd)) < 0) {
+ return -RIG_EIO;
+ }
+
+ /* 3. Loop di accumulo */
+ while (retry > 0) {
+ usleep(10000); //150000
+
+ memset(buf, 0, sizeof(buf));
+ (void) read_block(RIGPORT(rig), buf, sizeof(buf) - 1);
+
+ if (buf[0] != '\0') {
+ strncat(target_buf, (char *)buf, target_len - strlen(target_buf) - 1);
+
+ /* Se troviamo il prompt con lo spazio, abbiamo finito */
+ if (strstr(target_buf, "SSB> ")) {
+ return RIG_OK;
+ }
+ }
+ retry--;
+ }
+ return -RIG_EIO;
+}
+
+int harris_set_freq(RIG *rig, vfo_t vfo, freq_t freq)
+{
+ char cmd[64];
+
+ rig_debug(RIG_DEBUG_VERBOSE, "%s: impostazione frequenza a %.0f Hz\n", __func__, freq);
+
+ /* Il formato %08.0f è CRUCIALE:
+ - 0 significa 'riempi con zeri'
+ - 8 significa 'lunghezza totale di 8 caratteri'
+ - .0f significa 'numero reale senza decimali'
+ Esempio: 7000000 diventa 07000000 */
+ snprintf(cmd, sizeof(cmd), "FR %08.0f\r", freq);
+
+ /* Usiamo la nostra fidata harris_transaction */
+ if (harris_transaction(rig, cmd, NULL, 0) != RIG_OK) {
+ rig_debug(RIG_DEBUG_ERR, "%s: errore nella transazione FR\n", __func__);
+ return -RIG_EIO;
+ }
+
+ return RIG_OK;
+}
+
+int harris_get_freq(RIG *rig, vfo_t vfo, freq_t *freq)
+{
+ char buf[512];
+ char *p;
+
+ rig_debug(RIG_DEBUG_VERBOSE, "%s: richiesta frequenza\n", __func__);
+
+ /* 1. Eseguiamo la transazione completa */
+ if (harris_transaction(rig, "FR\r", buf, sizeof(buf)) != RIG_OK) {
+ rig_debug(RIG_DEBUG_ERR, "%s: errore nella transazione FR\n", __func__);
+ return -RIG_EIO;
+ }
+
+ /* 2. Cerchiamo la riga della frequenza di ricezione "RxFr " */
+ p = strstr(buf, "RxFr ");
+ if (p) {
+ /* Saltiamo "RxFr " (5 caratteri) e leggiamo il numero */
+ /* sscanf è più robusto di atof per stringhe che terminano con caratteri speciali */
+ if (sscanf(p + 5, "%lf", freq) != 1) {
+ rig_debug(RIG_DEBUG_ERR, "%s: formato frequenza non riconosciuto in [%s]\n", __func__, p);
+ return -RIG_EPROTO;
+ }
+
+ rig_debug(RIG_DEBUG_VERBOSE, "%s: frequenza letta: %.0f Hz\n", __func__, *freq);
+ return RIG_OK;
+ }
+
+ rig_debug(RIG_DEBUG_ERR, "%s: stringa RxFr non trovata nella risposta\n", __func__);
+ return -RIG_EPROTO;
+}
+
+int harris_open(RIG *rig)
+{
+ rig_debug(RIG_DEBUG_VERBOSE, "%s: Apertura e sincronizzazione prompt\n", __func__);
+
+ /* Inviamo un semplice ritorno a capo per sollecitare il prompt */
+ /* Passiamo NULL come buffer di risposta perché ci interessa solo l'esito (RIG_OK) */
+ if (harris_transaction(rig, "\r", NULL, 0) != RIG_OK) {
+ rig_debug(RIG_DEBUG_ERR, "%s: La radio non risponde al prompt iniziale\n", __func__);
+ return -RIG_EIO;
+ }
+
+ rig_debug(RIG_DEBUG_VERBOSE, "%s: Connessione stabilita con successo\n", __func__);
+ return RIG_OK;
+}
+
+static float find_closest_bandwidth(float target, const float *list) {
+ float closest = list[0];
+ float min_diff = 99.0; // Valore iniziale alto
+
+ for (int i = 0; list[i] != 0; i++) {
+ float diff = target - list[i];
+ if (diff < 0) diff = -diff; // Valore assoluto
+
+ if (diff < min_diff) {
+ min_diff = diff;
+ closest = list[i];
+ }
+ }
+ return closest;
+}
+
+int harris_set_pb_width(RIG *rig, vfo_t vfo, pbwidth_t width)
+{
+ char cmd[64];
+ rmode_t current_mode;
+ pbwidth_t current_width;
+ const float *bw_list;
+
+ rig_debug(RIG_DEBUG_VERBOSE, "%s: richiesta variazione larghezza banda a %ld Hz\n", __func__, width);
+
+ /* 1. Recuperiamo il modo attuale per sapere quale tabella usare */
+ if (harris_get_mode(rig, vfo, ¤t_mode, ¤t_width) != RIG_OK) {
+ return -RIG_EIO;
+ }
+
+ /* 2. Selezioniamo la tabella corretta */
+ switch (current_mode) {
+ case RIG_MODE_USB:
+ case RIG_MODE_LSB: bw_list = bw_ssb; break;
+ case RIG_MODE_CW: bw_list = bw_cw; break;
+ case RIG_MODE_AM: bw_list = bw_am; break;
+ default: bw_list = bw_ssb; // Fallback
+ }
+
+ /* 3. Approssimazione e invio */
+ float target_khz = (float)width / 1000.0;
+ float final_khz = find_closest_bandwidth(target_khz, bw_list);
+
+ snprintf(cmd, sizeof(cmd), "BAND %.2f\r", final_khz);
+ return harris_transaction(rig, cmd, NULL, 0);
+}
+
+int harris_set_mode(RIG *rig, vfo_t vfo, rmode_t mode, pbwidth_t width)
+{
+ char cmd[64];
+ const char *mstr;
+
+ switch (mode) {
+ case RIG_MODE_USB: mstr = "USB"; break;
+ case RIG_MODE_LSB: mstr = "LSB"; break;
+ case RIG_MODE_CW: mstr = "CW"; break;
+ case RIG_MODE_AM: mstr = "AME"; break;
+ default: return -RIG_EINVAL;
+ }
+
+ /* 1. Cambia il Modo */
+ snprintf(cmd, sizeof(cmd), "MODE %s\r", mstr);
+ if (harris_transaction(rig, cmd, NULL, 0) != RIG_OK) return -RIG_EIO;
+
+ /* 2. Cambia la banda usando la nuova funzione (se width > 0) */
+ if (width > 0 && width != RIG_PASSBAND_NORMAL) {
+ return harris_set_pb_width(rig, vfo, width);
+ }
+
+ return RIG_OK;
+}
+
+int harris_get_mode(RIG *rig, vfo_t vfo, rmode_t *mode, pbwidth_t *width)
+{
+ char buf[512];
+ char *p;
+
+ if (harris_transaction(rig, "MODE\r", buf, sizeof(buf)) != RIG_OK) return -RIG_EIO;
+
+ /* Parsing Modo */
+ p = strstr(buf, "MODE ");
+ if (p) {
+ p += 5;
+ if (strncmp(p, "USB", 3) == 0) *mode = RIG_MODE_USB;
+ else if (strncmp(p, "LSB", 3) == 0) *mode = RIG_MODE_LSB;
+ else if (strncmp(p, "CW", 2) == 0) *mode = RIG_MODE_CW;
+ else if (strncmp(p, "AME", 3) == 0 || strncmp(p, "AM", 2) == 0) *mode = RIG_MODE_AM;
+ }
+
+ /* Parsing Banda (Filtro) */
+ p = strstr(buf, "BAND ");
+ if (p) {
+ *width = (pbwidth_t)(atof(p + 5) * 1000.0);
+ }
+
+ return RIG_OK;
+}
+
+int harris_get_level(RIG *rig, vfo_t vfo, setting_t level, value_t *val)
+{
+ char buf[2048];
+
+ /* Caso speciale per il Preamp: il comando SH non lo mostra nel dump */
+ if (level == RIG_LEVEL_PREAMP) {
+ if (harris_transaction(rig, "PRE\r", buf, sizeof(buf)) != RIG_OK) {
+ return -RIG_EIO;
+ }
+ val->i = strstr(buf, "Preamp Enabled") ? 1 : 0;
+ return RIG_OK;
+ }
+
+ /* Per tutti gli altri livelli usiamo il dump SH */
+ if (harris_transaction(rig, "SH\r", buf, sizeof(buf)) != RIG_OK) {
+ return -RIG_EIO;
+ }
+
+ switch (level) {
+ case RIG_LEVEL_SQL:
+ if (strstr(buf, "SQ_LEVEL LOW")) val->f = 0.1f;
+ else if (strstr(buf, "SQ_LEVEL MED")) val->f = 0.5f;
+ else if (strstr(buf, "SQ_LEVEL HIGH")) val->f = 1.0f;
+ else val->f = 0.0f;
+ break;
+
+ case RIG_LEVEL_RFPOWER:
+ if (strstr(buf, "POWER low")) val->f = 0.1f;
+ else if (strstr(buf, "POWER med")) val->f = 0.5f;
+ else if (strstr(buf, "POWER hi")) val->f = 1.0f;
+ else val->f = 0.0f;
+ break;
+
+ case RIG_LEVEL_AGC:
+ if (strstr(buf, "AGC OFF")) val->i = RIG_AGC_OFF;
+ else if (strstr(buf, "AGC SLOW")) val->i = RIG_AGC_SLOW;
+ else if (strstr(buf, "AGC MED")) val->i = RIG_AGC_MEDIUM;
+ else if (strstr(buf, "AGC FAST")) val->i = RIG_AGC_FAST;
+ break;
+
+ case RIG_LEVEL_RF:
+ {
+ char *p = strstr(buf, "RFG ");
+ if (p) val->f = (float)atoi(p + 4) / 100.0f;
+ else val->f = 1.0f;
+ }
+ break;
+
+ default:
+ return -RIG_EINVAL;
+ }
+
+ return RIG_OK;
+}
+
+int harris_set_level(RIG *rig, vfo_t vfo, setting_t level, value_t val)
+{
+ char cmd[64];
+ const char *p_str;
+
+ switch (level) {
+ case RIG_LEVEL_SQL:
+ if (val.f <= 0.33f) p_str = "LOW";
+ else if (val.f <= 0.66f) p_str = "MED";
+ else p_str = "HIGH";
+ snprintf(cmd, sizeof(cmd), "SQ_L %s\r", p_str);
+ break;
+
+ case RIG_LEVEL_RFPOWER:
+ if (val.f <= 0.33f) p_str = "LOW";
+ else if (val.f <= 0.66f) p_str = "MED";
+ else p_str = "HIGH";
+ snprintf(cmd, sizeof(cmd), "POW %s\r", p_str);
+ break;
+
+ case RIG_LEVEL_AGC:
+ if (val.i == RIG_AGC_OFF) p_str = "OF";
+ else if (val.i == RIG_AGC_SLOW) p_str = "SLOW";
+ else if (val.i == RIG_AGC_MEDIUM) p_str = "MED";
+ else if (val.i == RIG_AGC_FAST) p_str = "FAST";
+ else p_str = "SLOW";
+ snprintf(cmd, sizeof(cmd), "AGC %s\r", p_str); // Usiamo AGC esteso
+ break;
+
+ case RIG_LEVEL_RF:
+ snprintf(cmd, sizeof(cmd), "RFG %d\r", (int)(val.f * 100));
+ break;
+
+ case RIG_LEVEL_PREAMP:
+ // Cruciale: Solo "ENA" e "BYP" funzionano davvero
+ snprintf(cmd, sizeof(cmd), "PRE %s\r", (val.i > 0) ? "ENA" : "BYP");
+ break;
+
+ default:
+ return -RIG_EINVAL;
+ }
+
+ return harris_transaction(rig, cmd, NULL, 0);
+}
+
+
+int harris_set_func(RIG *rig, vfo_t vfo, setting_t func, int status)
+{
+ char cmd[64];
+
+ /* Supportiamo solo lo Squelch in questa funzione */
+ if (func != RIG_FUNC_SQL) {
+ rig_debug(RIG_DEBUG_TRACE, "%s: funzione %lu non supportata\n", __func__, func);
+ return -RIG_EINVAL;
+ }
+
+ /* Comando Harris: SQ ON per attivare, SQ OF per disattivare */
+ /* Nota: Usiamo 'OF' con una sola F come da logica dei tuoi test precedenti */
+ snprintf(cmd, sizeof(cmd), "SQ %s\r", status ? "ON" : "OF");
+
+ rig_debug(RIG_DEBUG_VERBOSE, "%s: impostazione Squelch status %d [%s]\n",
+ __func__, status, cmd);
+
+ /* Usiamo la transazione centralizzata per attendere il prompt SSB> */
+ return harris_transaction(rig, cmd, NULL, 0);
+}
+
+int harris_get_ptt(RIG *rig, vfo_t vfo, ptt_t *ptt)
+{
+ char buf[512];
+
+ rig_debug(RIG_DEBUG_VERBOSE, "%s: query stato PTT\n", __func__);
+
+ /* Usiamo la transazione centralizzata inviando solo 'K' */
+ if (harris_transaction(rig, "K\r", buf, sizeof(buf)) != RIG_OK) {
+ return -RIG_EIO;
+ }
+
+ /* Analisi della risposta nel buffer */
+ /* La radio tipicamente risponde con "KEY ON", "KEY MIC" o "KEY OFF" */
+ if (strstr(buf, "KEY ON") || strstr(buf, "KEY MIC")) {
+ *ptt = RIG_PTT_ON;
+ } else if (strstr(buf, "KEY OFF")) {
+ *ptt = RIG_PTT_OFF;
+ } else {
+ /* Fallback di sicurezza basato su stringhe parziali */
+ if (strstr(buf, "ON")) {
+ *ptt = RIG_PTT_ON;
+ } else {
+ *ptt = RIG_PTT_OFF;
+ }
+ }
+
+ rig_debug(RIG_DEBUG_TRACE, "%s: PTT rilevato: %s\n",
+ __func__, (*ptt == RIG_PTT_ON) ? "ON" : "OFF");
+
+ return RIG_OK;
+}
+
+int harris_set_ptt(RIG *rig, vfo_t vfo, ptt_t ptt)
+{
+ char cmd[16];
+
+ /* Costruiamo il comando: K ON per attivare, K OF per disattivare */
+ /* Nota: mantengo 'OF' con una sola F come da tua implementazione originale */
+ snprintf(cmd, sizeof(cmd), "K %s\r", (ptt == RIG_PTT_ON) ? "ON" : "OF");
+
+ rig_debug(RIG_DEBUG_VERBOSE, "%s: impostazione PTT [%s]\n", __func__, cmd);
+
+ /* Invio tramite transazione (ignora la risposta testuale, cerca solo il prompt) */
+ return harris_transaction(rig, cmd, NULL, 0);
+}
+
+int harris_init(RIG *rig) {
+ struct harris_priv_data *priv;
+
+ priv = (struct harris_priv_data *)calloc(1, sizeof(struct harris_priv_data));
+ if (!priv) return -RIG_ENOMEM;
+
+ rig->caps->priv = (void *)priv;
+ return RIG_OK;
+}
+
+int harris_cleanup(RIG *rig) {
+ if (rig->caps->priv) {
+ free((void *)rig->caps->priv);
+ rig->caps->priv = NULL;
+ }
+ return RIG_OK;
+}
+
+int harris_close(RIG *rig) {
+ return RIG_OK;
+}
+
+/* This macro expands the initrigs5_harris function. */
+DECLARE_INITRIG_BACKEND(harris)
+{
+ rig_debug(RIG_DEBUG_VERBOSE, "%s: _init called\n", __func__);
+ rig_register((struct rig_caps *)&prc138_caps);
+ return RIG_OK;
+}
diff --git a/rigs/harris/harris.h b/rigs/harris/harris.h
new file mode 100644
index 000000000..1697628a9
--- /dev/null
+++ b/rigs/harris/harris.h
@@ -0,0 +1,27 @@
+#ifndef _HARRIS_H
+#define _HARRIS_H
+
+#include <hamlib/rig.h>
+
+struct harris_priv_data {
+ freq_t current_freq;
+ rmode_t current_mode;
+};
+
+/* Prototypes for prc138.c */
+int harris_init(RIG *rig);
+int harris_cleanup(RIG *rig);
+int harris_open(RIG *rig);
+int harris_close(RIG *rig);
+int harris_set_freq(RIG *rig, vfo_t vfo, freq_t freq);
+int harris_get_freq(RIG *rig, vfo_t vfo, freq_t *freq);
+int harris_set_mode(RIG *rig, vfo_t vfo, rmode_t mode, pbwidth_t width);
+int harris_get_mode(RIG *rig, vfo_t vfo, rmode_t *mode, pbwidth_t *width);
+int harris_set_level(RIG *rig, vfo_t vfo, setting_t level, value_t val);
+int harris_get_level(RIG *rig, vfo_t vfo, setting_t level, value_t *val);
+int harris_set_func(RIG *rig, vfo_t vfo, setting_t func, int status);
+int harris_get_bw(RIG *rig, vfo_t vfo, mode_t mode, pbwidth_t *width);
+int harris_get_ptt(RIG *rig, vfo_t vfo, ptt_t *ptt);
+int harris_set_ptt(RIG *rig, vfo_t vfo, ptt_t ptt);
+
+#endif
diff --git a/rigs/harris/prc138.c b/rigs/harris/prc138.c
new file mode 100644
index 000000000..d0eacb52e
--- /dev/null
+++ b/rigs/harris/prc138.c
@@ -0,0 +1,87 @@
+#include "harris.h"
+#include "prc138.h"
+
+/**
+ * Harris PRC-138 Capabilities
+ */
+struct rig_caps prc138_caps = {
+ .rig_model = RIG_MODEL_PRC138,
+ .model_name = "PRC-138",
+ .mfg_name = "Harris",
+ .version = "1.0.6",
+ .port_type = RIG_PORT_SERIAL,
+
+ /* Frequency Ranges with correct brace nesting */
+ .rx_range_list1 = {
+ {
+ .startf = kHz(1600), .endf = MHz(60), .modes = PRC138_MODES,
+ .low_power = -1, .high_power = -1, .vfo = PRC138_VFO
+ },
+ RIG_FRNG_END,
+ },
+ .tx_range_list1 = {
+ {
+ .startf = kHz(1600), .endf = MHz(60), .modes = PRC138_MODES,
+ .low_power = W(1), .high_power = W(20), .vfo = PRC138_VFO
+ },
+ RIG_FRNG_END,
+ },
+ .tuning_steps = { {RIG_MODE_ALL, 100}, {RIG_MODE_ALL, RIG_TS_ANY}, {0, 0} },
+
+ /* Serial Parameters */
+ .serial_rate_min = 75,
+ .serial_rate_max = 9600,
+ .serial_data_bits = 8,
+ .serial_stop_bits = 1,
+ .serial_parity = RIG_PARITY_NONE,
+ .serial_handshake = RIG_HANDSHAKE_NONE,
+ .write_delay = 0, //50
+ .post_write_delay = 50, //100
+ .timeout = 200, //200
+ .retry = 0, //3
+
+ /* Passband filters definition directly inside caps to fix pointer warning */
+ .filters = {
+ /* SSB (USB/LSB): 2.7 (def), 1.5, 2.0, 2.4, 3.0 kHz */
+ {RIG_MODE_SSB, kHz(2.7)},
+ {RIG_MODE_SSB, kHz(1.5)},
+ {RIG_MODE_SSB, kHz(2.0)},
+ {RIG_MODE_SSB, kHz(2.4)},
+ {RIG_MODE_SSB, kHz(3.0)},
+
+ /* CW: 1.0 (def), 0.35, 0.68, 1.5 kHz */
+ {RIG_MODE_CW, kHz(1.0)},
+ {RIG_MODE_CW, 350},
+ {RIG_MODE_CW, 680},
+ {RIG_MODE_CW, kHz(1.5)},
+
+ /* AME: 6.0 (def), 3.0, 4.0, 5.0 kHz */
+ {RIG_MODE_AM, kHz(6.0)},
+ {RIG_MODE_AM, kHz(3.0)},
+ {RIG_MODE_AM, kHz(4.0)},
+ {RIG_MODE_AM, kHz(5.0)},
+
+ RIG_FLT_END,
+ },
+
+ /* Capabilities */
+ .ptt_type = RIG_PTT_RIG,
+ .has_get_level = RIG_LEVEL_SQL | RIG_LEVEL_RFPOWER | RIG_LEVEL_AGC | RIG_LEVEL_RF | RIG_LEVEL_PREAMP,
+ .has_set_level = RIG_LEVEL_SQL | RIG_LEVEL_RFPOWER | RIG_LEVEL_AGC | RIG_LEVEL_RF | RIG_LEVEL_PREAMP,
+ .has_set_func = RIG_FUNC_SQL,
+
+ /* Function Callbacks */
+ .rig_init = harris_init,
+ .rig_cleanup = harris_cleanup,
+ .rig_open = harris_open,
+ .rig_close = harris_close,
+ .set_freq = harris_set_freq,
+ .get_freq = harris_get_freq,
+ .set_mode = harris_set_mode,
+ .get_mode = harris_get_mode,
+ .set_ptt = harris_set_ptt,
+ .get_ptt = harris_get_ptt,
+ .set_level = harris_set_level,
+ .get_level = harris_get_level,
+ .set_func = harris_set_func,
+};
diff --git a/rigs/harris/prc138.h b/rigs/harris/prc138.h
new file mode 100644
index 000000000..17142bbc6
--- /dev/null
+++ b/rigs/harris/prc138.h
@@ -0,0 +1,11 @@
+#ifndef _PRC138_H
+#define _PRC138_H
+
+#include <hamlib/rig.h>
+
+#define PRC138_MODES (RIG_MODE_USB | RIG_MODE_LSB | RIG_MODE_CW | RIG_MODE_AM)
+#define PRC138_VFO (RIG_VFO_A)
+
+extern struct rig_caps prc138_caps;
+
+#endif
diff --git a/src/register.c b/src/register.c
index cc3e09127..dd9ccfab1 100644
--- a/src/register.c
+++ b/src/register.c
@@ -92,7 +92,7 @@ DEFINE_INITRIG_BACKEND(anytone);
DEFINE_INITRIG_BACKEND(motorola);
DEFINE_INITRIG_BACKEND(commradio);
DEFINE_INITRIG_BACKEND(simplecat);
-
+DEFINE_INITRIG_BACKEND(harris);
//! @endcond
#ifdef HAVE_WINRADIO
@@ -157,6 +157,7 @@ static struct
{ RIG_MOTOROLA, RIG_BACKEND_MOTOROLA, RIG_FUNCNAMA(motorola) },
{ RIG_COMMRADIO, RIG_BACKEND_COMMRADIO, RIG_FUNCNAMA(commradio) },
{ RIG_SIMPLECAT, RIG_BACKEND_SIMPLECAT, RIG_FUNCNAMA(simplecat) },
+ { RIG_HARRIS, RIG_BACKEND_HARRIS, RIG_FUNCNAMA(harris) },
{ 0, NULL }, /* end */
};
-----------------------------------------------------------------------
Summary of changes:
NEWS | 1 +
configure.ac | 3 +-
include/hamlib/riglist.h | 17 ++
rigs/{dorji => harris}/Android.mk | 4 +-
rigs/harris/Makefile.am | 6 +
rigs/harris/harris.c | 442 +++++++++++++++++++++++++++++++
rigs/harris/harris.h | 53 ++++
rigs/harris/prc138.c | 113 ++++++++
rigs/{tentec/rx331.h => harris/prc138.h} | 22 +-
src/register.c | 3 +-
10 files changed, 651 insertions(+), 13 deletions(-)
copy rigs/{dorji => harris}/Android.mk (76%)
create mode 100644 rigs/harris/Makefile.am
create mode 100644 rigs/harris/harris.c
create mode 100644 rigs/harris/harris.h
create mode 100644 rigs/harris/prc138.c
copy rigs/{tentec/rx331.h => harris/prc138.h} (62%)
hooks/post-receive
--
Hamlib -- Ham radio control libraries
|
|
From: n0nb <n0...@us...> - 2026-04-10 23:42:58
|
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 452544e08ce14b51bb266645c92f1ba90de2d0d6 (commit)
via 4f4507fa8c8bb05040cd36ae7bb5866183b2a306 (commit)
via a27c1a22fda37081ebd371dacc1fbbdaf786df8f (commit)
via c7c45f2997a3cc7527bc69a36eea32e6d8cb9e7c (commit)
via 2cf182eb2af1eb67be4748d690010d0e7b33185a (commit)
via c3df0fc251e0f66c7586b9bb2f0a5095f48990d5 (commit)
via f880cac0ad19c8da13d82428dbfbf562e093921f (commit)
from bf5bea401268b28cce611a6ed7509b2dada74f5c (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 452544e08ce14b51bb266645c92f1ba90de2d0d6
Author: Nate Bargmann <n0...@n0...>
Date: Fri Apr 10 18:21:00 2026 -0500
Fixes to PR #2028
Add Android.mk.
Add header files to Makefile.am
Replace .rig_model member with RIG_MODEL() macro in prc138_caps
structure.
diff --git a/rigs/harris/Android.mk b/rigs/harris/Android.mk
new file mode 100644
index 000000000..e0226e1e1
--- /dev/null
+++ b/rigs/harris/Android.mk
@@ -0,0 +1,12 @@
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := harris.c prc138.c
+LOCAL_MODULE := harris
+
+LOCAL_CFLAGS :=
+LOCAL_C_INCLUDES := android include src
+LOCAL_LDLIBS := -lhamlib -Lobj/local/$(TARGET_ARCH_ABI)
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/rigs/harris/Makefile.am b/rigs/harris/Makefile.am
index 0264bc37a..2f3636240 100644
--- a/rigs/harris/Makefile.am
+++ b/rigs/harris/Makefile.am
@@ -1,4 +1,4 @@
-HARRISSRC = harris.c prc138.c
+HARRISSRC = harris.c harris.h prc138.c prc138.h
noinst_LTLIBRARIES = libhamlib-harris.la
libhamlib_harris_la_SOURCES = $(HARRISSRC)
diff --git a/rigs/harris/prc138.c b/rigs/harris/prc138.c
index e45fe7834..2e27599a6 100644
--- a/rigs/harris/prc138.c
+++ b/rigs/harris/prc138.c
@@ -31,7 +31,7 @@
* Harris PRC-138 Capabilities
*/
struct rig_caps prc138_caps = {
- .rig_model = RIG_MODEL_PRC138,
+ RIG_MODEL(RIG_MODEL_PRC138),
.model_name = "PRC-138",
.mfg_name = "Harris",
.version = "1.0.6",
commit 4f4507fa8c8bb05040cd36ae7bb5866183b2a306
Merge: a27c1a22f bf5bea401
Author: Nate Bargmann <n0...@n0...>
Date: Fri Apr 10 17:21:52 2026 -0500
Merge branch 'master' into PRC138
diff --cc configure.ac
index c2942656e,bca61fe59..f4b1d107f
--- a/configure.ac
+++ b/configure.ac
@@@ -66,7 -66,7 +66,7 @@@ dnl added to AC_CONFIG_FILES near the e
dnl Beware of duplication should a backend directory include both rig and
dnl rotor definitions, e.g. "dummy". Optional backends will not be listed
dnl here but will be added later, e.g. "winradio".
- RIG_BACKEND_LIST="rigs/adat rigs/alinco rigs/aor rigs/barrett rigs/codan rigs/dorji rigs/drake rigs/dummy rigs/elad rigs/flexradio rigs/icom rigs/icmarine rigs/jrc rigs/kachina rigs/kenwood rigs/kit rigs/lowe rigs/pcr rigs/prm80 rigs/racal rigs/rft rigs/rs rigs/skanti rigs/tapr rigs/tentec rigs/tuner rigs/uniden rigs/wj rigs/yaesu rigs/gomspace rigs/mds rigs/anytone rigs/motorola rigs/commradio rigs/guohetec rigs/harris"
-RIG_BACKEND_LIST="rigs/adat rigs/alinco rigs/aor rigs/barrett rigs/codan rigs/dorji rigs/drake rigs/dummy rigs/elad rigs/flexradio rigs/icom rigs/icmarine rigs/jrc rigs/kachina rigs/kenwood rigs/kit rigs/lowe rigs/pcr rigs/prm80 rigs/racal rigs/rft rigs/rs rigs/simplecat rigs/skanti rigs/tapr rigs/tentec rigs/tuner rigs/uniden rigs/wj rigs/yaesu rigs/gomspace rigs/mds rigs/anytone rigs/motorola rigs/commradio rigs/guohetec"
++RIG_BACKEND_LIST="rigs/adat rigs/alinco rigs/aor rigs/barrett rigs/codan rigs/dorji rigs/drake rigs/dummy rigs/elad rigs/flexradio rigs/icom rigs/icmarine rigs/jrc rigs/kachina rigs/kenwood rigs/kit rigs/lowe rigs/pcr rigs/prm80 rigs/racal rigs/rft rigs/rs rigs/simplecat rigs/skanti rigs/tapr rigs/tentec rigs/tuner rigs/uniden rigs/wj rigs/yaesu rigs/gomspace rigs/mds rigs/anytone rigs/motorola rigs/commradio rigs/guohetec rigs/harris"
RIG_BACKEND_OPTIONAL_LIST=""
ROT_BACKEND_LIST="rotators/amsat rotators/apex rotators/ars rotators/celestron rotators/cnctrk rotators/grbltrk rotators/easycomm rotators/ether6 rotators/flir rotators/fodtrack rotators/gs232a rotators/heathkit rotators/m2 rotators/meade rotators/rotorez rotators/sartek rotators/saebrtrack rotators/spid rotators/ts7400 rotators/prosistel rotators/ioptron rotators/satel rotators/skywatcher rotators/radant"
ROT_BACKEND_OPTIONAL_LIST=""
diff --cc include/hamlib/riglist.h
index a2bb386c9,b2cd832df..9eb036263
--- a/include/hamlib/riglist.h
+++ b/include/hamlib/riglist.h
@@@ -1123,21 -1123,21 +1123,37 @@@
#define RIG_MODEL_Q900 RIG_MAKE_MODEL(RIG_GUOHETEC, 2)
///@}
+ /*
+ * Simple CAT Protocol
+ */
+ /** The `SIMPLECAT` family. */
+ #define RIG_SIMPLECAT 41
+ /** Used in register.c for the `be_name`. */
+ #define RIG_BACKEND_SIMPLECAT "simplecat"
+
+ /**
+ * \name SIMPLECAT
+ * Simple CAT models.
+ */
+ ///@{
+ /// Model of the `RIG_SIMPLECAT` backend family.
+ #define RIG_MODEL_SIMPLECAT RIG_MAKE_MODEL(RIG_SIMPLECAT, 1)
++
+/*
+ * HARRIS
+ */
+/** The `HARRIS` family. */
- #define RIG_HARRIS 41
++#define RIG_HARRIS 42
+/** Used in register.c for the `be_name`. */
+#define RIG_BACKEND_HARRIS "harris"
+
+/**
+ * \name HARRIS
+ * HARRIS models.
+ */
+///@{
+/// Model of the `RIG_HARRIS` backend family.
+#define RIG_MODEL_PRC138 RIG_MAKE_MODEL(RIG_HARRIS, 1)
///@}
/** Convenience type definition for rig model. */
diff --cc src/register.c
index c0d18e489,cc3e09127..d0ad4a913
--- a/src/register.c
+++ b/src/register.c
@@@ -91,7 -91,8 +91,9 @@@ DEFINE_INITRIG_BACKEND(mds)
DEFINE_INITRIG_BACKEND(anytone);
DEFINE_INITRIG_BACKEND(motorola);
DEFINE_INITRIG_BACKEND(commradio);
+ DEFINE_INITRIG_BACKEND(simplecat);
+DEFINE_INITRIG_BACKEND(harris);
+
//! @endcond
#ifdef HAVE_WINRADIO
@@@ -155,7 -156,7 +157,8 @@@ static struc
{ RIG_ANYTONE, RIG_BACKEND_ANYTONE, RIG_FUNCNAMA(anytone) },
{ RIG_MOTOROLA, RIG_BACKEND_MOTOROLA, RIG_FUNCNAMA(motorola) },
{ RIG_COMMRADIO, RIG_BACKEND_COMMRADIO, RIG_FUNCNAMA(commradio) },
+ { RIG_SIMPLECAT, RIG_BACKEND_SIMPLECAT, RIG_FUNCNAMA(simplecat) },
+ { RIG_HARRIS, RIG_BACKEND_HARRIS, RIG_FUNCNAMA(harris) },
{ 0, NULL }, /* end */
};
commit a27c1a22fda37081ebd371dacc1fbbdaf786df8f
Author: Rega57 <ant...@bl...>
Date: Sat Apr 4 20:45:26 2026 +0200
Warning fixed long long
Line 353 debug long long function
diff --git a/rigs/harris/harris.c b/rigs/harris/harris.c
index a8cc05da6..21978869a 100644
--- a/rigs/harris/harris.c
+++ b/rigs/harris/harris.c
@@ -350,7 +350,7 @@ int harris_set_func(RIG *rig, vfo_t vfo, setting_t func, int status)
/* Only Squelch is supported in this function */
if (func != RIG_FUNC_SQL) {
- rig_debug(RIG_DEBUG_TRACE, "%s: function %lu not supported\n", __func__, func);
+ rig_debug(RIG_DEBUG_TRACE, "%s: function %llu not supported\n", __func__, (unsigned long long)func);
return -RIG_EINVAL;
}
commit c7c45f2997a3cc7527bc69a36eea32e6d8cb9e7c
Author: Rega57 <ant...@bl...>
Date: Sat Apr 4 17:00:20 2026 +0200
Initial comment with GPL added
Initial comment with GPL added
diff --git a/rigs/harris/harris.c b/rigs/harris/harris.c
index 27f549573..a8cc05da6 100644
--- a/rigs/harris/harris.c
+++ b/rigs/harris/harris.c
@@ -1,3 +1,29 @@
+/*
+ * Harris PRC-138 support developed by Antonio Regazzoni - HB9RBS
+ * Tested with three different PRC138 versions with following motherboard
+ * Firmware (module 01A) : 8211A, 8214D, 8214F.
+ * 04 april 2026
+ *
+ *
+ * Copyright (c) 2004-2010 by Stephane Fillod
+ *
+ *
+ * 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 <ctype.h>
#include <unistd.h>
#include <stdio.h>
diff --git a/rigs/harris/harris.h b/rigs/harris/harris.h
index 1697628a9..070e2a97f 100644
--- a/rigs/harris/harris.h
+++ b/rigs/harris/harris.h
@@ -1,3 +1,29 @@
+/*
+ * Harris PRC-138 support developed by Antonio Regazzoni - HB9RBS
+ * Tested with three different PRC138 versions with following motherboard
+ * Firmware (module 01A) : 8211A, 8214D, 8214F.
+ * 04 april 2026
+ *
+ *
+ * Copyright (c) 2004-2010 by Stephane Fillod
+ *
+ *
+ * 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 _HARRIS_H
#define _HARRIS_H
diff --git a/rigs/harris/prc138.c b/rigs/harris/prc138.c
index d0eacb52e..e45fe7834 100644
--- a/rigs/harris/prc138.c
+++ b/rigs/harris/prc138.c
@@ -1,3 +1,29 @@
+/*
+ * Harris PRC-138 support developed by Antonio Regazzoni - HB9RBS
+ * Tested with three different PRC138 versions with following motherboard
+ * Firmware (module 01A) : 8211A, 8214D, 8214F.
+ * 04 april 2026
+ *
+ *
+ * Copyright (c) 2004-2010 by Stephane Fillod
+ *
+ *
+ * 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 "harris.h"
#include "prc138.h"
diff --git a/rigs/harris/prc138.h b/rigs/harris/prc138.h
index 17142bbc6..2c2ceeeb5 100644
--- a/rigs/harris/prc138.h
+++ b/rigs/harris/prc138.h
@@ -1,3 +1,29 @@
+/*
+ * Harris PRC-138 support developed by Antonio Regazzoni - HB9RBS
+ * Tested with three different PRC138 versions with following motherboard
+ * Firmware (module 01A) : 8211A, 8214D, 8214F.
+ * 04 april 2026
+ *
+ *
+ * Copyright (c) 2004-2010 by Stephane Fillod
+ *
+ *
+ * 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 _PRC138_H
#define _PRC138_H
commit 2cf182eb2af1eb67be4748d690010d0e7b33185a
Author: Rega57 <ant...@bl...>
Date: Sat Apr 4 15:37:16 2026 +0200
Forced update
Forced update
diff --git a/rigs/harris/harris.c b/rigs/harris/harris.c
index 742b36fc1..27f549573 100644
--- a/rigs/harris/harris.c
+++ b/rigs/harris/harris.c
@@ -414,3 +414,4 @@ DECLARE_INITRIG_BACKEND(harris)
rig_register((struct rig_caps *)&prc138_caps);
return RIG_OK;
}
+
commit c3df0fc251e0f66c7586b9bb2f0a5095f48990d5
Author: Rega57 <ant...@bl...>
Date: Sat Apr 4 15:19:18 2026 +0200
Update harris.c
Replaced italian comments and logs with english text.
diff --git a/rigs/harris/harris.c b/rigs/harris/harris.c
index ccea2f6b3..742b36fc1 100644
--- a/rigs/harris/harris.c
+++ b/rigs/harris/harris.c
@@ -23,15 +23,15 @@ static int harris_transaction(RIG *rig, const char *cmd, char *resp, int resp_le
target_buf[0] = '\0';
- /* 1. Pulizia fisica del buffer */
+ /* 1. Physical buffer flush */
rig_flush(RIGPORT(rig));
- /* 2. Invio del comando */
+ /* 2. Send command */
if (write_block(RIGPORT(rig), (unsigned char *)cmd, strlen(cmd)) < 0) {
return -RIG_EIO;
}
- /* 3. Loop di accumulo */
+ /* 3. Accumulation loop */
while (retry > 0) {
usleep(10000); //150000
@@ -41,7 +41,7 @@ static int harris_transaction(RIG *rig, const char *cmd, char *resp, int resp_le
if (buf[0] != '\0') {
strncat(target_buf, (char *)buf, target_len - strlen(target_buf) - 1);
- /* Se troviamo il prompt con lo spazio, abbiamo finito */
+ /* If we find the prompt with space, we are done */
if (strstr(target_buf, "SSB> ")) {
return RIG_OK;
}
@@ -55,18 +55,18 @@ int harris_set_freq(RIG *rig, vfo_t vfo, freq_t freq)
{
char cmd[64];
- rig_debug(RIG_DEBUG_VERBOSE, "%s: impostazione frequenza a %.0f Hz\n", __func__, freq);
+ rig_debug(RIG_DEBUG_VERBOSE, "%s: setting frequency to %.0f Hz\n", __func__, freq);
- /* Il formato %08.0f è CRUCIALE:
- - 0 significa 'riempi con zeri'
- - 8 significa 'lunghezza totale di 8 caratteri'
- - .0f significa 'numero reale senza decimali'
- Esempio: 7000000 diventa 07000000 */
+ /* The %08.0f format is CRITICAL:
+ - 0 means 'pad with zeros'
+ - 8 means 'total length of 8 characters'
+ - .0f means 'real number without decimals'
+ Example: 7000000 becomes 07000000 */
snprintf(cmd, sizeof(cmd), "FR %08.0f\r", freq);
- /* Usiamo la nostra fidata harris_transaction */
+ /* Use our trusted harris_transaction */
if (harris_transaction(rig, cmd, NULL, 0) != RIG_OK) {
- rig_debug(RIG_DEBUG_ERR, "%s: errore nella transazione FR\n", __func__);
+ rig_debug(RIG_DEBUG_ERR, "%s: error in FR transaction\n", __func__);
return -RIG_EIO;
}
@@ -78,54 +78,54 @@ int harris_get_freq(RIG *rig, vfo_t vfo, freq_t *freq)
char buf[512];
char *p;
- rig_debug(RIG_DEBUG_VERBOSE, "%s: richiesta frequenza\n", __func__);
+ rig_debug(RIG_DEBUG_VERBOSE, "%s: frequency request\n", __func__);
- /* 1. Eseguiamo la transazione completa */
+ /* 1. Perform complete transaction */
if (harris_transaction(rig, "FR\r", buf, sizeof(buf)) != RIG_OK) {
- rig_debug(RIG_DEBUG_ERR, "%s: errore nella transazione FR\n", __func__);
+ rig_debug(RIG_DEBUG_ERR, "%s: error in FR transaction\n", __func__);
return -RIG_EIO;
}
- /* 2. Cerchiamo la riga della frequenza di ricezione "RxFr " */
+ /* 2. Look for the Rx frequency line "RxFr " */
p = strstr(buf, "RxFr ");
if (p) {
- /* Saltiamo "RxFr " (5 caratteri) e leggiamo il numero */
- /* sscanf è più robusto di atof per stringhe che terminano con caratteri speciali */
+ /* Skip "RxFr " (5 characters) and read the number */
+ /* sscanf is more robust than atof for strings ending with special characters */
if (sscanf(p + 5, "%lf", freq) != 1) {
- rig_debug(RIG_DEBUG_ERR, "%s: formato frequenza non riconosciuto in [%s]\n", __func__, p);
+ rig_debug(RIG_DEBUG_ERR, "%s: frequency format not recognized in [%s]\n", __func__, p);
return -RIG_EPROTO;
}
- rig_debug(RIG_DEBUG_VERBOSE, "%s: frequenza letta: %.0f Hz\n", __func__, *freq);
+ rig_debug(RIG_DEBUG_VERBOSE, "%s: frequency read: %.0f Hz\n", __func__, *freq);
return RIG_OK;
}
- rig_debug(RIG_DEBUG_ERR, "%s: stringa RxFr non trovata nella risposta\n", __func__);
+ rig_debug(RIG_DEBUG_ERR, "%s: RxFr string not found in response\n", __func__);
return -RIG_EPROTO;
}
int harris_open(RIG *rig)
{
- rig_debug(RIG_DEBUG_VERBOSE, "%s: Apertura e sincronizzazione prompt\n", __func__);
+ rig_debug(RIG_DEBUG_VERBOSE, "%s: Opening and prompt synchronization\n", __func__);
- /* Inviamo un semplice ritorno a capo per sollecitare il prompt */
- /* Passiamo NULL come buffer di risposta perché ci interessa solo l'esito (RIG_OK) */
+ /* Send a simple carriage return to solicit the prompt */
+ /* Pass NULL as response buffer because we only care about the result (RIG_OK) */
if (harris_transaction(rig, "\r", NULL, 0) != RIG_OK) {
- rig_debug(RIG_DEBUG_ERR, "%s: La radio non risponde al prompt iniziale\n", __func__);
+ rig_debug(RIG_DEBUG_ERR, "%s: Radio not responding to initial prompt\n", __func__);
return -RIG_EIO;
}
- rig_debug(RIG_DEBUG_VERBOSE, "%s: Connessione stabilita con successo\n", __func__);
+ rig_debug(RIG_DEBUG_VERBOSE, "%s: Connection successfully established\n", __func__);
return RIG_OK;
}
static float find_closest_bandwidth(float target, const float *list) {
float closest = list[0];
- float min_diff = 99.0; // Valore iniziale alto
+ float min_diff = 99.0; // High initial value
for (int i = 0; list[i] != 0; i++) {
float diff = target - list[i];
- if (diff < 0) diff = -diff; // Valore assoluto
+ if (diff < 0) diff = -diff; // Absolute value
if (diff < min_diff) {
min_diff = diff;
@@ -142,14 +142,14 @@ int harris_set_pb_width(RIG *rig, vfo_t vfo, pbwidth_t width)
pbwidth_t current_width;
const float *bw_list;
- rig_debug(RIG_DEBUG_VERBOSE, "%s: richiesta variazione larghezza banda a %ld Hz\n", __func__, width);
+ rig_debug(RIG_DEBUG_VERBOSE, "%s: bandwidth change request to %ld Hz\n", __func__, width);
- /* 1. Recuperiamo il modo attuale per sapere quale tabella usare */
+ /* 1. Retrieve current mode to determine which table to use */
if (harris_get_mode(rig, vfo, ¤t_mode, ¤t_width) != RIG_OK) {
return -RIG_EIO;
}
- /* 2. Selezioniamo la tabella corretta */
+ /* 2. Select the correct table */
switch (current_mode) {
case RIG_MODE_USB:
case RIG_MODE_LSB: bw_list = bw_ssb; break;
@@ -158,7 +158,7 @@ int harris_set_pb_width(RIG *rig, vfo_t vfo, pbwidth_t width)
default: bw_list = bw_ssb; // Fallback
}
- /* 3. Approssimazione e invio */
+ /* 3. Approximation and sending */
float target_khz = (float)width / 1000.0;
float final_khz = find_closest_bandwidth(target_khz, bw_list);
@@ -179,11 +179,11 @@ int harris_set_mode(RIG *rig, vfo_t vfo, rmode_t mode, pbwidth_t width)
default: return -RIG_EINVAL;
}
- /* 1. Cambia il Modo */
+ /* 1. Change Mode */
snprintf(cmd, sizeof(cmd), "MODE %s\r", mstr);
if (harris_transaction(rig, cmd, NULL, 0) != RIG_OK) return -RIG_EIO;
- /* 2. Cambia la banda usando la nuova funzione (se width > 0) */
+ /* 2. Change bandwidth using the new function (if width > 0) */
if (width > 0 && width != RIG_PASSBAND_NORMAL) {
return harris_set_pb_width(rig, vfo, width);
}
@@ -198,7 +198,7 @@ int harris_get_mode(RIG *rig, vfo_t vfo, rmode_t *mode, pbwidth_t *width)
if (harris_transaction(rig, "MODE\r", buf, sizeof(buf)) != RIG_OK) return -RIG_EIO;
- /* Parsing Modo */
+ /* Mode Parsing */
p = strstr(buf, "MODE ");
if (p) {
p += 5;
@@ -208,7 +208,7 @@ int harris_get_mode(RIG *rig, vfo_t vfo, rmode_t *mode, pbwidth_t *width)
else if (strncmp(p, "AME", 3) == 0 || strncmp(p, "AM", 2) == 0) *mode = RIG_MODE_AM;
}
- /* Parsing Banda (Filtro) */
+ /* Band Parsing (Filter) */
p = strstr(buf, "BAND ");
if (p) {
*width = (pbwidth_t)(atof(p + 5) * 1000.0);
@@ -221,7 +221,7 @@ int harris_get_level(RIG *rig, vfo_t vfo, setting_t level, value_t *val)
{
char buf[2048];
- /* Caso speciale per il Preamp: il comando SH non lo mostra nel dump */
+ /* Special case for Preamp: SH command doesn't show it in dump */
if (level == RIG_LEVEL_PREAMP) {
if (harris_transaction(rig, "PRE\r", buf, sizeof(buf)) != RIG_OK) {
return -RIG_EIO;
@@ -230,7 +230,7 @@ int harris_get_level(RIG *rig, vfo_t vfo, setting_t level, value_t *val)
return RIG_OK;
}
- /* Per tutti gli altri livelli usiamo il dump SH */
+ /* For all other levels we use the SH dump */
if (harris_transaction(rig, "SH\r", buf, sizeof(buf)) != RIG_OK) {
return -RIG_EIO;
}
@@ -298,7 +298,7 @@ int harris_set_level(RIG *rig, vfo_t vfo, setting_t level, value_t val)
else if (val.i == RIG_AGC_MEDIUM) p_str = "MED";
else if (val.i == RIG_AGC_FAST) p_str = "FAST";
else p_str = "SLOW";
- snprintf(cmd, sizeof(cmd), "AGC %s\r", p_str); // Usiamo AGC esteso
+ snprintf(cmd, sizeof(cmd), "AGC %s\r", p_str); // Use extended AGC
break;
case RIG_LEVEL_RF:
@@ -306,7 +306,7 @@ int harris_set_level(RIG *rig, vfo_t vfo, setting_t level, value_t val)
break;
case RIG_LEVEL_PREAMP:
- // Cruciale: Solo "ENA" e "BYP" funzionano davvero
+ // Crucial: Only "ENA" and "BYP" actually work
snprintf(cmd, sizeof(cmd), "PRE %s\r", (val.i > 0) ? "ENA" : "BYP");
break;
@@ -322,20 +322,20 @@ int harris_set_func(RIG *rig, vfo_t vfo, setting_t func, int status)
{
char cmd[64];
- /* Supportiamo solo lo Squelch in questa funzione */
+ /* Only Squelch is supported in this function */
if (func != RIG_FUNC_SQL) {
- rig_debug(RIG_DEBUG_TRACE, "%s: funzione %lu non supportata\n", __func__, func);
+ rig_debug(RIG_DEBUG_TRACE, "%s: function %lu not supported\n", __func__, func);
return -RIG_EINVAL;
}
- /* Comando Harris: SQ ON per attivare, SQ OF per disattivare */
- /* Nota: Usiamo 'OF' con una sola F come da logica dei tuoi test precedenti */
+ /* Harris Command: SQ ON to activate, SQ OF to deactivate */
+ /* Note: Using 'OF' with single F as per previous test logic */
snprintf(cmd, sizeof(cmd), "SQ %s\r", status ? "ON" : "OF");
- rig_debug(RIG_DEBUG_VERBOSE, "%s: impostazione Squelch status %d [%s]\n",
+ rig_debug(RIG_DEBUG_VERBOSE, "%s: setting Squelch status %d [%s]\n",
__func__, status, cmd);
- /* Usiamo la transazione centralizzata per attendere il prompt SSB> */
+ /* Use centralized transaction to wait for SSB> prompt */
return harris_transaction(rig, cmd, NULL, 0);
}
@@ -343,21 +343,21 @@ int harris_get_ptt(RIG *rig, vfo_t vfo, ptt_t *ptt)
{
char buf[512];
- rig_debug(RIG_DEBUG_VERBOSE, "%s: query stato PTT\n", __func__);
+ rig_debug(RIG_DEBUG_VERBOSE, "%s: PTT status query\n", __func__);
- /* Usiamo la transazione centralizzata inviando solo 'K' */
+ /* Use centralized transaction by sending only 'K' */
if (harris_transaction(rig, "K\r", buf, sizeof(buf)) != RIG_OK) {
return -RIG_EIO;
}
- /* Analisi della risposta nel buffer */
- /* La radio tipicamente risponde con "KEY ON", "KEY MIC" o "KEY OFF" */
+ /* Response analysis in buffer */
+ /* Radio typically responds with "KEY ON", "KEY MIC" or "KEY OFF" */
if (strstr(buf, "KEY ON") || strstr(buf, "KEY MIC")) {
*ptt = RIG_PTT_ON;
} else if (strstr(buf, "KEY OFF")) {
*ptt = RIG_PTT_OFF;
} else {
- /* Fallback di sicurezza basato su stringhe parziali */
+ /* Safety fallback based on partial strings */
if (strstr(buf, "ON")) {
*ptt = RIG_PTT_ON;
} else {
@@ -365,7 +365,7 @@ int harris_get_ptt(RIG *rig, vfo_t vfo, ptt_t *ptt)
}
}
- rig_debug(RIG_DEBUG_TRACE, "%s: PTT rilevato: %s\n",
+ rig_debug(RIG_DEBUG_TRACE, "%s: PTT detected: %s\n",
__func__, (*ptt == RIG_PTT_ON) ? "ON" : "OFF");
return RIG_OK;
@@ -375,13 +375,13 @@ int harris_set_ptt(RIG *rig, vfo_t vfo, ptt_t ptt)
{
char cmd[16];
- /* Costruiamo il comando: K ON per attivare, K OF per disattivare */
- /* Nota: mantengo 'OF' con una sola F come da tua implementazione originale */
+ /* Build command: K ON to activate, K OF to deactivate */
+ /* Note: maintaining 'OF' with single F as per original implementation */
snprintf(cmd, sizeof(cmd), "K %s\r", (ptt == RIG_PTT_ON) ? "ON" : "OF");
- rig_debug(RIG_DEBUG_VERBOSE, "%s: impostazione PTT [%s]\n", __func__, cmd);
+ rig_debug(RIG_DEBUG_VERBOSE, "%s: setting PTT [%s]\n", __func__, cmd);
- /* Invio tramite transazione (ignora la risposta testuale, cerca solo il prompt) */
+ /* Send via transaction (ignore text response, just look for prompt) */
return harris_transaction(rig, cmd, NULL, 0);
}
commit f880cac0ad19c8da13d82428dbfbf562e093921f
Author: Rega57 <ant...@bl...>
Date: Sun Mar 29 17:28:25 2026 +0200
Add support for Harris PRC-138
This is the first implementation of basic funtionality of Harris PRC-138.
diff --git a/configure.ac b/configure.ac
index 170591879..c2942656e 100644
--- a/configure.ac
+++ b/configure.ac
@@ -66,7 +66,7 @@ dnl added to AC_CONFIG_FILES near the end of this file. See README.developer
dnl Beware of duplication should a backend directory include both rig and
dnl rotor definitions, e.g. "dummy". Optional backends will not be listed
dnl here but will be added later, e.g. "winradio".
-RIG_BACKEND_LIST="rigs/adat rigs/alinco rigs/aor rigs/barrett rigs/codan rigs/dorji rigs/drake rigs/dummy rigs/elad rigs/flexradio rigs/icom rigs/icmarine rigs/jrc rigs/kachina rigs/kenwood rigs/kit rigs/lowe rigs/pcr rigs/prm80 rigs/racal rigs/rft rigs/rs rigs/skanti rigs/tapr rigs/tentec rigs/tuner rigs/uniden rigs/wj rigs/yaesu rigs/gomspace rigs/mds rigs/anytone rigs/motorola rigs/commradio rigs/guohetec"
+RIG_BACKEND_LIST="rigs/adat rigs/alinco rigs/aor rigs/barrett rigs/codan rigs/dorji rigs/drake rigs/dummy rigs/elad rigs/flexradio rigs/icom rigs/icmarine rigs/jrc rigs/kachina rigs/kenwood rigs/kit rigs/lowe rigs/pcr rigs/prm80 rigs/racal rigs/rft rigs/rs rigs/skanti rigs/tapr rigs/tentec rigs/tuner rigs/uniden rigs/wj rigs/yaesu rigs/gomspace rigs/mds rigs/anytone rigs/motorola rigs/commradio rigs/guohetec rigs/harris"
RIG_BACKEND_OPTIONAL_LIST=""
ROT_BACKEND_LIST="rotators/amsat rotators/apex rotators/ars rotators/celestron rotators/cnctrk rotators/grbltrk rotators/easycomm rotators/ether6 rotators/flir rotators/fodtrack rotators/gs232a rotators/heathkit rotators/m2 rotators/meade rotators/rotorez rotators/sartek rotators/saebrtrack rotators/spid rotators/ts7400 rotators/prosistel rotators/ioptron rotators/satel rotators/skywatcher rotators/radant"
ROT_BACKEND_OPTIONAL_LIST=""
@@ -931,6 +931,7 @@ rigs/drake/Makefile
rigs/dummy/Makefile
rigs/elad/Makefile
rigs/flexradio/Makefile
+rigs/harris/Makefile
rigs/icmarine/Makefile
rigs/icom/Makefile
rigs/jrc/Makefile
diff --git a/include/hamlib/riglist.h b/include/hamlib/riglist.h
index ee7bbb986..a2bb386c9 100644
--- a/include/hamlib/riglist.h
+++ b/include/hamlib/riglist.h
@@ -1123,6 +1123,23 @@
#define RIG_MODEL_Q900 RIG_MAKE_MODEL(RIG_GUOHETEC, 2)
///@}
+/*
+ * HARRIS
+ */
+/** The `HARRIS` family. */
+#define RIG_HARRIS 41
+/** Used in register.c for the `be_name`. */
+#define RIG_BACKEND_HARRIS "harris"
+
+/**
+ * \name HARRIS
+ * HARRIS models.
+ */
+///@{
+/// Model of the `RIG_HARRIS` backend family.
+#define RIG_MODEL_PRC138 RIG_MAKE_MODEL(RIG_HARRIS, 1)
+///@}
+
/** Convenience type definition for rig model. */
typedef uint32_t rig_model_t;
diff --git a/rigs/harris/Makefile.am b/rigs/harris/Makefile.am
new file mode 100644
index 000000000..0264bc37a
--- /dev/null
+++ b/rigs/harris/Makefile.am
@@ -0,0 +1,6 @@
+HARRISSRC = harris.c prc138.c
+
+noinst_LTLIBRARIES = libhamlib-harris.la
+libhamlib_harris_la_SOURCES = $(HARRISSRC)
+
+EXTRA_DIST = Android.mk
diff --git a/rigs/harris/harris.c b/rigs/harris/harris.c
new file mode 100644
index 000000000..ccea2f6b3
--- /dev/null
+++ b/rigs/harris/harris.c
@@ -0,0 +1,416 @@
+#include <ctype.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "hamlib/rig.h"
+#include "register.h"
+#include "iofunc.h"
+#include "harris.h"
+#include "prc138.h"
+
+static const float bw_ssb[] = {1.5, 2.0, 2.4, 2.7, 3.0, 0};
+static const float bw_cw[] = {0.35, 0.68, 1.0, 1.5, 0};
+static const float bw_am[] = {3.0, 4.0, 5.0, 6.0, 0};
+
+static int harris_transaction(RIG *rig, const char *cmd, char *resp, int resp_len)
+{
+ unsigned char buf[128];
+ char local_buf[512];
+ char *target_buf = resp ? resp : local_buf;
+ int target_len = resp ? resp_len : sizeof(local_buf);
+ int retry = 15;
+
+ target_buf[0] = '\0';
+
+ /* 1. Pulizia fisica del buffer */
+ rig_flush(RIGPORT(rig));
+
+ /* 2. Invio del comando */
+ if (write_block(RIGPORT(rig), (unsigned char *)cmd, strlen(cmd)) < 0) {
+ return -RIG_EIO;
+ }
+
+ /* 3. Loop di accumulo */
+ while (retry > 0) {
+ usleep(10000); //150000
+
+ memset(buf, 0, sizeof(buf));
+ (void) read_block(RIGPORT(rig), buf, sizeof(buf) - 1);
+
+ if (buf[0] != '\0') {
+ strncat(target_buf, (char *)buf, target_len - strlen(target_buf) - 1);
+
+ /* Se troviamo il prompt con lo spazio, abbiamo finito */
+ if (strstr(target_buf, "SSB> ")) {
+ return RIG_OK;
+ }
+ }
+ retry--;
+ }
+ return -RIG_EIO;
+}
+
+int harris_set_freq(RIG *rig, vfo_t vfo, freq_t freq)
+{
+ char cmd[64];
+
+ rig_debug(RIG_DEBUG_VERBOSE, "%s: impostazione frequenza a %.0f Hz\n", __func__, freq);
+
+ /* Il formato %08.0f è CRUCIALE:
+ - 0 significa 'riempi con zeri'
+ - 8 significa 'lunghezza totale di 8 caratteri'
+ - .0f significa 'numero reale senza decimali'
+ Esempio: 7000000 diventa 07000000 */
+ snprintf(cmd, sizeof(cmd), "FR %08.0f\r", freq);
+
+ /* Usiamo la nostra fidata harris_transaction */
+ if (harris_transaction(rig, cmd, NULL, 0) != RIG_OK) {
+ rig_debug(RIG_DEBUG_ERR, "%s: errore nella transazione FR\n", __func__);
+ return -RIG_EIO;
+ }
+
+ return RIG_OK;
+}
+
+int harris_get_freq(RIG *rig, vfo_t vfo, freq_t *freq)
+{
+ char buf[512];
+ char *p;
+
+ rig_debug(RIG_DEBUG_VERBOSE, "%s: richiesta frequenza\n", __func__);
+
+ /* 1. Eseguiamo la transazione completa */
+ if (harris_transaction(rig, "FR\r", buf, sizeof(buf)) != RIG_OK) {
+ rig_debug(RIG_DEBUG_ERR, "%s: errore nella transazione FR\n", __func__);
+ return -RIG_EIO;
+ }
+
+ /* 2. Cerchiamo la riga della frequenza di ricezione "RxFr " */
+ p = strstr(buf, "RxFr ");
+ if (p) {
+ /* Saltiamo "RxFr " (5 caratteri) e leggiamo il numero */
+ /* sscanf è più robusto di atof per stringhe che terminano con caratteri speciali */
+ if (sscanf(p + 5, "%lf", freq) != 1) {
+ rig_debug(RIG_DEBUG_ERR, "%s: formato frequenza non riconosciuto in [%s]\n", __func__, p);
+ return -RIG_EPROTO;
+ }
+
+ rig_debug(RIG_DEBUG_VERBOSE, "%s: frequenza letta: %.0f Hz\n", __func__, *freq);
+ return RIG_OK;
+ }
+
+ rig_debug(RIG_DEBUG_ERR, "%s: stringa RxFr non trovata nella risposta\n", __func__);
+ return -RIG_EPROTO;
+}
+
+int harris_open(RIG *rig)
+{
+ rig_debug(RIG_DEBUG_VERBOSE, "%s: Apertura e sincronizzazione prompt\n", __func__);
+
+ /* Inviamo un semplice ritorno a capo per sollecitare il prompt */
+ /* Passiamo NULL come buffer di risposta perché ci interessa solo l'esito (RIG_OK) */
+ if (harris_transaction(rig, "\r", NULL, 0) != RIG_OK) {
+ rig_debug(RIG_DEBUG_ERR, "%s: La radio non risponde al prompt iniziale\n", __func__);
+ return -RIG_EIO;
+ }
+
+ rig_debug(RIG_DEBUG_VERBOSE, "%s: Connessione stabilita con successo\n", __func__);
+ return RIG_OK;
+}
+
+static float find_closest_bandwidth(float target, const float *list) {
+ float closest = list[0];
+ float min_diff = 99.0; // Valore iniziale alto
+
+ for (int i = 0; list[i] != 0; i++) {
+ float diff = target - list[i];
+ if (diff < 0) diff = -diff; // Valore assoluto
+
+ if (diff < min_diff) {
+ min_diff = diff;
+ closest = list[i];
+ }
+ }
+ return closest;
+}
+
+int harris_set_pb_width(RIG *rig, vfo_t vfo, pbwidth_t width)
+{
+ char cmd[64];
+ rmode_t current_mode;
+ pbwidth_t current_width;
+ const float *bw_list;
+
+ rig_debug(RIG_DEBUG_VERBOSE, "%s: richiesta variazione larghezza banda a %ld Hz\n", __func__, width);
+
+ /* 1. Recuperiamo il modo attuale per sapere quale tabella usare */
+ if (harris_get_mode(rig, vfo, ¤t_mode, ¤t_width) != RIG_OK) {
+ return -RIG_EIO;
+ }
+
+ /* 2. Selezioniamo la tabella corretta */
+ switch (current_mode) {
+ case RIG_MODE_USB:
+ case RIG_MODE_LSB: bw_list = bw_ssb; break;
+ case RIG_MODE_CW: bw_list = bw_cw; break;
+ case RIG_MODE_AM: bw_list = bw_am; break;
+ default: bw_list = bw_ssb; // Fallback
+ }
+
+ /* 3. Approssimazione e invio */
+ float target_khz = (float)width / 1000.0;
+ float final_khz = find_closest_bandwidth(target_khz, bw_list);
+
+ snprintf(cmd, sizeof(cmd), "BAND %.2f\r", final_khz);
+ return harris_transaction(rig, cmd, NULL, 0);
+}
+
+int harris_set_mode(RIG *rig, vfo_t vfo, rmode_t mode, pbwidth_t width)
+{
+ char cmd[64];
+ const char *mstr;
+
+ switch (mode) {
+ case RIG_MODE_USB: mstr = "USB"; break;
+ case RIG_MODE_LSB: mstr = "LSB"; break;
+ case RIG_MODE_CW: mstr = "CW"; break;
+ case RIG_MODE_AM: mstr = "AME"; break;
+ default: return -RIG_EINVAL;
+ }
+
+ /* 1. Cambia il Modo */
+ snprintf(cmd, sizeof(cmd), "MODE %s\r", mstr);
+ if (harris_transaction(rig, cmd, NULL, 0) != RIG_OK) return -RIG_EIO;
+
+ /* 2. Cambia la banda usando la nuova funzione (se width > 0) */
+ if (width > 0 && width != RIG_PASSBAND_NORMAL) {
+ return harris_set_pb_width(rig, vfo, width);
+ }
+
+ return RIG_OK;
+}
+
+int harris_get_mode(RIG *rig, vfo_t vfo, rmode_t *mode, pbwidth_t *width)
+{
+ char buf[512];
+ char *p;
+
+ if (harris_transaction(rig, "MODE\r", buf, sizeof(buf)) != RIG_OK) return -RIG_EIO;
+
+ /* Parsing Modo */
+ p = strstr(buf, "MODE ");
+ if (p) {
+ p += 5;
+ if (strncmp(p, "USB", 3) == 0) *mode = RIG_MODE_USB;
+ else if (strncmp(p, "LSB", 3) == 0) *mode = RIG_MODE_LSB;
+ else if (strncmp(p, "CW", 2) == 0) *mode = RIG_MODE_CW;
+ else if (strncmp(p, "AME", 3) == 0 || strncmp(p, "AM", 2) == 0) *mode = RIG_MODE_AM;
+ }
+
+ /* Parsing Banda (Filtro) */
+ p = strstr(buf, "BAND ");
+ if (p) {
+ *width = (pbwidth_t)(atof(p + 5) * 1000.0);
+ }
+
+ return RIG_OK;
+}
+
+int harris_get_level(RIG *rig, vfo_t vfo, setting_t level, value_t *val)
+{
+ char buf[2048];
+
+ /* Caso speciale per il Preamp: il comando SH non lo mostra nel dump */
+ if (level == RIG_LEVEL_PREAMP) {
+ if (harris_transaction(rig, "PRE\r", buf, sizeof(buf)) != RIG_OK) {
+ return -RIG_EIO;
+ }
+ val->i = strstr(buf, "Preamp Enabled") ? 1 : 0;
+ return RIG_OK;
+ }
+
+ /* Per tutti gli altri livelli usiamo il dump SH */
+ if (harris_transaction(rig, "SH\r", buf, sizeof(buf)) != RIG_OK) {
+ return -RIG_EIO;
+ }
+
+ switch (level) {
+ case RIG_LEVEL_SQL:
+ if (strstr(buf, "SQ_LEVEL LOW")) val->f = 0.1f;
+ else if (strstr(buf, "SQ_LEVEL MED")) val->f = 0.5f;
+ else if (strstr(buf, "SQ_LEVEL HIGH")) val->f = 1.0f;
+ else val->f = 0.0f;
+ break;
+
+ case RIG_LEVEL_RFPOWER:
+ if (strstr(buf, "POWER low")) val->f = 0.1f;
+ else if (strstr(buf, "POWER med")) val->f = 0.5f;
+ else if (strstr(buf, "POWER hi")) val->f = 1.0f;
+ else val->f = 0.0f;
+ break;
+
+ case RIG_LEVEL_AGC:
+ if (strstr(buf, "AGC OFF")) val->i = RIG_AGC_OFF;
+ else if (strstr(buf, "AGC SLOW")) val->i = RIG_AGC_SLOW;
+ else if (strstr(buf, "AGC MED")) val->i = RIG_AGC_MEDIUM;
+ else if (strstr(buf, "AGC FAST")) val->i = RIG_AGC_FAST;
+ break;
+
+ case RIG_LEVEL_RF:
+ {
+ char *p = strstr(buf, "RFG ");
+ if (p) val->f = (float)atoi(p + 4) / 100.0f;
+ else val->f = 1.0f;
+ }
+ break;
+
+ default:
+ return -RIG_EINVAL;
+ }
+
+ return RIG_OK;
+}
+
+int harris_set_level(RIG *rig, vfo_t vfo, setting_t level, value_t val)
+{
+ char cmd[64];
+ const char *p_str;
+
+ switch (level) {
+ case RIG_LEVEL_SQL:
+ if (val.f <= 0.33f) p_str = "LOW";
+ else if (val.f <= 0.66f) p_str = "MED";
+ else p_str = "HIGH";
+ snprintf(cmd, sizeof(cmd), "SQ_L %s\r", p_str);
+ break;
+
+ case RIG_LEVEL_RFPOWER:
+ if (val.f <= 0.33f) p_str = "LOW";
+ else if (val.f <= 0.66f) p_str = "MED";
+ else p_str = "HIGH";
+ snprintf(cmd, sizeof(cmd), "POW %s\r", p_str);
+ break;
+
+ case RIG_LEVEL_AGC:
+ if (val.i == RIG_AGC_OFF) p_str = "OF";
+ else if (val.i == RIG_AGC_SLOW) p_str = "SLOW";
+ else if (val.i == RIG_AGC_MEDIUM) p_str = "MED";
+ else if (val.i == RIG_AGC_FAST) p_str = "FAST";
+ else p_str = "SLOW";
+ snprintf(cmd, sizeof(cmd), "AGC %s\r", p_str); // Usiamo AGC esteso
+ break;
+
+ case RIG_LEVEL_RF:
+ snprintf(cmd, sizeof(cmd), "RFG %d\r", (int)(val.f * 100));
+ break;
+
+ case RIG_LEVEL_PREAMP:
+ // Cruciale: Solo "ENA" e "BYP" funzionano davvero
+ snprintf(cmd, sizeof(cmd), "PRE %s\r", (val.i > 0) ? "ENA" : "BYP");
+ break;
+
+ default:
+ return -RIG_EINVAL;
+ }
+
+ return harris_transaction(rig, cmd, NULL, 0);
+}
+
+
+int harris_set_func(RIG *rig, vfo_t vfo, setting_t func, int status)
+{
+ char cmd[64];
+
+ /* Supportiamo solo lo Squelch in questa funzione */
+ if (func != RIG_FUNC_SQL) {
+ rig_debug(RIG_DEBUG_TRACE, "%s: funzione %lu non supportata\n", __func__, func);
+ return -RIG_EINVAL;
+ }
+
+ /* Comando Harris: SQ ON per attivare, SQ OF per disattivare */
+ /* Nota: Usiamo 'OF' con una sola F come da logica dei tuoi test precedenti */
+ snprintf(cmd, sizeof(cmd), "SQ %s\r", status ? "ON" : "OF");
+
+ rig_debug(RIG_DEBUG_VERBOSE, "%s: impostazione Squelch status %d [%s]\n",
+ __func__, status, cmd);
+
+ /* Usiamo la transazione centralizzata per attendere il prompt SSB> */
+ return harris_transaction(rig, cmd, NULL, 0);
+}
+
+int harris_get_ptt(RIG *rig, vfo_t vfo, ptt_t *ptt)
+{
+ char buf[512];
+
+ rig_debug(RIG_DEBUG_VERBOSE, "%s: query stato PTT\n", __func__);
+
+ /* Usiamo la transazione centralizzata inviando solo 'K' */
+ if (harris_transaction(rig, "K\r", buf, sizeof(buf)) != RIG_OK) {
+ return -RIG_EIO;
+ }
+
+ /* Analisi della risposta nel buffer */
+ /* La radio tipicamente risponde con "KEY ON", "KEY MIC" o "KEY OFF" */
+ if (strstr(buf, "KEY ON") || strstr(buf, "KEY MIC")) {
+ *ptt = RIG_PTT_ON;
+ } else if (strstr(buf, "KEY OFF")) {
+ *ptt = RIG_PTT_OFF;
+ } else {
+ /* Fallback di sicurezza basato su stringhe parziali */
+ if (strstr(buf, "ON")) {
+ *ptt = RIG_PTT_ON;
+ } else {
+ *ptt = RIG_PTT_OFF;
+ }
+ }
+
+ rig_debug(RIG_DEBUG_TRACE, "%s: PTT rilevato: %s\n",
+ __func__, (*ptt == RIG_PTT_ON) ? "ON" : "OFF");
+
+ return RIG_OK;
+}
+
+int harris_set_ptt(RIG *rig, vfo_t vfo, ptt_t ptt)
+{
+ char cmd[16];
+
+ /* Costruiamo il comando: K ON per attivare, K OF per disattivare */
+ /* Nota: mantengo 'OF' con una sola F come da tua implementazione originale */
+ snprintf(cmd, sizeof(cmd), "K %s\r", (ptt == RIG_PTT_ON) ? "ON" : "OF");
+
+ rig_debug(RIG_DEBUG_VERBOSE, "%s: impostazione PTT [%s]\n", __func__, cmd);
+
+ /* Invio tramite transazione (ignora la risposta testuale, cerca solo il prompt) */
+ return harris_transaction(rig, cmd, NULL, 0);
+}
+
+int harris_init(RIG *rig) {
+ struct harris_priv_data *priv;
+
+ priv = (struct harris_priv_data *)calloc(1, sizeof(struct harris_priv_data));
+ if (!priv) return -RIG_ENOMEM;
+
+ rig->caps->priv = (void *)priv;
+ return RIG_OK;
+}
+
+int harris_cleanup(RIG *rig) {
+ if (rig->caps->priv) {
+ free((void *)rig->caps->priv);
+ rig->caps->priv = NULL;
+ }
+ return RIG_OK;
+}
+
+int harris_close(RIG *rig) {
+ return RIG_OK;
+}
+
+/* This macro expands the initrigs5_harris function. */
+DECLARE_INITRIG_BACKEND(harris)
+{
+ rig_debug(RIG_DEBUG_VERBOSE, "%s: _init called\n", __func__);
+ rig_register((struct rig_caps *)&prc138_caps);
+ return RIG_OK;
+}
diff --git a/rigs/harris/harris.h b/rigs/harris/harris.h
new file mode 100644
index 000000000..1697628a9
--- /dev/null
+++ b/rigs/harris/harris.h
@@ -0,0 +1,27 @@
+#ifndef _HARRIS_H
+#define _HARRIS_H
+
+#include <hamlib/rig.h>
+
+struct harris_priv_data {
+ freq_t current_freq;
+ rmode_t current_mode;
+};
+
+/* Prototypes for prc138.c */
+int harris_init(RIG *rig);
+int harris_cleanup(RIG *rig);
+int harris_open(RIG *rig);
+int harris_close(RIG *rig);
+int harris_set_freq(RIG *rig, vfo_t vfo, freq_t freq);
+int harris_get_freq(RIG *rig, vfo_t vfo, freq_t *freq);
+int harris_set_mode(RIG *rig, vfo_t vfo, rmode_t mode, pbwidth_t width);
+int harris_get_mode(RIG *rig, vfo_t vfo, rmode_t *mode, pbwidth_t *width);
+int harris_set_level(RIG *rig, vfo_t vfo, setting_t level, value_t val);
+int harris_get_level(RIG *rig, vfo_t vfo, setting_t level, value_t *val);
+int harris_set_func(RIG *rig, vfo_t vfo, setting_t func, int status);
+int harris_get_bw(RIG *rig, vfo_t vfo, mode_t mode, pbwidth_t *width);
+int harris_get_ptt(RIG *rig, vfo_t vfo, ptt_t *ptt);
+int harris_set_ptt(RIG *rig, vfo_t vfo, ptt_t ptt);
+
+#endif
diff --git a/rigs/harris/prc138.c b/rigs/harris/prc138.c
new file mode 100644
index 000000000..d0eacb52e
--- /dev/null
+++ b/rigs/harris/prc138.c
@@ -0,0 +1,87 @@
+#include "harris.h"
+#include "prc138.h"
+
+/**
+ * Harris PRC-138 Capabilities
+ */
+struct rig_caps prc138_caps = {
+ .rig_model = RIG_MODEL_PRC138,
+ .model_name = "PRC-138",
+ .mfg_name = "Harris",
+ .version = "1.0.6",
+ .port_type = RIG_PORT_SERIAL,
+
+ /* Frequency Ranges with correct brace nesting */
+ .rx_range_list1 = {
+ {
+ .startf = kHz(1600), .endf = MHz(60), .modes = PRC138_MODES,
+ .low_power = -1, .high_power = -1, .vfo = PRC138_VFO
+ },
+ RIG_FRNG_END,
+ },
+ .tx_range_list1 = {
+ {
+ .startf = kHz(1600), .endf = MHz(60), .modes = PRC138_MODES,
+ .low_power = W(1), .high_power = W(20), .vfo = PRC138_VFO
+ },
+ RIG_FRNG_END,
+ },
+ .tuning_steps = { {RIG_MODE_ALL, 100}, {RIG_MODE_ALL, RIG_TS_ANY}, {0, 0} },
+
+ /* Serial Parameters */
+ .serial_rate_min = 75,
+ .serial_rate_max = 9600,
+ .serial_data_bits = 8,
+ .serial_stop_bits = 1,
+ .serial_parity = RIG_PARITY_NONE,
+ .serial_handshake = RIG_HANDSHAKE_NONE,
+ .write_delay = 0, //50
+ .post_write_delay = 50, //100
+ .timeout = 200, //200
+ .retry = 0, //3
+
+ /* Passband filters definition directly inside caps to fix pointer warning */
+ .filters = {
+ /* SSB (USB/LSB): 2.7 (def), 1.5, 2.0, 2.4, 3.0 kHz */
+ {RIG_MODE_SSB, kHz(2.7)},
+ {RIG_MODE_SSB, kHz(1.5)},
+ {RIG_MODE_SSB, kHz(2.0)},
+ {RIG_MODE_SSB, kHz(2.4)},
+ {RIG_MODE_SSB, kHz(3.0)},
+
+ /* CW: 1.0 (def), 0.35, 0.68, 1.5 kHz */
+ {RIG_MODE_CW, kHz(1.0)},
+ {RIG_MODE_CW, 350},
+ {RIG_MODE_CW, 680},
+ {RIG_MODE_CW, kHz(1.5)},
+
+ /* AME: 6.0 (def), 3.0, 4.0, 5.0 kHz */
+ {RIG_MODE_AM, kHz(6.0)},
+ {RIG_MODE_AM, kHz(3.0)},
+ {RIG_MODE_AM, kHz(4.0)},
+ {RIG_MODE_AM, kHz(5.0)},
+
+ RIG_FLT_END,
+ },
+
+ /* Capabilities */
+ .ptt_type = RIG_PTT_RIG,
+ .has_get_level = RIG_LEVEL_SQL | RIG_LEVEL_RFPOWER | RIG_LEVEL_AGC | RIG_LEVEL_RF | RIG_LEVEL_PREAMP,
+ .has_set_level = RIG_LEVEL_SQL | RIG_LEVEL_RFPOWER | RIG_LEVEL_AGC | RIG_LEVEL_RF | RIG_LEVEL_PREAMP,
+ .has_set_func = RIG_FUNC_SQL,
+
+ /* Function Callbacks */
+ .rig_init = harris_init,
+ .rig_cleanup = harris_cleanup,
+ .rig_open = harris_open,
+ .rig_close = harris_close,
+ .set_freq = harris_set_freq,
+ .get_freq = harris_get_freq,
+ .set_mode = harris_set_mode,
+ .get_mode = harris_get_mode,
+ .set_ptt = harris_set_ptt,
+ .get_ptt = harris_get_ptt,
+ .set_level = harris_set_level,
+ .get_level = harris_get_level,
+ .set_func = harris_set_func,
+};
diff --git a/rigs/harris/prc138.h b/rigs/harris/prc138.h
new file mode 100644
index 000000000..17142bbc6
--- /dev/null
+++ b/rigs/harris/prc138.h
@@ -0,0 +1,11 @@
+#ifndef _PRC138_H
+#define _PRC138_H
+
+#include <hamlib/rig.h>
+
+#define PRC138_MODES (RIG_MODE_USB | RIG_MODE_LSB | RIG_MODE_CW | RIG_MODE_AM)
+#define PRC138_VFO (RIG_VFO_A)
+
+extern struct rig_caps prc138_caps;
+
+#endif
diff --git a/src/register.c b/src/register.c
index 17b94eb32..c0d18e489 100644
--- a/src/register.c
+++ b/src/register.c
@@ -91,6 +91,7 @@ DEFINE_INITRIG_BACKEND(mds);
DEFINE_INITRIG_BACKEND(anytone);
DEFINE_INITRIG_BACKEND(motorola);
DEFINE_INITRIG_BACKEND(commradio);
+DEFINE_INITRIG_BACKEND(harris);
//! @endcond
#ifdef HAVE_WINRADIO
@@ -154,6 +155,7 @@ static struct
{ RIG_ANYTONE, RIG_BACKEND_ANYTONE, RIG_FUNCNAMA(anytone) },
{ RIG_MOTOROLA, RIG_BACKEND_MOTOROLA, RIG_FUNCNAMA(motorola) },
{ RIG_COMMRADIO, RIG_BACKEND_COMMRADIO, RIG_FUNCNAMA(commradio) },
+ { RIG_HARRIS, RIG_BACKEND_HARRIS, RIG_FUNCNAMA(harris) },
{ 0, NULL }, /* end */
};
-----------------------------------------------------------------------
Summary of changes:
configure.ac | 3 +-
include/hamlib/riglist.h | 16 ++
rigs/{dorji => harris}/Android.mk | 4 +-
rigs/harris/Makefile.am | 6 +
rigs/harris/harris.c | 443 +++++++++++++++++++++++++++++++
rigs/harris/harris.h | 53 ++++
rigs/harris/prc138.c | 113 ++++++++
rigs/{tentec/rx331.h => harris/prc138.h} | 22 +-
src/register.c | 2 +
9 files changed, 650 insertions(+), 12 deletions(-)
copy rigs/{dorji => harris}/Android.mk (76%)
create mode 100644 rigs/harris/Makefile.am
create mode 100644 rigs/harris/harris.c
create mode 100644 rigs/harris/harris.h
create mode 100644 rigs/harris/prc138.c
copy rigs/{tentec/rx331.h => harris/prc138.h} (62%)
hooks/post-receive
--
Hamlib -- Ham radio control libraries
|