FTX-1: Fix code review issues and add missing function handlers

Critical fixes:
- Fix RIT/XIT double-negation parsing bug (atoi already handles sign)
- Add ±9999 Hz range validation for RIT/XIT offsets

High priority fixes:
- Add RIG_FUNC_TONE/TSQL handlers using CT command modes
- Add RIG_FUNC_RIT/XIT handlers for clarifier enable/disable
- Add SPA-1 guard to prevent TUNE on Field Head (no tuner available)

Medium priority fixes:
- Fix VFO handling bug in squelch (was using "? 0 : 0")
- Add error checking for power restoration during head detection
This commit is contained in:
KJ5HST 2025-12-17 20:34:24 -06:00
parent 5fd7ab8851
commit 1fdf727e42
5 changed files with 84 additions and 19 deletions

View file

@ -255,7 +255,13 @@ static int ftx1_probe_field_head_power(RIG *rig)
/* Restore original power setting */
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "%s", original_power);
newcat_set_cmd(rig);
ret = newcat_set_cmd(rig);
if (ret != RIG_OK)
{
rig_debug(RIG_DEBUG_WARN, "%s: failed to restore original power setting\n",
__func__);
}
if (power_accepted)
{

View file

@ -102,12 +102,8 @@ int ftx1_get_rit(RIG *rig, vfo_t vfo, shortfreq_t *rit)
/* Check if RX clarifier (RIT) is enabled */
if (rdata->rx_clarifier == '1')
{
/* atoi() handles the sign prefix correctly - no need to negate again */
*rit = atoi(rdata->clarifier);
/* Handle sign - clarifier field includes +/- prefix */
if (rdata->clarifier[0] == '-')
{
*rit = -*rit;
}
}
else
{
@ -137,6 +133,14 @@ int ftx1_set_rit(RIG *rig, vfo_t vfo, shortfreq_t rit)
rig_debug(RIG_DEBUG_VERBOSE, "%s called with rit=%ld\n", __func__, (long)rit);
/* Validate range: FTX-1 supports ±9999 Hz */
if (rit < -9999 || rit > 9999)
{
rig_debug(RIG_DEBUG_ERR, "%s: RIT offset %ld out of range (±9999 Hz)\n",
__func__, (long)rit);
return -RIG_EINVAL;
}
if (rit == 0)
{
/* Clear RIT - RC0; */
@ -196,12 +200,8 @@ int ftx1_get_xit(RIG *rig, vfo_t vfo, shortfreq_t *xit)
/* Check if TX clarifier (XIT) is enabled */
if (rdata->tx_clarifier == '1')
{
/* atoi() handles the sign prefix correctly - no need to negate again */
*xit = atoi(rdata->clarifier);
/* Handle sign - clarifier field includes +/- prefix */
if (rdata->clarifier[0] == '-')
{
*xit = -*xit;
}
}
else
{
@ -231,6 +231,14 @@ int ftx1_set_xit(RIG *rig, vfo_t vfo, shortfreq_t xit)
rig_debug(RIG_DEBUG_VERBOSE, "%s called with xit=%ld\n", __func__, (long)xit);
/* Validate range: FTX-1 supports ±9999 Hz */
if (xit < -9999 || xit > 9999)
{
rig_debug(RIG_DEBUG_ERR, "%s: XIT offset %ld out of range (±9999 Hz)\n",
__func__, (long)xit);
return -RIG_EINVAL;
}
if (xit == 0)
{
/* Clear XIT - TC0; */

View file

@ -48,6 +48,7 @@
#include "misc.h"
#include "yaesu.h"
#include "newcat.h"
#include "../ftx1.h"
/* Extern helpers from ftx1_filter.c */
extern int ftx1_set_anf_helper(RIG *rig, vfo_t vfo, int status);
@ -153,6 +154,14 @@ extern int ftx1_set_dcs_code(RIG *rig, vfo_t vfo, tone_t code);
extern int ftx1_get_dcs_code(RIG *rig, vfo_t vfo, tone_t *code);
extern int ftx1_set_dcs_sql(RIG *rig, vfo_t vfo, tone_t code);
extern int ftx1_get_dcs_sql(RIG *rig, vfo_t vfo, tone_t *code);
extern int ftx1_set_ctcss_mode(RIG *rig, tone_t mode);
extern int ftx1_get_ctcss_mode(RIG *rig, tone_t *mode);
/* Extern helpers from ftx1_clarifier.c */
extern int ftx1_set_rit(RIG *rig, vfo_t vfo, shortfreq_t rit);
extern int ftx1_get_rit(RIG *rig, vfo_t vfo, shortfreq_t *rit);
extern int ftx1_set_xit(RIG *rig, vfo_t vfo, shortfreq_t xit);
extern int ftx1_get_xit(RIG *rig, vfo_t vfo, shortfreq_t *xit);
/* Extern helpers from ftx1_info.c */
extern int ftx1_set_trn(RIG *rig, int trn);
@ -194,6 +203,18 @@ int ftx1_set_func(RIG *rig, vfo_t vfo, setting_t func, int status)
return ftx1_set_breakin(rig, status ? 1 : 0);
case RIG_FUNC_FBKIN:
return ftx1_set_breakin(rig, status ? 2 : 0);
case RIG_FUNC_TONE:
return ftx1_set_ctcss_mode(rig, status ? FTX1_CTCSS_MODE_ENC : FTX1_CTCSS_MODE_OFF);
case RIG_FUNC_TSQL:
return ftx1_set_ctcss_mode(rig, status ? FTX1_CTCSS_MODE_TSQ : FTX1_CTCSS_MODE_OFF);
case RIG_FUNC_RIT:
/* FTX-1: Setting RIT to 0 disables it; to enable, use set_rit with offset */
if (!status) return ftx1_set_rit(rig, vfo, 0);
return RIG_OK; /* Enable is no-op; must use set_rit with offset value */
case RIG_FUNC_XIT:
/* FTX-1: Setting XIT to 0 disables it; to enable, use set_xit with offset */
if (!status) return ftx1_set_xit(rig, vfo, 0);
return RIG_OK; /* Enable is no-op; must use set_xit with offset value */
/* Note: Contour (CO command) not exposed as RIG_FUNC_CONTOUR doesn't exist in Hamlib */
default:
return newcat_set_func(rig, vfo, func, status);
@ -238,6 +259,34 @@ int ftx1_get_func(RIG *rig, vfo_t vfo, setting_t func, int *status)
ret = ftx1_get_breakin(rig, &mode);
if (ret == RIG_OK) *status = (mode == 2) ? 1 : 0;
return ret;
case RIG_FUNC_TONE:
{
tone_t ctcss_mode;
ret = ftx1_get_ctcss_mode(rig, &ctcss_mode);
if (ret == RIG_OK) *status = (ctcss_mode == FTX1_CTCSS_MODE_ENC) ? 1 : 0;
return ret;
}
case RIG_FUNC_TSQL:
{
tone_t ctcss_mode;
ret = ftx1_get_ctcss_mode(rig, &ctcss_mode);
if (ret == RIG_OK) *status = (ctcss_mode == FTX1_CTCSS_MODE_TSQ) ? 1 : 0;
return ret;
}
case RIG_FUNC_RIT:
{
shortfreq_t rit_offset;
ret = ftx1_get_rit(rig, vfo, &rit_offset);
if (ret == RIG_OK) *status = (rit_offset != 0) ? 1 : 0;
return ret;
}
case RIG_FUNC_XIT:
{
shortfreq_t xit_offset;
ret = ftx1_get_xit(rig, vfo, &xit_offset);
if (ret == RIG_OK) *status = (xit_offset != 0) ? 1 : 0;
return ret;
}
/* Note: Contour (CO command) not exposed as RIG_FUNC_CONTOUR doesn't exist in Hamlib */
default:
return newcat_get_func(rig, vfo, func, status);

View file

@ -331,15 +331,9 @@ int ftx1_get_breakin(RIG *rig, int *mode)
int ftx1_set_squelch(RIG *rig, vfo_t vfo, float val)
{
struct newcat_priv_data *priv = STATE(rig)->priv;
int p1 = (vfo == RIG_VFO_SUB || vfo == RIG_VFO_B || vfo == RIG_VFO_CURR) ? 0 : 0;
int p1 = FTX1_VFO_TO_P1(vfo);
int level = (int)(val * 100);
/* Handle VFO_CURR as MAIN */
if (vfo == RIG_VFO_SUB || vfo == RIG_VFO_B)
{
p1 = 1;
}
if (level < 0) level = 0;
if (level > 100) level = 100;
@ -356,7 +350,7 @@ int ftx1_get_squelch(RIG *rig, vfo_t vfo, float *val)
struct newcat_priv_data *priv = STATE(rig)->priv;
int ret, p1, level;
p1 = (vfo == RIG_VFO_SUB || vfo == RIG_VFO_B) ? 1 : 0;
p1 = FTX1_VFO_TO_P1(vfo);
rig_debug(RIG_DEBUG_VERBOSE, "%s: vfo=%s p1=%d\n", __func__,
rig_strvfo(vfo), p1);

View file

@ -20,6 +20,7 @@
#include "misc.h"
#include "yaesu.h"
#include "newcat.h"
#include "../ftx1.h"
/*
* ftx1_set_vfo
@ -233,6 +234,13 @@ int ftx1_vfo_op(RIG *rig, vfo_t vfo, vfo_op_t op)
/* AC110: Tuner start (turns on tuner and starts tune) */
/* Format: AC P1 P2 P3; P1=1 (on), P2=1 (start tune), P3=0 (MAIN) */
/* Note: This causes transmission! */
/* Tuner is only available on SPA-1/Optima head */
if (!ftx1_has_spa1())
{
rig_debug(RIG_DEBUG_WARN, "%s: TUNE not available on Field Head\n",
__func__);
return -RIG_ENAVAIL;
}
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "AC110;");
break;