Add routines to convert between morse code dot duration and milliseconds. Implement Yaesu break-in delay level correctly using these conversion routines.

pull/435/head
Mikael Nousiainen 2020-11-07 15:03:54 +02:00
rodzic df5fb8d6c8
commit 7cbe39d5ab
3 zmienionych plików z 136 dodań i 91 usunięć

Wyświetl plik

@ -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); snprintf(priv->cmd_str, sizeof(priv->cmd_str), "PL%03d%c", fpf, cat_term);
break; 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")) if (!newcat_valid_command(rig, "SD"))
{ {
return -RIG_ENAVAIL; return -RIG_ENAVAIL;
} }
// we don't get full resolution as long as val->i is in integer tenths // Convert 10/ths of dots to milliseconds using the current key speed
// consider changing this to float or to milliseconds err = newcat_get_level(rig, vfo, RIG_LEVEL_KEYSPD, &keyspd);
val.i *= 100; // tenths to ms conversion if (err != RIG_OK)
{
return err;
}
millis = dot10ths_to_millis(val.i, keyspd.i);
if (is_ftdx101) if (is_ftdx101)
{ {
if (val.i <= 30) { snprintf(priv->cmd_str, sizeof(priv->cmd_str), "SD00;"); } 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 (val.i <= 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 (val.i <= 100) { snprintf(priv->cmd_str, sizeof(priv->cmd_str), "SD02;"); } 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 (val.i <= 150) { snprintf(priv->cmd_str, sizeof(priv->cmd_str), "SD03;"); } else if (millis > 2900) { snprintf(priv->cmd_str, sizeof(priv->cmd_str), "SD33;"); }
else
else if (val.i <= 200) { snprintf(priv->cmd_str, sizeof(priv->cmd_str), "SD04;"); } {
// This covers 300-2900 06-32
else if (val.i <= 250) { snprintf(priv->cmd_str, sizeof(priv->cmd_str), "SD05;"); } snprintf(priv->cmd_str, sizeof(priv->cmd_str), "SD%02d;", 6 + ((millis - 300) / 100));
}
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)); }
} }
else if (is_ftdx5000) 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) snprintf(priv->cmd_str, sizeof(priv->cmd_str), "SD%04d%c", millis, cat_term);
{
val.i = 5000;
}
snprintf(priv->cmd_str, sizeof(priv->cmd_str), "SD%04d%c", val.i, cat_term);
} }
else if (is_ft950 || is_ft450 || is_ft891 || is_ft991 || is_ftdx1200 || is_ftdx3000) 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) snprintf(priv->cmd_str, sizeof(priv->cmd_str), "SD%04d%c", millis, cat_term);
{
val.i = 3000;
}
snprintf(priv->cmd_str, sizeof(priv->cmd_str), "SD%04d%c", val.i, cat_term);
} }
else if (is_ft2000 || is_ftdx9000) 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) snprintf(priv->cmd_str, sizeof(priv->cmd_str), "SD%04d%c", millis, cat_term);
{
val.i = 5000;
}
snprintf(priv->cmd_str, sizeof(priv->cmd_str), "SD%04d%c", val.i, cat_term);
} }
else // default else // default
{ {
if (val.i < 1) if (millis < 1)
{ {
val.i = 1; millis = 1;
}
if (millis > 5000)
{
millis = 5000;
} }
if (val.i > 5000) snprintf(priv->cmd_str, sizeof(priv->cmd_str), "SD%04d%c", millis, cat_term);
{
val.i = 5000;
}
snprintf(priv->cmd_str, sizeof(priv->cmd_str), "SD%04d%c", val.i, cat_term);
} }
break; break;
}
case RIG_LEVEL_SQL: case RIG_LEVEL_SQL:
if (!newcat_valid_command(rig, "SQ")) 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; return -RIG_ENAVAIL;
} }
/* should be tenth of dots */
snprintf(priv->cmd_str, sizeof(priv->cmd_str), "SD%c", cat_term); snprintf(priv->cmd_str, sizeof(priv->cmd_str), "SD%c", cat_term);
break; 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; val->f = (float)atoi(retlvl) / scale;
break; break;
case RIG_LEVEL_BKINDL: case RIG_LEVEL_BKINDL: {
val->i = atoi(retlvl); /* milliseconds */ int raw_value = atoi(retlvl);
int millis;
value_t keyspd;
if (is_ftdx101) if (is_ftdx101)
{ {
switch (val->i) switch (raw_value)
{ {
case 0: val->i = 1; break; case 0: millis = 30; break;
case 1: millis = 50; break;
case 1: val->i = 1; break; case 2: millis = 100; break;
case 3: millis = 150; break;
case 2: val->i = 1; break; case 4: millis = 200; break;
case 5: millis = 250; break;
case 3: val->i = 2; break; case 6: millis = 300; break;
default:
case 4: val->i = 2; break; millis = (raw_value - 6) * 100 + 300;
case 5: val->i = 3; break;
case 6: val->i = 3; break;
default: val->i = (val->i - 6) + 3;
} }
return RIG_OK;
} }
else
if (val->i < 1)
{ {
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 // Convert milliseconds to 10/ths of dots using the current key speed
// TODO: Fix BKINDL conversion from milliseconds ??? err = newcat_get_level(rig, vfo, RIG_LEVEL_KEYSPD, &keyspd);
val->i = 5000 / val->i; /* ms -to- tenth_dots-per-second */ if (err != RIG_OK)
if (val->i < 1)
{ {
val->i = 1; return err;
} }
val->i = millis_to_dot10ths(millis, keyspd.i);
break; break;
}
case RIG_LEVEL_STRENGTH: case RIG_LEVEL_STRENGTH:
if (rig->caps->str_cal.size > 0) 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)); 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 // Return dbS9 -- does >S9 mean 10dB increments? If not, add to rig driver
if (val->i > 0) { val->i = (atoi(retlvl) - 9) * 10; } if (val->i > 0)
else { val->i = (atoi(retlvl) - 9) * 6; } // Return dbS9 does >S9 mean 10dB increments? {
val->i = (atoi(retlvl) - 9) * 10;
}
else
{
val->i = (atoi(retlvl) - 9) * 6;
}
} }
break; break;
case RIG_LEVEL_RAWSTR: case RIG_LEVEL_RAWSTR:
case RIG_LEVEL_KEYSPD: case RIG_LEVEL_KEYSPD:
val->i = atoi(retlvl);
break;
case RIG_LEVEL_IF: case RIG_LEVEL_IF:
// IS00+0400 // IS00+0400
rig_debug(RIG_DEBUG_TRACE, "%s: ret_data=%s(%d), retlvl=%s\n", __func__, 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; break;
case RIG_LEVEL_NR: case RIG_LEVEL_NR:
if (is_ft450)
/* ratio 0 - 1.0 */
if (newcat_is_rig(rig, RIG_MODEL_FT450))
{ {
val->f = (float)(atoi(retlvl) / 11.); val->f = (float)(atoi(retlvl) / 11.);
} }

Wyświetl plik

@ -49,6 +49,7 @@
#endif #endif
#include <unistd.h> #include <unistd.h>
#include <math.h>
#include <hamlib/rig.h> #include <hamlib/rig.h>
#include <hamlib/amplifier.h> #include <hamlib/amplifier.h>
@ -230,6 +231,48 @@ unsigned long long HAMLIB_API from_bcd_be(const unsigned char bcd_data[],
return f; 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 //! @cond Doxygen_Suppress
#ifndef llabs #ifndef llabs

Wyświetl plik

@ -72,6 +72,10 @@ extern HAMLIB_EXPORT(unsigned long long) from_bcd_be(const unsigned char
bcd_data[], bcd_data[],
unsigned bcd_len); 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); extern HAMLIB_EXPORT(int) sprintf_freq(char *str, freq_t);
/* flag that determines if AI mode should be restored on exit on /* flag that determines if AI mode should be restored on exit on