From 4135a65503abfb1e41ffb520212f4a53ba2b25f2 Mon Sep 17 00:00:00 2001 From: Michael Black W9MDB Date: Fri, 26 Mar 2021 10:51:00 -0500 Subject: [PATCH] Add TARGETABLE_FREQ and TARGETABLE mode to IC7300 IC7610 IC7800 IC785X IC9700 This reduces VFO swapping during get_freq and get_mode operations Log4OMV2 2.0.12 supports vfo mode using new get_vfo_info call New debug level RIG_DEBUG_CACHE as it can get very verbose https://github.com/Hamlib/Hamlib/issues/626 --- include/hamlib/rig.h | 6 +- rigs/icom/frame.c | 1 + rigs/icom/ic7300.c | 8 +- rigs/icom/ic7610.c | 4 +- rigs/icom/ic7800.c | 4 +- rigs/icom/ic785x.c | 4 +- rigs/icom/icom.c | 225 +++++++++++++++++++++++++++++++++++-------- rigs/icom/icom.h | 3 +- src/rig.c | 73 ++++++++++++-- 9 files changed, 264 insertions(+), 64 deletions(-) diff --git a/include/hamlib/rig.h b/include/hamlib/rig.h index 8c878da12..fbb76171c 100644 --- a/include/hamlib/rig.h +++ b/include/hamlib/rig.h @@ -168,7 +168,8 @@ enum rig_debug_level_e { RIG_DEBUG_ERR, /*!< error case (e.g. protocol, memory allocation) */ RIG_DEBUG_WARN, /*!< warning */ RIG_DEBUG_VERBOSE, /*!< verbose */ - RIG_DEBUG_TRACE /*!< tracing */ + RIG_DEBUG_TRACE, /*!< tracing */ + RIG_DEBUG_CACHE /*!< caching */ }; @@ -2085,7 +2086,8 @@ typedef enum { HAMLIB_CACHE_FREQ, HAMLIB_CACHE_MODE, HAMLIB_CACHE_PTT, - HAMLIB_CACHE_SPLIT + HAMLIB_CACHE_SPLIT, + HAMLIB_CACHE_WIDTH } hamlib_cache_t; /** diff --git a/rigs/icom/frame.c b/rigs/icom/frame.c index 5e7076257..3030b5031 100644 --- a/rigs/icom/frame.c +++ b/rigs/icom/frame.c @@ -562,6 +562,7 @@ int rig2icom_mode(RIG *rig, vfo_t vfo, rmode_t mode, pbwidth_t width, void icom2rig_mode(RIG *rig, unsigned char md, int pd, rmode_t *mode, pbwidth_t *width) { + ENTERFUNC; rig_debug(RIG_DEBUG_TRACE, "%s: mode=0x%02x, pd=%d\n", __func__, md, pd); *width = RIG_PASSBAND_NORMAL; diff --git a/rigs/icom/ic7300.c b/rigs/icom/ic7300.c index c5ed85cf3..80a1ee0bd 100644 --- a/rigs/icom/ic7300.c +++ b/rigs/icom/ic7300.c @@ -301,7 +301,7 @@ const struct rig_caps ic7300_caps = RIG_MODEL(RIG_MODEL_IC7300), .model_name = "IC-7300", .mfg_name = "Icom", - .version = BACKEND_VER ".3", + .version = BACKEND_VER ".4", .copyright = "LGPL", .status = RIG_STATUS_STABLE, .rig_type = RIG_TYPE_TRANSCEIVER, @@ -340,7 +340,7 @@ const struct rig_caps ic7300_caps = .max_rit = Hz(9999), .max_xit = Hz(9999), .max_ifshift = Hz(0), - .targetable_vfo = 0, + .targetable_vfo = RIG_TARGETABLE_FREQ|RIG_TARGETABLE_MODE, .vfo_ops = IC7300_VFO_OPS, .scan_ops = IC7300_SCAN_OPS, .transceive = RIG_TRN_RIG, @@ -474,7 +474,7 @@ const struct rig_caps ic9700_caps = RIG_MODEL(RIG_MODEL_IC9700), .model_name = "IC-9700", .mfg_name = "Icom", - .version = BACKEND_VER ".2", + .version = BACKEND_VER ".3", .copyright = "LGPL", .status = RIG_STATUS_STABLE, .rig_type = RIG_TYPE_TRANSCEIVER, @@ -512,7 +512,7 @@ const struct rig_caps ic9700_caps = .max_rit = Hz(9999), .max_xit = Hz(9999), .max_ifshift = Hz(0), - .targetable_vfo = 0, + .targetable_vfo = RIG_TARGETABLE_FREQ|RIG_TARGETABLE_MODE, .vfo_ops = IC9700_VFO_OPS, .scan_ops = IC9700_SCAN_OPS, .transceive = RIG_TRN_RIG, diff --git a/rigs/icom/ic7610.c b/rigs/icom/ic7610.c index f26b3b678..b569f4666 100644 --- a/rigs/icom/ic7610.c +++ b/rigs/icom/ic7610.c @@ -169,7 +169,7 @@ const struct rig_caps ic7610_caps = RIG_MODEL(RIG_MODEL_IC7610), .model_name = "IC-7610", .mfg_name = "Icom", - .version = BACKEND_VER ".1", + .version = BACKEND_VER ".2", .copyright = "LGPL", .status = RIG_STATUS_STABLE, .rig_type = RIG_TYPE_TRANSCEIVER, @@ -208,7 +208,7 @@ const struct rig_caps ic7610_caps = .max_rit = Hz(9999), .max_xit = Hz(9999), .max_ifshift = Hz(0), - .targetable_vfo = 0, + .targetable_vfo = RIG_TARGETABLE_FREQ|RIG_TARGETABLE_MODE, .vfo_ops = IC7610_VFO_OPS, .scan_ops = IC7610_SCAN_OPS, .transceive = RIG_TRN_RIG, diff --git a/rigs/icom/ic7800.c b/rigs/icom/ic7800.c index 83091b3c4..641b18b15 100644 --- a/rigs/icom/ic7800.c +++ b/rigs/icom/ic7800.c @@ -157,7 +157,7 @@ const struct rig_caps ic7800_caps = RIG_MODEL(RIG_MODEL_IC7800), .model_name = "IC-7800", .mfg_name = "Icom", - .version = BACKEND_VER ".0", + .version = BACKEND_VER ".1", .copyright = "LGPL", .status = RIG_STATUS_UNTESTED, .rig_type = RIG_TYPE_TRANSCEIVER, @@ -196,7 +196,7 @@ const struct rig_caps ic7800_caps = .max_rit = Hz(9999), .max_xit = Hz(9999), .max_ifshift = Hz(0), - .targetable_vfo = 0, + .targetable_vfo = RIG_TARGETABLE_FREQ|RIG_TARGETABLE_MODE, .vfo_ops = IC7800_VFO_OPS, .scan_ops = IC7800_SCAN_OPS, .transceive = RIG_TRN_RIG, diff --git a/rigs/icom/ic785x.c b/rigs/icom/ic785x.c index 99029bb50..37927f51f 100644 --- a/rigs/icom/ic785x.c +++ b/rigs/icom/ic785x.c @@ -163,7 +163,7 @@ const struct rig_caps ic785x_caps = RIG_MODEL(RIG_MODEL_IC785x), .model_name = "IC-785x", .mfg_name = "Icom", - .version = BACKEND_VER ".0", + .version = BACKEND_VER ".1", .copyright = "LGPL", .status = RIG_STATUS_BETA, .rig_type = RIG_TYPE_TRANSCEIVER, @@ -202,7 +202,7 @@ const struct rig_caps ic785x_caps = .max_rit = Hz(9999), .max_xit = Hz(9999), .max_ifshift = Hz(0), - .targetable_vfo = 0, + .targetable_vfo = RIG_TARGETABLE_FREQ|RIG_TARGETABLE_MODE, .vfo_ops = IC785x_VFO_OPS, .scan_ops = IC785x_SCAN_OPS, .transceive = RIG_TRN_RIG, diff --git a/rigs/icom/icom.c b/rigs/icom/icom.c index 015d89c73..082d88699 100644 --- a/rigs/icom/icom.c +++ b/rigs/icom/icom.c @@ -666,6 +666,8 @@ icom_init(RIG *rig) priv->rx_vfo = RIG_VFO_NONE; rig->state.current_vfo = RIG_VFO_NONE; priv->filter = RIG_PASSBAND_NOCHANGE; + priv->x25cmdfails = 0; + priv->x1cx03cmdfails = 0; rig_debug(RIG_DEBUG_TRACE, "%s: done\n", __func__); @@ -736,7 +738,7 @@ int icom_get_usb_echo_off(RIG *rig) rig_debug(RIG_DEBUG_VERBOSE, "%s: USB echo on detected\n", __func__); // we should have a freq response so we'll read it and don't really care // flushing doesn't always work as it depends on timing - read_icom_frame(&rs->rigport,buf,sizeof(buf)); + read_icom_frame(&rs->rigport, buf, sizeof(buf)); } else { @@ -1139,11 +1141,13 @@ int icom_get_freq(RIG *rig, vfo_t vfo, freq_t *freq) struct icom_priv_data *priv; struct rig_state *rs; unsigned char freqbuf[MAXFRAMELEN]; + int freqbuf_offset = 1; unsigned char ackbuf[MAXFRAMELEN]; - int freq_len, retval; + int freq_len, retval = -RIG_EINTERNAL; int cmd, subcmd; int ack_len = sizeof(ackbuf); int civ_731_mode = 0; // even these rigs have 5-byte channels + vfo_t vfo_save = rig->state.current_vfo; rig_debug(RIG_DEBUG_VERBOSE, "%s called for %s, curr_vfo=%s\n", __func__, rig_strvfo(vfo), rig_strvfo(rig->state.current_vfo)); @@ -1209,14 +1213,6 @@ int icom_get_freq(RIG *rig, vfo_t vfo, freq_t *freq) #endif - retval = set_vfo_curr(rig, vfo, rig->state.current_vfo); - - if (retval != RIG_OK) - { - if (vfo == RIG_VFO_MEM && civ_731_mode) { priv->civ_731_mode = 1; } - - RETURNFUNC(retval); - } #if 0 @@ -1253,7 +1249,7 @@ int icom_get_freq(RIG *rig, vfo_t vfo, freq_t *freq) if (rig->state.current_vfo == RIG_VFO_NONE) { - retval = rig_set_vfo(rig, vfo); + retval = rig_set_vfo(rig, RIG_VFO_A); // we default to VFOA if (retval != RIG_OK) { @@ -1262,7 +1258,57 @@ int icom_get_freq(RIG *rig, vfo_t vfo, freq_t *freq) } } - retval = icom_transaction(rig, cmd, subcmd, NULL, 0, freqbuf, &freq_len); + // we'll use 0x25 command to get unselected frequency + // we are always assuming we're on VFOA/Main to start with + if (priv->x25cmdfails == 0) + { + int cmd2 = 0x25; + int subcmd2 = 0x00; + vfo_t vfo_unselected = RIG_VFO_B | RIG_VFO_SUB | RIG_VFO_SUB_B | RIG_VFO_MAIN_B; + + // if we ask for unselected but we're not on unselected subcmd2 changes + if ((vfo & vfo_unselected) && !(rig->state.current_vfo & vfo_unselected)) + { + subcmd2 = 0x01; // get unselected VFO + } + + retval = icom_transaction(rig, cmd2, subcmd2, NULL, 0, freqbuf, &freq_len); + + if (retval != RIG_OK) + { + priv->x25cmdfails = 1; + rig_debug(RIG_DEBUG_WARN, + "%s: rig does not support 0x25 CI-V cmd...vfo swapping will occur\n", __func__); + } + + freq_len--; // 0x25 cmd is 1 byte longer than 0x03 cmd + freqbuf_offset = 2; + } + + if (priv->x25cmdfails) // then we're doing this the hard way....swap+read + { + retval = set_vfo_curr(rig, vfo, rig->state.current_vfo); + + if (retval != RIG_OK) + { + if (vfo == RIG_VFO_MEM && civ_731_mode) { priv->civ_731_mode = 1; } + + RETURNFUNC(retval); + } + + retval = icom_transaction(rig, cmd, subcmd, NULL, 0, freqbuf, &freq_len); + set_vfo_curr(rig, vfo_save, rig->state.current_vfo); + } + +#if 0 + else if (!priv->x25cmdfails + && (vfo & (RIG_VFO_A | RIG_VFO_MAIN | RIG_VFO_MAIN_A | RIG_VFO_SUB_A))) + { + // we can use the 0x03 command for the default VFO + retval = icom_transaction(rig, cmd, subcmd, NULL, 0, freqbuf, &freq_len); + } + +#endif if (retval != RIG_OK) { @@ -1307,7 +1353,7 @@ int icom_get_freq(RIG *rig, vfo_t vfo, freq_t *freq) /* * from_bcd requires nibble len */ - *freq = from_bcd(freqbuf + 1, freq_len * 2); + *freq = from_bcd(freqbuf + freqbuf_offset, freq_len * 2); if (vfo == RIG_VFO_MEM && civ_731_mode) { priv->civ_731_mode = 1; } @@ -1456,7 +1502,8 @@ pbwidth_t icom_get_dsp_flt(RIG *rig, rmode_t mode) S_MEM_FILT_WDTH; struct icom_priv_data *priv = (struct icom_priv_data *) rig->state.priv; - rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__); + rig_debug(RIG_DEBUG_VERBOSE, "%s called, mode=%s\n", __func__, + rig_strrmode(mode)); if (rig_has_get_func(rig, RIG_FUNC_RF) && (mode & (RIG_MODE_RTTY | RIG_MODE_RTTYR))) @@ -1507,6 +1554,8 @@ pbwidth_t icom_get_dsp_flt(RIG *rig, rmode_t mode) { int i; i = (int) from_bcd(resbuf + 2, 2); + rig_debug(RIG_DEBUG_TRACE, "%s: i=%d, [0]=%02x, [1]=%02x, [2]=%02x, [3]=%02x\n", + __func__, i, resbuf[0], resbuf[1], resbuf[2], resbuf[3]); if (mode & RIG_MODE_AM) { @@ -1514,13 +1563,14 @@ pbwidth_t icom_get_dsp_flt(RIG *rig, rmode_t mode) } else if (mode & (RIG_MODE_CW | RIG_MODE_USB | RIG_MODE_LSB | RIG_MODE_RTTY | - RIG_MODE_RTTYR)) + RIG_MODE_RTTYR | RIG_MODE_PKTUSB | RIG_MODE_PKTLSB)) { - return (i < 10 ? (i + 1) * 50 : (i - 4) * 100); + rig_debug(RIG_DEBUG_TRACE, "%s: using width=%d\n", __func__, i); + RETURNFUNC(i < 10 ? (i + 1) * 50 : (i - 4) * 100); } } - return (0); + RETURNFUNC(0); } int icom_set_dsp_flt(RIG *rig, rmode_t mode, pbwidth_t width) @@ -1827,35 +1877,51 @@ int icom_get_mode_with_data(RIG *rig, vfo_t vfo, rmode_t *mode, int data_len, retval; unsigned char dm_sub_cmd = RIG_MODEL_IC7200 == rig->caps->rig_model ? 0x04 : S_MEM_DATA_MODE; + struct rig_state *rs; + struct icom_priv_data *priv; rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__); - retval = icom_get_mode(rig, vfo, mode, width); - rig_debug(RIG_DEBUG_VERBOSE, "%s mode=%d\n", __func__, (int)*mode); + rs = &rig->state; + priv = (struct icom_priv_data *) rs->priv; + + retval = icom_get_mode(rig, vfo, mode, width); if (retval != RIG_OK) { RETURNFUNC(retval); } + rig_debug(RIG_DEBUG_VERBOSE, "%s mode=%d\n", __func__, (int)*mode); + switch (*mode) { case RIG_MODE_USB: case RIG_MODE_LSB: case RIG_MODE_AM: case RIG_MODE_FM: + /* * fetch data mode on/off */ - retval = - icom_transaction(rig, C_CTL_MEM, dm_sub_cmd, 0, 0, databuf, - &data_len); - - if (retval != RIG_OK) + if (rig->caps->targetable_vfo & RIG_TARGETABLE_MODE) { - rig_debug(RIG_DEBUG_ERR, "%s: protocol error (%#.2x), len=%d\n", - __func__, databuf[0], data_len); - RETURNFUNC(-RIG_ERJCTED); + // then we already got data mode so we fake the databuf answer + databuf[2] = priv->datamode; + data_len = 3; + } + else + { + retval = + icom_transaction(rig, C_CTL_MEM, dm_sub_cmd, 0, 0, databuf, + &data_len); + + if (retval != RIG_OK) + { + rig_debug(RIG_DEBUG_ERR, "%s: protocol error (%#.2x), len=%d\n", + __func__, databuf[0], data_len); + RETURNFUNC(-RIG_ERJCTED); + } } /* @@ -1932,7 +1998,37 @@ int icom_get_mode(RIG *rig, vfo_t vfo, rmode_t *mode, pbwidth_t *width) priv_caps = (const struct icom_priv_caps *) rig->caps->priv; priv_data = (struct icom_priv_data *) rig->state.priv; - retval = icom_transaction(rig, C_RD_MODE, -1, NULL, 0, modebuf, &mode_len); + *width = 0; + + if (rig->caps->targetable_vfo & RIG_TARGETABLE_MODE) + { + int vfosel = 0x00; + + if (vfo & (RIG_VFO_B | RIG_VFO_SUB | RIG_VFO_SUB_B | RIG_VFO_MAIN_B)) { vfosel = 0x01; } + + // use cache for the non-selected VFO -- can't get it by VFO + // this avoids vfo swapping but accurate answers for these rigs + *width = rig->state.cache.widthMainB; + + if (vfo == RIG_VFO_SUB_B) { *width = rig->state.cache.widthSubB; } + + // then get non-selected VFO mode/width + retval = icom_transaction(rig, 0x26, vfosel, NULL, 0, modebuf, &mode_len); + rig_debug(RIG_DEBUG_TRACE, + "%s: mode_len=%d, modebuf=%02x %02x %02x %02x %02x\n", __func__, mode_len, + modebuf[0], modebuf[1], modebuf[2], modebuf[3], modebuf[4]); + // mode_len=5, modebuf=26 01 01 01 01 + // last 3 bytes are mode, datamode, filter (1-3) + priv_data->datamode = modebuf[3]; + priv_data->filter = modebuf[4]; + modebuf[1] = modebuf[2]; // copy mode to 2-byte format + modebuf[2] = modebuf[4]; // copy filter to 2-byte format + mode_len = 2; + } + else + { + retval = icom_transaction(rig, C_RD_MODE, -1, NULL, 0, modebuf, &mode_len); + } if (--mode_len == 3) { @@ -1998,19 +2094,61 @@ int icom_get_mode(RIG *rig, vfo_t vfo, rmode_t *mode, pbwidth_t *width) * Lets check for dsp filters */ - if (width != NULL && (retval = icom_get_dsp_flt(rig, *mode)) != 0) + // if we already set width we won't update with except during set_vfo or set_mode + // reason is we can't get width without swapping vfos -- yuck!! + if (width != NULL) { - *width = retval; - rig_debug(RIG_DEBUG_TRACE, "%s: vfo=%s returning mode=%s, width=%d\n", __func__, - rig_strvfo(vfo), rig_strrmode(*mode), (int)*width); - } - else - { - rig_debug(RIG_DEBUG_TRACE, - "%s: vfo=%s returning mode=%s, width not available\n", __func__, - rig_strvfo(vfo), rig_strrmode(*mode)); + if (vfo & (RIG_VFO_A | RIG_VFO_MAIN | RIG_VFO_SUB_A | RIG_VFO_MAIN_A)) + { + // then we get our current vfo..i.e. VFOA + if (rig->state.current_vfo != RIG_VFO_A) + { + rig_debug(RIG_DEBUG_TRACE, "%s(%d): forcing default VFO_A\n", __func__, + __LINE__); + rig_set_vfo(rig, RIG_VFO_A); // force VFOA + } + + retval = icom_get_dsp_flt(rig, *mode); + *width = retval; + + if (retval == 0) + { + rig_debug(RIG_DEBUG_TRACE, + "%s: vfo=%s returning mode=%s, width not available\n", __func__, + rig_strvfo(vfo), rig_strrmode(*mode)); + } + } + else if (rig->state.cache.widthMainB == 0) + { + // we need to swap vfos to get the bandwidth -- yuck + // so we read it once and will let set_mode and transceive capability (4.3 hamlib) update it + vfo_t vfosave = rig->state.current_vfo; + + if (vfosave != vfo) + { + // right now forcing VFOA/B arrangement -- reverse not supported yet + rig_set_vfo(rig, RIG_VFO_B); + retval = icom_get_dsp_flt(rig, *mode); + *width = retval; + // dont' really care about cache time here + // this is just to prevent vfo swapping while getting width + rig->state.cache.widthMainB = retval; + rig_debug(RIG_DEBUG_TRACE, "%s(%d): vfosave=%s, currvfo=%s\n", __func__, + __LINE__, rig_strvfo(vfo), rig_strvfo(rig->state.current_vfo)); + rig_set_vfo(rig, RIG_VFO_A); + rig_debug(RIG_DEBUG_TRACE, "%s: vfo=%s returning mode=%s, width=%d\n", __func__, + rig_strvfo(vfo), rig_strrmode(*mode), (int)*width); + } + else + { + rig_debug(RIG_DEBUG_WARN, + "%s: vfo arrangement not supported yet, vfo=%s, currvfo=%s\n", __func__, + rig_strvfo(vfo), rig_strvfo(vfosave)); + } + } } + RETURNFUNC(RIG_OK); } @@ -2102,18 +2240,20 @@ int icom_set_vfo(RIG *rig, vfo_t vfo) { // If we're being asked for A/Main but we are a MainA/MainB rig change it vfo = RIG_VFO_MAIN_A; - } + } else if ((vfo == RIG_VFO_B || vfo == RIG_VFO_SUB) && VFO_HAS_DUAL) { // If we're being asked for B/Sub but we are a MainA/MainB rig change it vfo = RIG_VFO_MAIN_B; + // If we're in satmode for rigs like IC9700 we want the 2nd VFO if (rig->state.cache.satmode) { vfo = RIG_VFO_SUB_A; } } - else if ((vfo == RIG_VFO_A || vfo == RIG_VFO_B) && !VFO_HAS_A_B && VFO_HAS_MAIN_SUB) + else if ((vfo == RIG_VFO_A || vfo == RIG_VFO_B) && !VFO_HAS_A_B + && VFO_HAS_MAIN_SUB) { // If we're being asked for A/B but we are a Main/Sub rig change it vfo_t vfo_old = vfo; @@ -5626,7 +5766,8 @@ int icom_set_func(RIG *rig, vfo_t vfo, setting_t func, int status) fct_sc = S_MEM_SATMODE; } - priv->x25cmdfails = status; // we reset this to current status -- fails in SATMODE + priv->x25cmdfails = + status; // we reset this to current status -- fails in SATMODE priv->x1cx03cmdfails = 0; // we reset this to try it again rig->state.cache.satmode = status; @@ -5836,6 +5977,7 @@ int icom_get_func(RIG *rig, vfo_t vfo, setting_t func, int *status) fct_cn = C_CTL_FUNC; fct_sc = S_MEM_SATMODE; } + break; @@ -5867,6 +6009,7 @@ int icom_get_func(RIG *rig, vfo_t vfo, setting_t func, int *status) else { *status = ackbuf[2] == 2 ? 1 : 0; + if (func == RIG_FUNC_SATMODE) { struct rig_state *rs = &rig->state; diff --git a/rigs/icom/icom.h b/rigs/icom/icom.h index dc1cc3940..c43fc4844 100644 --- a/rigs/icom/icom.h +++ b/rigs/icom/icom.h @@ -30,7 +30,7 @@ #include #endif -#define BACKEND_VER "20210322" +#define BACKEND_VER "20210326" /* * defines used by comp_cal_str in rig.c @@ -204,6 +204,7 @@ struct icom_priv_data int x1cx03cmdfails; // This will get set if the 0x1c 0x03 command fails so we try just once int poweron; // to prevent powering on more than once unsigned char filter; // Current filter selected + unsigned char datamode; // Current datamode }; extern const struct ts_sc_list r8500_ts_sc_list[]; diff --git a/src/rig.c b/src/rig.c index 9011d4726..ffa9560ed 100644 --- a/src/rig.c +++ b/src/rig.c @@ -350,6 +350,18 @@ int rig_check_rig_caps() return rc; } +static void cache_show(RIG *rig, const char *func, int line) +{ + rig_debug(RIG_DEBUG_CACHE, + "%s(%d): freqMainA=%.0f, modeMainA=%s, widthMainA=%d\n", func, line, + rig->state.cache.freqMainA, rig_strrmode(rig->state.cache.modeMainA), + (int)rig->state.cache.widthMainA); + rig_debug(RIG_DEBUG_CACHE, + "%s(%d): freqMainB=%.0f, modeMainB=%s, widthMainB=%d\n", func, line, + rig->state.cache.freqMainB, rig_strrmode(rig->state.cache.modeMainB), + (int)rig->state.cache.widthMainB); +} + /** * \brief allocate a new RIG handle * \param rig_model The rig model for this new handle @@ -1331,6 +1343,8 @@ static int set_cache_mode(RIG *rig, vfo_t vfo, mode_t mode, pbwidth_t width) { ENTERFUNC; + cache_show(rig, __func__, __LINE__); + if (vfo == RIG_VFO_CURR) { // if CURR then update this before we figure out the real VFO @@ -1390,6 +1404,7 @@ static int set_cache_mode(RIG *rig, vfo_t vfo, mode_t mode, pbwidth_t width) RETURNFUNC(-RIG_EINTERNAL); } + cache_show(rig, __func__, __LINE__); RETURNFUNC(RIG_OK); } @@ -1400,6 +1415,7 @@ static int set_cache_freq(RIG *rig, vfo_t vfo, freq_t freq) ENTERFUNC; rig_debug(RIG_DEBUG_TRACE, "%s: vfo=%s, current_vfo=%s\n", __func__, rig_strvfo(vfo), rig_strvfo(rig->state.current_vfo)); + cache_show(rig, __func__, __LINE__); if (vfo == RIG_VFO_CURR) { @@ -1485,6 +1501,7 @@ static int set_cache_freq(RIG *rig, vfo_t vfo, freq_t freq) RETURNFUNC(-RIG_EINVAL); } + cache_show(rig, __func__, __LINE__); RETURNFUNC(RIG_OK); } @@ -1503,7 +1520,6 @@ int rig_get_cache(RIG *rig, vfo_t vfo, freq_t *freq, int *cache_ms_freq, // If we're in satmode we map SUB to SUB_A if (vfo == RIG_VFO_SUB && rig->state.cache.satmode) { vfo = RIG_VFO_SUB_A; }; - // VFO_C to be implemented switch (vfo) { case RIG_VFO_A: @@ -1726,6 +1742,7 @@ int HAMLIB_API rig_set_freq(RIG *rig, vfo_t vfo, freq_t freq) set_cache_freq(rig, vfo, (freq_t)0); #if 0 // this verification seems to be causing bad behavior on some reigs + if (caps->get_freq) { retcode = rig_get_freq(rig, vfo, &tfreq); @@ -1744,6 +1761,7 @@ int HAMLIB_API rig_set_freq(RIG *rig, vfo_t vfo, freq_t freq) } } else { retry = 0; } + #else tfreq = freq; #endif @@ -1866,6 +1884,7 @@ int HAMLIB_API rig_get_freq(RIG *rig, vfo_t vfo, freq_t *freq) pbwidth_t width; rig_debug(RIG_DEBUG_VERBOSE, "%s called vfo=%s\n", __func__, rig_strvfo(vfo)); + cache_show(rig, __func__, __LINE__); #if 0 // don't think we really need this check @@ -1897,6 +1916,8 @@ int HAMLIB_API rig_get_freq(RIG *rig, vfo_t vfo, freq_t *freq) RETURNFUNC(RIG_OK); } + cache_show(rig, __func__, __LINE__); + // there are some rigs that can't get VFOA freq while VFOB is transmitting // so we'll return the cached VFOA freq for them // should we use the cached ptt maybe? No -- we have to be 100% sure we're in PTT to ignore this request @@ -1929,6 +1950,8 @@ int HAMLIB_API rig_get_freq(RIG *rig, vfo_t vfo, freq_t *freq) rig_debug(RIG_DEBUG_TRACE, "%s: cache check1 age=%dms\n", __func__, cache_ms_freq); + cache_show(rig, __func__, __LINE__); + if (freq != 0 && cache_ms_freq < rig->state.cache.timeout_ms) { rig_debug(RIG_DEBUG_TRACE, "%s: %s cache hit age=%dms, freq=%.0f\n", __func__, @@ -1965,6 +1988,8 @@ int HAMLIB_API rig_get_freq(RIG *rig, vfo_t vfo, freq_t *freq) retcode = caps->get_freq(rig, vfo, freq); + cache_show(rig, __func__, __LINE__); + // sometimes a network rig like FLRig will return freq=0 // so we'll just reuse the cache for that condition if (*freq == 0) @@ -1978,6 +2003,7 @@ int HAMLIB_API rig_get_freq(RIG *rig, vfo_t vfo, freq_t *freq) if (retcode == RIG_OK) { set_cache_freq(rig, vfo, *freq); + cache_show(rig, __func__, __LINE__); } } else @@ -1996,13 +2022,17 @@ int HAMLIB_API rig_get_freq(RIG *rig, vfo_t vfo, freq_t *freq) RETURNFUNC(retcode); } + cache_show(rig, __func__, __LINE__); + retcode = caps->get_freq(rig, vfo, freq); /* try and revert even if we had an error above */ rc2 = caps->set_vfo(rig, curr_vfo); if (RIG_OK == retcode) { + cache_show(rig, __func__, __LINE__); set_cache_freq(rig, vfo, *freq); + cache_show(rig, __func__, __LINE__); /* return the first error code */ retcode = rc2; } @@ -2025,7 +2055,9 @@ int HAMLIB_API rig_get_freq(RIG *rig, vfo_t vfo, freq_t *freq) *freq += rig->state.lo_freq; } + cache_show(rig, __func__, __LINE__); set_cache_freq(rig, vfo, *freq); + cache_show(rig, __func__, __LINE__); RETURNFUNC(retcode); } @@ -2141,8 +2173,7 @@ int HAMLIB_API rig_set_mode(RIG *rig, vfo_t vfo, rmode_t mode, pbwidth_t width) RETURNFUNC(retcode); } - -/** +/* * \brief get the mode of the target VFO * \param rig The rig handle * \param vfo The target VFO @@ -2184,14 +2215,18 @@ int HAMLIB_API rig_get_mode(RIG *rig, RETURNFUNC(-RIG_ENAVAIL); } + *mode = RIG_MODE_NONE; + cache_show(rig, __func__, __LINE__); int cache_ms_freq, cache_ms_mode, cache_ms_width; rig_get_cache(rig, vfo, &freq, &cache_ms_freq, mode, &cache_ms_mode, width, &cache_ms_width); rig_debug(RIG_DEBUG_TRACE, "%s: %s cache check age=%dms\n", __func__, rig_strvfo(vfo), cache_ms_freq); - if (cache_ms_mode < rig->state.cache.timeout_ms - || cache_ms_width < rig->state.cache.timeout_ms) + cache_show(rig, __func__, __LINE__); + + if ((*mode != RIG_MODE_NONE && cache_ms_mode < rig->state.cache.timeout_ms) + && cache_ms_width < rig->state.cache.timeout_ms) { rig_debug(RIG_DEBUG_TRACE, "%s: cache hit age mode=%dms, width=%dms\n", __func__, cache_ms_mode, cache_ms_width); @@ -2211,12 +2246,12 @@ int HAMLIB_API rig_get_mode(RIG *rig, retcode = caps->get_mode(rig, vfo, mode, width); rig_debug(RIG_DEBUG_TRACE, "%s: retcode after get_mode=%d\n", __func__, retcode); + cache_show(rig, __func__, __LINE__); } else { int rc2; vfo_t curr_vfo; - rig_debug(RIG_DEBUG_TRACE, "%s(%d): debug\n", __func__, __LINE__); if (!caps->set_vfo) { @@ -2224,7 +2259,11 @@ int HAMLIB_API rig_get_mode(RIG *rig, } curr_vfo = rig->state.current_vfo; - retcode = caps->set_vfo(rig, vfo); + rig_debug(RIG_DEBUG_TRACE, "%s(%d): vfo=%s, curr_vfo=%s\n", __func__, __LINE__, + rig_strvfo(vfo), rig_strvfo(curr_vfo)); + retcode = caps->set_vfo(rig, vfo == RIG_VFO_CURR ? RIG_VFO_A : vfo); + + cache_show(rig, __func__, __LINE__); if (retcode != RIG_OK) { @@ -2248,6 +2287,7 @@ int HAMLIB_API rig_get_mode(RIG *rig, rig_debug(RIG_DEBUG_TRACE, "%s(%d): debug\n", __func__, __LINE__); rig->state.current_mode = *mode; rig->state.current_width = *width; + cache_show(rig, __func__, __LINE__); } if (*width == RIG_PASSBAND_NORMAL && *mode != RIG_MODE_NONE) @@ -2257,6 +2297,7 @@ int HAMLIB_API rig_get_mode(RIG *rig, } set_cache_mode(rig, vfo, *mode, *width); + cache_show(rig, __func__, __LINE__); RETURNFUNC(retcode); } @@ -2478,6 +2519,7 @@ int HAMLIB_API rig_set_vfo(RIG *rig, vfo_t vfo) { rig->state.current_vfo = vfo; rig->state.cache.vfo = vfo; + elapsed_ms(&rig->state.cache.time_vfo, HAMLIB_ELAPSED_SET); rig_debug(RIG_DEBUG_TRACE, "%s: rig->state.current_vfo=%s\n", __func__, rig_strvfo(vfo)); } @@ -2491,7 +2533,7 @@ int HAMLIB_API rig_set_vfo(RIG *rig, vfo_t vfo) // we only get the freq if we set the vfo OK if (retcode == RIG_OK && caps->get_freq) { - retcode = caps->get_freq(rig, RIG_VFO_CURR, &curr_freq); + retcode = caps->get_freq(rig, vfo, &curr_freq); rig_debug(RIG_DEBUG_TRACE, "%s: retcode from rig_get_freq = %.10000s\n", __func__, rigerror(retcode)); @@ -2502,6 +2544,7 @@ int HAMLIB_API rig_set_vfo(RIG *rig, vfo_t vfo) set_cache_freq(rig, RIG_VFO_ALL, (freq_t)0); } +#if 0 // with new cache should not have to expire here anymore // expire several cached items when we switch VFOs elapsed_ms(&rig->state.cache.time_vfo, HAMLIB_ELAPSED_INVALIDATE); elapsed_ms(&rig->state.cache.time_modeMainA, HAMLIB_ELAPSED_INVALIDATE); @@ -2510,6 +2553,7 @@ int HAMLIB_API rig_set_vfo(RIG *rig, vfo_t vfo) elapsed_ms(&rig->state.cache.time_widthMainA, HAMLIB_ELAPSED_INVALIDATE); elapsed_ms(&rig->state.cache.time_widthMainB, HAMLIB_ELAPSED_INVALIDATE); elapsed_ms(&rig->state.cache.time_widthMainC, HAMLIB_ELAPSED_INVALIDATE); +#endif rig_debug(RIG_DEBUG_TRACE, "%s: return %d, vfo=%s\n", __func__, retcode, rig_strvfo(vfo)); @@ -2665,7 +2709,9 @@ int HAMLIB_API rig_set_ptt(RIG *rig, vfo_t vfo, ptt_t ptt) rigerror(retcode)); retcode = RIG_OK; // fake the retcode so we retry } + if (tptt != ptt) { rig_debug(RIG_DEBUG_WARN, "%s: failed, retry=%d\n", __func__, retry); } + #else tptt = ptt; #endif @@ -2700,6 +2746,7 @@ int HAMLIB_API rig_set_ptt(RIG *rig, vfo_t vfo, ptt_t ptt) retcode = rig_get_ptt(rig, vfo, &tptt); if (tptt != ptt) { rig_debug(RIG_DEBUG_WARN, "%s: failed, retry=%d\n", __func__, retry); } + #else tptt = ptt; #endif @@ -3559,6 +3606,7 @@ int HAMLIB_API rig_set_split_freq(RIG *rig, vfo_t vfo, freq_t tx_freq) do { #if 0 // this verification seems to be causing bad behavior on some reigs + if (caps->set_split_freq) { retcode = caps->set_split_freq(rig, vfo, tx_freq); @@ -3569,6 +3617,7 @@ int HAMLIB_API rig_set_split_freq(RIG *rig, vfo_t vfo, freq_t tx_freq) retcode = rig_set_freq(rig, RIG_VFO_CURR, tx_freq); rig_get_freq(rig, vfo, &tfreq); } + #else tfreq = tx_freq; #endif @@ -4001,6 +4050,7 @@ int HAMLIB_API rig_set_split_freq_mode(RIG *rig, retcode = caps->set_split_freq_mode(rig, vfo, tx_freq, tx_mode, tx_width); #if 0 // this verification seems to be causing bad behavior on some reigs + // we query freq after set to ensure it really gets done do { @@ -4014,6 +4064,7 @@ int HAMLIB_API rig_set_split_freq_mode(RIG *rig, tfreq, retry, retcode, retcode2); hl_usleep(50 * 1000); // 50ms sleep may help here } + tfreq = tx_freq; retcode2 = RIG_OK; } @@ -4021,6 +4072,7 @@ int HAMLIB_API rig_set_split_freq_mode(RIG *rig, && retcode2 == RIG_OK); if (tfreq != tx_freq) { retcode = -RIG_EPROTO; } + #endif RETURNFUNC(retcode); @@ -5939,7 +5991,7 @@ int HAMLIB_API rig_get_vfo_info(RIG *rig, vfo_t vfo, freq_t *freq, RETURNFUNC(-RIG_EINVAL); } - if (vfo == RIG_VFO_CURR) { vfo = rig->state.current_vfo; } + //if (vfo == RIG_VFO_CURR) { vfo = rig->state.current_vfo; } // we can't use the cached values as some clients may only call this function // like Log4OM which mostly does polling @@ -5951,7 +6003,8 @@ int HAMLIB_API rig_get_vfo_info(RIG *rig, vfo_t vfo, freq_t *freq, if (retval != RIG_OK) { RETURNFUNC(retval); } - retval = rig_get_split(rig, vfo, split); + // we should only need to ask for VFO_CURR to minimize display swapping + retval = rig_get_split(rig, RIG_VFO_CURR, split); if (retval != RIG_OK) { RETURNFUNC(retval); }