From 7cbe39d5ab130eb38542332515a4573677e5ed10 Mon Sep 17 00:00:00 2001 From: Mikael Nousiainen Date: Sat, 7 Nov 2020 15:03:54 +0200 Subject: [PATCH] Add routines to convert between morse code dot duration and milliseconds. Implement Yaesu break-in delay level correctly using these conversion routines. --- rigs/yaesu/newcat.c | 180 ++++++++++++++++++++++---------------------- src/misc.c | 43 +++++++++++ src/misc.h | 4 + 3 files changed, 136 insertions(+), 91 deletions(-) diff --git a/rigs/yaesu/newcat.c b/rigs/yaesu/newcat.c index 1e1ee9b95..2bfc827ce 100644 --- a/rigs/yaesu/newcat.c +++ b/rigs/yaesu/newcat.c @@ -3208,96 +3208,94 @@ int newcat_set_level(RIG *rig, vfo_t vfo, setting_t level, value_t val) snprintf(priv->cmd_str, sizeof(priv->cmd_str), "PL%03d%c", fpf, cat_term); break; - case RIG_LEVEL_BKINDL: + case RIG_LEVEL_BKINDL: { + int millis; + value_t keyspd; - /* Standard: word "PARIS" == 50 Unit Intervals, UIs */ - /* 1 dot == 2 UIs */ - /* tenth_dots-per-second -to- milliseconds */ if (!newcat_valid_command(rig, "SD")) { return -RIG_ENAVAIL; } - // we don't get full resolution as long as val->i is in integer tenths - // consider changing this to float or to milliseconds - val.i *= 100; // tenths to ms conversion + // Convert 10/ths of dots to milliseconds using the current key speed + err = newcat_get_level(rig, vfo, RIG_LEVEL_KEYSPD, &keyspd); + if (err != RIG_OK) + { + return err; + } + + millis = dot10ths_to_millis(val.i, keyspd.i); if (is_ftdx101) { - if (val.i <= 30) { snprintf(priv->cmd_str, sizeof(priv->cmd_str), "SD00;"); } - - else if (val.i <= 50) { snprintf(priv->cmd_str, sizeof(priv->cmd_str), "SD01;"); } - - else if (val.i <= 100) { snprintf(priv->cmd_str, sizeof(priv->cmd_str), "SD02;"); } - - else if (val.i <= 150) { snprintf(priv->cmd_str, sizeof(priv->cmd_str), "SD03;"); } - - else if (val.i <= 200) { snprintf(priv->cmd_str, sizeof(priv->cmd_str), "SD04;"); } - - else if (val.i <= 250) { snprintf(priv->cmd_str, sizeof(priv->cmd_str), "SD05;"); } - - else if (val.i > 2900) { snprintf(priv->cmd_str, sizeof(priv->cmd_str), "SD33;"); } - // this covers 300-2900 06-32 - else { snprintf(priv->cmd_str, sizeof(priv->cmd_str), "SD%02d;", 6 + ((val.i - 300) / 100)); } + if (millis <= 30) { snprintf(priv->cmd_str, sizeof(priv->cmd_str), "SD00;"); } + else if (millis <= 50) { snprintf(priv->cmd_str, sizeof(priv->cmd_str), "SD01;"); } + else if (millis <= 100) { snprintf(priv->cmd_str, sizeof(priv->cmd_str), "SD02;"); } + else if (millis <= 150) { snprintf(priv->cmd_str, sizeof(priv->cmd_str), "SD03;"); } + else if (millis <= 200) { snprintf(priv->cmd_str, sizeof(priv->cmd_str), "SD04;"); } + else if (millis <= 250) { snprintf(priv->cmd_str, sizeof(priv->cmd_str), "SD05;"); } + else if (millis > 2900) { snprintf(priv->cmd_str, sizeof(priv->cmd_str), "SD33;"); } + else + { + // This covers 300-2900 06-32 + snprintf(priv->cmd_str, sizeof(priv->cmd_str), "SD%02d;", 6 + ((millis - 300) / 100)); + } } else if (is_ftdx5000) { - if (val.i < 20) + if (millis < 20) { - val.i = 20; + millis = 20; + } + if (millis > 5000) + { + millis = 5000; } - if (val.i > 5000) - { - val.i = 5000; - } - - snprintf(priv->cmd_str, sizeof(priv->cmd_str), "SD%04d%c", val.i, cat_term); + snprintf(priv->cmd_str, sizeof(priv->cmd_str), "SD%04d%c", millis, cat_term); } else if (is_ft950 || is_ft450 || is_ft891 || is_ft991 || is_ftdx1200 || is_ftdx3000) { - if (val.i < 30) + if (millis < 30) { - val.i = 30; + millis = 30; + } + if (millis > 3000) + { + millis = 3000; } - if (val.i > 3000) - { - val.i = 3000; - } - - snprintf(priv->cmd_str, sizeof(priv->cmd_str), "SD%04d%c", val.i, cat_term); + snprintf(priv->cmd_str, sizeof(priv->cmd_str), "SD%04d%c", millis, cat_term); } else if (is_ft2000 || is_ftdx9000) { - if (val.i < 0) + if (millis < 0) { - val.i = 0; + millis = 0; + } + if (millis > 5000) + { + millis = 5000; } - if (val.i > 5000) - { - val.i = 5000; - } - - snprintf(priv->cmd_str, sizeof(priv->cmd_str), "SD%04d%c", val.i, cat_term); + snprintf(priv->cmd_str, sizeof(priv->cmd_str), "SD%04d%c", millis, cat_term); } else // default { - if (val.i < 1) + if (millis < 1) { - val.i = 1; + millis = 1; + } + if (millis > 5000) + { + millis = 5000; } - if (val.i > 5000) - { - val.i = 5000; - } - - snprintf(priv->cmd_str, sizeof(priv->cmd_str), "SD%04d%c", val.i, cat_term); + snprintf(priv->cmd_str, sizeof(priv->cmd_str), "SD%04d%c", millis, cat_term); } break; + } case RIG_LEVEL_SQL: if (!newcat_valid_command(rig, "SQ")) @@ -3711,7 +3709,6 @@ int newcat_get_level(RIG *rig, vfo_t vfo, setting_t level, value_t *val) return -RIG_ENAVAIL; } - /* should be tenth of dots */ snprintf(priv->cmd_str, sizeof(priv->cmd_str), "SD%c", cat_term); break; @@ -4094,49 +4091,42 @@ int newcat_get_level(RIG *rig, vfo_t vfo, setting_t level, value_t *val) val->f = (float)atoi(retlvl) / scale; break; - case RIG_LEVEL_BKINDL: - val->i = atoi(retlvl); /* milliseconds */ + case RIG_LEVEL_BKINDL: { + int raw_value = atoi(retlvl); + int millis; + value_t keyspd; if (is_ftdx101) { - switch (val->i) + switch (raw_value) { - case 0: val->i = 1; break; - - case 1: val->i = 1; break; - - case 2: val->i = 1; break; - - case 3: val->i = 2; break; - - case 4: val->i = 2; break; - - case 5: val->i = 3; break; - - case 6: val->i = 3; break; - - default: val->i = (val->i - 6) + 3; + case 0: millis = 30; break; + case 1: millis = 50; break; + case 2: millis = 100; break; + case 3: millis = 150; break; + case 4: millis = 200; break; + case 5: millis = 250; break; + case 6: millis = 300; break; + default: + millis = (raw_value - 6) * 100 + 300; } - - return RIG_OK; } - - if (val->i < 1) + else { - val->i = 1; + // The rest of Yaesu rigs indicate break-in delay directly as milliseconds + millis = raw_value; } - // The rest of Yaesu rigs indicate break-in delay directly as milliseconds - // TODO: Fix BKINDL conversion from milliseconds ??? - val->i = 5000 / val->i; /* ms -to- tenth_dots-per-second */ - - if (val->i < 1) + // Convert milliseconds to 10/ths of dots using the current key speed + err = newcat_get_level(rig, vfo, RIG_LEVEL_KEYSPD, &keyspd); + if (err != RIG_OK) { - val->i = 1; + return err; } + val->i = millis_to_dot10ths(millis, keyspd.i); break; - + } case RIG_LEVEL_STRENGTH: if (rig->caps->str_cal.size > 0) { @@ -4149,17 +4139,27 @@ int newcat_get_level(RIG *rig, vfo_t vfo, setting_t level, value_t *val) { val->i = round(rig_raw2val(atoi(retlvl), &yaesu_default_str_cal)); } - else // some Yaesu rigs return straight s-meter answers + else { + // Some Yaesu rigs return straight S-meter answers // Return dbS9 -- does >S9 mean 10dB increments? If not, add to rig driver - if (val->i > 0) { val->i = (atoi(retlvl) - 9) * 10; } - else { val->i = (atoi(retlvl) - 9) * 6; } // Return dbS9 does >S9 mean 10dB increments? + if (val->i > 0) + { + val->i = (atoi(retlvl) - 9) * 10; + } + else + { + val->i = (atoi(retlvl) - 9) * 6; + } } break; case RIG_LEVEL_RAWSTR: case RIG_LEVEL_KEYSPD: + val->i = atoi(retlvl); + break; + case RIG_LEVEL_IF: // IS00+0400 rig_debug(RIG_DEBUG_TRACE, "%s: ret_data=%s(%d), retlvl=%s\n", __func__, @@ -4183,9 +4183,7 @@ int newcat_get_level(RIG *rig, vfo_t vfo, setting_t level, value_t *val) break; case RIG_LEVEL_NR: - - /* ratio 0 - 1.0 */ - if (newcat_is_rig(rig, RIG_MODEL_FT450)) + if (is_ft450) { val->f = (float)(atoi(retlvl) / 11.); } diff --git a/src/misc.c b/src/misc.c index b867c9f39..d4f5e6814 100644 --- a/src/misc.c +++ b/src/misc.c @@ -49,6 +49,7 @@ #endif #include +#include #include #include @@ -230,6 +231,48 @@ unsigned long long HAMLIB_API from_bcd_be(const unsigned char bcd_data[], return f; } +/** + * \brief Convert duration of one morse code dot (element) to milliseconds at the given speed. + * \param wpm morse code speed in words per minute + * \return double duration in milliseconds + * + * The morse code speed is calculated using the standard based on word PARIS. + * + * "If you send PARIS 5 times in a minute (5WPM) you have sent 250 elements (using correct spacing). + * 250 elements into 60 seconds per minute = 240 milliseconds per element." + * + * Source: http://kent-engineers.com/codespeed.htm + */ +double morse_code_dot_to_millis(int wpm) +{ + return 240.0 * (5.0 / (double) wpm); +} + +/** + * \brief Convert duration of tenths of morse code dots to milliseconds at the given speed. + * \param tenths_of_dots number of 1/10ths of dots + * \param wpm morse code speed in words per minute + * \return int duration in milliseconds + * + * The morse code speed is calculated using the standard based on word PARIS. + */ +int dot10ths_to_millis(int dot10ths, int wpm) +{ + return ceil(morse_code_dot_to_millis(wpm) * (double) dot10ths / 10.0); +} + +/** + * \brief Convert duration in milliseconds to tenths of morse code dots at the given speed. + * \param millis duration in milliseconds + * \param wpm morse code speed in words per minute + * \return int number of 1/10ths of dots + * + * The morse code speed is calculated using the standard based on word PARIS. + */ +int millis_to_dot10ths(int millis, int wpm) +{ + return ceil(millis / morse_code_dot_to_millis(wpm) * 10.0); +} //! @cond Doxygen_Suppress #ifndef llabs diff --git a/src/misc.h b/src/misc.h index 5378f1da7..de88ec683 100644 --- a/src/misc.h +++ b/src/misc.h @@ -72,6 +72,10 @@ extern HAMLIB_EXPORT(unsigned long long) from_bcd_be(const unsigned char bcd_data[], unsigned bcd_len); +extern HAMLIB_EXPORT(double) morse_code_dot_to_millis(int wpm); +extern HAMLIB_EXPORT(int) dot10ths_to_millis(int dot10ths, int wpm); +extern HAMLIB_EXPORT(int) millis_to_dot10ths(int millis, int wpm); + extern HAMLIB_EXPORT(int) sprintf_freq(char *str, freq_t); /* flag that determines if AI mode should be restored on exit on