Implement rig_{set,get}_split_freq_mode() for IC-756 series.

This implementation reduces  the number of VFO excahnges or  sets to a
minimum when setting the TX VFO frequency and mode together.

This also  includes a  much smarter implementation  of the  logic used
when the  new config option 'no_xchg'  is enabled.  Now it  is able to
accurately  determine  the  original   VFO  selected  and  leaves  the
sequences with the  same VFO selected.  There is one  corner case when
both VFOs are identical (frequency, mode and width) at the start where
it has  to take a  guess as to the  selected originally VFO  (Icom CAT
protocol has no  command to elicit this information). In  that case it
guesses as the last VFO  selected using Hamlib.  Applications can gain
absolute certainty  by setting the  VFO themselves prior to  using the
rig_{set,get}_{split,}_{freq,mode,freq_mode}() function  series.  This
now gives seamless  TX VFO configuration without  any relay clattering
or TX/RX audio glitches.
Hamlib-3.1
Bill Somerville 2014-04-28 23:05:59 +01:00 zatwierdzone przez Bill Somerville
rodzic e5aa3639ed
commit e593afef95
3 zmienionych plików z 328 dodań i 8 usunięć

Wyświetl plik

@ -241,6 +241,8 @@ const struct rig_caps ic756_caps = {
.get_split_freq = icom_get_split_freq,
.set_split_mode = icom_set_split_mode,
.get_split_mode = icom_get_split_mode,
.set_split_freq_mode = icom_set_split_freq_mode,
.get_split_freq_mode = icom_get_split_freq_mode,
.set_split_vfo = icom_set_split_vfo,
.get_split_vfo = icom_mem_get_split_vfo,
@ -390,6 +392,8 @@ const struct rig_caps ic756pro_caps = {
.get_split_freq = icom_get_split_freq,
.set_split_mode = icom_set_split_mode,
.get_split_mode = icom_get_split_mode,
.set_split_freq_mode = icom_set_split_freq_mode,
.get_split_freq_mode = icom_get_split_freq_mode,
.set_split_vfo = icom_set_split_vfo,
.get_split_vfo = icom_mem_get_split_vfo,
@ -596,6 +600,8 @@ const struct rig_caps ic756pro2_caps = {
.get_split_freq = icom_get_split_freq,
.set_split_mode = icom_set_split_mode,
.get_split_mode = icom_get_split_mode,
.set_split_freq_mode = icom_set_split_freq_mode,
.get_split_freq_mode = icom_get_split_freq_mode,
.set_split_vfo = icom_set_split_vfo,
.get_split_vfo = icom_mem_get_split_vfo,
@ -933,6 +939,8 @@ const struct rig_caps ic756pro3_caps = {
.get_split_freq = icom_get_split_freq,
.set_split_mode = icom_set_split_mode,
.get_split_mode = icom_get_split_mode,
.set_split_freq_mode = icom_set_split_freq_mode,
.get_split_freq_mode = icom_get_split_freq_mode,
.set_split_vfo = icom_set_split_vfo,
.get_split_vfo = icom_mem_get_split_vfo,

Wyświetl plik

@ -1700,6 +1700,26 @@ int icom_set_split_freq(RIG *rig, vfo_t vfo, freq_t tx_freq)
return 0;
}
/* strategy here is to attempt to leave the original VFO selected
even though Icom provides no way to tell what the current VFO is. So
we read current frequency and mode and compare with SUB/B, this
gives up a clue so long as both VFOs are not the same frequency and
mode (and we don't really care if they are, the price for not using
VFO_XCHG, which will glitch the RX and TX and, possibly clatter the
rig relays). */
freq_t orig_freq, second_freq;
rmode_t orig_mode, second_mode;
pbwidth_t orig_width, second_width;
status = icom_get_freq(rig, RIG_VFO_CURR, &orig_freq);
if (status != RIG_OK)
return status;
status = rig->caps->get_mode (rig, RIG_VFO_CURR, &orig_mode, &orig_width);
if (status != RIG_OK)
return status;
status = get_split_vfos(rig, &rx_vfo, &tx_vfo);
if (status != RIG_OK)
return status;
@ -1708,13 +1728,28 @@ int icom_set_split_freq(RIG *rig, vfo_t vfo, freq_t tx_freq)
if (status != RIG_OK)
return status;
status = icom_get_freq(rig, RIG_VFO_CURR, &second_freq);
if (status != RIG_OK)
return status;
status = rig->caps->get_mode (rig, RIG_VFO_CURR, &second_mode, &second_width);
if (status != RIG_OK)
return status;
status = icom_set_freq(rig, RIG_VFO_CURR, tx_freq);
if (status != RIG_OK)
return status;
status = icom_set_vfo(rig, rx_vfo);
if (status != RIG_OK)
return status;
if (second_freq != orig_freq || second_mode != orig_mode || second_width != orig_width) {
/* RX VFO must have been selected when we started so switch back
to it */
status = icom_set_vfo(rig, rx_vfo);
rig->state.current_vfo = rx_vfo;
} else {
/* here we don't know the original VFO so we use the last one set
by any other command */
status = icom_set_vfo (rig, rig->state.current_vfo);
}
return status;
}
@ -1752,6 +1787,26 @@ int icom_get_split_freq(RIG *rig, vfo_t vfo, freq_t *tx_freq)
return 0;
}
/* strategy here is to attempt to leave the original VFO selected
even though Icom provides no way to tell what the current VFO is. So
we read current frequency and mode and compare with SUB/B, this
gives up a clue so long as both VFOs are not the same frequency and
mode (and we don't really care if they are, the price for not using
VFO_XCHG, which will glitch the RX and TX and, possibly clatter the
rig relays). */
freq_t orig_freq;
rmode_t orig_mode, second_mode;
pbwidth_t orig_width, second_width;
status = icom_get_freq(rig, RIG_VFO_CURR, &orig_freq);
if (status != RIG_OK)
return status;
status = rig->caps->get_mode (rig, RIG_VFO_CURR, &orig_mode, &orig_width);
if (status != RIG_OK)
return status;
status = get_split_vfos(rig, &rx_vfo, &tx_vfo);
if (status != RIG_OK)
return status;
@ -1764,10 +1819,20 @@ int icom_get_split_freq(RIG *rig, vfo_t vfo, freq_t *tx_freq)
if (status != RIG_OK)
return status;
status = icom_set_vfo(rig, rx_vfo);
status = rig->caps->get_mode (rig, RIG_VFO_CURR, &second_mode, &second_width);
if (status != RIG_OK)
return status;
if (*tx_freq != orig_freq || second_mode != orig_mode || second_width != orig_width) {
/* RX VFO must have been selected when we started so switch back
to it */
status = icom_set_vfo(rig, rx_vfo);
} else {
/* here we don't know the original VFO so we use the last one set
by any other command */
status = icom_set_vfo (rig, rig->state.current_vfo);
}
return status;
}
@ -1804,6 +1869,26 @@ int icom_set_split_mode(RIG *rig, vfo_t vfo, rmode_t tx_mode, pbwidth_t tx_width
return 0;
}
/* strategy here is to attempt to leave the original VFO selected
even though Icom provides no way to tell what the current VFO is. So
we read current frequency and mode and compare with SUB/B, this
gives up a clue so long as both VFOs are not the same frequency and
mode (and we don't really care if they are, the price for not using
VFO_XCHG, which will glitch the RX and TX and, possibly clatter the
rig relays). */
freq_t orig_freq, second_freq;
rmode_t orig_mode, second_mode;
pbwidth_t orig_width, second_width;
status = icom_get_freq(rig, RIG_VFO_CURR, &orig_freq);
if (status != RIG_OK)
return status;
status = rig->caps->get_mode (rig, RIG_VFO_CURR, &orig_mode, &orig_width);
if (status != RIG_OK)
return status;
status = get_split_vfos(rig, &rx_vfo, &tx_vfo);
if (status != RIG_OK)
return status;
@ -1812,13 +1897,27 @@ int icom_set_split_mode(RIG *rig, vfo_t vfo, rmode_t tx_mode, pbwidth_t tx_width
if (status != RIG_OK)
return status;
status = icom_get_freq(rig, RIG_VFO_CURR, &second_freq);
if (status != RIG_OK)
return status;
status = rig->caps->get_mode (rig, RIG_VFO_CURR, &second_mode, &second_width);
if (status != RIG_OK)
return status;
status = rig->caps->set_mode(rig, RIG_VFO_CURR, tx_mode, tx_width);
if (status != RIG_OK)
return status;
status = icom_set_vfo(rig, rx_vfo);
if (status != RIG_OK)
return status;
if (second_freq != orig_freq || second_mode != orig_mode || second_width != orig_width) {
/* RX VFO must have been selected when we started so switch back
to it */
status = icom_set_vfo(rig, rx_vfo);
} else {
/* here we don't know the original VFO so we use the last one set
by any other command */
status = icom_set_vfo (rig, rig->state.current_vfo);
}
return status;
}
@ -1857,6 +1956,26 @@ int icom_get_split_mode(RIG *rig, vfo_t vfo, rmode_t *tx_mode, pbwidth_t *tx_wid
return 0;
}
/* strategy here is to attempt to leave the original VFO selected
even though Icom provides no way to tell what the current VFO is. So
we read current frequency and mode and compare with SUB/B, this
gives up a clue so long as both VFOs are not the same frequency and
mode (and we don't really care if they are, the price for not using
VFO_XCHG, which will glitch the RX and TX and, possibly clatter the
rig relays). */
freq_t orig_freq, second_freq;
rmode_t orig_mode;
pbwidth_t orig_width;
status = icom_get_freq(rig, RIG_VFO_CURR, &orig_freq);
if (status != RIG_OK)
return status;
status = rig->caps->get_mode (rig, RIG_VFO_CURR, &orig_mode, &orig_width);
if (status != RIG_OK)
return status;
status = get_split_vfos(rig, &rx_vfo, &tx_vfo);
if (status != RIG_OK)
return status;
@ -1865,14 +1984,205 @@ int icom_get_split_mode(RIG *rig, vfo_t vfo, rmode_t *tx_mode, pbwidth_t *tx_wid
if (status != RIG_OK)
return status;
status = icom_get_freq(rig, RIG_VFO_CURR, &second_freq);
if (status != RIG_OK)
return status;
status = rig->caps->get_mode(rig, RIG_VFO_CURR, tx_mode, tx_width);
if (status != RIG_OK)
return status;
status = icom_set_vfo(rig, rx_vfo);
if (second_freq != orig_freq || *tx_mode != orig_mode || *tx_width != orig_width) {
/* RX VFO must have been selected when we started so switch back
to it */
status = icom_set_vfo(rig, rx_vfo);
} else {
/* here we don't know the original VFO so we use the last one set
by any other command */
status = icom_set_vfo (rig, rig->state.current_vfo);
}
return status;
}
/*
* icom_set_split_freq_mode
* Assumes rig!=NULL, rig->state.priv!=NULL,
* icom_set_vfo,icom_set_mode works for this rig
* FIXME: status
*/
int icom_set_split_freq_mode(RIG *rig, vfo_t vfo, freq_t tx_freq, rmode_t tx_mode, pbwidth_t tx_width)
{
int status;
vfo_t rx_vfo, tx_vfo;
struct icom_priv_data *priv;
struct rig_state *rs;
rs = &rig->state;
priv = (struct icom_priv_data*)rs->priv;
/* This method works also in memory mode(RIG_VFO_MEM) */
if (!priv->no_xchg && rig_has_vfo_op(rig, RIG_OP_XCHG)) {
status = icom_vfo_op(rig, vfo, RIG_OP_XCHG);
if (status != RIG_OK)
return status;
status = rig_set_freq(rig, RIG_VFO_CURR, tx_freq);
if (status != RIG_OK)
return status;
status = rig->caps->set_mode(rig, RIG_VFO_CURR, tx_mode, tx_width);
if (status != RIG_OK)
return status;
status = icom_vfo_op(rig, vfo, RIG_OP_XCHG);
if (status != RIG_OK)
return status;
return 0;
}
/* strategy here is to attempt to leave the original VFO selected
even though Icom provides no way to tell what the current VFO is. So
we read current frequency and mode and compare with SUB/B, this
gives up a clue so long as both VFOs are not the same frequency and
mode (and we don't really care if they are, the price for not using
VFO_XCHG, which will glitch the RX and TX and, possibly clatter the
rig relays). */
freq_t orig_freq, second_freq;
rmode_t orig_mode, second_mode;
pbwidth_t orig_width, second_width;
status = icom_get_freq(rig, RIG_VFO_CURR, &orig_freq);
if (status != RIG_OK)
return status;
status = rig->caps->get_mode (rig, RIG_VFO_CURR, &orig_mode, &orig_width);
if (status != RIG_OK)
return status;
status = get_split_vfos(rig, &rx_vfo, &tx_vfo);
if (status != RIG_OK)
return status;
status = icom_set_vfo(rig, tx_vfo);
if (status != RIG_OK)
return status;
status = icom_get_freq(rig, RIG_VFO_CURR, &second_freq);
if (status != RIG_OK)
return status;
status = rig->caps->get_mode (rig, RIG_VFO_CURR, &second_mode, &second_width);
if (status != RIG_OK)
return status;
status = rig_set_freq(rig, RIG_VFO_CURR, tx_freq);
if (status != RIG_OK)
return status;
status = rig->caps->set_mode(rig, RIG_VFO_CURR, tx_mode, tx_width);
if (status != RIG_OK)
return status;
if (second_freq != orig_freq || second_mode != orig_mode || second_width != orig_width) {
/* RX VFO must have been selected when we started so switch back
to it */
status = icom_set_vfo(rig, rx_vfo);
} else {
/* here we don't know the original VFO so we use the last one set
by any other command */
status = icom_set_vfo (rig, rig->state.current_vfo);
}
return status;
}
/*
* icom_get_split_freq_mode
* Assumes rig!=NULL, rig->state.priv!=NULL,
* rx_mode!=NULL, rx_width!=NULL, tx_mode!=NULL, tx_width!=NULL
* icom_set_vfo,icom_get_mode works for this rig
* FIXME: status
*/
int icom_get_split_freq_mode(RIG *rig, vfo_t vfo, freq_t *tx_freq, rmode_t *tx_mode, pbwidth_t *tx_width)
{
int status;
vfo_t rx_vfo, tx_vfo;
struct icom_priv_data *priv;
struct rig_state *rs;
rs = &rig->state;
priv = (struct icom_priv_data*)rs->priv;
/* This method works also in memory mode(RIG_VFO_MEM) */
if (!priv->no_xchg && rig_has_vfo_op(rig, RIG_OP_XCHG)) {
status = icom_vfo_op(rig, vfo, RIG_OP_XCHG);
if (status != RIG_OK)
return status;
status = rig_get_freq(rig, RIG_VFO_CURR, tx_freq);
if (status != RIG_OK)
return status;
status = rig->caps->get_mode(rig, RIG_VFO_CURR, tx_mode, tx_width);
if (status != RIG_OK)
return status;
status = icom_vfo_op(rig, vfo, RIG_OP_XCHG);
if (status != RIG_OK)
return status;
return 0;
}
/* strategy here is to attempt to leave the original VFO selected
even though Icom provides no way to tell what the current VFO is. So
we read current frequency and mode and compare with SUB/B, this
gives up a clue so long as both VFOs are not the same frequency and
mode (and we don't really care if they are, the price for not using
VFO_XCHG, which will glitch the RX and TX and, possibly clatter the
rig relays). */
freq_t orig_freq;
rmode_t orig_mode;
pbwidth_t orig_width;
status = icom_get_freq(rig, RIG_VFO_CURR, &orig_freq);
if (status != RIG_OK)
return status;
status = rig->caps->get_mode (rig, RIG_VFO_CURR, &orig_mode, &orig_width);
if (status != RIG_OK)
return status;
status = get_split_vfos(rig, &rx_vfo, &tx_vfo);
if (status != RIG_OK)
return status;
status = icom_set_vfo(rig, tx_vfo);
if (status != RIG_OK)
return status;
status = icom_get_freq(rig, RIG_VFO_CURR, tx_freq);
if (status != RIG_OK)
return status;
status = rig->caps->get_mode(rig, RIG_VFO_CURR, tx_mode, tx_width);
if (status != RIG_OK)
return status;
if (*tx_freq != orig_freq || *tx_mode != orig_mode || *tx_width != orig_width) {
/* RX VFO must have been selected when we started so switch back
to it */
status = icom_set_vfo(rig, rx_vfo);
} else {
/* here we don't know the original VFO so we use the last one set
by any other command */
status = icom_set_vfo (rig, rig->state.current_vfo);
}
return status;
}

Wyświetl plik

@ -159,6 +159,8 @@ int icom_set_split_freq(RIG *rig, vfo_t vfo, freq_t tx_freq);
int icom_get_split_freq(RIG *rig, vfo_t vfo, freq_t *tx_freq);
int icom_set_split_mode(RIG *rig, vfo_t vfo, rmode_t tx_mode, pbwidth_t tx_width);
int icom_get_split_mode(RIG *rig, vfo_t vfo, rmode_t *tx_mode, pbwidth_t *tx_width);
int icom_set_split_freq_mode(RIG *rig, vfo_t vfo, freq_t tx_freq, rmode_t tx_mode, pbwidth_t tx_width);
int icom_get_split_freq_mode(RIG *rig, vfo_t vfo, freq_t *tx_freq, rmode_t *tx_mode, pbwidth_t *tx_width);
int icom_set_split_vfo(RIG *rig, vfo_t vfo, split_t split, vfo_t tx_vfo);
int icom_get_split_vfo(RIG *rig, vfo_t vfo, split_t *split, vfo_t *tx_vfo);
int icom_mem_get_split_vfo(RIG *rig, vfo_t vfo, split_t *split, vfo_t *tx_vfo);