Streamline VFO targeting and split functionality. Rewrite Icom backend routines to always avoid VFO swapping is the rig supports the 'targetable' commands 0x25 and 0x26. Work in progress.

pull/1481/head
Mikael Nousiainen 2023-10-29 10:28:36 +02:00
rodzic 325277f269
commit 8ab8aafe48
17 zmienionych plików z 779 dodań i 865 usunięć

Wyświetl plik

@ -540,9 +540,17 @@ static int dummy_set_mode(RIG *rig, vfo_t vfo, rmode_t mode, pbwidth_t width)
case RIG_VFO_MAIN:
case RIG_VFO_A: width = priv->vfo_a.width; break;
case RIG_VFO_MAIN_A: width = priv->vfo_maina.width; break;
case RIG_VFO_MAIN_B: width = priv->vfo_mainb.width; break;
case RIG_VFO_SUB:
case RIG_VFO_B: width = priv->vfo_b.width; break;
case RIG_VFO_SUB_A: width = priv->vfo_suba.width; break;
case RIG_VFO_SUB_B: width = priv->vfo_subb.width; break;
case RIG_VFO_C: width = priv->vfo_c.width; break;
}
}
@ -552,9 +560,17 @@ static int dummy_set_mode(RIG *rig, vfo_t vfo, rmode_t mode, pbwidth_t width)
case RIG_VFO_MAIN:
case RIG_VFO_A: priv->vfo_a.mode = mode; priv->vfo_a.width = width; break;
case RIG_VFO_MAIN_A: priv->vfo_maina.mode = mode; priv->vfo_maina.width = width; break;
case RIG_VFO_MAIN_B: priv->vfo_mainb.mode = mode; priv->vfo_mainb.width = width; break;
case RIG_VFO_SUB:
case RIG_VFO_B: priv->vfo_b.mode = mode; priv->vfo_b.width = width; break;
case RIG_VFO_SUB_A: priv->vfo_suba.mode = mode; priv->vfo_suba.width = width; break;
case RIG_VFO_SUB_B: priv->vfo_subb.mode = mode; priv->vfo_subb.width = width; break;
case RIG_VFO_C: priv->vfo_c.mode = mode; priv->vfo_c.width = width; break;
default:
@ -941,11 +957,11 @@ static int dummy_set_split_freq(RIG *rig, vfo_t vfo, freq_t tx_freq)
int retval;
ENTERFUNC;
rig_debug(RIG_DEBUG_VERBOSE, "%s: vfo=%s freq=%.0f\n", __func__, rig_strvfo(vfo), tx_freq);
retval = dummy_set_freq(rig, vfo, tx_freq);
priv->curr->tx_freq = tx_freq;
rig_debug(RIG_DEBUG_VERBOSE, "%s: priv->curr->tx_freq = %.0f\n", __func__,
priv->curr->tx_freq);
rig_debug(RIG_DEBUG_VERBOSE, "%s: freq=%.0f\n", __func__, tx_freq);
RETURNFUNC(retval);
}
@ -953,15 +969,15 @@ static int dummy_set_split_freq(RIG *rig, vfo_t vfo, freq_t tx_freq)
static int dummy_get_split_freq(RIG *rig, vfo_t vfo, freq_t *tx_freq)
{
struct dummy_priv_data *priv = (struct dummy_priv_data *)rig->state.priv;
int retval;
ENTERFUNC;
rig_debug(RIG_DEBUG_VERBOSE, "%s: vfo=%s\n", __func__, rig_strvfo(vfo));
*tx_freq = priv->curr->tx_freq;
rig_debug(RIG_DEBUG_VERBOSE, "%s: priv->curr->tx_freq = %.0f\n", __func__,
priv->curr->tx_freq);
retval = dummy_get_freq(rig, vfo, tx_freq);
rig_debug(RIG_DEBUG_VERBOSE, "%s: freq=%.0f\n", __func__, *tx_freq);
RETURNFUNC(RIG_OK);
RETURNFUNC(retval);
}
static int dummy_set_split_mode(RIG *rig, vfo_t vfo, rmode_t tx_mode,
@ -969,41 +985,50 @@ static int dummy_set_split_mode(RIG *rig, vfo_t vfo, rmode_t tx_mode,
{
struct dummy_priv_data *priv = (struct dummy_priv_data *)rig->state.priv;
channel_t *curr = priv->curr;
int retval;
ENTERFUNC;
rig_debug(RIG_DEBUG_VERBOSE, "%s: vfo=%s tx_mode=%s tx_width=%ld\n",
__func__, rig_strvfo(vfo), rig_strrmode(tx_mode), tx_width);
retval = dummy_set_mode(rig, vfo, tx_mode, tx_width);
curr->tx_mode = tx_mode;
if (RIG_PASSBAND_NOCHANGE == tx_width) { RETURNFUNC(RIG_OK); }
if (RIG_PASSBAND_NOCHANGE == tx_width)
{
RETURNFUNC(retval);
}
curr->tx_width = tx_width;
RETURNFUNC(RIG_OK);
RETURNFUNC(retval);
}
static int dummy_get_split_mode(RIG *rig, vfo_t vfo, rmode_t *tx_mode,
pbwidth_t *tx_width)
{
struct dummy_priv_data *priv = (struct dummy_priv_data *)rig->state.priv;
const channel_t *curr = priv->curr;
int retval;
ENTERFUNC;
rig_debug(RIG_DEBUG_VERBOSE, "%s: vfo=%s\n", __func__, rig_strvfo(vfo));
*tx_mode = curr->tx_mode;
*tx_width = curr->tx_width;
retval = dummy_get_mode(rig, vfo, tx_mode, tx_width);
RETURNFUNC(RIG_OK);
rig_debug(RIG_DEBUG_VERBOSE, "%s: vfo=%s tx_mode=%s tx_width=%ld\n",
__func__, rig_strvfo(vfo), rig_strrmode(*tx_mode), *tx_width);
RETURNFUNC(retval);
}
static int dummy_set_split_vfo(RIG *rig, vfo_t vfo, split_t split, vfo_t tx_vfo)
{
struct dummy_priv_data *priv = (struct dummy_priv_data *)rig->state.priv;
channel_t *curr = priv->curr;
ENTERFUNC;
rig_debug(RIG_DEBUG_VERBOSE, "%s: split=%d, vfo=%s, tx_vfo=%s\n",
__func__, split, rig_strvfo(vfo), rig_strvfo(tx_vfo));
curr->split = split;
priv->split = split;
priv->tx_vfo = tx_vfo;
RETURNFUNC(RIG_OK);
@ -1014,10 +1039,14 @@ static int dummy_get_split_vfo(RIG *rig, vfo_t vfo, split_t *split,
vfo_t *tx_vfo)
{
struct dummy_priv_data *priv = (struct dummy_priv_data *)rig->state.priv;
const channel_t *curr = priv->curr;
ENTERFUNC;
*split = curr->split;
*split = priv->split;
*tx_vfo = priv->tx_vfo;
rig_debug(RIG_DEBUG_VERBOSE, "%s: split=%d, vfo=%s, tx_vfo=%s\n",
__func__, *split, rig_strvfo(vfo), rig_strvfo(*tx_vfo));
RETURNFUNC(RIG_OK);
}
@ -2311,6 +2340,13 @@ struct rig_caps dummy_caps =
[LVL_SPECTRUM_REF] = {.min = {.f = -30.0f}, .max = {.f = 10.0f}, .step = {.f = 0.5f}},
[LVL_SPECTRUM_AVG] = {.min = {.i = 0}, .max = {.i = 3}, .step = {.i = 1}},
},
.parm_gran = {
[PARM_BACKLIGHT] = {.min = {.f = 0.0f}, .max = {.f = 1.0f}, .step = {.f = 1.0f / 255.0f}},
[PARM_BANDSELECT] = {.step = {.s = "BANDUNUSED,BAND70CM,BAND33CM,BAND23CM"}},
[PARM_BEEP] = {.min = {.i = 0}, .max = {.i = 1}},
[PARM_SCREENSAVER] = {.min = {.i = 0}, .max = {.i = 3}, .step = {.i = 1}},
[PARM_KEYERTYPE] = {.step = {.s = "STRAIGHT,BUG,PADDLE"}},
},
.ctcss_list = common_ctcss_list,
.dcs_list = full_dcs_list,
.chan_list = {

Wyświetl plik

@ -735,7 +735,7 @@ const struct rig_caps ic7300_caps =
[PARM_BEEP] = {.min = {.i = 0}, .max = {.i = 1}, .step = {.i = 1}},
[PARM_SCREENSAVER] = {.min = {.i = 0}, .max = {.i = 3}, .step = {.i = 1}},
[PARM_TIME] = {.min = {.i = 0}, .max = {.i = 86399}, .step = {.i = 1}},
[PARM_KEYERTYPE] = {.step = {.s = "STRAIGHT, BUG, PADDLE"}},
[PARM_KEYERTYPE] = {.step = {.s = "STRAIGHT,BUG,PADDLE"}},
},
.ext_tokens = ic7300_ext_tokens,
@ -978,7 +978,7 @@ struct rig_caps ic9700_caps =
[PARM_BANDSELECT] = {.step = {.s = "BANDUNUSED,BAND70CM,BAND33CM,BAND23CM"}},
[PARM_BEEP] = {.min = {.i = 0}, .max = {.i = 1}},
[PARM_SCREENSAVER] = {.min = {.i = 0}, .max = {.i = 3}, .step = {.i = 1}},
[PARM_KEYERTYPE] = {.step = {.s = "STRAIGHT, BUG, PADDLE"}},
[PARM_KEYERTYPE] = {.step = {.s = "STRAIGHT,BUG,PADDLE"}},
},
.ext_tokens = ic9700_ext_tokens,
.extlevels = icom_ext_levels,
@ -1572,7 +1572,7 @@ const struct rig_caps ic905_caps =
[PARM_BANDSELECT] = {.step = {.s = "BANDUNUSED,BAND70CM,BAND33CM,BAND23CM,BAND23CM,BAND13CM,BAND3CM"}},
[PARM_BEEP] = {.min = {.i = 0}, .max = {.i = 1}},
[PARM_SCREENSAVER] = {.min = {.i = 0}, .max = {.i = 3}, .step = {.i = 1}},
[PARM_KEYERTYPE] = {.step = {.s = "STRAIGHT, BUG, PADDLE"}},
[PARM_KEYERTYPE] = {.step = {.s = "STRAIGHT,BUG,PADDLE"}},
},
.ext_tokens = ic705_ext_tokens,
.extlevels = icom_ext_levels,

