FTX-1: Fix capability gaps - DCD, CWPITCH, RPTR_OFFS, BAND_UP/DOWN

- Add DCD support via RI command P8 (squelch status)
  * Implement ftx1_get_dcd() using RI command response
  * Change dcd_type from RIG_DCD_NONE to RIG_DCD_RIG
  * P8=0 means SQL closed, P8=1 means SQL open (signal present)

- Add RIG_LEVEL_CWPITCH to has_get_level/has_set_level
  * Implementation already existed via KP command (300-1050 Hz)
  * Now properly advertised in rig_caps

- Implement repeater offset frequency (set_rptr_offs/get_rptr_offs)
  * Use per-band EX menu tokens (TOK_FM_RPT_SHIFT_28/50/144/430)
  * Auto-detect band from VFO frequency
  * Convert between Hz and menu units per band

- Implement RIG_OP_BAND_UP and RIG_OP_BAND_DOWN
  * ftx1_band_up() uses BU0; command
  * ftx1_band_down() uses BD0; command
  * Previously returned -RIG_ENIMPL despite being in vfo_ops

- Add missing APRS_DEST token (EX060109) for menu parity (402 items)

- Document NA (narrow) helpers exist but no RIG_FUNC_NAR in Hamlib API
This commit is contained in:
KJ5HST 2025-12-19 13:48:19 -06:00
parent 6515c7596d
commit 2c0ba29d53
8 changed files with 300 additions and 10 deletions

View file

