From 3b2225e4891cf4420814b19c214b8c64e174539d Mon Sep 17 00:00:00 2001 From: Michael Black W9MDB Date: Mon, 11 May 2020 19:00:52 -0400 Subject: [PATCH] Fix IC-910 split mode operation with gpredict https://github.com/Hamlib/Hamlib/issues/237 --- rigs/icom/ic910.c | 16 +++++--- rigs/icom/icom.c | 93 +++++++++++++++++++++++++++++++++++++++++++---- rigs/icom/icom.h | 5 ++- src/rig.c | 12 +++--- 4 files changed, 108 insertions(+), 18 deletions(-) diff --git a/rigs/icom/ic910.c b/rigs/icom/ic910.c index 148ed6883..b5d91ab3b 100644 --- a/rigs/icom/ic910.c +++ b/rigs/icom/ic910.c @@ -266,21 +266,27 @@ static int ic910_get_freq(RIG *rig, vfo_t vfo, freq_t *freq) { int retval; freq_t origfreq; + vfo_t vfo_save; /* start off by reading the current VFO frequency */ if ((retval = icom_get_freq(rig, RIG_VFO_CURR, &origfreq)) != RIG_OK) { return retval; } + vfo_save = rig->state.current_vfo; + rig_debug(RIG_DEBUG_TRACE, "%s: vfo=%s\n", __func__, rig_strvfo(vfo)); if (RIG_VFO_A == vfo || RIG_VFO_B == vfo) { /* switch to desired VFO and read its frequency */ - if ((retval = icom_set_vfo(rig, vfo)) != RIG_OK) { return retval; } + if (vfo_save != vfo) + { + if ((retval = icom_set_vfo(rig, vfo)) != RIG_OK) { return retval; } + } if ((retval = icom_get_freq(rig, vfo, freq)) != RIG_OK) { return retval; } - if (*freq != origfreq) + if (vfo_save != vfo) { /* swap VFOs back as original was the other one */ - icom_set_vfo(rig, RIG_VFO_A == vfo ? RIG_VFO_B : RIG_VFO_A); + icom_set_vfo(rig, vfo_save); } } else if (RIG_VFO_MAIN == vfo || RIG_VFO_SUB == vfo) @@ -480,7 +486,7 @@ const struct rig_caps ic910_caps = .max_rit = Hz(0), /* SSB,CW: +-1.0kHz FM: +-5.0kHz */ .max_xit = Hz(0), .max_ifshift = Hz(0), /* 1.2kHz manual knob */ - .targetable_vfo = RIG_TARGETABLE_FREQ, +// .targetable_vfo = RIG_TARGETABLE_FREQ, .vfo_ops = IC910_VFO_OPS, .scan_ops = IC910_SCAN_OPS, .transceive = RIG_TRN_RIG, @@ -566,7 +572,7 @@ const struct rig_caps ic910_caps = .set_ptt = icom_set_ptt, .get_ptt = icom_get_ptt, - .set_vfo = icom_set_vfo, + .set_vfo = icom_set_vfo, .get_ts = icom_get_ts, .set_ts = icom_set_ts, .get_func = ic910_get_func, diff --git a/rigs/icom/icom.c b/rigs/icom/icom.c index e50747059..3f11f92f5 100644 --- a/rigs/icom/icom.c +++ b/rigs/icom/icom.c @@ -766,6 +766,7 @@ icom_rig_open(RIG *rig) } retval = rig_get_func(rig, RIG_VFO_CURR, RIG_FUNC_SATMODE, &satmode); + priv->satmode = satmode; rig_debug(RIG_DEBUG_VERBOSE, "%s: satmode=%d\n", __func__, satmode); // RIG_OK return means this rig has satmode capabiltiy and Main/Sub VFOs @@ -1004,6 +1005,17 @@ int icom_set_freq(RIG *rig, vfo_t vfo, freq_t freq) } priv->curr_freq = freq; + + switch(vfo) + { + case RIG_VFO_A: priv->vfoa_freq = freq;break; + case RIG_VFO_B: priv->vfob_freq = freq;break; + case RIG_VFO_MAIN: priv->sub_freq = freq;break; + case RIG_VFO_SUB: priv->main_freq = freq;break; + default: + rig_debug(RIG_DEBUG_ERR,"%s: unknown VFO? VFO=%s\n", __func__, rig_strvfo(vfo)); + } + return RIG_OK; } @@ -1028,6 +1040,20 @@ int icom_get_freq(RIG *rig, vfo_t vfo, freq_t *freq) rs = &rig->state; priv = (struct icom_priv_data *) rs->priv; + if (rig->caps->rig_model == RIG_MODEL_IC910) + { + ptt_t ptt; + retval = rig_get_ptt(rig,RIG_VFO_CURR,&ptt); + if (retval != RIG_OK) { + return retval; + } + if (ptt) { + rig_debug(RIG_DEBUG_TRACE, "%s: split is on so returning last known freq\n", __func__); + *freq = priv->vfoa_freq; + return RIG_OK; + } + } + #if 0 // disabled to test if IC9700 satmode/gpredict still works OK if (priv->curr_vfo == RIG_VFO_NONE) @@ -1080,6 +1106,13 @@ int icom_get_freq(RIG *rig, vfo_t vfo, freq_t *freq) } } + if (vfo == RIG_VFO_CURR) + { + vfo = priv->curr_vfo; + rig_debug(RIG_DEBUG_VERBOSE, "%s: CurrVFO changed to %s\n", __func__, rig_strvfo(vfo)); + } + + retval = set_vfo_curr(rig, vfo, priv->curr_vfo); if (retval != RIG_OK) @@ -1092,9 +1125,19 @@ int icom_get_freq(RIG *rig, vfo_t vfo, freq_t *freq) // Pick the appropriate VFO when VFO_RX is requested if (vfo == RIG_VFO_RX) { - rig_debug(RIG_DEBUG_TRACE, "%s: VFO_RX requested, vfo=%s\n", __func__, - rig_strvfo(vfo)); vfo = (rig->state.vfo_list & RIG_VFO_B) ? RIG_VFO_A : RIG_VFO_MAIN; + rig_debug(RIG_DEBUG_TRACE, "%s: VFO_RX requested, new vfo=%s\n", __func__, + rig_strvfo(vfo)); + } + else if (vfo == RIG_VFO_TX) { + if (rig->state.vfo_list == VFO_HAS_MAIN_SUB_A_B_ONLY) + { + vfo = RIG_VFO_A; + if (priv->split_on) vfo = RIG_VFO_B; + else if (priv->satmode) vfo = RIG_VFO_SUB; + } + rig_debug(RIG_DEBUG_TRACE, "%s: VFO_TX requested, new vfo=%s\n", __func__, + rig_strvfo(vfo)); } rig_debug(RIG_DEBUG_VERBOSE, "%s: using vfo=%s\n", __func__, @@ -1160,6 +1203,16 @@ int icom_get_freq(RIG *rig, vfo_t vfo, freq_t *freq) if (vfo == RIG_VFO_MEM && civ_731_mode) { priv->civ_731_mode = 1; } + switch(vfo) + { + case RIG_VFO_A: priv->vfoa_freq = *freq;break; + case RIG_VFO_B: priv->vfob_freq = *freq;break; + case RIG_VFO_MAIN: priv->sub_freq = *freq;break; + case RIG_VFO_SUB: priv->main_freq = *freq;break; + default: + rig_debug(RIG_DEBUG_ERR,"%s: unknown VFO? VFO=%s\n", __func__, rig_strvfo(vfo)); + } + return RIG_OK; } @@ -1927,6 +1980,8 @@ int icom_set_vfo(RIG *rig, vfo_t vfo) case RIG_VFO_TX: icvfo = priv->split_on ? S_VFOB : S_VFOA; + vfo = priv->split_on ? RIG_VFO_B : RIG_VFO_A; + rig_debug(RIG_DEBUG_TRACE,"%s: RIG_VFO_TX changing vfo to %s\n", __func__, rig_strvfo(vfo)); break; case RIG_VFO_VFO: @@ -2033,6 +2088,7 @@ int icom_set_vfo(RIG *rig, vfo_t vfo) } priv->curr_vfo = vfo; + rig->state.current_vfo = vfo; return RIG_OK; } @@ -3638,6 +3694,7 @@ int icom_get_split_vfos(const RIG *rig, vfo_t *rx_vfo, vfo_t *tx_vfo) // e.g. IC9700 split on Main/Sub does not work // only Main VFOA/B and SubRx/MainTx split works rig_get_func((RIG *)rig, RIG_VFO_CURR, RIG_FUNC_SATMODE, &satmode); + priv->satmode = satmode; // don't care about retval here...only care about satmode=1 if (satmode) @@ -3695,7 +3752,7 @@ int icom_set_split_freq(RIG *rig, vfo_t vfo, freq_t tx_freq) icom_set_default_vfo(rig); } - set_vfo_curr(rig, RIG_VFO_CURR, RIG_VFO_CURR); + set_vfo_curr(rig, RIG_VFO_TX, RIG_VFO_TX); // If the rigs supports the 0x25 command we'll use it // This eliminates VFO swapping and improves split operations @@ -3704,6 +3761,7 @@ int icom_set_split_freq(RIG *rig, vfo_t vfo, freq_t tx_freq) int satmode = 0; // retval not important here...only satmode=1 means anything rig_get_func(rig, RIG_VFO_CURR, RIG_FUNC_SATMODE, &satmode); + priv->satmode = satmode; rig_debug(RIG_DEBUG_VERBOSE, "%s: satmode=%d\n", __func__, satmode); if (satmode == 0) // only worth trying if not in satmode @@ -3791,7 +3849,7 @@ int icom_set_split_freq(RIG *rig, vfo_t vfo, freq_t tx_freq) return retval; } - if (RIG_OK != (retval = rig_set_freq(rig, RIG_VFO_CURR, tx_freq))) + if (RIG_OK != (retval = rig_set_freq(rig, tx_vfo, tx_freq))) { return retval; } @@ -3859,6 +3917,21 @@ int icom_get_split_freq(RIG *rig, vfo_t vfo, freq_t *tx_freq) rs = &rig->state; priv = (struct icom_priv_data *) rs->priv; + rig_debug(RIG_DEBUG_VERBOSE, "%s: ic910#1\n", __func__); + if (rig->caps->rig_model == RIG_MODEL_IC910) + { + ptt_t ptt; + rig_debug(RIG_DEBUG_VERBOSE, "%s: ic910#2\n", __func__); + retval = rig_get_ptt(rig,RIG_VFO_CURR,&ptt); + if (retval != RIG_OK) { + return retval; + } + if (ptt) { + rig_debug(RIG_DEBUG_TRACE, "%s: split is on so returning last known freq\n", __func__); + *tx_freq = priv->vfob_freq; + return RIG_OK; + } + } rig_debug(RIG_DEBUG_VERBOSE, "%s curr_vfo=%s\n", __func__, rig_strvfo(priv->curr_vfo)); @@ -3877,6 +3950,7 @@ int icom_get_split_freq(RIG *rig, vfo_t vfo, freq_t *tx_freq) int satmode = 0; // don't care about the retval here..only satmode=1 is important rig_get_func(rig, RIG_VFO_CURR, RIG_FUNC_SATMODE, &satmode); + priv->satmode = satmode; rig_debug(RIG_DEBUG_VERBOSE, "%s: satmode=%d\n", __func__, satmode); if (satmode == 0) // only worth trying if not in satmode @@ -3932,7 +4006,7 @@ int icom_get_split_freq(RIG *rig, vfo_t vfo, freq_t *tx_freq) { return retval; } - + priv->vfob_freq = *tx_freq; if (RIG_OK != (retval = icom_vfo_op(rig, vfo, RIG_OP_XCHG))) { return retval; @@ -4009,6 +4083,7 @@ int icom_get_split_freq(RIG *rig, vfo_t vfo, freq_t *tx_freq) } } + priv->vfob_freq = *tx_freq; return retval; } @@ -4533,12 +4608,12 @@ int icom_set_split_vfo(RIG *rig, vfo_t vfo, split_t split, vfo_t tx_vfo) if (VFO_HAS_A_B && (tx_vfo == RIG_VFO_A || tx_vfo == RIG_VFO_B)) { rig_debug(RIG_DEBUG_TRACE, "%s: vfo clause 2\n", __func__); - rig_debug(RIG_DEBUG_TRACE, "%s: set_vfo to VFO_A because tx_vfo=%s\n", __func__, + rig_debug(RIG_DEBUG_TRACE, "%s: rx_vfo to VFO_A, tx_vfo to VFO_B because tx_vfo=%s\n", __func__, rig_strvfo(tx_vfo)); priv->tx_vfo = RIG_VFO_B; priv->rx_vfo = RIG_VFO_A; - //vfo_final = RIG_VFO_A; + vfo_final = RIG_VFO_A; } else if (VFO_HAS_MAIN_SUB_A_B_ONLY && (tx_vfo == RIG_VFO_MAIN || tx_vfo == RIG_VFO_SUB)) @@ -4689,6 +4764,7 @@ int icom_get_split_vfo(RIG *rig, vfo_t vfo, split_t *split, vfo_t *tx_vfo) } rig_get_func(rig, RIG_VFO_CURR, RIG_FUNC_SATMODE, &satmode); + priv->satmode = satmode; priv->split_on = RIG_SPLIT_ON == *split; @@ -5039,6 +5115,7 @@ int icom_set_func(RIG *rig, vfo_t vfo, setting_t func, int status) priv->x25cmdfails = 0; // we reset this to try it again priv->x1cx03cmdfails = 0; // we reset this to try it again + priv->satmode = status; break; @@ -6931,6 +7008,8 @@ static int set_vfo_curr(RIG *rig, vfo_t vfo, vfo_t curr_vfo) rig_debug(RIG_DEBUG_TRACE, "%s: curr_vfo now=%s\n", __func__, rig_strvfo(priv->curr_vfo)); + rig->state.current_vfo = vfo; + return RIG_OK; } diff --git a/rigs/icom/icom.h b/rigs/icom/icom.h index 003c13a58..bf4e85543 100644 --- a/rigs/icom/icom.h +++ b/rigs/icom/icom.h @@ -31,7 +31,7 @@ #include #endif -#define BACKEND_VER "20200505" +#define BACKEND_VER "20200511" /* * defines used by comp_cal_str in rig.c @@ -187,8 +187,11 @@ struct icom_priv_data 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 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 int x25cmdfails; // This will get set if the 0x25 command fails so we try just once int x1cx03cmdfails; // This will get set if the 0x1c 0x03 command fails so we try just once + int satmode; // Remember satmode for handling TX/RX VFOs and such }; extern const struct ts_sc_list r8500_ts_sc_list[]; diff --git a/src/rig.c b/src/rig.c index 1e77a9170..c3499f925 100644 --- a/src/rig.c +++ b/src/rig.c @@ -1191,7 +1191,6 @@ static int twiddling(RIG *rig) return 1; // would be better as error but other software won't handle it } } - return 0; // } @@ -1270,6 +1269,7 @@ int HAMLIB_API rig_set_freq(RIG *rig, vfo_t vfo, freq_t freq) curr_vfo = rig->state.current_vfo; retcode = caps->set_vfo(rig, vfo); + vfo = rig->state.current_vfo; // can't call get_vfo since Icoms don't have it if (retcode != RIG_OK) { @@ -1341,8 +1341,8 @@ int HAMLIB_API rig_get_freq(RIG *rig, vfo_t vfo, freq_t *freq) if (cache_ms < rig->state.cache.timeout_ms && rig->state.cache.vfo_freq == vfo) { - rig_debug(RIG_DEBUG_TRACE, "%s: %s cache hit age=%dms\n", __func__, - rig_strvfo(vfo), cache_ms); + rig_debug(RIG_DEBUG_TRACE, "%s: %s cache hit age=%dms, freq=%g\n", __func__, + rig_strvfo(vfo), cache_ms, *freq); *freq = rig->state.cache.freq; return RIG_OK; } @@ -1364,8 +1364,10 @@ int HAMLIB_API rig_get_freq(RIG *rig, vfo_t vfo, freq_t *freq) || vfo == RIG_VFO_CURR || vfo == rig->state.current_vfo) { retcode = caps->get_freq(rig, vfo, freq); - rig->state.cache.freq = *freq; - rig->state.cache.vfo_freq = vfo; + if (retcode == RIG_OK) { + rig->state.cache.freq = *freq; + rig->state.cache.vfo_freq = vfo; + } } else {