Wyświetl plik

@ -157,7 +157,7 @@ const struct rig_caps ic7410_caps =
.parm_gran = {
[PARM_BACKLIGHT] = {.min = {.f = 0.0f}, .max = {.f = 1.0f}, .step = {.f = 1.0f / 255.0f}},
[PARM_ANN] = {.min = {.i = 0}, .max = {.i = 2}, .step = {.i = 1}},
[PARM_KEYERTYPE] = {.step = {.s = "STRAIGHT, BUG, PADDLE"}},
[PARM_KEYERTYPE] = {.step = {.s = "STRAIGHT,BUG,PADDLE"}},
},
.ctcss_list = common_ctcss_list,

Wyświetl plik

@ -315,7 +315,7 @@ struct rig_caps ic7600_caps =
[PARM_TIME] = {.min = {.i = 0}, .max = {.i = 86399}, .step = {.i = 1}},
[PARM_ANN] = {.min = {.i = 0}, .max = {.i = 2}, .step = {.i = 1}},
[PARM_APO] = { .min = { .i = 1 }, .max = { .i = 1439} },
[PARM_KEYERTYPE] = {.step = {.s = "STRAIGHT, BUG, PADDLE"}},
[PARM_KEYERTYPE] = {.step = {.s = "STRAIGHT,BUG,PADDLE"}},
},
.ext_tokens = ic7600_ext_tokens,

Wyświetl plik

@ -398,7 +398,7 @@ struct rig_caps ic7610_caps =
[PARM_BEEP] = {.min = {.i = 0}, .max = {.i = 1}, .step = {.i = 1}},
[PARM_TIME] = {.min = {.i = 0}, .max = {.i = 86399}, .step = {.i = 1}},
[PARM_ANN] = {.min = {.i = 0}, .max = {.i = 2}, .step = {.i = 1}},
[PARM_KEYERTYPE] = {.step = {.s = "STRAIGHT, BUG, PADDLE"}},
[PARM_KEYERTYPE] = {.step = {.s = "STRAIGHT,BUG,PADDLE"}},
},
.ext_tokens = ic7610_ext_tokens,

Wyświetl plik

@ -282,7 +282,7 @@ const struct rig_caps ic785x_caps =
[PARM_BEEP] = {.min = {.i = 0}, .max = {.i = 1}, .step = {.i = 1}},
[PARM_TIME] = {.min = {.i = 0}, .max = {.i = 86399}, .step = {.i = 1}},
[PARM_ANN] = {.min = {.i = 0}, .max = {.i = 2}, .step = {.i = 1}},
[PARM_KEYERTYPE] = {.step = {.s = "STRAIGHT, BUG, PADDLE"}},
[PARM_KEYERTYPE] = {.step = {.s = "STRAIGHT,BUG,PADDLE"}},
},
.ext_tokens = ic785x_ext_tokens,

Wyświetl plik

@ -69,14 +69,14 @@ int ic821h_set_split_vfo(RIG *rig, vfo_t vfo, split_t split, vfo_t tx_vfo)
split; // we emulate satmode of other rigs since we apparently can't query
rig_debug(RIG_DEBUG_TRACE, "%s: tx_vfo==MAIN so assuming sat mode=%d\n",
__func__, rig->state.cache.satmode);
priv->tx_vfo = split == RIG_SPLIT_ON ? RIG_VFO_SUB : RIG_VFO_MAIN;
rig->state.tx_vfo = split == RIG_SPLIT_ON ? RIG_VFO_SUB : RIG_VFO_MAIN;
// the IC821 seems to be backwards in satmode -- setting Main select Sub and vice versa
retval = rig_set_vfo(rig, RIG_VFO_SUB);
}
else if (tx_vfo == RIG_VFO_A)
{
retval = rig_set_vfo(rig, RIG_VFO_A);
priv->tx_vfo = split == RIG_SPLIT_ON ? RIG_VFO_B : RIG_VFO_A;
rig->state.tx_vfo = split == RIG_SPLIT_ON ? RIG_VFO_B : RIG_VFO_A;
}
else
{

Wyświetl plik

@ -142,7 +142,7 @@ const struct rig_caps ic9100_caps =
[PARM_BACKLIGHT] = {.min = {.f = 0.0f}, .max = {.f = 1.0f}, .step = {.f = 1.0f / 255.0f}},
[PARM_BANDSELECT] = {.step = {.s = "BANDUNUSED,BAND160M,BAND80M,BAND40M,BAND30M,BAND20M,BAND17M,BAND15M,BAND12M,BAND10M,BAND6M,BANDGEN"}},
[PARM_ANN] = {.min = {.i = 0}, .max = {.i = 2}, .step = {.i = 1}},
[PARM_KEYERTYPE] = {.step = {.s = "STRAIGHT, BUG, PADDLE"}},
[PARM_KEYERTYPE] = {.step = {.s = "STRAIGHT,BUG,PADDLE"}},
},
.ctcss_list = common_ctcss_list,

Plik diff jest za duży Load Diff

Wyświetl plik

@ -253,22 +253,28 @@ struct icom_priv_data
int civ_731_mode; /*!< Off: freqs on 10 digits, On: freqs on 8 digits */
int no_xchg; /*!< Off: use VFO XCHG to set other VFO, On: use set VFO to set other VFO */
int no_1a_03_cmd; /*!< Rig doesn't tell IF widths */
int split_on; /*!< Record split state */
int split_on_deprecated; /*!< @deprecated Use rig_cache.split - Record split state */
pltstate_t *pltstate; /*!< Only on optoscan */
int serial_USB_echo_off; /*!< USB is not set to echo */
/* we track vfos internally for use with different functions like split */
/* this allows queries using CURR_VFO and Main/Sub to behave */
vfo_t rx_vfo;
vfo_t tx_vfo;
freq_t curr_freq; /*!< Our current freq depending on which vfo is selected */
freq_t main_freq; /*!< Track last setting of main -- not being used yet */
freq_t sub_freq; /*!< Track last setting of sub -- not being used yet */
freq_t maina_freq;
freq_t mainb_freq;
freq_t suba_freq;
freq_t subb_freq;
freq_t vfoa_freq; /*!< Track last setting of vfoa -- used to return last freq when ptt is asserted */
freq_t vfob_freq; /*!< Track last setting of vfob -- used to return last freq when ptt is asserted */
/**
* Icom backends track VFOs internally for use with different functions like split.
* This allows queries using CURR_VFO and Main/Sub to work correctly.
*
* The fields in this struct are no longer used, because rig_state and rig_cache structs provide
* the same functionality for all rigs globally.
*/
vfo_t rx_vfo_deprecated; /*!< @deprecated Use rig_state.rx_vfo */
vfo_t tx_vfo_deprecated; /*!< @deprecated Use rig_state.tx_vfo */
freq_t curr_freq_deprecated; /*!< @deprecated Use rig_cache.freqCurr - Our current freq depending on which vfo is selected */
freq_t main_freq_deprecated; /*!< @deprecated Use rig_cache.freqMainA - Track last setting of main -- not being used yet */
freq_t sub_freq_deprecated; /*!< @deprecated Use rig_cache.freqSubA - Track last setting of sub -- not being used yet */
freq_t maina_freq_deprecated; /*!< @deprecated Use rig_cache.freqMainA */
freq_t mainb_freq_deprecated; /*!< @deprecated Use rig_cache.freqMainB */
freq_t suba_freq_deprecated; /*!< @deprecated Use rig_cache.freqSubA */
freq_t subb_freq_deprecated; /*!< @deprecated Use rig_cache.freqSubB */
freq_t vfoa_freq_deprecated; /*!< @deprecated Use rig_cache.freqMainA - Track last setting of vfoa -- used to return last freq when ptt is asserted */
freq_t vfob_freq_deprecated; /*!< @deprecated Use rig_cache.freqMainB - Track last setting of vfob -- used to return last freq when ptt is asserted */
int x25cmdfails; /*!< This will get set if the 0x25 command fails so we try just once */
int x26cmdfails; /*!< This will get set if the 0x26 command fails so we try just once */
int x1cx03cmdfails; /*!< This will get set if the 0x1c 0x03 command fails so we try just once */
@ -277,7 +283,7 @@ struct icom_priv_data
unsigned char datamode; /*!< Current datamode */
int spectrum_scope_count; /*!< Number of spectrum scopes, calculated from caps */
struct icom_spectrum_scope_cache spectrum_scope_cache[HAMLIB_MAX_SPECTRUM_SCOPES]; /*!< Cached Icom spectrum scope data used during reception of the data. The array index must match the scope ID. */
freq_t other_freq; /*!< Our other freq depending on which vfo is selected */
freq_t other_freq_deprecated; /*!< @deprecated Use rig_cache.freqOther - Our other freq depending on which vfo is selected */
int vfo_flag; // used to skip vfo check when frequencies are equal
};