@ -112,6 +112,7 @@ extern int ftx1_stop_morse_func(RIG *rig, vfo_t vfo);
extern int ftx1_wait_morse_func(RIG *rig, vfo_t vfo);
extern int ftx1_set_trn_func(RIG *rig, int trn);
extern int ftx1_get_trn_func(RIG *rig, int *trn);
extern int ftx1_get_dcd(RIG *rig, vfo_t vfo, dcd_t *dcd);
/* Externs from ftx1_mem.c */
extern int ftx1_set_mem(RIG *rig, vfo_t vfo, int ch);
@ -140,6 +141,8 @@ extern int ftx1_set_freq(RIG *rig, vfo_t vfo, freq_t freq);
extern int ftx1_get_freq(RIG *rig, vfo_t vfo, freq_t *freq);
extern int ftx1_set_rptr_shift(RIG *rig, vfo_t vfo, rptr_shift_t shift);
extern int ftx1_get_rptr_shift(RIG *rig, vfo_t vfo, rptr_shift_t *shift);
extern int ftx1_set_rptr_offs(RIG *rig, vfo_t vfo, shortfreq_t offs);
extern int ftx1_get_rptr_offs(RIG *rig, vfo_t vfo, shortfreq_t *offs);
/* Externs from ftx1_vfo.c */
extern int ftx1_vfo_op(RIG *rig, vfo_t vfo, vfo_op_t op);
@ -513,7 +516,7 @@ struct rig_caps ftx1_caps = {
.status = RIG_STATUS_BETA, /* Update to stable once complete */
.rig_type = RIG_TYPE_TRANSCEIVER,
.ptt_type = RIG_PTT_RIG,
.dcd_type = RIG_DCD_NONE, /* FTX-1 CAT has no squelch status command */
.dcd_type = RIG_DCD_RIG, /* FTX-1 RI command P8 provides squelch status */
.port_type = RIG_PORT_SERIAL,
.serial_rate_min = 4800,
.serial_rate_max = 115200,
@ -528,10 +531,11 @@ struct rig_caps ftx1_caps = {
/* Note: ARO, FAGC, DIVERSITY return '?' from FTX-1 firmware - not supported */
/* DUAL_WATCH uses FR command for dual/single receive mode */
/* Contour (CO command) is FTX-1 specific - handle via ext_level */
/* Note: NA command (narrow filter) available via ftx1_set_na_helper/ftx1_get_na_helper but no RIG_FUNC_NAR exists in Hamlib */
.has_get_func = RIG_FUNC_COMP | RIG_FUNC_VOX | RIG_FUNC_TONE | RIG_FUNC_TSQL | RIG_FUNC_SBKIN | RIG_FUNC_FBKIN | RIG_FUNC_NB | RIG_FUNC_NR | RIG_FUNC_MN | RIG_FUNC_LOCK | RIG_FUNC_MON | RIG_FUNC_TUNER | RIG_FUNC_RIT | RIG_FUNC_XIT | RIG_FUNC_APF | RIG_FUNC_ANF | RIG_FUNC_DUAL_WATCH,
.has_set_func = RIG_FUNC_COMP | RIG_FUNC_VOX | RIG_FUNC_TONE | RIG_FUNC_TSQL | RIG_FUNC_SBKIN | RIG_FUNC_FBKIN | RIG_FUNC_NB | RIG_FUNC_NR | RIG_FUNC_MN | RIG_FUNC_LOCK | RIG_FUNC_MON | RIG_FUNC_TUNER | RIG_FUNC_RIT | RIG_FUNC_XIT | RIG_FUNC_APF | RIG_FUNC_ANF | RIG_FUNC_DUAL_WATCH,
.has_get_level = RIG_LEVEL_AF | RIG_LEVEL_RF | RIG_LEVEL_SQL | RIG_LEVEL_IF | RIG_LEVEL_APF | RIG_LEVEL_NB | RIG_LEVEL_NR | RIG_LEVEL_PBT_IN | RIG_LEVEL_PBT_OUT | RIG_LEVEL_RFPOWER | RIG_LEVEL_MICGAIN | RIG_LEVEL_KEYSPD | RIG_LEVEL_NOTCHF | RIG_LEVEL_COMP | RIG_LEVEL_AGC | RIG_LEVEL_BKINDL | RIG_LEVEL_BALANCE | RIG_LEVEL_METER | RIG_LEVEL_VOXGAIN | RIG_LEVEL_VOXDELAY | RIG_LEVEL_ANTIVOX | RIG_LEVEL_RAWSTR | RIG_LEVEL_SWR | RIG_LEVEL_ALC | RIG_LEVEL_STRENGTH | RIG_LEVEL_ATT | RIG_LEVEL_PREAMP | RIG_LEVEL_MONITOR_GAIN,
.has_set_level = RIG_LEVEL_SET(RIG_LEVEL_AF | RIG_LEVEL_RF | RIG_LEVEL_SQL | RIG_LEVEL_IF | RIG_LEVEL_APF | RIG_LEVEL_NB | RIG_LEVEL_NR | RIG_LEVEL_PBT_IN | RIG_LEVEL_PBT_OUT | RIG_LEVEL_RFPOWER | RIG_LEVEL_MICGAIN | RIG_LEVEL_KEYSPD | RIG_LEVEL_NOTCHF | RIG_LEVEL_COMP | RIG_LEVEL_AGC | RIG_LEVEL_BKINDL | RIG_LEVEL_BALANCE | RIG_LEVEL_METER | RIG_LEVEL_VOXGAIN | RIG_LEVEL_VOXDELAY | RIG_LEVEL_ANTIVOX | RIG_LEVEL_RAWSTR | RIG_LEVEL_SWR | RIG_LEVEL_ALC | RIG_LEVEL_STRENGTH | RIG_LEVEL_ATT | RIG_LEVEL_PREAMP | RIG_LEVEL_MONITOR_GAIN),
.has_get_level = RIG_LEVEL_AF | RIG_LEVEL_RF | RIG_LEVEL_SQL | RIG_LEVEL_IF | RIG_LEVEL_APF | RIG_LEVEL_NB | RIG_LEVEL_NR | RIG_LEVEL_PBT_IN | RIG_LEVEL_PBT_OUT | RIG_LEVEL_RFPOWER | RIG_LEVEL_MICGAIN | RIG_LEVEL_KEYSPD | RIG_LEVEL_NOTCHF | RIG_LEVEL_COMP | RIG_LEVEL_AGC | RIG_LEVEL_BKINDL | RIG_LEVEL_BALANCE | RIG_LEVEL_METER | RIG_LEVEL_VOXGAIN | RIG_LEVEL_VOXDELAY | RIG_LEVEL_ANTIVOX | RIG_LEVEL_RAWSTR | RIG_LEVEL_SWR | RIG_LEVEL_ALC | RIG_LEVEL_STRENGTH | RIG_LEVEL_ATT | RIG_LEVEL_PREAMP | RIG_LEVEL_MONITOR_GAIN | RIG_LEVEL_CWPITCH,
.has_set_level = RIG_LEVEL_SET(RIG_LEVEL_AF | RIG_LEVEL_RF | RIG_LEVEL_SQL | RIG_LEVEL_IF | RIG_LEVEL_APF | RIG_LEVEL_NB | RIG_LEVEL_NR | RIG_LEVEL_PBT_IN | RIG_LEVEL_PBT_OUT | RIG_LEVEL_RFPOWER | RIG_LEVEL_MICGAIN | RIG_LEVEL_KEYSPD | RIG_LEVEL_NOTCHF | RIG_LEVEL_COMP | RIG_LEVEL_AGC | RIG_LEVEL_BKINDL | RIG_LEVEL_BALANCE | RIG_LEVEL_METER | RIG_LEVEL_VOXGAIN | RIG_LEVEL_VOXDELAY | RIG_LEVEL_ANTIVOX | RIG_LEVEL_RAWSTR | RIG_LEVEL_SWR | RIG_LEVEL_ALC | RIG_LEVEL_STRENGTH | RIG_LEVEL_ATT | RIG_LEVEL_PREAMP | RIG_LEVEL_MONITOR_GAIN | RIG_LEVEL_CWPITCH),
.has_get_parm = RIG_PARM_NONE,
.has_set_parm = RIG_PARM_NONE,
.level_gran = {
@ -696,6 +700,7 @@ struct rig_caps ftx1_caps = {
.get_vfo = ftx1_get_vfo,
.set_ptt = ftx1_set_ptt_func,
.get_ptt = ftx1_get_ptt_func,
.get_dcd = ftx1_get_dcd, /* RI command P8 provides squelch/DCD status */
.set_powerstat = ftx1_set_powerstat_func,
.get_powerstat = ftx1_get_powerstat_func,
.set_func = ftx1_set_func,
@ -739,6 +744,8 @@ struct rig_caps ftx1_caps = {
.get_xit = ftx1_get_xit,
.set_rptr_shift = ftx1_set_rptr_shift,
.get_rptr_shift = ftx1_get_rptr_shift,
.set_rptr_offs = ftx1_set_rptr_offs,
.get_rptr_offs = ftx1_get_rptr_offs,
.set_split_vfo = ftx1_set_split_vfo,
.get_split_vfo = ftx1_get_split_vfo,
.set_split_freq = ftx1_set_split_freq,

View file

@ -291,3 +291,151 @@ int ftx1_get_rptr_shift(RIG *rig, vfo_t vfo, rptr_shift_t *shift)
return RIG_OK;
}
/*
* =============================================================================
* Repeater Offset Frequency Functions
* =============================================================================
* FTX-1 stores repeater offset frequencies in EX menu items per band:
* EX010316 (TOK_FM_RPT_SHIFT_28) - 28 MHz band (0-1000 kHz)
* EX010317 (TOK_FM_RPT_SHIFT_50) - 50 MHz band (0-4000 kHz)
* EX010318 (TOK_FM_RPT_SHIFT_144) - 144 MHz band (0-100 x 10 kHz = 0-1000 kHz)
* EX010319 (TOK_FM_RPT_SHIFT_430) - 430 MHz band (0-100 x 100 kHz = 0-10000 kHz)
*
* The menu values are in different units per band.
*/
#include "../ftx1.h"
#include "ftx1_menu.h"
/*
* ftx1_get_band_offset_token - Get menu token for current band's repeater offset
*
* Returns the token for the appropriate band, or 0 if not applicable.
* Also returns the multiplier to convert menu value to Hz.
*/
static hamlib_token_t ftx1_get_band_offset_token(freq_t freq, int *multiplier)
{
if (freq >= MHz(420) && freq <= MHz(470))
{
/* 430 MHz band - menu value is in 100 kHz units */
*multiplier = 100000;
return TOK_FM_RPT_SHIFT_430;
}
else if (freq >= MHz(144) && freq <= MHz(148))
{
/* 144 MHz band - menu value is in 10 kHz units */
*multiplier = 10000;
return TOK_FM_RPT_SHIFT_144;
}
else if (freq >= MHz(50) && freq <= MHz(54))
{
/* 50 MHz band - menu value is in kHz */
*multiplier = 1000;
return TOK_FM_RPT_SHIFT_50;
}
else if (freq >= MHz(28) && freq <= MHz(30))
{
/* 28 MHz band - menu value is in kHz */
*multiplier = 1000;
return TOK_FM_RPT_SHIFT_28;
}
/* Band doesn't support repeater offset */
*multiplier = 0;
return 0;
}
/*
* ftx1_set_rptr_offs - Set repeater offset frequency
*
* Sets the offset for the current band via EX menu.
* Requires reading current frequency to determine which band's offset to set.
*/
int ftx1_set_rptr_offs(RIG *rig, vfo_t vfo, shortfreq_t offs)
{
int ret;
freq_t freq;
hamlib_token_t token;
int multiplier;
value_t val;
rig_debug(RIG_DEBUG_VERBOSE, "%s: vfo=%s offs=%ld\n",
__func__, rig_strvfo(vfo), offs);
/* Get current frequency to determine band */
ret = ftx1_get_freq(rig, vfo, &freq);
if (ret != RIG_OK)
{
rig_debug(RIG_DEBUG_ERR, "%s: failed to get frequency\n", __func__);
return ret;
}
/* Get appropriate token for this band */
token = ftx1_get_band_offset_token(freq, &multiplier);
if (token == 0 || multiplier == 0)
{
rig_debug(RIG_DEBUG_WARN, "%s: band at %.0f Hz doesn't support repeater offset\n",
__func__, freq);
return -RIG_ENAVAIL;
}
/* Convert Hz offset to menu value */
val.i = (int)(offs / multiplier);
rig_debug(RIG_DEBUG_VERBOSE, "%s: freq=%.0f token=0x%lx val=%d (offs=%ld, mult=%d)\n",
__func__, freq, (unsigned long)token, val.i, offs, multiplier);
/* Set via menu system */
return ftx1_menu_set_token(rig, token, val);
}
/*
* ftx1_get_rptr_offs - Get repeater offset frequency
*
* Gets the offset for the current band via EX menu.
* Requires reading current frequency to determine which band's offset to read.
*/
int ftx1_get_rptr_offs(RIG *rig, vfo_t vfo, shortfreq_t *offs)
{
int ret;
freq_t freq;
hamlib_token_t token;
int multiplier;
value_t val;
rig_debug(RIG_DEBUG_VERBOSE, "%s: vfo=%s\n", __func__, rig_strvfo(vfo));
/* Get current frequency to determine band */
ret = ftx1_get_freq(rig, vfo, &freq);
if (ret != RIG_OK)
{
rig_debug(RIG_DEBUG_ERR, "%s: failed to get frequency\n", __func__);
return ret;
}
/* Get appropriate token for this band */
token = ftx1_get_band_offset_token(freq, &multiplier);
if (token == 0 || multiplier == 0)
{
rig_debug(RIG_DEBUG_WARN, "%s: band at %.0f Hz doesn't support repeater offset\n",
__func__, freq);
*offs = 0;
return RIG_OK; /* Return 0 offset for bands without repeater */
}
/* Get via menu system */
ret = ftx1_menu_get_token(rig, token, &val);
if (ret != RIG_OK)
{
return ret;
}
/* Convert menu value to Hz offset */
*offs = (shortfreq_t)val.i * multiplier;
rig_debug(RIG_DEBUG_VERBOSE, "%s: freq=%.0f token=0x%lx val=%d offs=%ld\n",
__func__, freq, (unsigned long)token, val.i, *offs);
return RIG_OK;
}

View file

@ -224,6 +224,7 @@ int ftx1_set_func(RIG *rig, vfo_t vfo, setting_t func, int status)
case RIG_FUNC_DUAL_WATCH:
/* FTX-1: FR command controls dual/single receive mode */
return ftx1_set_dual_receive(rig, status);
/* Note: NA command (narrow) available via ftx1_set_na_helper but no RIG_FUNC_NAR in Hamlib */
/* Note: Contour (CO command) not exposed as RIG_FUNC_CONTOUR doesn't exist in Hamlib */
default:
return newcat_set_func(rig, vfo, func, status);
@ -299,6 +300,7 @@ int ftx1_get_func(RIG *rig, vfo_t vfo, setting_t func, int *status)
case RIG_FUNC_DUAL_WATCH:
/* FTX-1: FR command controls dual/single receive mode */
return ftx1_get_dual_receive(rig, status);
/* Note: NA command (narrow) available via ftx1_get_na_helper but no RIG_FUNC_NAR in Hamlib */
/* 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

@ -335,6 +335,8 @@ static const struct ftx1_menu_item ftx1_menu_table[] = {
{ TOK_APRS_AF_MUTE, "APRS_AF_MUTE", 1, 0, 1, 0 },
{ TOK_APRS_TX_DELAY, "APRS_TX_DELAY", 1, 0, 6, 0 },
{ TOK_APRS_CALLSIGN, "APRS_CALLSIGN", 8, 0, 0, FTX1_MENU_FLAG_STRING },
/* Items 06-08 don't exist */
{ TOK_APRS_DEST, "APRS_DEST", 6, 0, 0, FTX1_MENU_FLAG_STRING }, /* Fixed: APYX01 */
/* EX0602: MSG TEMPLATE */
{ TOK_APRS_MSG_TEXT1, "APRS_MSG_TEXT1", 16, 0, 0, FTX1_MENU_FLAG_STRING },

View file

@ -356,6 +356,8 @@
#define TOK_APRS_AF_MUTE FTX1_TOKEN(6, 1, 3)
#define TOK_APRS_TX_DELAY FTX1_TOKEN(6, 1, 4)
#define TOK_APRS_CALLSIGN FTX1_TOKEN(6, 1, 5)
/* Note: Items 06-08 don't exist per CAT manual */
#define TOK_APRS_DEST FTX1_TOKEN(6, 1, 9) /* APRS DESTINATION (fixed: APYX01) */
/* EX0602: MSG TEMPLATE */
#define TOK_APRS_MSG_TEXT1 FTX1_TOKEN(6, 2, 1)

View file

@ -36,6 +36,18 @@ VFO Commands (ftx1_vfo.c):
Frequency Commands (ftx1_freq.c):
FA P1...P9; - VFO-A Frequency (9-digit Hz, e.g., FA014250000;) [WORKING]
FB P1...P9; - VFO-B Frequency (9-digit Hz) [WORKING]
OS P1 P2; - Offset Shift (repeater direction) [WORKING - set/read]
P1=VFO (0=MAIN, 1=SUB), P2=Shift (0=Simplex, 1=Plus, 2=Minus, 3=ARS)
Repeater Offset Frequency (ftx1_freq.c):
Repeater offset values are stored per-band in EX menu items:
EX010316 (TOK_FM_RPT_SHIFT_28) - 28 MHz band (0-1000 kHz)
EX010317 (TOK_FM_RPT_SHIFT_50) - 50 MHz band (0-4000 kHz)
EX010318 (TOK_FM_RPT_SHIFT_144) - 144 MHz band (0-1000 kHz, in 10kHz units)
EX010319 (TOK_FM_RPT_SHIFT_430) - 430 MHz band (0-10000 kHz, in 100kHz units)
ftx1_set_rptr_offs() and ftx1_get_rptr_offs() automatically detect the current
band from VFO frequency and access the appropriate menu token.
RIT/XIT Clarifier Commands (ftx1_clarifier.c):
*** SPECIAL ACKNOWLEDGMENT - JEREMY MILLER (KO4SSD) ***
@ -435,7 +447,10 @@ Commands:
Read: PB0; Response: PB0n (n=channel or 0 if stopped)
PL P1; - Processor Level [WORKING - read-only]
PR P1; - Processor on/off [WORKING - read-only]
RI P1; - RIT Information [WORKING - read-only]
RI; - Radio Information [WORKING - read-only, used for DCD/squelch status]
Response: RI P1 P2 P3 P4 P5 P6 P7 P8 P9 P10 P11 P12 P13;
P8 = SQL status: 0=Closed (no signal), 1=Open (BUSY/signal present)
Used by ftx1_get_dcd() to report squelch/DCD state
SF P1 P2; - Sub Dial (FUNC Knob) assignment [WORKING - read-only recommended]
P1=VFO (0), P2=single hex char (0-H)
0=None, 7=Mic Gain, D=RF Power, G=CW Pitch, H=BK Delay
@ -708,10 +723,13 @@ Supported Features
- Manual/auto notch filter
- Beat cancel and contour controls
- CW keyer with memories (1-5)
- CW pitch adjustment (300-1050 Hz via KP command)
- VOX with adjustable gain and delay
- Memory channels (1-99) plus PMS (100-117)
- Antenna tuner control
- S-meter, SWR, ALC, power meter readings
- DCD (squelch status) via RI command P8
- Repeater shift direction and offset frequency (per-band via EX menu)
Tuner Control
-------------
@ -752,20 +770,20 @@ Header File:
Source Files:
ftx1.c - Main driver, rig_caps, open/close, SPA-1 detection
ftx1_vfo.c - VFO select (VS), split (ST/FT), VFO operations (AB/BA/SV)
ftx1_freq.c - Frequency get/set (FA/FB)
ftx1_freq.c - Frequency (FA/FB), repeater shift (OS), repeater offset (EX menu)
ftx1_mode.c - Mode documentation (delegates to newcat)
ftx1_audio.c - AF/RF/Mic gain (AG/RG/MG), power (PC), meters (SM/RM), AGC (GT)
ftx1_clarifier.c - RIT/XIT using RC/TC commands (Jeremy Miller KO4SSD - PR #1826)
ftx1_func.c - Central dispatcher for func/level operations
ftx1_info.c - Radio info (ID/IF/OI), AI mode, IF shift (IS), date/time (DT)
ftx1_mem.c - Memory operations (MC/MR/MW/MT/MZ/MA/MB/AM/BM/VM/CH)
ftx1_tx.c - PTT (TX), VOX (VX), tuner (AC), break-in (BI), power (PS)
ftx1_tx.c - PTT (TX), VOX (VX), tuner (AC), break-in (BI), power (PS), DCD (RI)
ftx1_cw.c - CW keyer (KS/KP/KR/KY/KM/SD/CS)
ftx1_ctcss.c - CTCSS/DCS tone control (CN/CT/DC)
ftx1_noise.c - Noise blanker (NL), noise reduction (RL)
ftx1_filter.c - Notch (BP), contour/APF (CO), beat cancel (BC)
ftx1_preamp.c - Preamp (PA), attenuator (RA)
ftx1_scan.c - Scan (SC), band select (BS), tuning step (TS), zero-in (ZI)
ftx1_scan.c - Scan (SC), band select (BS), band up/down (BU/BD), tuning step (TS), zero-in (ZI)
ftx1_ext.c - Extended menu basics (EX), spectrum scope (SS), encoder offset (EO)
ftx1_menu.c - Complete EX menu (~250 items): all 11 groups, set/get, ext_parm
ftx1_menu.h - EX menu token definitions (TOK_*), item structures, flags
@ -773,6 +791,26 @@ Source Files:
================================================================================
REVISION HISTORY
================================================================================
2025-12-19 Gap fixes and additional capability support
- Added DCD (squelch status) support via RI command P8
* Implemented ftx1_get_dcd() in ftx1_tx.c
* Changed dcd_type from RIG_DCD_NONE to RIG_DCD_RIG
* RI command returns 13 parameters, P8 is SQL status (0=closed, 1=open)
- Added RIG_LEVEL_CWPITCH to has_get_level/has_set_level
* Implementation already existed via KP command (300-1050 Hz)
* Now properly advertised in rig_caps
- Added repeater offset frequency support (set_rptr_offs/get_rptr_offs)
* Implemented in ftx1_freq.c using per-band EX menu tokens
* TOK_FM_RPT_SHIFT_28/50/144/430 for band-specific offsets
* Auto-detects band from VFO frequency
- Implemented RIG_OP_BAND_UP and RIG_OP_BAND_DOWN
* ftx1_band_up() uses BU0; command
* ftx1_band_down() uses BD0; command
* Cycles through amateur bands on MAIN VFO
- Note: NA (narrow filter) helpers exist but Hamlib has no RIG_FUNC_NAR
* ftx1_set_na_helper() and ftx1_get_na_helper() available internally
* Cannot be exposed via standard Hamlib func interface
2025-12-19 Implemented complete EX menu support (~250 menu items)
- Created ftx1_menu.h with token definitions for all EX commands
Token encoding: 0xGGSSII maps directly to EX group/section/item

View file

@ -24,6 +24,8 @@
* CAT Commands in this file:
* SC P1; - Scan Control (0=stop, 1=up, 2=down)
* BS P1P2; - Band Select (P1P2=band code)
* BU P1; - Band Up (P1=VFO, cycles to higher band)
* BD P1; - Band Down (P1=VFO, cycles to lower band)
* UP; - Frequency/Channel Up
* DN; - Frequency/Channel Down
* TS P1P2; - Tuning Step (00-14 code for step size)
@ -235,6 +237,36 @@ int ftx1_freq_down(RIG *rig)
return newcat_set_cmd(rig);
}
/*
* Band Up (BU P1;)
* CAT command: BU P1; (P1=0 for MAIN VFO)
* Cycles to the next higher amateur band
*/
int ftx1_band_up(RIG *rig)
{
struct newcat_priv_data *priv = STATE(rig)->priv;
rig_debug(RIG_DEBUG_VERBOSE, "%s\n", __func__);
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "BU0;");
return newcat_set_cmd(rig);
}
/*
* Band Down (BD P1;)
* CAT command: BD P1; (P1=0 for MAIN VFO)
* Cycles to the next lower amateur band
*/
int ftx1_band_down(RIG *rig)
{
struct newcat_priv_data *priv = STATE(rig)->priv;
rig_debug(RIG_DEBUG_VERBOSE, "%s\n", __func__);
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "BD0;");
return newcat_set_cmd(rig);
}
/* Set Tuning Step (TS P1P2;) */
int ftx1_set_ts(RIG *rig, vfo_t vfo, shortfreq_t ts)
{
@ -302,10 +334,9 @@ int ftx1_vfo_op_scan(RIG *rig, vfo_t vfo, vfo_op_t op)
case RIG_OP_DOWN:
return ftx1_freq_down(rig);
case RIG_OP_BAND_UP:
/* Not directly supported, could cycle bands */
return -RIG_ENIMPL;
return ftx1_band_up(rig);
case RIG_OP_BAND_DOWN:
return -RIG_ENIMPL;
return ftx1_band_down(rig);
default:
return -RIG_EINVAL;
}

View file

@ -522,3 +522,63 @@ int ftx1_get_tx_watch(RIG *rig, int *status)
return RIG_OK;
}
/*
* =============================================================================
* RI Command: Read Radio Information (for DCD/Squelch status)
* =============================================================================
* CAT format: RI;
* Response: RI P1 P2 P3 P4 P5 P6 P7 P8 P9 P10 P11 P12 P13;
*
* P8 = SQL (Squelch) status:
* 0 = SQL Closed (no signal / below threshold)
* 1 = SQL Open (BUSY - signal present / above threshold)
*
* This is used for DCD (Data Carrier Detect) functionality.
*/
/*
* ftx1_get_dcd - Get DCD (squelch) status via RI command P8
*
* Returns RIG_DCD_ON when squelch is open (signal present),
* RIG_DCD_OFF when squelch is closed (no signal).
*/
int ftx1_get_dcd(RIG *rig, vfo_t vfo, dcd_t *dcd)
{
struct newcat_priv_data *priv = STATE(rig)->priv;
int ret;
int p1, p2, p3, p4, p5, p6, p7, p8;
(void)vfo; /* FTX-1 RI command returns overall status, not per-VFO */
rig_debug(RIG_DEBUG_VERBOSE, "%s\n", __func__);
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "RI;");
ret = newcat_get_cmd(rig);
if (ret != RIG_OK)
{
return ret;
}
/*
* Response format: RI P1 P2 P3 P4 P5 P6 P7 P8 P9 P10 P11 P12 P13;
* Each P is a single digit. We need P8 (SQL status).
* Parse 8 digits to get to P8.
*/
if (sscanf(priv->ret_data + 2, "%1d%1d%1d%1d%1d%1d%1d%1d",
&p1, &p2, &p3, &p4, &p5, &p6, &p7, &p8) != 8)
{
rig_debug(RIG_DEBUG_ERR, "%s: failed to parse '%s'\n",
__func__, priv->ret_data);
return -RIG_EPROTO;
}
/* P8: 0=SQL Closed (no signal), 1=SQL Open (BUSY/signal present) */
*dcd = (p8 == 1) ? RIG_DCD_ON : RIG_DCD_OFF;
rig_debug(RIG_DEBUG_VERBOSE, "%s: P8(SQL)=%d dcd=%s\n",
__func__, p8, (*dcd == RIG_DCD_ON) ? "ON" : "OFF");
return RIG_OK;
}