Prioritize radio-supplied tuning steps

This makes the UI consider the radio's tuning steps, if defined as
the first course of action. The existing code tried the standard
set followed by the radio's set, assuming the radio's would be a
subset, which is of course not always true.

This also makes required_step() consider the radio-specific steps
after the standard ones, if there are any strange ones to allow the
radio to define ones that are not in the standard list.

Related to #10968
This commit is contained in:
Dan Smith 2024-09-09 18:38:40 -07:00 committed by Dan Smith
parent a557fddee9
commit 43f6ad60dc
3 changed files with 25 additions and 11 deletions

View File

@ -814,6 +814,10 @@ def LIST(v):
assert hasattr(v, '__iter__') assert hasattr(v, '__iter__')
def LIST_NONZERO_INT(v):
assert all(x > 0 for x in v)
def INT(min=0, max=None): def INT(min=0, max=None):
def checkint(v): def checkint(v):
assert isinstance(v, int) assert isinstance(v, int)
@ -865,7 +869,7 @@ class RadioFeatures:
"valid_modes": LIST, "valid_modes": LIST,
"valid_tmodes": LIST, "valid_tmodes": LIST,
"valid_duplexes": LIST, "valid_duplexes": LIST,
"valid_tuning_steps": LIST, "valid_tuning_steps": LIST_NONZERO_INT,
"valid_bands": LIST, "valid_bands": LIST,
"valid_skips": LIST, "valid_skips": LIST,
"valid_power_levels": LIST, "valid_power_levels": LIST,
@ -1736,10 +1740,21 @@ def required_step(freq, allowed=None):
8.33: is_8_33, 8.33: is_8_33,
} }
# Try the above "standard" steps first in order
for step, validate in steps.items(): for step, validate in steps.items():
if step in allowed and validate(freq): if step in allowed and validate(freq):
return step return step
# Try any additional steps in the allowed list
for step in allowed:
if step in steps:
# Already tried
continue
if make_is(int(step * 1000))(freq):
LOG.debug('Chose non-standard step %s for %s' % (
step, format_freq(freq)))
return step
raise errors.InvalidDataError("Unable to find a supported " + raise errors.InvalidDataError("Unable to find a supported " +
"tuning step for %s" % format_freq(freq)) "tuning step for %s" % format_freq(freq))

View File

@ -1337,18 +1337,12 @@ class ChirpMemEdit(common.ChirpEditor, common.ChirpSyncEditor):
else: else:
want_tuning_step = 5.0 want_tuning_step = 5.0
try: try:
# First calculate the needed step in case it is not supported # Try to find a tuning step for the frequency that the radio
# by the radio. If we fail to find one the radio supports, # supports, or with the default set
# we will use this one and then the error message about it
# being unsupported will be accurate.
want_tuning_step = chirp_common.required_step(mem.freq)
# Now try to find a suitable one that the radio supports.
want_tuning_step = chirp_common.required_step( want_tuning_step = chirp_common.required_step(
mem.freq, features.valid_tuning_steps) mem.freq, features.valid_tuning_steps or None)
LOG.debug('Chose radio-supported step %s' % want_tuning_step)
except errors.InvalidDataError as e: except errors.InvalidDataError as e:
LOG.warning(e) LOG.warning('Failed to find step: %s' % e)
if 'tuning_step' in only and want_tuning_step: if 'tuning_step' in only and want_tuning_step:
mem.tuning_step = want_tuning_step mem.tuning_step = want_tuning_step

View File

@ -503,6 +503,11 @@ class TestStepFunctions(base.BaseTest):
self.assertEqual(2.5, chirp_common.required_step(self._005[0], self.assertEqual(2.5, chirp_common.required_step(self._005[0],
allowed=[2.5])) allowed=[2.5]))
def test_required_step_finds_radio_specific(self):
# Make sure we find a radio-specific step, 10Hz in this case
self.assertEqual(0.01, chirp_common.required_step(
146000010, allowed=[5.0, 10.0, 0.01, 20.0]))
def test_required_step_fail(self): def test_required_step_fail(self):
self.assertRaises(errors.InvalidDataError, self.assertRaises(errors.InvalidDataError,
chirp_common.required_step, chirp_common.required_step,