From 542585029d489f30b4c1dbdcb8a269c4d63187aa Mon Sep 17 00:00:00 2001 From: Bill Somerville Date: Fri, 13 Mar 2015 12:37:29 +0000 Subject: [PATCH 1/4] Initial back end implementation for the Kenwood TS-990s --- include/hamlib/rig.h | 3 +- include/hamlib/riglist.h | 1 + kenwood/Makefile.am | 2 +- kenwood/kenwood.c | 626 +++++++++++++++++++++++++++++++------- kenwood/kenwood.h | 6 +- kenwood/ts2000.c | 2 +- kenwood/ts870s.c | 10 +- kenwood/ts990s.c | 631 +++++++++++++++++++++++++++++++++++++++ kenwood/ts990s.h | 29 ++ 9 files changed, 1187 insertions(+), 123 deletions(-) create mode 100644 kenwood/ts990s.c create mode 100644 kenwood/ts990s.h diff --git a/include/hamlib/rig.h b/include/hamlib/rig.h index 3842cb91b..c35d722c1 100644 --- a/include/hamlib/rig.h +++ b/include/hamlib/rig.h @@ -139,7 +139,7 @@ typedef struct rig RIG; #define FRQRANGESIZ 30 #define MAXCHANDESC 30 /* describe channel eg: "WWV 5Mhz" */ #define TSLSTSIZ 20 /* max tuning step list size, zero ended */ -#define FLTLSTSIZ 42 /* max mode/filter list size, zero ended */ +#define FLTLSTSIZ 60 /* max mode/filter list size, zero ended */ #define MAXDBLSTSIZ 8 /* max preamp/att levels supported, zero ended */ #define CHANLSTSIZ 16 /* max mem_list size, zero ended */ #define MAX_CAL_LENGTH 32 /* max calibration plots in cal_table_t */ @@ -805,6 +805,7 @@ typedef enum { RIG_MODE_SAL = (1<<17),/*!< \c SAL -- Synchronous AM lower sideband */ RIG_MODE_SAH = (1<<18),/*!< \c SAH -- Synchronous AM upper (higher) sideband */ RIG_MODE_DSB = (1<<19),/*!< \c DSB -- Double sideband suppressed carrier */ + RIG_MODE_FMN = (1<<21),/*!< \c FMN -- FM Narrow Kenwood ts990s */ RIG_MODE_TESTS_MAX /*!< \c MUST ALWAYS BE LAST, Max Count for dumpcaps.c */ } rmode_t; diff --git a/include/hamlib/riglist.h b/include/hamlib/riglist.h index 8e90c1c5f..fa7fb23f2 100644 --- a/include/hamlib/riglist.h +++ b/include/hamlib/riglist.h @@ -141,6 +141,7 @@ #define RIG_MODEL_F6K RIG_MAKE_MODEL(RIG_KENWOOD, 36) /* Flex 6000 Series */ #define RIG_MODEL_TS590SG RIG_MAKE_MODEL(RIG_KENWOOD, 37) #define RIG_MODEL_XG3 RIG_MAKE_MODEL(RIG_KENWOOD, 38) +#define RIG_MODEL_TS990S RIG_MAKE_MODEL(RIG_KENWOOD, 39) /* * Icom diff --git a/kenwood/Makefile.am b/kenwood/Makefile.am index 2aa5232c3..8526be00e 100644 --- a/kenwood/Makefile.am +++ b/kenwood/Makefile.am @@ -2,7 +2,7 @@ TSSRC = ts850.c ts870s.c ts570.c ts450s.c ts950.c ts50s.c \ ts790.c ts2000.c k2.c k3.c xg3.c ts930.c \ ts680.c ts690.c ts140.c ts480.c trc80.c ts590.c \ - flex6xxx.c + ts990s.c ts990s.h flex6xxx.c IC10SRC = ts440.c ts940.c ts711.c ts811.c r5000.c diff --git a/kenwood/kenwood.c b/kenwood/kenwood.c index 2fcde74f9..b857ec5d8 100644 --- a/kenwood/kenwood.c +++ b/kenwood/kenwood.c @@ -39,6 +39,7 @@ #include "cal.h" #include "kenwood.h" +#include "ts990s.h" #ifndef max #define max(a,b) (((a) (b)) ? (a) : (b)) @@ -82,6 +83,7 @@ static const struct kenwood_id kenwood_id_list[] = { { RIG_MODEL_TS2000, 19 }, { RIG_MODEL_TS480, 20 }, { RIG_MODEL_TS590S, 21 }, + { RIG_MODEL_TS990S, 22 }, { RIG_MODEL_TS590SG, 23 }, { RIG_MODEL_NONE, UNKNOWN_ID }, /* end marker */ }; @@ -104,6 +106,7 @@ static const struct kenwood_id_string kenwood_id_string_list[] = { { RIG_MODEL_TS2000, "019" }, { RIG_MODEL_TS480, "020" }, { RIG_MODEL_TS590S, "021" }, + { RIG_MODEL_TS990S, "022" }, { RIG_MODEL_TS590SG, "023" }, { RIG_MODEL_THD7A, "TH-D7" }, { RIG_MODEL_THD7AG, "TH-D7G" }, @@ -672,7 +675,6 @@ int kenwood_set_vfo(RIG *rig, vfo_t vfo) char vfo_function; switch (vfo) { - case RIG_VFO_VFO: case RIG_VFO_A: vfo_function = '0'; break; @@ -717,7 +719,66 @@ int kenwood_set_vfo(RIG *rig, vfo_t vfo) } -/* FR FT +/* CB + * Sets the operating VFO, does not set split + * VFO, but leaves it unchanged if in split VFO mode. + * + */ +int kenwood_set_vfo_main_sub(RIG *rig, vfo_t vfo) +{ + rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__); + + if (!rig) + return -RIG_EINVAL; + + char cmdbuf[6]; + char vfo_function; + + switch (vfo) { + case RIG_VFO_MAIN: + vfo_function = '0'; + break; + + case RIG_VFO_SUB: + vfo_function = '1'; + break; + + case RIG_VFO_CURR: + return RIG_OK; + + default: + rig_debug(RIG_DEBUG_ERR, "%s: unsupported VFO %d\n", __func__, vfo); + return -RIG_EINVAL; + } + + sprintf(cmdbuf, "CB%c", vfo_function); + return kenwood_transaction(rig, cmdbuf, NULL, 0); +} + + +/* CB + * Gets the operating VFO + * + */ +int kenwood_get_vfo_main_sub(RIG *rig, vfo_t * vfo) +{ + char buf[4]; + int rc; + + rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__); + + if (!rig || !vfo) + return -RIG_EINVAL; + + if (RIG_OK == (rc = kenwood_safe_transaction(rig, "CB", buf, sizeof (buf), 3))) + { + *vfo = buf[2] == '1' ? RIG_VFO_SUB : RIG_VFO_MAIN; + } + return rc; +} + + +/* FR FT TB * Sets the split RX/TX VFO or M.CH mode of the transceiver. * */ @@ -733,9 +794,14 @@ int kenwood_set_split_vfo(RIG *rig, vfo_t vfo, split_t split, vfo_t txvfo) int retval; unsigned char vfo_function; + if (RIG_MODEL_TS990S == rig->caps->rig_model) + { + sprintf(cmdbuf, "TB%c", RIG_SPLIT_ON == split ? '1' : '0'); + return kenwood_transaction(rig, cmdbuf, NULL, 0); + } + if(vfo != RIG_VFO_CURR) { switch (vfo) { - case RIG_VFO_VFO: case RIG_VFO_A: vfo_function = '0'; break; case RIG_VFO_B: vfo_function = '1'; break; case RIG_VFO_MEM: vfo_function = '2'; break; @@ -810,7 +876,7 @@ int kenwood_set_split(RIG *rig, vfo_t vfo, split_t split, vfo_t txvfo) } -/* IF +/* IF TB * Gets split VFO status from kenwood_get_if() * */ @@ -824,6 +890,25 @@ int kenwood_get_split_vfo_if(RIG *rig, vfo_t rxvfo, split_t *split, vfo_t *txvfo struct kenwood_priv_data *priv = rig->state.priv; int retval; + if (RIG_MODEL_TS990S == rig->caps->rig_model) + { + char buf[4]; + if (RIG_OK == (retval = kenwood_safe_transaction (rig, "TB", buf, sizeof (buf), 3))) + { + if ('1' == buf[2]) + { + *split = RIG_SPLIT_ON; + *txvfo = RIG_VFO_SUB; + } + else + { + *split = RIG_SPLIT_OFF; + *txvfo = RIG_VFO_MAIN; + } + } + return retval; + } + retval = kenwood_get_if(rig); if (retval != RIG_OK) return retval; @@ -935,9 +1020,17 @@ int kenwood_set_freq(RIG *rig, vfo_t vfo, freq_t freq) tvfo = (vfo==RIG_VFO_CURR || vfo==RIG_VFO_VFO) ? rig->state.current_vfo : vfo; switch (tvfo) { - case RIG_VFO_A: vfo_letter = 'A'; break; - case RIG_VFO_B: vfo_letter = 'B'; break; - case RIG_VFO_C: vfo_letter = 'C'; break; + case RIG_VFO_A: + case RIG_VFO_MAIN: + vfo_letter = 'A'; + break; + case RIG_VFO_B: + case RIG_VFO_SUB: + vfo_letter = 'B'; + break; + case RIG_VFO_C: + vfo_letter = 'C'; + break; default: rig_debug(RIG_DEBUG_ERR, "%s: unsupported VFO %d\n", __func__, vfo); return -RIG_EINVAL; @@ -965,20 +1058,20 @@ int kenwood_set_freq(RIG *rig, vfo_t vfo, freq_t freq) err = kenwood_get_if(rig); if (RIG_OK != err) { - return err; + return err; } if ('1' == priv->info[32] && priv->info[30] != ('A' == vfo_letter ? '0' : '1')) { - /* split mode and setting "back" VFO */ + /* split mode and setting "back" VFO */ - /* set other VFO to whatever it is at currently */ - err = kenwood_safe_transaction (rig, 'A' == vfo_letter ? "FB" : "FA", freqbuf, 16, 13); - if (RIG_OK != err) - { - return err; - } - err = kenwood_transaction (rig, freqbuf, NULL, 0); + /* set other VFO to whatever it is at currently */ + err = kenwood_safe_transaction (rig, 'A' == vfo_letter ? "FB" : "FA", freqbuf, 16, 13); + if (RIG_OK != err) + { + return err; + } + err = kenwood_transaction (rig, freqbuf, NULL, 0); } } @@ -1032,9 +1125,17 @@ int kenwood_get_freq(RIG *rig, vfo_t vfo, freq_t *freq) } switch (tvfo) { - case RIG_VFO_A: vfo_letter = 'A'; break; - case RIG_VFO_B: vfo_letter = 'B'; break; - case RIG_VFO_C: vfo_letter = 'C'; break; + case RIG_VFO_A: + case RIG_VFO_MAIN: + vfo_letter = 'A'; + break; + case RIG_VFO_B: + case RIG_VFO_SUB: + vfo_letter = 'B'; + break; + case RIG_VFO_C: + vfo_letter = 'C'; + break; default: rig_debug(RIG_DEBUG_ERR, "%s: unsupported VFO %d\n", __func__, vfo); @@ -1133,7 +1234,14 @@ int kenwood_scan(RIG *rig, vfo_t vfo, scan_t scan, int ch) if (!rig) return -RIG_EINVAL; - return kenwood_transaction(rig, scan == RIG_SCAN_STOP ? "SC0" : "SC1", NULL, 0); + if (RIG_MODEL_TS990S == rig->caps->rig_model) + { + return kenwood_transaction(rig, scan == RIG_SCAN_STOP ? "SC00" : "SC01", NULL, 0); + } + else + { + return kenwood_transaction(rig, scan == RIG_SCAN_STOP ? "SC0" : "SC1", NULL, 0); + } } /* @@ -1193,19 +1301,19 @@ int kenwood_set_mode(RIG *rig, vfo_t vfo, rmode_t mode, pbwidth_t width) switch (mode) { case RIG_MODE_PKTUSB: - data_mode = '1'; - mode = RIG_MODE_USB; - break; + data_mode = '1'; + mode = RIG_MODE_USB; + break; case RIG_MODE_PKTLSB: - data_mode = '1'; - mode = RIG_MODE_LSB; - break; + data_mode = '1'; + mode = RIG_MODE_LSB; + break; case RIG_MODE_PKTFM: - data_mode = '1'; - mode = RIG_MODE_FM; - break; + data_mode = '1'; + mode = RIG_MODE_FM; + break; default: break; } @@ -1214,11 +1322,50 @@ int kenwood_set_mode(RIG *rig, vfo_t vfo, rmode_t mode, pbwidth_t width) kmode = rmode2kenwood(mode, caps->mode_table); if (kmode < 0 ) { rig_debug(RIG_DEBUG_WARN, "%s: unsupported mode '%s'\n", - __func__, rig_strrmode(mode)); + __func__, rig_strrmode(mode)); return -RIG_EINVAL; } - sprintf(buf, "MD%c", '0' + kmode); + if (RIG_MODEL_TS990S == rig->caps->rig_model) + { + char c; + char v; + + if (RIG_VFO_CURR == vfo || RIG_VFO_VFO == vfo) + { + if (RIG_OK != (err = kenwood_get_vfo_main_sub (rig, &vfo))) + { + return err; + } + } + switch (vfo) + { + case RIG_VFO_MAIN: + v = '0'; + break; + + case RIG_VFO_SUB: + v = '1'; + break; + + default: + rig_debug(RIG_DEBUG_ERR, "%s: unsupported VFO %d\n", __func__, vfo); + return -RIG_EINVAL; + } + if (kmode <= 9) + { + c = '0' + kmode; + } + else + { + c = 'A' + kmode - 10; + } + sprintf(buf, "OM%c%c", v, c); + } + else + { + sprintf(buf, "MD%c", '0' + kmode); + } err = kenwood_transaction(rig, buf, NULL, 0); if (err != RIG_OK) return err; @@ -1231,17 +1378,17 @@ int kenwood_set_mode(RIG *rig, vfo_t vfo, rmode_t mode, pbwidth_t width) int retval = kenwood_transaction (rig, buf, NULL, 0); if (RIG_OK != retval) { - return retval; + return retval; } } if (rig->caps->rig_model == RIG_MODEL_TS450S - || rig->caps->rig_model == RIG_MODEL_TS690S - || rig->caps->rig_model == RIG_MODEL_TS850 - || rig->caps->rig_model == RIG_MODEL_TS950SDX) { + || rig->caps->rig_model == RIG_MODEL_TS690S + || rig->caps->rig_model == RIG_MODEL_TS850 + || rig->caps->rig_model == RIG_MODEL_TS950SDX) { if (RIG_PASSBAND_NORMAL == width) - width = rig_passband_normal(rig, mode); + width = rig_passband_normal(rig, mode); err = kenwood_set_filter(rig, width); /* non fatal */ } @@ -1306,14 +1453,53 @@ int kenwood_get_mode(RIG *rig, vfo_t vfo, rmode_t *mode, pbwidth_t *width) return -RIG_EINVAL; struct kenwood_priv_caps *caps = kenwood_caps(rig); + char cmd[4]; char modebuf[10]; + int offs; int retval; - retval = kenwood_safe_transaction(rig, "MD", modebuf, 6, 3); + if (RIG_MODEL_TS990S == rig->caps->rig_model) + { + char c; + + if (RIG_VFO_CURR == vfo || RIG_VFO_VFO == vfo) + { + if (RIG_OK != (retval = kenwood_get_vfo_main_sub (rig, &vfo))) + { + return retval; + } + } + switch (vfo) + { + case RIG_VFO_MAIN: c = '0'; break; + case RIG_VFO_SUB: c = '1'; break; + default: + rig_debug(RIG_DEBUG_ERR, "%s: unsupported VFO %d\n", __func__, vfo); + return -RIG_EINVAL; + } + sprintf(cmd, "OM%c", c); + offs = 3; + } + else + { + sprintf(cmd, "MD"); + offs = 2; + } + + retval = kenwood_safe_transaction(rig, cmd, modebuf, 6, offs + 1); if (retval != RIG_OK) return retval; - *mode = kenwood2rmode(modebuf[2] - '0', caps->mode_table); + int kmode; + if (modebuf[offs] <= '9') + { + kmode = modebuf[offs] - '0'; + } + else + { + kmode = modebuf[offs] - 'A' + 10; + } + *mode = kenwood2rmode(kmode, caps->mode_table); if (RIG_MODEL_TS590S == rig->caps->rig_model || RIG_MODEL_TS590SG == rig->caps->rig_model) @@ -1322,17 +1508,17 @@ int kenwood_get_mode(RIG *rig, vfo_t vfo, rmode_t *mode, pbwidth_t *width) retval = kenwood_safe_transaction (rig, "DA", modebuf, 6, 3); if (retval != RIG_OK) { - return retval; + return retval; } if ('1' == modebuf[2]) { - switch (*mode) - { - case RIG_MODE_USB: *mode = RIG_MODE_PKTUSB; break; - case RIG_MODE_LSB: *mode = RIG_MODE_PKTLSB; break; - case RIG_MODE_FM: *mode = RIG_MODE_PKTFM; break; - default: break; - } + switch (*mode) + { + case RIG_MODE_USB: *mode = RIG_MODE_PKTUSB; break; + case RIG_MODE_LSB: *mode = RIG_MODE_PKTLSB; break; + case RIG_MODE_FM: *mode = RIG_MODE_PKTFM; break; + default: break; + } } } @@ -1480,7 +1666,7 @@ int kenwood_set_level(RIG *rig, vfo_t vfo, setting_t level, value_t val) return kenwood_transaction(rig, levelbuf, NULL, 0); } -int get_kenwood_level(RIG *rig, const char *cmd, int cmd_len, float *f) +int get_kenwood_level(RIG *rig, const char *cmd, float *f) { rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__); @@ -1490,15 +1676,15 @@ int get_kenwood_level(RIG *rig, const char *cmd, int cmd_len, float *f) char lvlbuf[10]; int retval; int lvl; + int len = strlen (cmd); - retval = kenwood_safe_transaction(rig, cmd, lvlbuf, 10, 5); + retval = kenwood_safe_transaction(rig, cmd, lvlbuf, 10, len + 3); if (retval != RIG_OK) return retval; /* 000..255 */ - sscanf(lvlbuf+2, "%d", &lvl); - *f = (float)lvl/255.0; - + sscanf(lvlbuf + len, "%d", &lvl); + *f = lvl / 255.0; return RIG_OK; }; @@ -1593,22 +1779,22 @@ int kenwood_get_level(RIG *rig, vfo_t vfo, setting_t level, value_t *val) break; case RIG_LEVEL_RFPOWER: - return get_kenwood_level(rig, "PC", 3, &val->f); + return get_kenwood_level(rig, "PC", &val->f); case RIG_LEVEL_AF: - return get_kenwood_level(rig, "AG", 3, &val->f); + return get_kenwood_level(rig, "AG", &val->f); case RIG_LEVEL_RF: - return get_kenwood_level(rig, "RG", 3, &val->f); + return get_kenwood_level(rig, "RG", &val->f); case RIG_LEVEL_SQL: - return get_kenwood_level(rig, "SQ", 3, &val->f); + return get_kenwood_level(rig, "SQ", &val->f); case RIG_LEVEL_MICGAIN: - return get_kenwood_level(rig, "MG", 3, &val->f); + return get_kenwood_level(rig, "MG", &val->f); case RIG_LEVEL_AGC: - ret = get_kenwood_level(rig, "GT", 3, &val->f); + ret = get_kenwood_level(rig, "GT", &val->f); agclevel = 255 * val->f; if (agclevel == 0) val->i = 0; else if (agclevel < 85) val->i = 1; @@ -1881,7 +2067,32 @@ int kenwood_set_ctcss_tone_tn(RIG *rig, vfo_t vfo, tone_t tone) if (tone != caps->ctcss_list[i]) return -RIG_EINVAL; - sprintf(buf, "TN%02d", i + 1); + if (RIG_MODEL_TS990S == rig->caps->rig_model) + { + char c; + + if (RIG_VFO_CURR == vfo || RIG_VFO_VFO == vfo) + { + int err; + if (RIG_OK != (err = kenwood_get_vfo_main_sub (rig, &vfo))) + { + return err; + } + } + switch (vfo) + { + case RIG_VFO_MAIN: c = '0'; break; + case RIG_VFO_SUB: c = '1'; break; + default: + rig_debug(RIG_DEBUG_ERR, "%s: unsupported VFO %d\n", __func__, vfo); + return -RIG_EINVAL; + } + sprintf(buf, "TN%c%02d", c, i + 1); + } + else + { + sprintf(buf, "TN%02d", i + 1); + } return kenwood_transaction(rig, buf, NULL, 0); } @@ -1905,12 +2116,40 @@ int kenwood_get_ctcss_tone(RIG *rig, vfo_t vfo, tone_t *tone) caps = rig->caps; - retval = kenwood_get_if(rig); + if (RIG_MODEL_TS990S == caps->rig_model) + { + char cmd[4]; + char buf[6]; + char c; + + if (RIG_VFO_CURR == vfo || RIG_VFO_VFO == vfo) + { + if (RIG_OK != (retval = kenwood_get_vfo_main_sub (rig, &vfo))) + { + return retval; + } + } + switch (vfo) + { + case RIG_VFO_MAIN: c = '0'; break; + case RIG_VFO_SUB: c = '1'; break; + default: + rig_debug(RIG_DEBUG_ERR, "%s: unsupported VFO %d\n", __func__, vfo); + return -RIG_EINVAL; + } + sprintf(cmd, "TN%c", c); + retval = kenwood_safe_transaction (rig, cmd, buf, sizeof (buf), 5); + memcpy (tonebuf, &buf[3], 2); + } + else + { + retval = kenwood_get_if(rig); + memcpy(tonebuf, &priv->info[34], 2); + } + if (retval != RIG_OK) return retval; - memcpy(tonebuf, &priv->info[34], 2); - tonebuf[2] = '\0'; tone_idx = atoi(tonebuf); @@ -1952,8 +2191,32 @@ int kenwood_set_ctcss_sql(RIG *rig, vfo_t vfo, tone_t tone) if (tone != caps->ctcss_list[i]) return -RIG_EINVAL; - sprintf(buf, "CN%02d", i + 1); + if (RIG_MODEL_TS990S == rig->caps->rig_model) + { + char c; + if (RIG_VFO_CURR == vfo || RIG_VFO_VFO == vfo) + { + int err; + if (RIG_OK != (err = kenwood_get_vfo_main_sub (rig, &vfo))) + { + return err; + } + } + switch (vfo) + { + case RIG_VFO_MAIN: c = '0'; break; + case RIG_VFO_SUB: c = '1'; break; + default: + rig_debug(RIG_DEBUG_ERR, "%s: unsupported VFO %d\n", __func__, vfo); + return -RIG_EINVAL; + } + sprintf(buf, "CN%c%02d", c, i + 1); + } + else + { + sprintf(buf, "CN%02d", i + 1); + } return kenwood_transaction(rig, buf, NULL, 0); } @@ -1965,17 +2228,47 @@ int kenwood_get_ctcss_sql(RIG *rig, vfo_t vfo, tone_t *tone) return -RIG_EINVAL; const struct rig_caps *caps; + char cmd[3]; char tonebuf[6]; + int offs; int i, retval; unsigned int tone_idx; caps = rig->caps; - retval = kenwood_safe_transaction(rig, "CT", tonebuf, 6, 4); + if (RIG_MODEL_TS990S == rig->caps->rig_model) + { + char c; + + if (RIG_VFO_CURR == vfo || RIG_VFO_VFO == vfo) + { + if (RIG_OK != (retval = kenwood_get_vfo_main_sub (rig, &vfo))) + { + return retval; + } + } + switch (vfo) + { + case RIG_VFO_MAIN: c = '0'; break; + case RIG_VFO_SUB: c = '1'; break; + default: + rig_debug(RIG_DEBUG_ERR, "%s: unsupported VFO %d\n", __func__, vfo); + return -RIG_EINVAL; + } + sprintf(cmd, "CN%c", c); + offs = 3; + } + else + { + sprintf(cmd, "CT"); + offs = 2; + } + + retval = kenwood_safe_transaction(rig, cmd, tonebuf, 6, offs + 2); if (retval != RIG_OK) return retval; - tone_idx = atoi(tonebuf+2); + tone_idx = atoi(tonebuf + offs); if (tone_idx == 0) { rig_debug(RIG_DEBUG_ERR, "%s: CTCSS is zero (%s)\n", @@ -2007,26 +2300,46 @@ int kenwood_set_ant(RIG * rig, vfo_t vfo, ant_t ant) if (!rig) return -RIG_EINVAL; - const char *cmd; + char cmd[8]; + char a; switch (ant) { - case RIG_ANT_1: - cmd = "AN1"; - break; - case RIG_ANT_2: - cmd = "AN2"; - break; - case RIG_ANT_3: - cmd = "AN3"; - break; - case RIG_ANT_4: - cmd = "AN4"; - break; + case RIG_ANT_1: a = '1'; break; + case RIG_ANT_2: a = '2'; break; + case RIG_ANT_3: a = '3'; break; + case RIG_ANT_4: a = '4'; break; default: return -RIG_EINVAL; } - return kenwood_simple_transaction(rig, cmd, 4); + if (RIG_MODEL_TS990S == rig->caps->rig_model) + { + char c; + + if (RIG_VFO_CURR == vfo || RIG_VFO_VFO == vfo) + { + int err; + if (RIG_OK != (err = kenwood_get_vfo_main_sub (rig, &vfo))) + { + return err; + } + } + switch (vfo) + { + case RIG_VFO_MAIN: c = '0'; break; + case RIG_VFO_SUB: c = '1'; break; + default: + rig_debug(RIG_DEBUG_ERR, "%s: unsupported VFO %d\n", __func__, vfo); + return -RIG_EINVAL; + } + sprintf (cmd, "AN0%c%c99", c, a); + } + else + { + sprintf (cmd, "AN%c", a); + } + + return kenwood_transaction(rig, cmd, NULL, 0); } int kenwood_set_ant_no_ack(RIG * rig, vfo_t vfo, ant_t ant) @@ -2068,17 +2381,27 @@ int kenwood_get_ant (RIG *rig, vfo_t vfo, ant_t *ant) if (!rig || !ant) return -RIG_EINVAL; - char ackbuf[6]; + char ackbuf[8]; + int offs; int retval; - retval = kenwood_safe_transaction(rig, "AN", ackbuf, 6, 3); + if (RIG_MODEL_TS990S == rig->caps->rig_model) + { + retval = kenwood_safe_transaction(rig, "AN0", ackbuf, sizeof (ackbuf), 7); + offs = 4; + } + else + { + retval = kenwood_safe_transaction(rig, "AN", ackbuf, sizeof (ackbuf), 3); + offs = 2; + } if (retval != RIG_OK) return retval; - if (ackbuf[2] < '1' || ackbuf[2] > '9') + if (ackbuf[offs] < '1' || ackbuf[offs] > '9') return -RIG_EPROTO; - *ant = RIG_ANT_N(ackbuf[2]-'1'); + *ant = RIG_ANT_N(ackbuf[offs]-'1'); /* XXX check that the returned antenna is valid for the current rig */ @@ -2165,7 +2488,12 @@ int kenwood_get_dcd(RIG *rig, vfo_t vfo, dcd_t *dcd) if (retval != RIG_OK) return retval; - *dcd = (busybuf[2] == '1') ? RIG_DCD_ON : RIG_DCD_OFF; + int offs = 2; + if (RIG_MODEL_TS990S == rig->caps->rig_model && RIG_VFO_SUB == vfo) + { + offs = 3; + } + *dcd = (busybuf[offs] == '1') ? RIG_DCD_ON : RIG_DCD_OFF; return RIG_OK; } @@ -2180,8 +2508,16 @@ int kenwood_set_trn(RIG *rig, int trn) if (!rig) return -RIG_EINVAL; - return kenwood_simple_transaction(rig, - (trn == RIG_TRN_RIG) ? "AI1" : "AI0", 0); + if (RIG_MODEL_TS990S == rig->caps->rig_model) + { + return kenwood_simple_transaction(rig, + (trn == RIG_TRN_RIG) ? "AI2" : "AI0", 0); + } + else + { + return kenwood_simple_transaction(rig, + (trn == RIG_TRN_RIG) ? "AI1" : "AI0", 0); + } } /* @@ -2255,21 +2591,31 @@ int kenwood_reset(RIG *rig, reset_t reset) char rstbuf[6]; char rst; - switch(reset) { - case RIG_RESET_VFO: - rst = '1'; - break; - - case RIG_RESET_MASTER: - rst = '2'; - break; - - default: - rig_debug(RIG_DEBUG_ERR, "%s: unsupported reset %d\n", - __func__, reset); - return -RIG_EINVAL; + if (RIG_MODEL_TS990S == rig->caps->rig_model) + { + switch (reset) + { + case RIG_RESET_SOFT: rst = '4'; break; + case RIG_RESET_VFO: rst = '3'; break; + case RIG_RESET_MCALL: rst = '2'; break; + case RIG_RESET_MASTER: rst = '5'; break; + default: + rig_debug(RIG_DEBUG_ERR, "%s: unsupported reset %d\n", + __func__, reset); + return -RIG_EINVAL; + } + } + else + { + switch(reset) { + case RIG_RESET_VFO: rst = '1'; break; + case RIG_RESET_MASTER: rst = '2'; break; + default: + rig_debug(RIG_DEBUG_ERR, "%s: unsupported reset %d\n", + __func__, reset); + return -RIG_EINVAL; + } } - sprintf(rstbuf, "SR%c", rst); /* this command has no answer */ @@ -2360,14 +2706,39 @@ int kenwood_set_mem(RIG *rig, vfo_t vfo, int ch) if (!rig) return -RIG_EINVAL; - char buf[8]; - /* - * "MCbmm;" - * where b is the bank number, mm the memory number. - * b can be a space - */ - sprintf(buf, "MC %02d", ch); + char buf[7]; + if (RIG_MODEL_TS990S == rig->caps->rig_model) + { + char c; + + if (RIG_VFO_CURR == vfo || RIG_VFO_VFO == vfo) + { + int err; + if (RIG_OK != (err = kenwood_get_vfo_main_sub (rig, &vfo))) + { + return err; + } + } + switch (vfo) + { + case RIG_VFO_MAIN: c = '0'; break; + case RIG_VFO_SUB: c = '1'; break; + default: + rig_debug(RIG_DEBUG_ERR, "%s: unsupported VFO %d\n", __func__, vfo); + return -RIG_EINVAL; + } + sprintf (buf, "MN%c%03d", c, ch); + } + else + { + /* + * "MCbmm;" + * where b is the bank number, mm the memory number. + * b can be a space + */ + sprintf(buf, "MC %02d", ch); + } return kenwood_transaction(rig, buf, NULL, 0); } @@ -2381,20 +2752,48 @@ int kenwood_get_mem(RIG *rig, vfo_t vfo, int *ch) if (!rig || !ch) return -RIG_EINVAL; + char cmd[4]; char membuf[10]; + int offs; int retval; - /* - * "MCbmm;" - * where b is the bank number, mm the memory number. - * b can be a space - */ + if (RIG_MODEL_TS990S == rig->caps->rig_model) + { + char c; - retval = kenwood_safe_transaction(rig, "MC", membuf, 10, 5); + if (RIG_VFO_CURR == vfo || RIG_VFO_VFO == vfo) + { + if (RIG_OK != (retval = kenwood_get_vfo_main_sub (rig, &vfo))) + { + return retval; + } + } + switch (vfo) + { + case RIG_VFO_MAIN: c = '0'; break; + case RIG_VFO_SUB: c = '1'; break; + default: + rig_debug(RIG_DEBUG_ERR, "%s: unsupported VFO %d\n", __func__, vfo); + return -RIG_EINVAL; + } + sprintf (cmd, "MN%c", c); + offs = 3; + } + else + { + /* + * "MCbmm;" + * where b is the bank number, mm the memory number. + * b can be a space + */ + sprintf (cmd, "MC"); + offs = 2; + } + retval = kenwood_safe_transaction(rig, cmd, membuf, sizeof (membuf), 3 + offs); if (retval != RIG_OK) return retval; - *ch = atoi(membuf+2); + *ch = atoi(membuf + offs); return RIG_OK; } @@ -2839,6 +3238,7 @@ DECLARE_INITRIG_BACKEND(kenwood) rig_register(&tmd710_caps); rig_register(&ts590_caps); + rig_register(&ts990s_caps); rig_register(&ts590sg_caps); rig_register(&ts480_caps); rig_register(&thf6a_caps); diff --git a/kenwood/kenwood.h b/kenwood/kenwood.h index 213a51f7f..436cc7664 100644 --- a/kenwood/kenwood.h +++ b/kenwood/kenwood.h @@ -32,7 +32,7 @@ #define EOM_KEN ';' #define EOM_TH '\r' -#define KENWOOD_MODE_TABLE_MAX 10 +#define KENWOOD_MODE_TABLE_MAX 24 #define KENWOOD_MAX_BUF_LEN 50 /* max answer len, arbitrary */ @@ -100,7 +100,9 @@ int kenwood_cleanup(RIG *rig); int kenwood_open(RIG *rig); int kenwood_set_vfo(RIG *rig, vfo_t vfo); +int kenwood_set_vfo_main_sub(RIG *rig, vfo_t vfo); int kenwood_get_vfo_if(RIG *rig, vfo_t *vfo); +int kenwood_get_vfo_main_sub(RIG *rig, vfo_t *vfo); int kenwood_set_split(RIG *rig, vfo_t vfo , split_t split, vfo_t txvfo); int kenwood_set_split_vfo(RIG *rig, vfo_t vfo , split_t split, vfo_t txvfo); int kenwood_get_split_vfo_if(RIG *rig, vfo_t rxvfo, split_t *split, vfo_t *txvfo); @@ -151,7 +153,7 @@ int kenwood_set_trn(RIG *rig, int trn); int kenwood_get_trn(RIG *rig, int *trn); /* only use if returned string has length 6, e.g. 'SQ011;' */ -int get_kenwood_level(RIG *rig, const char *cmd, int cmd_len, float *f); +int get_kenwood_level(RIG *rig, const char *cmd, float *f); int get_kenwood_func(RIG *rig, const char *cmd, int *status); extern const struct rig_caps ts950sdx_caps; diff --git a/kenwood/ts2000.c b/kenwood/ts2000.c index 2192b6ac7..8e02f1495 100644 --- a/kenwood/ts2000.c +++ b/kenwood/ts2000.c @@ -854,7 +854,7 @@ int ts2000_get_level(RIG *rig, vfo_t vfo, setting_t level, value_t *val) case RIG_LEVEL_AGC: /* FIX ME: ts2000 returns 0 -20 for AGC */ - ret = get_kenwood_level(rig, "GT", 2, &val->f); + ret = get_kenwood_level(rig, "GT", &val->f); agclevel = 255.0 * val->f; if (agclevel == 0) val->i = 0; else if (agclevel < 85) val->i = 1; diff --git a/kenwood/ts870s.c b/kenwood/ts870s.c index 6b880dad4..3da531b02 100644 --- a/kenwood/ts870s.c +++ b/kenwood/ts870s.c @@ -360,19 +360,19 @@ static int ts870s_get_level(RIG *rig, vfo_t vfo, setting_t level, value_t *val) case RIG_LEVEL_AF: - return get_kenwood_level(rig, "AG", 2, &val->f); + return get_kenwood_level(rig, "AG", &val->f); case RIG_LEVEL_RF: - return get_kenwood_level(rig, "RG", 2, &val->f); + return get_kenwood_level(rig, "RG", &val->f); case RIG_LEVEL_SQL: - return get_kenwood_level(rig, "SQ", 2, &val->f); + return get_kenwood_level(rig, "SQ", &val->f); case RIG_LEVEL_MICGAIN: - return get_kenwood_level(rig, "MG", 2, &val->f); + return get_kenwood_level(rig, "MG", &val->f); case RIG_LEVEL_AGC: - ret = get_kenwood_level(rig, "GT", 2, &val->f); + ret = get_kenwood_level(rig, "GT", &val->f); agclevel = 255 * val->f; if (agclevel == 0) val->i = 0; else if (agclevel < 85) val->i = 1; diff --git a/kenwood/ts990s.c b/kenwood/ts990s.c new file mode 100644 index 000000000..96fa7144e --- /dev/null +++ b/kenwood/ts990s.c @@ -0,0 +1,631 @@ +/* + * Hamlib Kenwood backend - TS990s description + * Copyright (c) 2000-2011 by Stephane Fillod + * Copyright (c) 2015 modified from ts2000.c by Bill Somerville G4WJS + * + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +#include +#include "kenwood.h" +#include "ts990s.h" + +#define TS990S_AM_MODES RIG_MODE_AM +#define TS990S_FM_MODES (RIG_MODE_FM|RIG_MODE_FMN) +#define TS990S_OTHER_MODES (RIG_MODE_CW|RIG_MODE_CWR|RIG_MODE_SSB|RIG_MODE_FM|RIG_MODE_RTTY|RIG_MODE_RTTYR|RIG_MODE_PKTUSB|RIG_MODE_PKTLSB) +#define TS990S_HP_MODES (TS990S_OTHER_MODES|TS990S_FM_MODES) +#define TS990S_ALL_MODES (TS990S_OTHER_MODES|TS990S_AM_MODES|TS990S_FM_MODES) + +#define TS990S_VFOS (RIG_VFO_MAIN|RIG_VFO_SUB) + +#define TS2000_FUNC_ALL (RIG_FUNC_TONE|RIG_FUNC_TSQL|RIG_FUNC_BC|RIG_FUNC_NB|RIG_FUNC_NR|RIG_FUNC_ANF|RIG_FUNC_COMP) + +#define TS2000_LEVEL_ALL (RIG_LEVEL_PREAMP|RIG_LEVEL_ATT|RIG_LEVEL_VOX|RIG_LEVEL_AF|RIG_LEVEL_RF|RIG_LEVEL_SQL|RIG_LEVEL_CWPITCH|RIG_LEVEL_RFPOWER|RIG_LEVEL_MICGAIN|RIG_LEVEL_KEYSPD|RIG_LEVEL_COMP|RIG_LEVEL_AGC|RIG_LEVEL_BKINDL|RIG_LEVEL_METER|RIG_LEVEL_VOXGAIN|RIG_LEVEL_ANTIVOX|RIG_LEVEL_RAWSTR|RIG_LEVEL_STRENGTH) + +#define TS990S_VFO_OP (RIG_OP_BAND_UP|RIG_OP_BAND_DOWN) +#define TS990S_SCAN_OP (RIG_SCAN_VFO) +#define TS990S_ANTS (RIG_ANT_1|RIG_ANT_2|RIG_ANT_3|RIG_ANT_4) + +#define TS990S_STR_CAL {9, {\ + {0x00, -54},\ + {0x03, -48},\ + {0x06, -36},\ + {0x09, -24},\ + {0x0C, -12},\ + {0x0F, 0},\ + {0x14, 20},\ + {0x19, 40},\ + {0x1E, 60}}\ + } + +/* memory capabilities */ +#define TS990S_MEM_CAP { \ + .freq = 1, \ + .mode = 1, \ + .tx_freq=1, \ + .tx_mode=1, \ + .split=1, \ + .rptr_shift=1, \ + .rptr_offs=1, \ + .funcs=RIG_FUNC_REV|RIG_FUNC_TONE|RIG_FUNC_TSQL,\ + .tuning_step=1, \ + .ctcss_tone=1, \ + .ctcss_sql=1, \ + .scan_group=1, \ + .flags=1, \ + .channel_desc=1 \ +} + + +/* prototypes */ +static int ts990s_get_level(RIG *rig, vfo_t vfo, setting_t level, value_t *val); + +static rmode_t ts990s_mode_table[KENWOOD_MODE_TABLE_MAX] = + { + [0] = RIG_MODE_NONE, + [1] = RIG_MODE_LSB, + [2] = RIG_MODE_USB, + [3] = RIG_MODE_CW, + [4] = RIG_MODE_FM, + [5] = RIG_MODE_AM, + [6] = RIG_MODE_RTTY, + [7] = RIG_MODE_CWR, + [8] = RIG_MODE_NONE, + [9] = RIG_MODE_RTTYR, + [10] = RIG_MODE_NONE, /* A */ + [11] = RIG_MODE_NONE, /* B */ + [12] = RIG_MODE_PKTLSB, /* C */ + [13] = RIG_MODE_PKTUSB, /* D */ + [14] = RIG_MODE_PKTFM, /* E */ + [15] = RIG_MODE_NONE, /* F */ + [16] = RIG_MODE_PKTLSB, /* G */ + [17] = RIG_MODE_PKTUSB, /* H */ + [18] = RIG_MODE_PKTFM, /* I */ + [19] = RIG_MODE_NONE, /* J */ + [20] = RIG_MODE_PKTLSB, /* K */ + [21] = RIG_MODE_PKTUSB, /* L */ + [22] = RIG_MODE_PKTFM, /* M */ + [23] = RIG_MODE_NONE, /* N */ + }; + +static struct kenwood_priv_caps ts990s_priv_caps = + { + .cmdtrm = EOM_KEN, + .mode_table = ts990s_mode_table, + }; + + +/* + * ts990s rig capabilities. + * + * part of infos comes from http://www.kenwood.net/ + */ +const struct rig_caps ts990s_caps = { +.rig_model = RIG_MODEL_TS990S, +.model_name = "TS-990s", +.mfg_name = "Kenwood", +.version = BACKEND_VER ".1", +.copyright = "LGPL", +.status = RIG_STATUS_BETA, +.rig_type = RIG_TYPE_TRANSCEIVER, +.ptt_type = RIG_PTT_RIG_MICDATA, +.dcd_type = RIG_DCD_RIG, +.port_type = RIG_PORT_SERIAL, +.serial_rate_min = 4800, +.serial_rate_max = 115200, +.serial_data_bits = 8, +.serial_stop_bits = 1, +.serial_parity = RIG_PARITY_NONE, +.serial_handshake = RIG_HANDSHAKE_HARDWARE, +.write_delay = 0, +.post_write_delay = 50, /* ms */ +.timeout = 200, +.retry = 3, + +.has_get_func = TS2000_FUNC_ALL, +.has_set_func = TS2000_FUNC_ALL, +.has_get_level = TS2000_LEVEL_ALL, +.has_set_level = RIG_LEVEL_SET(TS2000_LEVEL_ALL), +.has_get_parm = RIG_PARM_NONE, +.has_set_parm = RIG_PARM_NONE, /* FIXME: parms */ +.level_gran = {}, /* FIXME: granularity */ +.parm_gran = {}, +.vfo_ops = TS990S_VFO_OP, +.scan_ops = TS990S_SCAN_OP, +.ctcss_list = kenwood42_ctcss_list, +.preamp = { 20, RIG_DBLST_END, }, +.attenuator = { 6, 12, 18, RIG_DBLST_END, }, +.max_rit = Hz(9990), +.max_xit = Hz(9990), +.targetable_vfo = RIG_TARGETABLE_FREQ|RIG_TARGETABLE_MODE, +.transceive = RIG_TRN_RIG, +.bank_qty = 0, +.chan_desc_sz = 7, + +.chan_list = { + { 0, 299, RIG_MTYPE_MEM, TS990S_MEM_CAP }, + RIG_CHAN_END, +}, + +.rx_range_list1 = { + {kHz(300),MHz(60),TS990S_ALL_MODES,-1,-1,TS990S_VFOS,TS990S_ANTS}, + RIG_FRNG_END, + }, /* rx range */ +.tx_range_list1 = { + {kHz(1830),kHz(1850),TS990S_HP_MODES,W(5),W(200),TS990S_VFOS,TS990S_ANTS}, + {kHz(1830),kHz(1850),TS990S_AM_MODES,W(5),W(50),TS990S_VFOS,TS990S_ANTS}, + {kHz(3500),kHz(3800),TS990S_HP_MODES,W(5),W(200),TS990S_VFOS,TS990S_ANTS}, + {kHz(3500),kHz(3800),TS990S_AM_MODES,W(5),W(50),TS990S_VFOS,TS990S_ANTS}, + {MHz(7),kHz(7100),TS990S_HP_MODES,W(5),W(200),TS990S_VFOS,TS990S_ANTS}, + {MHz(7),kHz(7100),TS990S_AM_MODES,W(5),W(50),TS990S_VFOS,TS990S_ANTS}, + {MHz(10.1),MHz(10.15),TS990S_HP_MODES,W(5),W(200),TS990S_VFOS,TS990S_ANTS}, + {MHz(10.1),MHz(10.15),TS990S_AM_MODES,W(5),W(50),TS990S_VFOS,TS990S_ANTS}, + {MHz(14),kHz(14350),TS990S_HP_MODES,W(5),W(200),TS990S_VFOS,TS990S_ANTS}, + {MHz(14),kHz(14350),TS990S_AM_MODES,W(5),W(50),TS990S_VFOS,TS990S_ANTS}, + {kHz(18068),kHz(18168),TS990S_HP_MODES,W(5),W(200),TS990S_VFOS,TS990S_ANTS}, + {kHz(18068),kHz(18168),TS990S_AM_MODES,W(5),W(50),TS990S_VFOS,TS990S_ANTS}, + {MHz(21),kHz(21450),TS990S_HP_MODES,W(5),W(200),TS990S_VFOS,TS990S_ANTS}, + {MHz(21),kHz(21450),TS990S_AM_MODES,W(5),W(50),TS990S_VFOS,TS990S_ANTS}, + {kHz(24890),kHz(24990),TS990S_HP_MODES,W(5),W(200),TS990S_VFOS,TS990S_ANTS}, + {kHz(24890),kHz(24990),TS990S_AM_MODES,W(5),W(50),TS990S_VFOS,TS990S_ANTS}, + {MHz(28),kHz(29700),TS990S_HP_MODES,W(5),W(200),TS990S_VFOS,TS990S_ANTS}, + {MHz(28),kHz(29700),TS990S_AM_MODES,W(5),W(50),TS990S_VFOS,TS990S_ANTS}, + {MHz(50),MHz(50.2),TS990S_HP_MODES,W(5),W(200),TS990S_VFOS,TS990S_ANTS}, + {MHz(50),MHz(50.2),TS990S_AM_MODES,W(5),W(50),TS990S_VFOS,TS990S_ANTS}, + RIG_FRNG_END, + }, /* tx range */ + +.rx_range_list2 = { + {kHz(300),MHz(60),TS990S_ALL_MODES,-1,-1,TS990S_VFOS,TS990S_ANTS}, + RIG_FRNG_END, + }, /* rx range */ +.tx_range_list2 = { + {kHz(1800),MHz(2),TS990S_HP_MODES,W(5),W(200),TS990S_VFOS,TS990S_ANTS}, + {kHz(1800),MHz(2),TS990S_AM_MODES,W(5),W(50),TS990S_VFOS,TS990S_ANTS}, + {kHz(3500),MHz(4),TS990S_HP_MODES,W(5),W(200),TS990S_VFOS,TS990S_ANTS}, + {kHz(3500),MHz(4),TS990S_AM_MODES,W(5),W(50),TS990S_VFOS,TS990S_ANTS}, + {MHz(7),kHz(7300),TS990S_HP_MODES,W(5),W(200),TS990S_VFOS,TS990S_ANTS}, + {MHz(7),kHz(7300),TS990S_AM_MODES,W(5),W(50),TS990S_VFOS,TS990S_ANTS}, + {MHz(10.1),MHz(10.15),TS990S_HP_MODES,W(5),W(200),TS990S_VFOS,TS990S_ANTS}, + {MHz(10.1),MHz(10.15),TS990S_AM_MODES,W(5),W(50),TS990S_VFOS,TS990S_ANTS}, + {MHz(14),kHz(14350),TS990S_HP_MODES,W(5),W(200),TS990S_VFOS,TS990S_ANTS}, + {MHz(14),kHz(14350),TS990S_AM_MODES,W(5),W(50),TS990S_VFOS,TS990S_ANTS}, + {kHz(18068),kHz(18168),TS990S_HP_MODES,W(5),W(200),TS990S_VFOS,TS990S_ANTS}, + {kHz(18068),kHz(18168),TS990S_AM_MODES,W(5),W(50),TS990S_VFOS,TS990S_ANTS}, + {MHz(21),kHz(21450),TS990S_HP_MODES,W(5),W(200),TS990S_VFOS,TS990S_ANTS}, + {MHz(21),kHz(21450),TS990S_AM_MODES,W(5),W(50),TS990S_VFOS,TS990S_ANTS}, + {kHz(24890),kHz(24990),TS990S_HP_MODES,W(5),W(200),TS990S_VFOS,TS990S_ANTS}, + {kHz(24890),kHz(24990),TS990S_AM_MODES,W(5),W(50),TS990S_VFOS,TS990S_ANTS}, + {MHz(28),kHz(29700),TS990S_HP_MODES,W(5),W(200),TS990S_VFOS,TS990S_ANTS}, + {MHz(28),kHz(29700),TS990S_AM_MODES,W(5),W(50),TS990S_VFOS,TS990S_ANTS}, + {MHz(50),MHz(54),TS990S_HP_MODES,W(5),W(200),TS990S_VFOS,TS990S_ANTS}, + {MHz(50),MHz(54),TS990S_AM_MODES,W(5),W(50),TS990S_VFOS,TS990S_ANTS}, + RIG_FRNG_END, + }, /* tx range */ +.tuning_steps = { + {TS990S_OTHER_MODES,1}, + {TS990S_OTHER_MODES,kHz(0.5)}, + {TS990S_OTHER_MODES,kHz(1)}, + {TS990S_OTHER_MODES,kHz(2.5)}, + {TS990S_OTHER_MODES,kHz(5)}, + {TS990S_OTHER_MODES,kHz(10)}, + {(TS990S_AM_MODES|TS990S_FM_MODES),kHz(5)}, + {(TS990S_AM_MODES|TS990S_FM_MODES),kHz(6.25)}, + {(TS990S_AM_MODES|TS990S_FM_MODES),kHz(10)}, + {(TS990S_AM_MODES|TS990S_FM_MODES),kHz(12.5)}, + {(TS990S_AM_MODES|TS990S_FM_MODES),kHz(15)}, + {(TS990S_AM_MODES|TS990S_FM_MODES),kHz(20)}, + {TS990S_ALL_MODES,MHz(1)}, + {TS990S_ALL_MODES,0}, /* any tuning step */ + RIG_TS_END, + }, + + /* mode/filter list, remember: order matters! */ +.filters = { + {RIG_MODE_SSB|TS990S_FM_MODES, kHz(2.6)}, /* default normal */ + {RIG_MODE_SSB|TS990S_FM_MODES, kHz(2.0)}, /* default narrow - + arbitrary choice */ + {RIG_MODE_SSB|TS990S_FM_MODES, kHz(3.2)}, /* default wide - + arbitrary choice */ + {RIG_MODE_SSB|TS990S_FM_MODES, kHz(4.8)}, + {RIG_MODE_SSB|TS990S_FM_MODES, kHz(3.8)}, + {RIG_MODE_SSB|TS990S_FM_MODES, kHz(2.8)}, + {RIG_MODE_SSB|TS990S_FM_MODES, kHz(2.4)}, + {RIG_MODE_SSB|TS990S_FM_MODES, kHz(1.8)}, + {RIG_MODE_SSB|TS990S_FM_MODES, kHz(1.4)}, + {RIG_MODE_SSB|TS990S_FM_MODES, kHz(1.2)}, + {RIG_MODE_SSB|TS990S_FM_MODES, kHz(1.0)}, + {RIG_MODE_SSB|TS990S_FM_MODES, kHz(0.8)}, + {RIG_MODE_CW|RIG_MODE_CWR, Hz(500)}, /* default normal */ + {RIG_MODE_CW|RIG_MODE_CWR, Hz(250)}, /* default narrow - + arbitrary choice */ + {RIG_MODE_CW|RIG_MODE_CWR, kHz(1.0)}, /* default wide - arbitrary choice */ + {RIG_MODE_CW|RIG_MODE_CWR, kHz(2.5)}, + {RIG_MODE_CW|RIG_MODE_CWR, kHz(2.0)}, + {RIG_MODE_CW|RIG_MODE_CWR, kHz(1.5)}, + {RIG_MODE_CW|RIG_MODE_CWR, Hz(600)}, + {RIG_MODE_CW|RIG_MODE_CWR, Hz(400)}, + {RIG_MODE_CW|RIG_MODE_CWR, Hz(300)}, + {RIG_MODE_CW|RIG_MODE_CWR, Hz(200)}, + {RIG_MODE_CW|RIG_MODE_CWR, Hz(150)}, + {RIG_MODE_CW|RIG_MODE_CWR, Hz(100)}, + {RIG_MODE_CW|RIG_MODE_CWR, Hz(80)}, + {RIG_MODE_CW|RIG_MODE_CWR, Hz(50)}, + {RIG_MODE_RTTY|RIG_MODE_RTTYR, Hz(500)}, /* default normal */ + {RIG_MODE_RTTY|RIG_MODE_RTTYR, Hz(250)}, /* default narrow - + arbitrary choice */ + {RIG_MODE_RTTY|RIG_MODE_RTTYR, Hz(1500)}, /* default wide - + arbitrary choice */ + {RIG_MODE_RTTY|RIG_MODE_RTTYR, Hz(1000)}, + {RIG_MODE_RTTY|RIG_MODE_RTTYR, Hz(400)}, + {RIG_MODE_RTTY|RIG_MODE_RTTYR, Hz(300)}, + {RIG_MODE_AM, kHz(5)}, /* default normal */ + {RIG_MODE_AM, kHz(2.5)}, /* default narrow - arbitrary choice */ + {RIG_MODE_AM, kHz(4)}, + {RIG_MODE_AM, kHz(3)}, + {RIG_MODE_PKTLSB|RIG_MODE_PKTUSB, kHz(2.6)}, /* default normal */ + {RIG_MODE_PKTLSB|RIG_MODE_PKTUSB, Hz(500)}, /* default narrow - + arbitrary choice */ + {RIG_MODE_PKTLSB|RIG_MODE_PKTUSB, kHz(13)}, /* default wide - + arbitrary choice */ + {RIG_MODE_PKTLSB|RIG_MODE_PKTUSB, kHz(2.8)}, + {RIG_MODE_PKTLSB|RIG_MODE_PKTUSB, kHz(2.4)}, + {RIG_MODE_PKTLSB|RIG_MODE_PKTUSB, kHz(2.2)}, + {RIG_MODE_PKTLSB|RIG_MODE_PKTUSB, kHz(2.0)}, + {RIG_MODE_PKTLSB|RIG_MODE_PKTUSB, kHz(1.5)}, + {RIG_MODE_PKTLSB|RIG_MODE_PKTUSB, kHz(1.0)}, + {RIG_MODE_PKTLSB|RIG_MODE_PKTUSB, Hz(600)}, + {RIG_MODE_PKTLSB|RIG_MODE_PKTUSB, Hz(400)}, + {RIG_MODE_PKTLSB|RIG_MODE_PKTUSB, Hz(300)}, + {RIG_MODE_PKTLSB|RIG_MODE_PKTUSB, Hz(200)}, + {RIG_MODE_PKTLSB|RIG_MODE_PKTUSB, Hz(150)}, + {RIG_MODE_PKTLSB|RIG_MODE_PKTUSB, Hz(100)}, + {RIG_MODE_PKTLSB|RIG_MODE_PKTUSB, Hz(80)}, + {RIG_MODE_PKTLSB|RIG_MODE_PKTUSB, Hz(50)}, + RIG_FLT_END, + }, + +.str_cal = TS990S_STR_CAL, + +.priv = (void *)&ts990s_priv_caps, + +.rig_init = kenwood_init, +.rig_open = kenwood_open, +.rig_cleanup = kenwood_cleanup, +.set_freq = kenwood_set_freq, +.get_freq = kenwood_get_freq, +.set_rit = kenwood_set_rit, +.get_rit = kenwood_get_rit, +.set_xit = kenwood_set_xit, +.get_xit = kenwood_get_xit, +.set_mode = kenwood_set_mode, +.get_mode = kenwood_get_mode, +.set_vfo = kenwood_set_vfo_main_sub, +.get_vfo = kenwood_get_vfo_main_sub, +.set_split_vfo = kenwood_set_split_vfo, +.get_split_vfo = kenwood_get_split_vfo_if, +.set_ctcss_tone = kenwood_set_ctcss_tone_tn, +.get_ctcss_tone = kenwood_get_ctcss_tone, +.set_ctcss_sql = kenwood_set_ctcss_sql, +.get_ctcss_sql = kenwood_get_ctcss_sql, +.get_ptt = kenwood_get_ptt, +.set_ptt = kenwood_set_ptt, +.get_dcd = kenwood_get_dcd, +.set_func = kenwood_set_func, +.get_func = kenwood_get_func, +.set_level = kenwood_set_level, +.get_level = ts990s_get_level, +.set_ant = kenwood_set_ant, +.get_ant = kenwood_get_ant, +.send_morse = kenwood_send_morse, +.vfo_op = kenwood_vfo_op, +.scan = kenwood_scan, +.set_mem = kenwood_set_mem, +.get_mem = kenwood_get_mem, +.set_trn = kenwood_set_trn, +.get_trn = kenwood_get_trn, +.set_powerstat = kenwood_set_powerstat, +.get_powerstat = kenwood_get_powerstat, +.reset = kenwood_reset, + +}; + +/* + * Function definitions below + */ + +/* + * ts2000_get_level + * Assumes rig!=NULL, val!=NULL + */ + +int ts990s_get_level(RIG *rig, vfo_t vfo, setting_t level, value_t *val) +{ + char lvlbuf[50]; + int lvl, retval = RIG_OK; + + if (RIG_VFO_CURR == vfo || RIG_VFO_VFO == vfo) + { + if (RIG_OK != (retval = kenwood_get_vfo_main_sub (rig, &vfo))) + { + return retval; + } + } + + switch (level) { + + case RIG_LEVEL_PREAMP: + retval = kenwood_safe_transaction (rig, "PA", lvlbuf, sizeof (lvlbuf), 4); + if (retval != RIG_OK) + return retval; + switch (vfo) + { + case RIG_VFO_MAIN: + val->i = '1' == lvlbuf[2] ? rig->state.preamp[0] : 0; + break; + + case RIG_VFO_SUB: + val->i = '1' == lvlbuf[3] ? rig->state.preamp[0] : 0; + break; + + default: + rig_debug(RIG_DEBUG_ERR, "%s: unsupported VFO %d\n", __func__, vfo); + return -RIG_EINVAL; + } + break; + + case RIG_LEVEL_ATT: + { + char v; + char cmd[4]; + switch (vfo) + { + case RIG_VFO_MAIN: v = '0'; break; + case RIG_VFO_SUB: v = '1'; break; + default: + rig_debug(RIG_DEBUG_ERR, "%s: unsupported VFO %d\n", __func__, vfo); + return -RIG_EINVAL; + } + sprintf (cmd, "RA%c", v); + retval = kenwood_safe_transaction (rig, cmd, lvlbuf, sizeof (lvlbuf), 4); + if (retval != RIG_OK) + return retval; + + if ('0' == lvlbuf[3]) + { + val->i = 0; + } + else + { + val->i = rig->state.attenuator[lvlbuf[3] - '1']; + } + } + break; + + case RIG_LEVEL_VOX: + retval = kenwood_safe_transaction (rig, "VD0", lvlbuf, sizeof (lvlbuf), 6); + if (retval != RIG_OK) + return retval; + sscanf(lvlbuf + 3, "%d", &lvl); + val->i = lvl * 3 / 2; /* 150ms units converted to 100ms units */ + break; + + case RIG_LEVEL_AF: + { + char v; + char cmd[4]; + switch (vfo) + { + case RIG_VFO_MAIN: v = '0'; break; + case RIG_VFO_SUB: v = '1'; break; + default: + rig_debug(RIG_DEBUG_ERR, "%s: unsupported VFO %d\n", __func__, vfo); + return -RIG_EINVAL; + } + sprintf (cmd, "AG%c", v); + retval = kenwood_safe_transaction (rig, cmd, lvlbuf, sizeof (lvlbuf), 6); + if (retval != RIG_OK) + return retval; + sscanf(lvlbuf + 3, "%d", &lvl); + val->f = lvl / 255.0; + } + break; + + case RIG_LEVEL_RF: + { + char v; + char cmd[4]; + switch (vfo) + { + case RIG_VFO_MAIN: v = '0'; break; + case RIG_VFO_SUB: v = '1'; break; + default: + rig_debug(RIG_DEBUG_ERR, "%s: unsupported VFO %d\n", __func__, vfo); + return -RIG_EINVAL; + } + sprintf (cmd, "RG%c", v); + retval = kenwood_safe_transaction (rig, cmd, lvlbuf, sizeof (lvlbuf), 6); + if (retval != RIG_OK) + return retval; + sscanf(lvlbuf + 3, "%d", &lvl); + val->f = lvl / 255.0; + } + break; + + case RIG_LEVEL_SQL: + { + char v; + char cmd[4]; + switch (vfo) + { + case RIG_VFO_MAIN: v = '0'; break; + case RIG_VFO_SUB: v = '1'; break; + default: + rig_debug(RIG_DEBUG_ERR, "%s: unsupported VFO %d\n", __func__, vfo); + return -RIG_EINVAL; + } + sprintf (cmd, "SQ%c", v); + retval = kenwood_safe_transaction (rig, cmd, lvlbuf, sizeof (lvlbuf), 6); + if (retval != RIG_OK) + return retval; + sscanf(lvlbuf + 3, "%d", &lvl); + val->f = lvl / 255.0; + } + break; + + case RIG_LEVEL_CWPITCH: + retval = kenwood_safe_transaction (rig, "PT", lvlbuf, sizeof (lvlbuf), 5); + if (retval != RIG_OK) + return retval; + sscanf(lvlbuf + 2, "%d", &lvl); + val->i = 300 + lvl * 10; + break; + + case RIG_LEVEL_RFPOWER: + retval = kenwood_safe_transaction (rig, "PC", lvlbuf, sizeof (lvlbuf), 5); + if (retval != RIG_OK) + return retval; + sscanf(lvlbuf + 2, "%d", &lvl); + val->f = lvl / 200.0; /* TODO: should we detect AM and scale? */ + break; + + case RIG_LEVEL_MICGAIN: + retval = get_kenwood_level (rig, "MG", &val->f); + if (retval != RIG_OK) + return retval; + break; + + case RIG_LEVEL_KEYSPD: + retval = kenwood_safe_transaction (rig, "KS", lvlbuf, sizeof (lvlbuf), 5); + if (retval != RIG_OK) + return retval; + sscanf(lvlbuf + 2, "%d", &lvl); + val->i = lvl; + break; + + case RIG_LEVEL_COMP: + retval = kenwood_safe_transaction (rig, "PL", lvlbuf, sizeof (lvlbuf), 8); + if (retval != RIG_OK) + return retval; + sscanf(lvlbuf + 2, "%d", &lvl); + lvl = lvl / 1000; /* report input level */ + val->f = lvl / 255.0; + break; + + case RIG_LEVEL_AGC: + { + char v; + char cmd[4]; + switch (vfo) + { + case RIG_VFO_MAIN: v = '0'; break; + case RIG_VFO_SUB: v = '1'; break; + default: + rig_debug(RIG_DEBUG_ERR, "%s: unsupported VFO %d\n", __func__, vfo); + return -RIG_EINVAL; + } + sprintf (cmd, "GC%c", v); + if (RIG_OK != (retval = kenwood_safe_transaction (rig, cmd, lvlbuf, sizeof (lvlbuf), 4))) + { + return retval; + } + switch (lvlbuf[3]) + { + case '0': val->i = RIG_AGC_OFF; break; + case '1': val->i = RIG_AGC_SLOW; break; + case '2': val->i = RIG_AGC_MEDIUM; break; + case '3': val->i = RIG_AGC_FAST; break; + } + } + break; + + case RIG_LEVEL_BKINDL: + retval = kenwood_safe_transaction (rig, "SD", lvlbuf, sizeof (lvlbuf), 6); + if (retval != RIG_OK) + return retval; + sscanf(lvlbuf + 2, "%d", &lvl); + val->i = lvl / 100; + break; + + case RIG_LEVEL_METER: + retval = kenwood_safe_transaction (rig, "RM", lvlbuf, sizeof (lvlbuf), 7); + if (retval != RIG_OK) + return retval; + switch (lvlbuf[2]) + { + case '1': val->i = RIG_METER_ALC; break; + case '2': val->i = RIG_METER_SWR; break; + case '3': val->i = RIG_METER_COMP; break; + case '4': val->i = RIG_METER_IC; break; + case '5': val->i = RIG_METER_VDD; break; + default: val->i = RIG_METER_NONE; break; + } + break; + + case RIG_LEVEL_VOXGAIN: + retval = get_kenwood_level (rig, "VG00", &val->f); + if (retval != RIG_OK) + return retval; + break; + + case RIG_LEVEL_ANTIVOX: + retval = get_kenwood_level (rig, "VG00", &val->f); + if (retval != RIG_OK) + return retval; + val->f = val->f * 255. / 20.; + break; + + case RIG_LEVEL_RAWSTR: + case RIG_LEVEL_STRENGTH: + { + char v; + char cmd[4]; + switch (vfo) + { + case RIG_VFO_MAIN: v = '0'; break; + case RIG_VFO_SUB: v = '1'; break; + default: + rig_debug(RIG_DEBUG_ERR, "%s: unsupported VFO %d\n", __func__, vfo); + return -RIG_EINVAL; + } + sprintf (cmd, "SM%c", v); + retval = kenwood_safe_transaction (rig, cmd, lvlbuf, sizeof (lvlbuf), 7); + if (retval != RIG_OK) + return retval; + /* Frontend expects: -54 = S0, 0 = S9 */ + sscanf(lvlbuf + 3, "%d", &val->i); + /* TS-990s returns values from 0 - 70 */ + /* so scale the value */ + if (level == RIG_LEVEL_STRENGTH) + val->i = (val->i * 54. / 70.) - 54; + } + break; + + default: + rig_debug(RIG_DEBUG_ERR,"Unsupported get_level %d", level); + return -RIG_EINVAL; + } + + return retval; +} diff --git a/kenwood/ts990s.h b/kenwood/ts990s.h new file mode 100644 index 000000000..9245beac7 --- /dev/null +++ b/kenwood/ts990s.h @@ -0,0 +1,29 @@ +/* + * Hamlib Kenwood backend - main header + * Copyright (c) 2015 by Bill Somerville G4WJS + * + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifndef TS990S_H__ +#define TS990S_H__ + +#include "hamlib/rig.h" + +extern const struct rig_caps ts990s_caps; + +#endif From 5861851117c4319ec8dbb97f1dc8f6ffd41b2942 Mon Sep 17 00:00:00 2001 From: Bill Somerville Date: Thu, 9 Apr 2015 17:54:28 +0100 Subject: [PATCH 2/4] Mode set is not VFO targetable on the Kenwood TS990s It is targetable for read so set as targetable and added extra code in set funnction to toggle VFOs where necessary. This is better than setting as not targetable since reads do not have to toffle VFOs. --- kenwood/kenwood.c | 57 +++++++++++++++++++++-------------------------- kenwood/ts990s.c | 2 +- 2 files changed, 26 insertions(+), 33 deletions(-) diff --git a/kenwood/kenwood.c b/kenwood/kenwood.c index b857ec5d8..e370b3318 100644 --- a/kenwood/kenwood.c +++ b/kenwood/kenwood.c @@ -1328,30 +1328,16 @@ int kenwood_set_mode(RIG *rig, vfo_t vfo, rmode_t mode, pbwidth_t width) if (RIG_MODEL_TS990S == rig->caps->rig_model) { + /* The TS990s has targetable read mode but can only set the mode + of the current VFO :( So we need to toggle the operating VFO + to set the "back" VFO mode. This is done here rather than not + setting caps.targetable_vfo to not include + RIG_TARGETABLE_MODE since the toggle is not required for + reading the mode. */ char c; - char v; - - if (RIG_VFO_CURR == vfo || RIG_VFO_VFO == vfo) - { - if (RIG_OK != (err = kenwood_get_vfo_main_sub (rig, &vfo))) - { - return err; - } - } - switch (vfo) - { - case RIG_VFO_MAIN: - v = '0'; - break; - - case RIG_VFO_SUB: - v = '1'; - break; - - default: - rig_debug(RIG_DEBUG_ERR, "%s: unsupported VFO %d\n", __func__, vfo); - return -RIG_EINVAL; - } + vfo_t curr_vfo; + err = kenwood_get_vfo_main_sub (rig, &curr_vfo); + if (err != RIG_OK) return err; if (kmode <= 9) { c = '0' + kmode; @@ -1360,26 +1346,33 @@ int kenwood_set_mode(RIG *rig, vfo_t vfo, rmode_t mode, pbwidth_t width) { c = 'A' + kmode - 10; } - sprintf(buf, "OM%c%c", v, c); + if (vfo != curr_vfo) + { + err = kenwood_set_vfo_main_sub (rig, vfo); + if (err != RIG_OK) return err; + } + sprintf(buf, "OM0%c", c); /* target vfo is ignored */ + int err = kenwood_transaction(rig, buf, NULL, 0); + if (vfo != curr_vfo) + { + int err2 = kenwood_set_vfo_main_sub (rig, curr_vfo); + if (RIG_OK == err && err2 != RIG_OK) return err2; + } } else { sprintf(buf, "MD%c", '0' + kmode); + err = kenwood_transaction(rig, buf, NULL, 0); } - err = kenwood_transaction(rig, buf, NULL, 0); - if (err != RIG_OK) - return err; + if (err != RIG_OK) return err; if (RIG_MODEL_TS590S == rig->caps->rig_model || RIG_MODEL_TS590SG == rig->caps->rig_model) { /* supports DATA sub modes - see above */ sprintf (buf, "DA%c", data_mode); - int retval = kenwood_transaction (rig, buf, NULL, 0); - if (RIG_OK != retval) - { - return retval; - } + err = kenwood_transaction (rig, buf, NULL, 0); + if (err != RIG_OK) return err; } if (rig->caps->rig_model == RIG_MODEL_TS450S diff --git a/kenwood/ts990s.c b/kenwood/ts990s.c index 96fa7144e..078b755e6 100644 --- a/kenwood/ts990s.c +++ b/kenwood/ts990s.c @@ -158,7 +158,7 @@ const struct rig_caps ts990s_caps = { .attenuator = { 6, 12, 18, RIG_DBLST_END, }, .max_rit = Hz(9990), .max_xit = Hz(9990), -.targetable_vfo = RIG_TARGETABLE_FREQ|RIG_TARGETABLE_MODE, +.targetable_vfo = RIG_TARGETABLE_FREQ | RIG_TARGETABLE_MODE, .transceive = RIG_TRN_RIG, .bank_qty = 0, .chan_desc_sz = 7, From 1968b98e3c747f7035cebc0b2de5ad456f132feb Mon Sep 17 00:00:00 2001 From: Bill Somerville Date: Fri, 10 Apr 2015 14:07:43 +0100 Subject: [PATCH 3/4] The Kenwood TS990s only does split Tx on SUB VFO --- kenwood/kenwood.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/kenwood/kenwood.c b/kenwood/kenwood.c index e370b3318..a58f48c40 100644 --- a/kenwood/kenwood.c +++ b/kenwood/kenwood.c @@ -796,6 +796,12 @@ int kenwood_set_split_vfo(RIG *rig, vfo_t vfo, split_t split, vfo_t txvfo) if (RIG_MODEL_TS990S == rig->caps->rig_model) { + if (split) + { + // Rx MAIN/Tx SUB is the only split method + retval = kenwood_set_vfo_main_sub (rig, RIG_VFO_MAIN); + if (retval != RIG_OK) return retval; + } sprintf(cmdbuf, "TB%c", RIG_SPLIT_ON == split ? '1' : '0'); return kenwood_transaction(rig, cmdbuf, NULL, 0); } @@ -1346,14 +1352,14 @@ int kenwood_set_mode(RIG *rig, vfo_t vfo, rmode_t mode, pbwidth_t width) { c = 'A' + kmode - 10; } - if (vfo != curr_vfo) + if (vfo != RIG_VFO_CURR && vfo != curr_vfo) { err = kenwood_set_vfo_main_sub (rig, vfo); if (err != RIG_OK) return err; } sprintf(buf, "OM0%c", c); /* target vfo is ignored */ int err = kenwood_transaction(rig, buf, NULL, 0); - if (vfo != curr_vfo) + if (vfo != RIG_VFO_CURR && vfo != curr_vfo) { int err2 = kenwood_set_vfo_main_sub (rig, curr_vfo); if (RIG_OK == err && err2 != RIG_OK) return err2; From b9eb755dc376581de13dfc7b16b1955a2e15dc63 Mon Sep 17 00:00:00 2001 From: Bill Somerville Date: Sat, 11 Apr 2015 15:17:39 +0100 Subject: [PATCH 4/4] The doesn't appear to be a way of getting PTT/SEND on the TS990s The IF command response byte for this is always 0 on this rig as documented and there doesn't seem to be an alternate way of querying. --- kenwood/ts990s.c | 1 - 1 file changed, 1 deletion(-) diff --git a/kenwood/ts990s.c b/kenwood/ts990s.c index 078b755e6..62f40b262 100644 --- a/kenwood/ts990s.c +++ b/kenwood/ts990s.c @@ -329,7 +329,6 @@ const struct rig_caps ts990s_caps = { .get_ctcss_tone = kenwood_get_ctcss_tone, .set_ctcss_sql = kenwood_set_ctcss_sql, .get_ctcss_sql = kenwood_get_ctcss_sql, -.get_ptt = kenwood_get_ptt, .set_ptt = kenwood_set_ptt, .get_dcd = kenwood_get_dcd, .set_func = kenwood_set_func,