Wyświetl plik

@ -98,6 +98,7 @@
#define C_CTL_RIT 0x21 /* RIT/XIT control */
#define C_CTL_DSD 0x22 /* D-STAR Data */
#define C_SEND_SEL_FREQ 0x25 /* Send/Recv sel/unsel VFO frequency */
#define C_SEND_SEL_MODE 0x26 /* Send/Recv sel/unsel VFO mode & filter */
#define C_CTL_SCP 0x27 /* Scope control & data */
#define C_SND_VOICE 0x28 /* Transmit Voice Memory Contents */
#define C_CTL_MTEXT 0x70 /* Microtelecom Extension */
@ -160,7 +161,7 @@
#define S_DUAL 0xc2 /* Dual watch (0 = off, 1 = on) */
#define S_MAIN 0xd0 /* Select MAIN band */
#define S_SUB 0xd1 /* Select SUB band */
#define S_SUB_SEL 0xd2 /* Read/Set Main/Sub selection */
#define S_BAND_SEL 0xd2 /* Read/Set Main/Sub band selection */
#define S_FRONTWIN 0xe0 /* Select front window */
/*
@ -359,8 +360,9 @@
/*
* Transmit control (C_CTL_PTT) subcommands
*/
#define S_PTT 0x00
#define S_ANT_TUN 0x01 /* Auto tuner 0=OFF, 1 = ON, 2=Start Tuning */
#define S_PTT 0x00
#define S_ANT_TUN 0x01 /* Auto tuner 0=OFF, 1 = ON, 2=Start Tuning */
#define S_RD_TX_FREQ 0x03 /* Read transmit frequency */
/*
* Band Edge control (C_CTL_EDGE) subcommands

Wyświetl plik

@ -891,7 +891,6 @@ int x108g_set_ptt(RIG *rig, vfo_t vfo, ptt_t ptt)
*/
static int x108g_set_split_vfo(RIG *rig, vfo_t vfo, split_t split, vfo_t tx_vfo)
{
struct icom_priv_data *priv = (struct icom_priv_data *)rig->state.priv;
unsigned char ackbuf[MAXFRAMELEN];
int ack_len = sizeof(ackbuf), rc;
int split_sc;
@ -907,7 +906,7 @@ static int x108g_set_split_vfo(RIG *rig, vfo_t vfo, split_t split, vfo_t tx_vfo)
case RIG_SPLIT_ON:
split_sc = S_SPLT_ON;
if (!priv->split_on)
if (rig->state.cache.split == RIG_SPLIT_OFF)
{
/* ensure VFO A is Rx and VFO B is Tx as we assume that elsewhere */
if ((rig->state.vfo_list & (RIG_VFO_A | RIG_VFO_B)) == (RIG_VFO_A | RIG_VFO_B))
@ -934,7 +933,7 @@ static int x108g_set_split_vfo(RIG *rig, vfo_t vfo, split_t split, vfo_t tx_vfo)
return -RIG_ERJCTED;
}
priv->split_on = RIG_SPLIT_ON == split;
rig->state.cache.split = split;
return RIG_OK;
}
@ -973,13 +972,17 @@ static int x108g_set_split_freq(RIG *rig, vfo_t vfo, freq_t tx_freq)
current VFO is VFO A and the split Tx VFO is always VFO B. These
assumptions allow us to deal with the lack of VFO and split
queries */
/* broken if user changes split on rig :( */
if ((rig->state.vfo_list & (RIG_VFO_A | RIG_VFO_B)) == (RIG_VFO_A | RIG_VFO_B)
&& priv->split_on) /* broken if user changes split on rig :( */
&& rig->state.cache.split != RIG_SPLIT_OFF)
{
/* VFO A/B style rigs swap VFO on split Tx so we need to disable
split for certainty */
if (RIG_OK != (rc = icom_transaction(rig, C_CTL_SPLT, S_SPLT_OFF, NULL, 0,
ackbuf, &ack_len))) { return rc; }
rc = icom_transaction(rig, C_CTL_SPLT, S_SPLT_OFF, NULL, 0, ackbuf, &ack_len);
if (rc != RIG_OK)
{
return rc;
}
if (ack_len != 2 || ackbuf[0] != 0x0f)
{
@ -998,11 +1001,14 @@ static int x108g_set_split_freq(RIG *rig, vfo_t vfo, freq_t tx_freq)
if (RIG_OK != (rc = icom_set_vfo(rig, rx_vfo))) { return rc; }
if ((rig->state.vfo_list & (RIG_VFO_A | RIG_VFO_B)) == (RIG_VFO_A | RIG_VFO_B)
&& priv->split_on)
&& rig->state.cache.split != RIG_SPLIT_OFF)
{
/* Re-enable split */
if (RIG_OK != (rc = icom_transaction(rig, C_CTL_SPLT, S_SPLT_ON, NULL, 0,
ackbuf, &ack_len))) { return rc; }
rc = icom_transaction(rig, C_CTL_SPLT, S_SPLT_ON, NULL, 0, ackbuf, &ack_len);
if (rc != RIG_OK)
{
return rc;
}
}
return rc;
@ -1043,13 +1049,17 @@ static int x108g_set_split_mode(RIG *rig, vfo_t vfo, rmode_t tx_mode,
current VFO is VFO A and the split Tx VFO is always VFO B. These
assumptions allow us to deal with the lack of VFO and split
queries */
/* broken if user changes split on rig :( */
if ((rig->state.vfo_list & (RIG_VFO_A | RIG_VFO_B)) == (RIG_VFO_A | RIG_VFO_B)
&& priv->split_on) /* broken if user changes split on rig :( */
&& rig->state.cache.split != RIG_SPLIT_OFF)
{
/* VFO A/B style rigs swap VFO on split Tx so we need to disable
split for certainty */
if (RIG_OK != (rc = icom_transaction(rig, C_CTL_SPLT, S_SPLT_OFF, NULL, 0,
ackbuf, &ack_len))) { return rc; }
rc = icom_transaction(rig, C_CTL_SPLT, S_SPLT_OFF, NULL, 0, ackbuf, &ack_len);
if (rc != RIG_OK)
{
return rc;
}
if (ack_len != 2 || ackbuf[0] != 0x0f)
{
@ -1069,13 +1079,15 @@ static int x108g_set_split_mode(RIG *rig, vfo_t vfo, rmode_t tx_mode,
if (RIG_OK != (rc = icom_set_vfo(rig, rx_vfo))) { return rc; }
if ((rig->state.vfo_list & (RIG_VFO_A | RIG_VFO_B)) == (RIG_VFO_A | RIG_VFO_B)
&& priv->split_on)
&& rig->state.cache.split != RIG_SPLIT_OFF)
{
/* Re-enable split */
if (RIG_OK != (rc = icom_transaction(rig, C_CTL_SPLT, S_SPLT_ON, NULL, 0,
ackbuf, &ack_len))) { return rc; }
rc = icom_transaction(rig, C_CTL_SPLT, S_SPLT_ON, NULL, 0, ackbuf, &ack_len);
if (rc != RIG_OK)
{
return rc;
}
}
return rc;
}

Wyświetl plik

@ -60,6 +60,16 @@ int rig_set_cache_mode(RIG *rig, vfo_t vfo, rmode_t mode, pbwidth_t width)
if (vfo == RIG_VFO_OTHER) { vfo = vfo_fixup(rig, vfo, rig->state.cache.split); }
if (vfo == rig->state.current_vfo)
{
rig->state.cache.modeCurr = mode;
if (width > 0)
{
rig->state.cache.widthCurr = width;
}
elapsed_ms(&rig->state.cache.time_modeCurr, HAMLIB_ELAPSED_SET);
}
switch (vfo)
{
case RIG_VFO_ALL: // we'll use NONE to reset all VFO caches
@ -153,6 +163,12 @@ int rig_set_cache_freq(RIG *rig, vfo_t vfo, freq_t freq)
rig_strvfo(vfo), freq);
}
if (vfo == rig->state.current_vfo)
{
rig->state.cache.freqCurr = freq;
elapsed_ms(&rig->state.cache.time_freqCurr, flag);
}
switch (vfo)
{
case RIG_VFO_ALL: // we'll use NONE to reset all VFO caches

Wyświetl plik

@ -515,7 +515,6 @@ static int multicast_publisher_write_data(multicast_publisher_args
return (RIG_OK);
}
#if 0 // disable until we figure out what to do about Windows poor performance
static int multicast_publisher_read_data(multicast_publisher_args
const *mcast_publisher_args, size_t length, unsigned char *data)
{
@ -558,7 +557,6 @@ static int multicast_publisher_read_data(multicast_publisher_args
return (RIG_OK);
}
#endif
#else
@ -638,7 +636,6 @@ static int multicast_publisher_write_data(const multicast_publisher_args
return (RIG_OK);
}
#if 0
static int multicast_publisher_read_data(const multicast_publisher_args
*mcast_publisher_args, size_t length, unsigned char *data)
{
@ -703,7 +700,6 @@ static int multicast_publisher_read_data(const multicast_publisher_args
return (RIG_OK);
}
#endif
#endif
@ -827,7 +823,6 @@ int network_publish_rig_spectrum_data(RIG *rig, struct rig_spectrum_line *line)
RETURNFUNC2(RIG_OK);
}
#if 0
static int multicast_publisher_read_packet(multicast_publisher_args
const *mcast_publisher_args,
uint8_t *type, struct rig_spectrum_line *spectrum_line,
@ -893,11 +888,10 @@ static int multicast_publisher_read_packet(multicast_publisher_args
return (RIG_OK);
}
#endif
void *multicast_publisher(void *arg)
{
//unsigned char spectrum_data[HAMLIB_MAX_SPECTRUM_DATA];
unsigned char spectrum_data[HAMLIB_MAX_SPECTRUM_DATA];
char snapshot_buffer[HAMLIB_MAX_SNAPSHOT_PACKET_SIZE];
struct multicast_publisher_args_s *args = (struct multicast_publisher_args_s *)
@ -923,29 +917,21 @@ void *multicast_publisher(void *arg)
while (rs->multicast_publisher_run == 1)
{
int i;
int result;
static freq_t freqA, freqB, freqC;
static mode_t modeA, modeB, modeC;
static pbwidth_t widthA, widthB, widthC;
static ptt_t ptt;
static split_t split;
#if 0
result = multicast_publisher_read_packet(args, &packet_type, &spectrum_line,
spectrum_data);
#endif
if (result != RIG_OK)
{
if (result == -RIG_ETIMEOUT)
{
// continue;
continue;
}
// TODO: how to detect closing of pipe, indicate with error code
// TODO: error handling, flush pipe in case of error?
//hl_usleep(500 * 1000);
// continue;
hl_usleep(500 * 1000);
continue;
}
result = snapshot_serialize(sizeof(snapshot_buffer), snapshot_buffer, rig,
@ -959,10 +945,8 @@ void *multicast_publisher(void *arg)
continue;
}
#if 0
rig_debug(RIG_DEBUG_CACHE, "%s: sending rig snapshot data: %s\n", __func__,
snapshot_buffer);
#endif
send_result = sendto(
socket_fd,
@ -978,68 +962,7 @@ void *multicast_publisher(void *arg)
rig_debug(RIG_DEBUG_ERR, "%s: error sending UDP packet: %s\n", __func__,
strerror(errno));
}
for(i=0;i<5;++i)
{
hl_usleep(200*1000);
if (rig->state.cache.freqMainA != freqA)
{
freqA = rig->state.cache.freqMainA;
break;
}
if (rig->state.cache.freqMainB != freqB)
{
freqB = rig->state.cache.freqMainB;
break;
}
if (rig->state.cache.freqMainC != freqC)
{
freqC = rig->state.cache.freqMainC;
break;
}
if (rig->state.cache.ptt != ptt)
{
ptt = rig->state.cache.ptt;
break;
}
if (rig->state.cache.split != split)
{
split = rig->state.cache.split;
break;
}
if (rig->state.cache.modeMainA != modeA)
{
modeA = rig->state.cache.modeMainA;
break;
}
if (rig->state.cache.modeMainB != modeB)
{
modeB = rig->state.cache.modeMainB;
break;
}
if (rig->state.cache.modeMainC != modeC)
{
modeC = rig->state.cache.modeMainC;
break;
}
if (rig->state.cache.widthMainA != widthA)
{
widthA = rig->state.cache.widthMainA;
break;
}
if (rig->state.cache.widthMainB != widthB)
{
widthB = rig->state.cache.widthMainB;
break;
}
if (rig->state.cache.widthMainC != widthC)
{
widthC = rig->state.cache.widthMainC;
break;
}
}
}
rs->multicast_publisher_run = 2; // stop value
rig_debug(RIG_DEBUG_VERBOSE, "%s(%d): Stopping multicast publisher\n", __FILE__,
__LINE__);

497
src/rig.c
Wyświetl plik

@ -21,6 +21,17 @@
*
*/
/**
* TEST: Remove use of private state cache for VFOs/frequencies/modes in Icom backends and migrate to using the rig_state cache
* TEST: Ignore VFO targeting in all set/get split freq/mode commands and use the TX VFO set by \set_split_vfo command instead
* TEST: If split is not enabled, make \get_split_freq return 0 Hz frequency and get_split_mode return NONE mode with 0 Hz filter to indicate split is OFF
* TEST: set_split_freq and set_split_mode turn split ON if it is not enabled yet
* TODO: Make sure Icom set_freq/get_freq/set_mode/get_mode + set_split_freq/get_split_freq/set_split_mode/get_split_mode all use the 0x25 and 0x26 commands in a consistent way to avoid VFO swapping (on both the selected/unselected type rigs and Main/Sub VFO rigs)
*
* TODO: Test targeted set_freq/get_freq/set_mode/get_mode + split commands
* TODO: Test latest WSJT-X in split mode
*/
/**
* \addtogroup rig
* @{
@ -669,6 +680,7 @@ RIG *HAMLIB_API rig_init(rig_model_t rig_model)
rs->vfo_comp = 0.0; /* override it with preferences */
rs->current_vfo = RIG_VFO_CURR; /* we don't know yet! */
rs->rx_vfo = RIG_VFO_CURR; /* we don't know yet! */
rs->tx_vfo = RIG_VFO_CURR; /* we don't know yet! */
rs->poll_interval = 0; // disable polling by default
rs->lo_freq = 0;
@ -1396,18 +1408,6 @@ int HAMLIB_API rig_open(RIG *rig)
rig_debug(RIG_DEBUG_TRACE, "%s: vfo_curr=%s, tx_vfo=%s\n", __func__,
rig_strvfo(rs->current_vfo), rig_strvfo(rs->tx_vfo));
#if 0 // done in the back end
if (backend_num == RIG_ICOM)
{
HAMLIB_TRACE;
rig_set_vfo(rig, RIG_VFO_A); // force VFOA as our startup VFO
rig_debug(RIG_DEBUG_TRACE, "%s: Icom rig so default vfo = %s\n", __func__,
rig_strvfo(rs->current_vfo));
}
#endif
if (rig->caps->set_vfo == NULL)
{
// for non-Icom rigs if there's no set_vfo then we need to set one
@ -1458,7 +1458,12 @@ int HAMLIB_API rig_open(RIG *rig)
split_t split = RIG_SPLIT_OFF;
vfo_t tx_vfo = RIG_VFO_NONE;
rig_get_freq(rig, RIG_VFO_B, &freq);
rig_get_split_vfo(rig, RIG_VFO_RX, &split, &tx_vfo);
// TODO: Does this actually update rs->tx_vfo and split status?
retval = rig_get_split_vfo(rig, RIG_VFO_RX, &split, &tx_vfo);
if (retval == RIG_OK && caps->get_split_vfo != NULL)
{
rs->tx_vfo = tx_vfo;
}
rig_debug(RIG_DEBUG_VERBOSE, "%s(%d): Current split=%d, tx_vfo=%s\n", __func__,
__LINE__, split, rig_strvfo(tx_vfo));
rmode_t mode;
@ -3004,27 +3009,6 @@ int HAMLIB_API rig_set_vfo(RIG *rig, vfo_t vfo)
if (curr_vfo == vfo) { RETURNFUNC(RIG_OK); }
}
#if 0 // removing this check 20210801 -- should be mapped already
// make sure we are asking for a VFO that the rig actually has
if ((vfo == RIG_VFO_A || vfo == RIG_VFO_B) && !VFO_HAS_A_B)
{
rig_debug(RIG_DEBUG_ERR, "%s: rig does not have %s\n", __func__,
rig_strvfo(vfo));
ELAPSED2;
RETURNFUNC(-RIG_EINVAL);
}
if ((vfo == RIG_VFO_MAIN || vfo == RIG_VFO_SUB) && !VFO_HAS_MAIN_SUB)
{
rig_debug(RIG_DEBUG_ERR, "%s: rig does not have %s\n", __func__,
rig_strvfo(vfo));
ELAPSED2;
RETURNFUNC(-RIG_EINVAL);
}
#endif
vfo = vfo_fixup(rig, vfo, rig->state.cache.split);
caps = rig->caps;
@ -4304,10 +4288,13 @@ int HAMLIB_API rig_get_rptr_offs(RIG *rig, vfo_t vfo, shortfreq_t *rptr_offs)
int HAMLIB_API rig_set_split_freq(RIG *rig, vfo_t vfo, freq_t tx_freq)
{
const struct rig_caps *caps;
const struct rig_state *rs;
int retcode, rc2;
vfo_t curr_vfo, tx_vfo;
freq_t tfreq = 0;
ENTERFUNC2;
if (CHECK_RIG_ARG(rig))
{
rig_debug(RIG_DEBUG_ERR, "%s: rig or rig->caps is null\n",__func__);
@ -4321,17 +4308,26 @@ int HAMLIB_API rig_set_split_freq(RIG *rig, vfo_t vfo, freq_t tx_freq)
rig_strvfo(vfo), rig_strvfo(rig->state.current_vfo), tx_freq);
caps = rig->caps;
rs = &rig->state;
/* Use previously setup TxVFO */
if (vfo == RIG_VFO_CURR || vfo == RIG_VFO_TX)
// Always use the previously selected TX VFO for split. The targeted VFO will have no effect.
tx_vfo = rs->tx_vfo;
if (rs->cache.split == RIG_SPLIT_OFF || tx_vfo == RIG_VFO_NONE || tx_vfo == RIG_VFO_CURR)
{
tx_vfo = rig->state.tx_vfo;
}
else
{
tx_vfo = vfo_fixup(rig, vfo, rig->state.cache.split);
// Turn split on if not enabled already
retcode = rig_set_split_vfo(rig, rs->current_vfo, RIG_SPLIT_ON, vfo_fixup(rig, RIG_VFO_OTHER, RIG_SPLIT_OFF));
if (retcode != RIG_OK)
{
rig_debug(RIG_DEBUG_ERR, "%s: error turning split on: result=%d\n", __func__, retcode);
ELAPSED2;
RETURNFUNC2(retcode);
}
}
// TX VFO may change after enabling split
tx_vfo = rs->tx_vfo;
rig_get_freq(rig, tx_vfo, &tfreq);
if (tfreq == tx_freq)
@ -4341,25 +4337,21 @@ int HAMLIB_API rig_set_split_freq(RIG *rig, vfo_t vfo, freq_t tx_freq)
RETURNFUNC2(RIG_OK);
}
if (caps->set_split_freq
&& (vfo == RIG_VFO_CURR
|| vfo == RIG_VFO_TX
|| tx_vfo == rig->state.current_vfo
|| (caps->targetable_vfo & RIG_TARGETABLE_FREQ)))
// Use set_split_freq directly if implemented and frequency is targetable
if (caps->set_split_freq && (caps->targetable_vfo & RIG_TARGETABLE_FREQ))
{
HAMLIB_TRACE;
retcode = caps->set_split_freq(rig, vfo, tx_freq);
retcode = caps->set_split_freq(rig, tx_vfo, tx_freq);
ELAPSED2;
if (retcode == RIG_OK)
{
rig_set_cache_freq(rig, tx_vfo, tx_freq);
}
RETURNFUNC2(retcode);
}
vfo = vfo_fixup(rig, vfo, rig->state.cache.split);
/* Assisted mode */
curr_vfo = rig->state.current_vfo;
if (caps->set_freq)
// Alternatively, use set_freq if frequency is targetable
if (caps->set_freq && (caps->targetable_vfo & RIG_TARGETABLE_FREQ))
{
int retry = 3;
@ -4368,7 +4360,10 @@ int HAMLIB_API rig_set_split_freq(RIG *rig, vfo_t vfo, freq_t tx_freq)
HAMLIB_TRACE;
retcode = rig_set_freq(rig, tx_vfo, tx_freq);
if (retcode != RIG_OK) { RETURNFUNC(retcode); }
if (retcode != RIG_OK)
{
RETURNFUNC(retcode);
}
#if 0 // this verification seems to be causing bad behavior on some rigs
retcode = rig_get_freq(rig, tx_vfo, &tfreq);
@ -4382,6 +4377,10 @@ int HAMLIB_API rig_set_split_freq(RIG *rig, vfo_t vfo, freq_t tx_freq)
RETURNFUNC2(retcode);
}
// Assisted mode: Swap VFOs and try either set_split_freq or set_freq
curr_vfo = rs->current_vfo;
vfo = vfo_fixup(rig, vfo, rs->cache.split);
if (caps->set_vfo)
{
HAMLIB_TRACE;
@ -4412,19 +4411,22 @@ int HAMLIB_API rig_set_split_freq(RIG *rig, vfo_t vfo, freq_t tx_freq)
{
HAMLIB_TRACE;
retcode = caps->set_split_freq(rig, vfo, tx_freq);
//rig_get_freq(rig, vfo, &tfreq);
}
else
{
HAMLIB_TRACE;
retcode = rig_set_freq(rig, RIG_VFO_CURR, tx_freq);
//rig_get_freq(rig, vfo, &tfreq);
}
tfreq = tx_freq;
}
while (tfreq != tx_freq && retry-- > 0 && retcode == RIG_OK);
if (retcode == RIG_OK)
{
rig_set_cache_freq(rig, tx_vfo, tx_freq);
}
/* try and revert even if we had an error above */
if (caps->set_vfo)
{
@ -4469,6 +4471,7 @@ int HAMLIB_API rig_set_split_freq(RIG *rig, vfo_t vfo, freq_t tx_freq)
int HAMLIB_API rig_get_split_freq(RIG *rig, vfo_t vfo, freq_t *tx_freq)
{
const struct rig_caps *caps;
const struct rig_state *rs;
int retcode = -RIG_EPROTO, rc2;
vfo_t tx_vfo;
@ -4487,42 +4490,48 @@ int HAMLIB_API rig_get_split_freq(RIG *rig, vfo_t vfo, freq_t *tx_freq)
RETURNFUNC(-RIG_EINVAL);
}
vfo = vfo_fixup(rig, vfo, rig->state.cache.split);
caps = rig->caps;
rs = &rig->state;
if (caps->get_split_freq
&& (vfo == RIG_VFO_CURR
|| vfo == RIG_VFO_TX
|| vfo == rig->state.current_vfo))
// Always use the previously selected TX VFO for split. The targeted VFO will have no effect.
tx_vfo = rs->tx_vfo;
if (rs->cache.split == RIG_SPLIT_OFF || tx_vfo == RIG_VFO_NONE || tx_vfo == RIG_VFO_CURR)
{
// Split frequency not available if split is off
*tx_freq = 0;
ELAPSED2;
RETURNFUNC(RIG_OK);
}
// Use get_split_freq directly if implemented and frequency is targetable
if (caps->get_split_freq && (caps->targetable_vfo & RIG_TARGETABLE_FREQ))
{
HAMLIB_TRACE;
retcode = caps->get_split_freq(rig, vfo, tx_freq);
retcode = caps->get_split_freq(rig, tx_vfo, tx_freq);
ELAPSED2;
if (retcode == RIG_OK)
{
rig_set_cache_freq(rig, tx_vfo, *tx_freq);
}
RETURNFUNC(retcode);
}
/* Assisted mode */
//save_vfo = rig->state.current_vfo;
/* Use previously setup TxVFO */
if (vfo == RIG_VFO_CURR || vfo == RIG_VFO_TX)
{
tx_vfo = rig->state.tx_vfo;
}
else
{
tx_vfo = vfo;
}
// Alternatively, use get_freq if frequency is targetable
if (caps->get_freq && (caps->targetable_vfo & RIG_TARGETABLE_FREQ))
{
HAMLIB_TRACE;
retcode = caps->get_freq(rig, tx_vfo, tx_freq);
ELAPSED2;
if (retcode == RIG_OK)
{
rig_set_cache_freq(rig, tx_vfo, *tx_freq);
}
RETURNFUNC(retcode);
}
// Assisted mode: Swap VFOs and try either get_split_freq or get_freq
vfo = vfo_fixup(rig, vfo, rs->cache.split);
if (caps->set_vfo)
{
@ -4566,6 +4575,11 @@ int HAMLIB_API rig_get_split_freq(RIG *rig, vfo_t vfo, freq_t *tx_freq)
tx_freq) : -RIG_ENIMPL;
}
if (retcode == RIG_OK)
{
rig_set_cache_freq(rig, tx_vfo, *tx_freq);
}
/* try and revert even if we had an error above */
if (caps->set_vfo)
{
@ -4630,6 +4644,7 @@ int HAMLIB_API rig_set_split_mode(RIG *rig,
pbwidth_t tx_width)
{
const struct rig_caps *caps;
const struct rig_state *rs;
int retcode, rc2;
vfo_t curr_vfo, tx_vfo, rx_vfo;
@ -4642,10 +4657,30 @@ int HAMLIB_API rig_set_split_mode(RIG *rig,
ELAPSED1;
ENTERFUNC;
caps = rig->caps;
rs = &rig->state;
// Always use the previously selected TX VFO for split. The targeted VFO will have no effect.
tx_vfo = rs->tx_vfo;
if (rs->cache.split == RIG_SPLIT_OFF || tx_vfo == RIG_VFO_NONE || tx_vfo == RIG_VFO_CURR)
{
// Turn split on if not enabled already
retcode = rig_set_split_vfo(rig, rs->current_vfo, RIG_SPLIT_ON, vfo_fixup(rig, RIG_VFO_OTHER, RIG_SPLIT_OFF));
if (retcode != RIG_OK)
{
rig_debug(RIG_DEBUG_ERR, "%s: error turning split on: result=%d\n", __func__, retcode);
ELAPSED2;
RETURNFUNC(retcode);
}
}
// TX VFO may change after enabling split
tx_vfo = rs->tx_vfo;
// we check both VFOs are in the same tx mode -- then we can ignore
// this could be make more intelligent but this should cover all cases where we can skip this
if (tx_mode == rig->state.cache.modeMainA
&& tx_mode == rig->state.cache.modeMainB)
if (tx_mode == rs->cache.modeMainA && tx_mode == rs->cache.modeMainB)
{
rig_debug(RIG_DEBUG_TRACE, "%s: mode already %s so no change required\n",
__func__, rig_strrmode(tx_mode));
@ -4655,57 +4690,47 @@ int HAMLIB_API rig_set_split_mode(RIG *rig,
else
{
rig_debug(RIG_DEBUG_TRACE, "%s: vfo=%s mode %s is different from A=%s and B=%s\n",
__func__, rig_strvfo(vfo), rig_strrmode(tx_mode), rig_strrmode(rig->state.cache.modeMainA),
rig_strrmode(rig->state.cache.modeMainB));
__func__, rig_strvfo(vfo), rig_strrmode(tx_mode), rig_strrmode(rs->cache.modeMainA),
rig_strrmode(rs->cache.modeMainB));
}
// do not mess with mode while PTT is on
if (rig->state.cache.ptt)
if (rs->cache.ptt)
{
rig_debug(RIG_DEBUG_VERBOSE, "%s PTT on so set_split_mode ignored\n", __func__);
ELAPSED2;
RETURNFUNC(RIG_OK);
}
caps = rig->caps;
if (caps->set_split_mode
&& (vfo == RIG_VFO_CURR
|| vfo == RIG_VFO_TX
|| vfo == rig->state.current_vfo
|| rig->caps->rig_model == RIG_MODEL_NETRIGCTL))
// Use set_split_mode directly if implemented and mode is targetable
if (caps->set_split_mode)
{
HAMLIB_TRACE;
retcode = caps->set_split_mode(rig, vfo, tx_mode, tx_width);
retcode = caps->set_split_mode(rig, tx_vfo, tx_mode, tx_width);
ELAPSED2;
if (retcode == RIG_OK)
{
rig_set_cache_mode(rig, tx_vfo, tx_mode, tx_width);
}
RETURNFUNC(retcode);
}
/* Assisted mode */
curr_vfo = rig->state.current_vfo;
/* Use previously setup TxVFO */
if (vfo == RIG_VFO_CURR || vfo == RIG_VFO_TX
|| rig->state.tx_vfo != RIG_VFO_NONE)
{
HAMLIB_TRACE;
tx_vfo = rig->state.tx_vfo;
}
else
{
HAMLIB_TRACE;
tx_vfo = vfo;
}
rig_debug(RIG_DEBUG_VERBOSE, "%s: curr_vfo=%s, tx_vfo=%s\n", __func__,
rig_strvfo(curr_vfo), rig_strvfo(tx_vfo));
// Alternatively, use set_mode if mode is targetable
if (caps->set_mode && ((caps->targetable_vfo & RIG_TARGETABLE_MODE)
|| (rig->caps->rig_model == RIG_MODEL_NETRIGCTL)))
{
HAMLIB_TRACE;
retcode = caps->set_mode(rig, tx_vfo, tx_mode, tx_width);
ELAPSED2;
if (retcode == RIG_OK)
{
rig_set_cache_mode(rig, tx_vfo, tx_mode, tx_width);
}
RETURNFUNC(retcode);
}
@ -4725,7 +4750,7 @@ int HAMLIB_API rig_set_split_mode(RIG *rig,
// we will reuse cached mode instead of trying to set mode again
if ((tx_vfo & (RIG_VFO_A | RIG_VFO_MAIN | RIG_VFO_MAIN_A | RIG_VFO_SUB_A))
&& (tx_mode == rig->state.cache.modeMainA))
&& (tx_mode == rs->cache.modeMainA))
{
rig_debug(RIG_DEBUG_VERBOSE, "%s(%d): VFOA mode=%s already set...ignoring\n",
__func__, __LINE__, rig_strrmode(tx_mode));
@ -4733,7 +4758,7 @@ int HAMLIB_API rig_set_split_mode(RIG *rig,
RETURNFUNC(RIG_OK);
}
else if ((tx_vfo & (RIG_VFO_B | RIG_VFO_SUB | RIG_VFO_MAIN_B | RIG_VFO_SUB_B))
&& (tx_mode == rig->state.cache.modeMainB))
&& (tx_mode == rs->cache.modeMainB))
{
rig_debug(RIG_DEBUG_VERBOSE, "%s(%d): VFOB mode=%s already set...ignoring\n",
__func__, __LINE__, rig_strrmode(tx_mode));
@ -4751,11 +4776,16 @@ int HAMLIB_API rig_set_split_mode(RIG *rig,
if (caps->rig_model == RIG_MODEL_NETRIGCTL)
{
// special handling for netrigctl to avoid set_vfo
retcode = caps->set_split_mode(rig, vfo, tx_mode, tx_width);
retcode = caps->set_split_mode(rig, tx_vfo, tx_mode, tx_width);
ELAPSED2;
if (retcode == RIG_OK)
{
rig_set_cache_mode(rig, tx_vfo, tx_mode, tx_width);
}
RETURNFUNC(retcode);
}
// Assisted mode: Turn split off, swap VFOs and try either set_split_mode or set_mode
rig_set_split_vfo(rig, rx_vfo, RIG_SPLIT_OFF, rx_vfo);
if (caps->set_vfo)
@ -4794,6 +4824,11 @@ int HAMLIB_API rig_set_split_mode(RIG *rig,
tx_width) : -RIG_ENIMPL;
}
if (retcode == RIG_OK)
{
rig_set_cache_mode(rig, tx_vfo, tx_mode, tx_width);
}
/* try and revert even if we had an error above */
if (caps->set_vfo)
{
@ -4824,7 +4859,6 @@ int HAMLIB_API rig_set_split_mode(RIG *rig,
}
#endif
ELAPSED2;
RETURNFUNC(retcode);
}
@ -4853,6 +4887,7 @@ int HAMLIB_API rig_get_split_mode(RIG *rig, vfo_t vfo, rmode_t *tx_mode,
pbwidth_t *tx_width)
{
const struct rig_caps *caps;
const struct rig_state *rs;
int retcode, rc2;
vfo_t curr_vfo, tx_vfo;
@ -4872,39 +4907,48 @@ int HAMLIB_API rig_get_split_mode(RIG *rig, vfo_t vfo, rmode_t *tx_mode,
}
caps = rig->caps;
rs = &rig->state;
if (caps->get_split_mode
&& (vfo == RIG_VFO_CURR
|| vfo == RIG_VFO_TX
|| vfo == rig->state.current_vfo))
// Always use the previously selected TX VFO for split. The targeted VFO will have no effect.
tx_vfo = rs->tx_vfo;
if (rs->cache.split == RIG_SPLIT_OFF || tx_vfo == RIG_VFO_NONE || tx_vfo == RIG_VFO_CURR)
{
// Split mode and filter width are not available if split is off
*tx_mode = RIG_MODE_NONE;
*tx_width = 0;
ELAPSED2;
RETURNFUNC(RIG_OK);
}
// Use get_split_mode directly if implemented and mode is targetable
if (caps->get_split_mode && (caps->targetable_vfo & RIG_TARGETABLE_MODE))
{
HAMLIB_TRACE;
retcode = caps->get_split_mode(rig, vfo, tx_mode, tx_width);
retcode = caps->get_split_mode(rig, tx_vfo, tx_mode, tx_width);
ELAPSED2;
if (retcode == RIG_OK)
{
rig_set_cache_mode(rig, tx_vfo, *tx_mode, *tx_width);
}
RETURNFUNC(retcode);
}
/* Assisted mode */
curr_vfo = rig->state.current_vfo;
/* Use previously setup TxVFO */
if (vfo == RIG_VFO_CURR || vfo == RIG_VFO_TX)
{
tx_vfo = rig->state.tx_vfo;
}
else
{
tx_vfo = vfo;
}
// Alternatively, use get_mode if mode is targetable
if (caps->get_mode && (caps->targetable_vfo & RIG_TARGETABLE_MODE))
{
HAMLIB_TRACE;
retcode = caps->get_mode(rig, tx_vfo, tx_mode, tx_width);
ELAPSED2;
if (retcode == RIG_OK)
{
rig_set_cache_mode(rig, tx_vfo, *tx_mode, *tx_width);
}
RETURNFUNC(retcode);
}
// Assisted mode: Swap VFOs and try either get_split_mode or get_mode
curr_vfo = rs->current_vfo;
if (caps->set_vfo)
{
@ -4940,6 +4984,11 @@ int HAMLIB_API rig_get_split_mode(RIG *rig, vfo_t vfo, rmode_t *tx_mode,
tx_width) : -RIG_ENIMPL;
}
if (retcode == RIG_OK)
{
rig_set_cache_mode(rig, tx_vfo, *tx_mode, *tx_width);
}
/* try and revert even if we had an error above */
if (caps->set_vfo)
{
@ -4998,6 +5047,8 @@ int HAMLIB_API rig_set_split_freq_mode(RIG *rig,
pbwidth_t tx_width)
{
const struct rig_caps *caps;
const struct rig_state *rs;
vfo_t tx_vfo;
int retcode;
if (CHECK_RIG_ARG(rig))
@ -5010,20 +5061,26 @@ int HAMLIB_API rig_set_split_freq_mode(RIG *rig,
ENTERFUNC;
caps = rig->caps;
rs = &rig->state;
// if split is off we'll turn it on
if (rig->state.cache.split == 0)
// Always use the previously selected TX VFO for split. The targeted VFO will have no effect.
tx_vfo = rs->tx_vfo;
if (rs->cache.split == RIG_SPLIT_OFF || tx_vfo == RIG_VFO_NONE || tx_vfo == RIG_VFO_CURR)
{
if (rig->state.current_vfo & (RIG_VFO_A | RIG_VFO_MAIN))
// Turn split on if not enabled already
retcode = rig_set_split_vfo(rig, rs->current_vfo, RIG_SPLIT_ON, vfo_fixup(rig, RIG_VFO_OTHER, RIG_SPLIT_OFF));
if (retcode != RIG_OK)
{
rig_set_split_vfo(rig, RIG_VFO_A, 1, RIG_VFO_B);
}
else
{
rig_set_split_vfo(rig, RIG_VFO_B, 1, RIG_VFO_A);
rig_debug(RIG_DEBUG_ERR, "%s: error turning split on: result=%d\n", __func__, retcode);
ELAPSED2;
RETURNFUNC(retcode);
}
}
// TX VFO may change after enabling split
tx_vfo = rs->tx_vfo;
vfo = vfo_fixup(rig, RIG_VFO_TX, rig->state.cache.split); // get the TX VFO
rig_debug(RIG_DEBUG_VERBOSE,
"%s: vfo=%s, tx_freq=%.0f, tx_mode=%s, tx_width=%d\n", __func__,
@ -5038,13 +5095,13 @@ int HAMLIB_API rig_set_split_freq_mode(RIG *rig,
#endif
HAMLIB_TRACE;
retcode = caps->set_split_freq_mode(rig, vfo, tx_freq, tx_mode, tx_width);
retcode = caps->set_split_freq_mode(rig, tx_vfo, tx_freq, tx_mode, tx_width);
#if 0 // this verification seems to be causing bad behavior on some rigs
// we query freq after set to ensure it really gets done
do
{
retcode = caps->set_split_freq_mode(rig, vfo, tx_freq, tx_mode, tx_width);
retcode = caps->set_split_freq_mode(rig, tx_vfo, tx_freq, tx_mode, tx_width);
retcode2 = rig_get_split_freq(rig, vfo, &tfreq);
if (tfreq != tx_freq)
@ -5066,6 +5123,11 @@ int HAMLIB_API rig_set_split_freq_mode(RIG *rig,
#endif
ELAPSED2;
if (retcode == RIG_OK)
{
rig_set_cache_freq(rig, tx_vfo, tx_freq);
rig_set_cache_mode(rig, tx_vfo, tx_mode, tx_width);
}
RETURNFUNC(retcode);
}
else
@ -5119,6 +5181,8 @@ int HAMLIB_API rig_get_split_freq_mode(RIG *rig,
pbwidth_t *tx_width)
{
const struct rig_caps *caps;
const struct rig_state *rs;
vfo_t tx_vfo;
int retcode;
if (CHECK_RIG_ARG(rig))
@ -5137,11 +5201,30 @@ int HAMLIB_API rig_get_split_freq_mode(RIG *rig,
}
caps = rig->caps;
rs = &rig->state;
// Always use the previously selected TX VFO for split. The targeted VFO will have no effect.
tx_vfo = rs->tx_vfo;
if (rs->cache.split == RIG_SPLIT_OFF || tx_vfo == RIG_VFO_NONE || tx_vfo == RIG_VFO_CURR)
{
// Split frequency, mode and filter width are not available if split is off
*tx_freq = 0;
*tx_mode = RIG_MODE_NONE;
*tx_width = 0;
ELAPSED2;
RETURNFUNC(RIG_OK);
}
if (caps->get_split_freq_mode)
{
retcode = caps->get_split_freq_mode(rig, vfo, tx_freq, tx_mode, tx_width);
retcode = caps->get_split_freq_mode(rig, tx_vfo, tx_freq, tx_mode, tx_width);
ELAPSED2;
if (retcode == RIG_OK)
{
rig_set_cache_freq(rig, tx_vfo, *tx_freq);
rig_set_cache_mode(rig, tx_vfo, *tx_mode, *tx_width);
}
RETURNFUNC(retcode);
}
@ -5181,6 +5264,7 @@ int HAMLIB_API rig_set_split_vfo(RIG *rig,
{
const struct rig_caps *caps;
int retcode;
struct rig_state *rs;
vfo_t curr_vfo;
if (CHECK_RIG_ARG(rig))
@ -5196,6 +5280,7 @@ int HAMLIB_API rig_set_split_vfo(RIG *rig,
rig_strvfo(rx_vfo), split, rig_strvfo(tx_vfo), rig->state.cache.split);
caps = rig->caps;
rs = &rig->state;
if (caps->set_split_vfo == NULL)
{
@ -5203,7 +5288,7 @@ int HAMLIB_API rig_set_split_vfo(RIG *rig,
RETURNFUNC(-RIG_ENAVAIL);
}
if (rig->state.cache.ptt)
if (rs->cache.ptt)
{
rig_debug(RIG_DEBUG_WARN, "%s: cannot execute when PTT is on\n", __func__);
ELAPSED2;
@ -5211,7 +5296,7 @@ int HAMLIB_API rig_set_split_vfo(RIG *rig,
}
// We fix up vfos for non-satmode rigs only
if (rig->caps->has_get_func & RIG_FUNC_SATMODE)
if (caps->has_get_func & RIG_FUNC_SATMODE)
{
rig_debug(RIG_DEBUG_TRACE, "%s: satmode rig...not fixing up vfos rx=%s tx=%s\n",
__func__, rig_strvfo(rx_vfo), rig_strvfo(tx_vfo));
@ -5220,21 +5305,25 @@ int HAMLIB_API rig_set_split_vfo(RIG *rig,
{
switch (tx_vfo)
{
case RIG_VFO_MAIN: rx_vfo = split == 1 ? RIG_VFO_SUB : RIG_VFO_MAIN; break;
case RIG_VFO_MAIN:
rx_vfo = split != RIG_SPLIT_OFF ? RIG_VFO_SUB : RIG_VFO_MAIN;
break;
case RIG_VFO_A: rx_vfo = split == 1 ? RIG_VFO_B : RIG_VFO_A; break;
case RIG_VFO_A:
rx_vfo = split != RIG_SPLIT_OFF ? RIG_VFO_B : RIG_VFO_A;
break;
case RIG_VFO_SUB: rx_vfo = split == 1 ? RIG_VFO_MAIN : RIG_VFO_SUB; break;
case RIG_VFO_SUB:
rx_vfo = split != RIG_SPLIT_OFF ? RIG_VFO_MAIN : RIG_VFO_SUB;
break;
case RIG_VFO_B: rx_vfo = split == 1 ? RIG_VFO_A : RIG_VFO_B; break;
case RIG_VFO_B:
rx_vfo = split != RIG_SPLIT_OFF ? RIG_VFO_A : RIG_VFO_B;
break;
}
//rig->state.cache.split = split; // this gets set later
//rig->state.cache.split_vfo = tx_vfo;
rx_vfo = vfo_fixup(rig, rx_vfo, split);
tx_vfo = vfo_fixup(rig, tx_vfo, split);
rig->state.rx_vfo = rx_vfo;
rig->state.tx_vfo = tx_vfo;
rig_debug(RIG_DEBUG_VERBOSE, "%s: final rxvfo=%s, txvfo=%s, split=%d\n",
__func__,
rig_strvfo(rx_vfo), rig_strvfo(tx_vfo), split);
@ -5244,14 +5333,14 @@ int HAMLIB_API rig_set_split_vfo(RIG *rig,
HAMLIB_TRACE;
if ((!(caps->targetable_vfo & RIG_TARGETABLE_FREQ))
&& (!(rig->caps->rig_model == RIG_MODEL_NETRIGCTL)))
&& (!(caps->rig_model == RIG_MODEL_NETRIGCTL)))
rig_set_vfo(rig, rx_vfo);
if (rx_vfo == RIG_VFO_CURR
|| rx_vfo == rig->state.current_vfo)
// Check if RX VFO is the currently active VFO and we don't need to change the VFO
if (rx_vfo == RIG_VFO_CURR || rx_vfo == rs->current_vfo)
{
// for non-targetable VFOs we will not set split again
if (rig->state.cache.split == split && rig->state.cache.split_vfo == tx_vfo)
if (rs->cache.split == split && rs->cache.split_vfo == tx_vfo)
{
rig_debug(RIG_DEBUG_VERBOSE, "%s(%d): split already set...ignoring\n", __func__,
__LINE__);
@ -5263,23 +5352,27 @@ int HAMLIB_API rig_set_split_vfo(RIG *rig,
if (retcode == RIG_OK)
{
rig->state.tx_vfo = tx_vfo;
// Only update cache on success
rs->rx_vfo = rx_vfo;
rs->tx_vfo = tx_vfo;
rs->cache.split = split;
rs->cache.split_vfo = tx_vfo;
}
rig->state.cache.split = split;
rig->state.cache.split_vfo = tx_vfo;
elapsed_ms(&rig->state.cache.time_split, HAMLIB_ELAPSED_SET);
elapsed_ms(&rs->cache.time_split, HAMLIB_ELAPSED_SET);
ELAPSED2;
RETURNFUNC(retcode);
}
// RX VFO change required
if (!caps->set_vfo)
{
ELAPSED2;
RETURNFUNC(-RIG_ENAVAIL);
}
curr_vfo = rig->state.current_vfo;
curr_vfo = rs->current_vfo;
HAMLIB_TRACE;
if (!(caps->targetable_vfo & RIG_TARGETABLE_FREQ))
@ -5296,7 +5389,7 @@ int HAMLIB_API rig_set_split_vfo(RIG *rig,
HAMLIB_TRACE;
retcode = caps->set_split_vfo(rig, rx_vfo, split, tx_vfo);
/* try and revert even if we had an error above */
/* try and revert VFO change even if we had an error above */
if (!(caps->targetable_vfo & RIG_TARGETABLE_FREQ))
{
int rc2 = caps->set_vfo(rig, curr_vfo);
@ -5310,12 +5403,14 @@ int HAMLIB_API rig_set_split_vfo(RIG *rig,
if (retcode == RIG_OK)
{
rig->state.tx_vfo = tx_vfo;
// Only update cache on success
rs->rx_vfo = rx_vfo;
rs->tx_vfo = tx_vfo;
rs->cache.split = split;
rs->cache.split_vfo = tx_vfo;
}
rig->state.cache.split = split;
rig->state.cache.split_vfo = tx_vfo;
elapsed_ms(&rig->state.cache.time_split, HAMLIB_ELAPSED_SET);
elapsed_ms(&rs->cache.time_split, HAMLIB_ELAPSED_SET);
ELAPSED2;
RETURNFUNC(retcode);
}
@ -5342,14 +5437,8 @@ int HAMLIB_API rig_get_split_vfo(RIG *rig,
vfo_t *tx_vfo)
{
const struct rig_caps *caps;
#if 0
int retcode, rc2;
#else
struct rig_state *rs;
int retcode;
#endif
#if 0
vfo_t curr_vfo;
#endif
int cache_ms;
if (CHECK_RIG_ARG(rig))
@ -5370,12 +5459,13 @@ int HAMLIB_API rig_get_split_vfo(RIG *rig,
}
caps = rig->caps;
rs = &rig->state;
if (caps->get_split_vfo == NULL)
{
// if we can't get the vfo we will return whatever we have cached
*split = rig->state.cache.split;
*tx_vfo = rig->state.cache.split_vfo;
*split = rs->cache.split;
*tx_vfo = rs->cache.split_vfo;
rig_debug(RIG_DEBUG_VERBOSE,
"%s: no get_split_vfo so returning split=%d, tx_vfo=%s\n", __func__, *split,
rig_strvfo(*tx_vfo));
@ -5386,10 +5476,10 @@ int HAMLIB_API rig_get_split_vfo(RIG *rig,
cache_ms = elapsed_ms(&rig->state.cache.time_split, HAMLIB_ELAPSED_GET);
rig_debug(RIG_DEBUG_TRACE, "%s: cache check age=%dms\n", __func__, cache_ms);
if (cache_ms < rig->state.cache.timeout_ms)
if (cache_ms < rs->cache.timeout_ms)
{
*split = rig->state.cache.split;
*tx_vfo = rig->state.cache.split_vfo;
*split = rs->cache.split;
*tx_vfo = rs->cache.split_vfo;
rig_debug(RIG_DEBUG_TRACE, "%s: cache hit age=%dms, split=%d, tx_vfo=%s\n",
__func__, cache_ms, *split, rig_strvfo(*tx_vfo));
ELAPSED2;
@ -5400,66 +5490,17 @@ int HAMLIB_API rig_get_split_vfo(RIG *rig,
rig_debug(RIG_DEBUG_TRACE, "%s: cache miss age=%dms\n", __func__, cache_ms);
}
/* overridden by backend at will */
*tx_vfo = rig->state.tx_vfo;
if ((vfo == RIG_VFO_CURR) || (vfo == rig->state.current_vfo))
{
HAMLIB_TRACE;
//retcode = RIG_OK;
//if (rig->caps->rig_model != RIG_MODEL_NETRIGCTL)
{
// rigctld doesn't like nested calls
retcode = caps->get_split_vfo(rig, vfo, split, tx_vfo);
rig->state.cache.split = *split;
rig->state.cache.split_vfo = *tx_vfo;
elapsed_ms(&rig->state.cache.time_split, HAMLIB_ELAPSED_SET);
rig_debug(RIG_DEBUG_TRACE, "%s: cache.split=%d\n", __func__,
rig->state.cache.split);
}
ELAPSED2;
RETURNFUNC(retcode);
}
if (!caps->set_vfo)
{
ELAPSED2;
RETURNFUNC(-RIG_ENAVAIL);
}
#if 0 // why were we doing this? Shouldn't need to set_vfo to figure out tx_vfo
curr_vfo = rig->state.current_vfo;
retcode = caps->set_vfo(rig, vfo);
if (retcode != RIG_OK)
{
ELAPSED2;
RETURNFUNC(retcode);
}
#endif
HAMLIB_TRACE;
retcode = caps->get_split_vfo(rig, vfo, split, tx_vfo);
#if 0 // see above
/* try and revert even if we had an error above */
rc2 = caps->set_vfo(rig, curr_vfo);
if (RIG_OK == retcode)
if (retcode == RIG_OK)
{
/* return the first error code */
retcode = rc2;
}
#endif
if (retcode == RIG_OK) // only update cache on success
{
rig->state.cache.split = *split;
rig->state.cache.split_vfo = *tx_vfo;
elapsed_ms(&rig->state.cache.time_split, HAMLIB_ELAPSED_SET);
// Only update cache on success
rs->cache.split = *split;
rs->cache.split_vfo = *tx_vfo;
elapsed_ms(&rs->cache.time_split, HAMLIB_ELAPSED_SET);
rig_debug(RIG_DEBUG_TRACE, "%s(%d): cache.split=%d\n", __func__, __LINE__,
rig->state.cache.split);
rs->cache.split);
}
ELAPSED2;

Wyświetl plik

@ -576,11 +576,10 @@ int rig_sprintf_parm_gran(char *str, int nlen, setting_t parm,
{
if (gran[i].step.s)
{
rig_debug(RIG_DEBUG_ERR, "%s: BAND_SELECT?\n", __func__);
len += sprintf(str + len,
"%s(%s) ",
ms,
gran[i].step.s);
len += sprintf(str + len,
"%s(%s) ",
ms,
gran[i].step.s);
}
}
else

Wyświetl plik

@ -247,6 +247,23 @@ int dumpcaps(RIG *rig, FILE *fout)
"Has targetable VFO: %s\n",
caps->targetable_vfo ? "Y" : "N");
fprintf(fout, "Targetable features:");
if (caps->targetable_vfo & RIG_TARGETABLE_FREQ) { fprintf(fout, " FREQ"); }
if (caps->targetable_vfo & RIG_TARGETABLE_MODE) { fprintf(fout, " MODE"); }
if (caps->targetable_vfo & RIG_TARGETABLE_TONE) { fprintf(fout, " TONE"); }
if (caps->targetable_vfo & RIG_TARGETABLE_FUNC) { fprintf(fout, " FUNC"); }
if (caps->targetable_vfo & RIG_TARGETABLE_LEVEL) { fprintf(fout, " LEVEL"); }
if (caps->targetable_vfo & RIG_TARGETABLE_RITXIT) { fprintf(fout, " RITXIT"); }
if (caps->targetable_vfo & RIG_TARGETABLE_PTT) { fprintf(fout, " PTT"); }
if (caps->targetable_vfo & RIG_TARGETABLE_MEM) { fprintf(fout, " MEM"); }
if (caps->targetable_vfo & RIG_TARGETABLE_BANK) { fprintf(fout, " BANK"); }
if (caps->targetable_vfo & RIG_TARGETABLE_ANT) { fprintf(fout, " ANT"); }
if (caps->targetable_vfo & RIG_TARGETABLE_ROOFING) { fprintf(fout, " ROOFING"); }
if (caps->targetable_vfo & RIG_TARGETABLE_SPECTRUM) { fprintf(fout, " SPECTRUM"); }
if (caps->targetable_vfo & RIG_TARGETABLE_BAND) { fprintf(fout, " BAND"); }
if (caps->targetable_vfo == 0) { fprintf(fout, " None"); }
fprintf(fout, "\n");
fprintf(fout,
"Has async data support: %s\n",
caps->async_data_supported ? "Y" : "N");