diff --git a/rigs/kenwood/kenwood.c b/rigs/kenwood/kenwood.c index 96d07ce39..055bb3e17 100644 --- a/rigs/kenwood/kenwood.c +++ b/rigs/kenwood/kenwood.c @@ -245,7 +245,8 @@ int kenwood_transaction(RIG *rig, const char *cmdstr, char *data, struct kenwood_priv_caps *caps = kenwood_caps(rig); struct rig_state *rs; - rig_debug(RIG_DEBUG_VERBOSE, "%s called cmd=%s datasize=%d\n", __func__, cmdstr, + rig_debug(RIG_DEBUG_VERBOSE, "%s called cmd=%s datasize=%d\n", __func__, + cmdstr ? cmdstr : "(NULL)", (int)datasize); if ((!cmdstr && !datasize) || (datasize && !data)) @@ -261,7 +262,7 @@ int kenwood_transaction(RIG *rig, const char *cmdstr, char *data, if (priv->is_emulation) { rs->rigport.post_write_delay = 0; } // if this is an IF cmdstr and not the first time through check cache - if (strcmp(cmdstr, "IF") == 0 && priv->cache_start.tv_sec != 0) + if (cmdstr && strcmp(cmdstr, "IF") == 0 && priv->cache_start.tv_sec != 0) { int cache_age_ms; @@ -280,8 +281,8 @@ int kenwood_transaction(RIG *rig, const char *cmdstr, char *data, // else we drop through and do the real IF command } - if (strlen(cmdstr) > 2 || strcmp(cmdstr, "RX") == 0 - || strncmp(cmdstr, "TX", 2) == 0 || strncmp(cmdstr, "ZZTX", 4) == 0) + if (cmdstr && (strlen(cmdstr) > 2 || strcmp(cmdstr, "RX") == 0 + || strncmp(cmdstr, "TX", 2) == 0 || strncmp(cmdstr, "ZZTX", 4)) == 0) { // then we must be setting something so we'll invalidate the cache rig_debug(RIG_DEBUG_TRACE, "%s: cache invalidated\n", __func__); @@ -613,7 +614,7 @@ transaction_read: transaction_quit: // update the cache - if (retval == RIG_OK && strcmp(cmdstr, "IF") == 0) + if (retval == RIG_OK && cmdstr && strcmp(cmdstr, "IF") == 0) { elapsed_ms(&priv->cache_start, HAMLIB_ELAPSED_SET); strncpy(priv->last_if_response, buffer, caps->if_len); @@ -3407,6 +3408,7 @@ int kenwood_get_level(RIG *rig, vfo_t vfo, setting_t level, value_t *val) switch (level) { int power_now, power_min, power_max; + int min_pitch, step_pitch; /* Hz */ case RIG_LEVEL_RAWSTR: if (RIG_IS_TS590S || RIG_IS_TS590SG) @@ -3739,15 +3741,29 @@ int kenwood_get_level(RIG *rig, vfo_t vfo, setting_t level, value_t *val) break; case RIG_LEVEL_CWPITCH: - retval = kenwood_safe_transaction(rig, "PT", lvlbuf, 50, 4); + if (RIG_IS_TS890S) + { + len = 5; + min_pitch = 300; + step_pitch = 5; + } + else + { + len = 4; + min_pitch = 400; + step_pitch = 50; + } + + retval = kenwood_safe_transaction(rig, "PT", lvlbuf, 50, len); if (retval != RIG_OK) { RETURNFUNC(retval); } - sscanf(lvlbuf + 2, "%d", &val->i); - val->i = (val->i * 1000) + 1000; /* 00 - 08 */ + sscanf(lvlbuf + 2, "%d", &val->i); /* 00 - 12 or 000 - 160 */ + val->i = (val->i * step_pitch) + min_pitch; /* 400 - 1000 or 300 - 1100 + */ break; case RIG_LEVEL_KEYSPD: diff --git a/rigs/kenwood/kenwood.h b/rigs/kenwood/kenwood.h index 120259350..e72787717 100644 --- a/rigs/kenwood/kenwood.h +++ b/rigs/kenwood/kenwood.h @@ -29,7 +29,7 @@ #include "misc.h" #include "idx_builtin.h" -#define BACKEND_VER "20221124" +#define BACKEND_VER "20221128" #define EOM_KEN ';' #define EOM_TH '\r' diff --git a/rigs/kenwood/ts890s.c b/rigs/kenwood/ts890s.c index e4350ee7b..bfcd067fc 100644 --- a/rigs/kenwood/ts890s.c +++ b/rigs/kenwood/ts890s.c @@ -36,8 +36,9 @@ #define TS890_AM_TX_MODES RIG_MODE_AM // TODO: Copied from TS-480, to be verified -#define TS890_LEVEL_ALL (RIG_LEVEL_RFPOWER|RIG_LEVEL_AF|RIG_LEVEL_RF|RIG_LEVEL_SQL|RIG_LEVEL_AGC|RIG_LEVEL_KEYSPD) -#define TS890_FUNC_ALL (RIG_FUNC_NB|RIG_FUNC_NB2|RIG_FUNC_COMP|RIG_FUNC_VOX|RIG_FUNC_NR|RIG_FUNC_NR|RIG_FUNC_BC|RIG_FUNC_BC2|RIG_FUNC_RIT|RIG_FUNC_XIT|RIG_FUNC_TUNER|RIG_FUNC_SEND_MORSE) +#define TS890_LEVEL_SET (RIG_LEVEL_RFPOWER|RIG_LEVEL_AF|RIG_LEVEL_RF|RIG_LEVEL_SQL|RIG_LEVEL_AGC|RIG_LEVEL_KEYSPD|RIG_LEVEL_CWPITCH) +#define TS890_LEVEL_GET (RIG_LEVEL_RFPOWER|RIG_LEVEL_AF|RIG_LEVEL_RF|RIG_LEVEL_SQL|RIG_LEVEL_AGC|RIG_LEVEL_KEYSPD|RIG_LEVEL_ALC|RIG_LEVEL_SWR|RIG_LEVEL_COMP_METER|RIG_LEVEL_ID_METER|RIG_LEVEL_VD_METER|RIG_LEVEL_TEMP_METER|RIG_LEVEL_CWPITCH) +#define TS890_FUNC_ALL (RIG_FUNC_NB|RIG_FUNC_NB2|RIG_FUNC_COMP|RIG_FUNC_VOX|RIG_FUNC_NR|RIG_FUNC_BC|RIG_FUNC_BC2|RIG_FUNC_RIT|RIG_FUNC_XIT|RIG_FUNC_TUNER|RIG_FUNC_SEND_MORSE) #define TS890_VFO_OPS (RIG_OP_UP|RIG_OP_DOWN|RIG_OP_BAND_UP|RIG_OP_BAND_DOWN|RIG_OP_CPY|RIG_OP_TUNE) @@ -95,6 +96,19 @@ int kenwood_ts890_set_level(RIG *rig, vfo_t vfo, setting_t level, value_t val) SNPRINTF(levelbuf, sizeof(levelbuf), "GC%d", kenwood_val); break; + case RIG_LEVEL_CWPITCH: + + // TODO: Merge this and formatting difference into kenwood.c + if (val.i < 300 || val.i > 1100) + { + return -RIG_EINVAL; + } + + /* 300 - 1100 Hz -> 000 - 160 */ + kenwood_val = (val.i - 298) / 5; /* Round to nearest 5Hz */ + SNPRINTF(levelbuf, sizeof(levelbuf), "PT%03d", kenwood_val); + break; + default: return kenwood_set_level(rig, vfo, level, val); } @@ -102,6 +116,55 @@ int kenwood_ts890_set_level(RIG *rig, vfo_t vfo, setting_t level, value_t val) return kenwood_transaction(rig, levelbuf, NULL, 0); } +/* Helper to get and parse meter values using RM + * Note that we turn readings on, but nothing off. + * 'pips' is the number of LED bars lit in the digital meter, max=70 + */ +static +int ts890_get_meter_reading(RIG *rig, char meter, int *pips) +{ + char reading[9]; /* 8 char + '\0' */ + int retval; + char target[] = "RMx1"; /* Turn on reading this meter */ + + target[2] = meter; + retval = kenwood_transaction(rig, target, NULL, 0); + + if (retval != RIG_OK) + { + return retval; + } + + /* Read the first value */ + retval = kenwood_transaction(rig, "RM", reading, sizeof(reading)); + + if (retval != RIG_OK) + { + return retval; + } + + /* Find the one we want */ + while (strncmp(reading, target, 3) != 0) + { + /* That wasn't it, get the next one */ + retval = kenwood_transaction(rig, NULL, reading, sizeof(reading)); + + if (retval != RIG_OK) + { + return retval; + } + + if (reading[0] != target[0] || reading[1] != target[1]) + { + /* Somebody else's data, bail */ + return -RIG_EPROTO; + } + } + + sscanf(reading + 3, "%4d", pips); + return RIG_OK; + +} int kenwood_ts890_get_level(RIG *rig, vfo_t vfo, setting_t level, value_t *val) { @@ -114,6 +177,7 @@ int kenwood_ts890_get_level(RIG *rig, vfo_t vfo, setting_t level, value_t *val) switch (level) { + // TODO: This doesn't appear in TS890_LEVEL_GET - should it? case RIG_LEVEL_VOXDELAY: retval = kenwood_safe_transaction(rig, "VD0", ackbuf, sizeof(ackbuf), 6); @@ -219,6 +283,94 @@ int kenwood_ts890_get_level(RIG *rig, vfo_t vfo, setting_t level, value_t *val) return RIG_OK; + case RIG_LEVEL_ALC: + retval = ts890_get_meter_reading(rig, '1', &levelint); + + if (retval != RIG_OK) + { + return retval; + } + + val->f = (float)levelint / 35.0; /* Half scale [0,35] -> [0.0,1.0] */ + return RIG_OK; + + case RIG_LEVEL_SWR: + retval = ts890_get_meter_reading(rig, '2', &levelint); + + if (retval != RIG_OK) + { + return retval; + } + + if (levelint < 0 || levelint >= 70) + { + val->f = 99.0; /* 99 == infinty */ + } + else + { +#if 0 + val->f = 70.0 / (70 - levelint); +#else + + /* Linear approximations of a very non-linear function */ + if (levelint < 12) { val->f = 1.0 + (float)levelint / 22.0; } + else if (levelint < 24) { val->f = 1.5 + (float)(levelint - 11) / 24.0; } + else if (levelint < 36) { val->f = 2.0 + (float)(levelint - 23) / 12.0; } + else { val->f = 3.0 + (float)(levelint - 35) / 6.0; } + +#endif + } + + return RIG_OK; + + case RIG_LEVEL_COMP_METER: + retval = ts890_get_meter_reading(rig, '3', &levelint); + + if (retval != RIG_OK) + { + return retval; + } + + if (levelint < 21) { val->f = (float)levelint / 2.0; } /* db */ + else if (levelint < 51) { val->f = 10.0 + (float)(levelint - 20) / 3.0; } + else { val->f = 20.0 + (float)(levelint - 50) / 4.0; } + + return RIG_OK; + + case RIG_LEVEL_ID_METER: + retval = ts890_get_meter_reading(rig, '4', &levelint); + + if (retval != RIG_OK) + { + return retval; + } + + val->f = (20.0 * (float)levelint) / 70.0; /* amperes */ + return RIG_OK; + + case RIG_LEVEL_VD_METER: + retval = ts890_get_meter_reading(rig, '5', &levelint); + + if (retval != RIG_OK) + { + return retval; + } + + val->f = (15.0 * (float)levelint) / 65.0; /* volts */ + return RIG_OK; + + case RIG_LEVEL_TEMP_METER: +#if 0 + retval = ts890_get_meter_reading(rig, '6', &levelint); + + if (retval != RIG_OK) + { + return retval; + } + +#endif + return -RIG_ENIMPL; + default: return kenwood_get_level(rig, vfo, level, val); } @@ -241,7 +393,7 @@ const struct rig_caps ts890s_caps = RIG_MODEL(RIG_MODEL_TS890S), .model_name = "TS-890S", .mfg_name = "Kenwood", - .version = BACKEND_VER ".6", + .version = BACKEND_VER ".7", .copyright = "LGPL", .status = RIG_STATUS_STABLE, .rig_type = RIG_TYPE_TRANSCEIVER, @@ -380,8 +532,8 @@ const struct rig_caps ts890s_caps = .send_morse = kenwood_send_morse, .wait_morse = rig_wait_morse, .scan = kenwood_scan, /* not working, invalid arguments using rigctl; kenwood_scan does only support on/off and not tone and CTCSS scan */ - .has_set_level = TS890_LEVEL_ALL, - .has_get_level = TS890_LEVEL_ALL, + .has_set_level = TS890_LEVEL_SET, + .has_get_level = TS890_LEVEL_GET, .set_level = kenwood_ts890_set_level, .get_level = kenwood_ts890_get_level, .level_gran =