[chirp_devel] [PATCH] [uv5r] add workmode vfo presets
# HG changeset patch # User Jim Unroe rock.unroe@gmail.com # Date 1359934996 18000 # Node ID f6ef3fde290991edb31f13f4cdb03370cb0955bb # Parent 41b8c8a428c3136a49ba9742b79752a6f764602d [uv5r] add workmode vfo presets #467
diff -r 41b8c8a428c3 -r f6ef3fde2909 chirp/settings.py --- a/chirp/settings.py Mon Jan 28 20:30:01 2013 -0500 +++ b/chirp/settings.py Sun Feb 03 18:43:16 2013 -0500 @@ -28,16 +28,20 @@ def __init__(self): self._current = None self._has_changed = False + self._callback = lambda x: x
def changed(self): """Returns True if the setting has been changed since init""" return self._has_changed
+ def set_callback(self, callback): + self._callback = callback + def set_value(self, value): """Sets the current value, triggers changed""" if self._current != None and value != self._current: self._has_changed = True - self._current = value + self._current = self._callback(value)
def get_value(self): """Gets the current value""" @@ -81,6 +85,45 @@ """Returns the step increment""" return self._step
+class RadioSettingValueFloat(RadioSettingValue): + """A floating-point setting""" + def __init__(self, minval, maxval, current, resolution=0.001, precision=5): + RadioSettingValue.__init__(self) + self._min = minval + self._max = maxval + self._res = resolution + self._pre = precision + self.set_value(current) + + def format(self, value=None): + """Formats the value into a string""" + if value is None: + value = self._current + fmt_string = "%%.%if" % self._pre + print fmt_string + return fmt_string % value + + def set_value(self, value): + try: + value = float(value) + except: + raise InvalidValueError("A floating point value is required") + if value > self._max or value < self._min: + raise InvalidValueError("Value %s not in range %s-%s" % ( + self.format(value), + self.format(self._min), self.format(self._max))) + + # FIXME: honor resolution + + RadioSettingValue.set_value(self, value) + + def get_min(self): + """Returns the minimum allowed value""" + return self._min + + def get_max(self): + """Returns the maximum allowed value""" + class RadioSettingValueBoolean(RadioSettingValue): """A boolean setting""" def __init__(self, current): diff -r 41b8c8a428c3 -r f6ef3fde2909 chirp/uv5r.py --- a/chirp/uv5r.py Mon Jan 28 20:30:01 2013 -0500 +++ b/chirp/uv5r.py Sun Feb 03 18:43:16 2013 -0500 @@ -20,8 +20,8 @@ from chirp import bitwise from chirp.settings import RadioSetting, RadioSettingGroup, \ RadioSettingValueInteger, RadioSettingValueList, \ - RadioSettingValueList, RadioSettingValueBoolean, \ - RadioSettingValueString + RadioSettingValueBoolean, RadioSettingValueString, \ + InvalidValueError
MEM_FORMAT = """ #seekto 0x0008; @@ -644,7 +644,7 @@ return int(version_tag[idx:idx+3]) raise Exception("Unrecognized firmware version string")
- def _get_settings(self): + def get_settings(self): _settings = self._memobj.settings[0] basic = RadioSettingGroup("basic", "Basic Settings") advanced = RadioSettingGroup("advanced", "Advanced Settings") @@ -884,15 +884,27 @@ RadioSettingValueInteger(0, 127, _mrcnb)) workmode.append(rs)
- options = ["VHF", "UHF"] - rs = RadioSetting("vfoa.band", "VFO A Band", - RadioSettingValueList(options, - options[self._memobj.vfoa.band])) + def convert_bytes_to_freq(bytes): + real_freq = 0 + for byte in bytes: + real_freq = (real_freq * 10) + byte + return real_freq + + def my_validate(value): + if 17400000 <= value and value < 40000000: + raise InvalidValueError("Can't be between 174000000-40000000") + return value + + val1a = RadioSettingValueInteger(13600000, 52000000, + convert_bytes_to_freq(self._memobj.vfoa.freq)) + val1a.set_callback(my_validate) + rs = RadioSetting("vfoa.freq", "VFO A Frequency", val1a) workmode.append(rs)
- rs = RadioSetting("vfob.band", "VFO B Band", - RadioSettingValueList(options, - options[self._memobj.vfob.band])) + val1b = RadioSettingValueInteger(13600000, 52000000, + convert_bytes_to_freq(self._memobj.vfob.freq)) + val1b.set_callback(my_validate) + rs = RadioSetting("vfob.freq", "VFO B Frequency", val1b) workmode.append(rs)
options = ["High", "Low"] @@ -949,33 +961,38 @@
return group
- def get_settings(self): - try: - return self._get_settings() - except: - import traceback - print "Failed to parse settings:" - traceback.print_exc() - return None - def set_settings(self, settings): + def convert_freq_to_bytes(freq): + bytes = [ 0 for x in range(0,8) ] # init list with 8 times 0 + for i in range(7, -1, -1): # go from 7 to 0 + bytes[i] = freq%10 # extract last digit + freq /= 10 # throw away last digit + return bytes + _settings = self._memobj.settings[0] for element in settings: if not isinstance(element, RadioSetting): self.set_settings(element) continue - try: - if "." in element.get_name(): - bits = element.get_name().split(".") - obj = self._memobj - for bit in bits[:-1]: - obj = getattr(obj, bit) - setting = bits[-1] - else: - obj = _settings - setting = element.get_name() - print "Setting %s = %s" % (setting, element.value) - setattr(obj, setting, element.value) - except Exception, e: - print element.get_name() - raise + elif element.get_name() == "vfoa.freq": + self._memobj.vfoa.freq = convert_freq_to_bytes(element.value.get_value()) + self._memobj.vfoa.band = element.value.get_value() > 20000000 + elif element.get_name() == "vfob.freq": + self._memobj.vfob.freq = convert_freq_to_bytes(element.value.get_value()) + self._memobj.vfob.band = element.value.get_value() > 20000000 + else: + try: + if "." in element.get_name(): + bits = element.get_name().split(".") + obj = self._memobj + for bit in bits[:-1]: + obj = getattr(obj, bit) + setting = bits[-1] + else: + obj = _settings + setting = element.get_name() + print "Setting %s = %s" % (setting, element.value) + setattr(obj, setting, element.value) + except Exception, e: + print element.get_name() + raise diff -r 41b8c8a428c3 -r f6ef3fde2909 chirpui/settingsedit.py --- a/chirpui/settingsedit.py Mon Jan 28 20:30:01 2013 -0500 +++ b/chirpui/settingsedit.py Sun Feb 03 18:43:16 2013 -0500 @@ -63,7 +63,12 @@ if self._top_setting_group is None: return
- job = common.RadioJob(None, "set_settings", self._top_setting_group) + def setting_cb(result): + if isinstance(result, Exception): + common.show_error(_("Error in setting value: %s") % result) + + job = common.RadioJob(setting_cb, "set_settings", + self._top_setting_group) job.set_desc("Setting radio settings") self._rthread.submit(job)
@@ -73,6 +78,8 @@ adj.configure(value.get_value(), value.get_min(), value.get_max(), value.get_step(), 1, 0) + elif isinstance(value, settings.RadioSettingValueFloat): + widget.set_text(value.format()) elif isinstance(value, settings.RadioSettingValueBoolean): widget.set_active(value.get_value()) elif isinstance(value, settings.RadioSettingValueList): @@ -89,9 +96,11 @@ print "Unsupported widget type %s for %s" % (value.__class__, element.get_name())
- def _save_setting(self, widget, value): + def _do_save_setting(self, widget, value): if isinstance(value, settings.RadioSettingValueInteger): value.set_value(widget.get_adjustment().get_value()) + elif isinstance(value, settings.RadioSettingValueFloat): + value.set_value(widget.get_text()) elif isinstance(value, settings.RadioSettingValueBoolean): value.set_value(widget.get_active()) elif isinstance(value, settings.RadioSettingValueList): @@ -105,6 +114,12 @@
self._save_settings()
+ def _save_setting(self, widget, value): + try: + self._do_save_setting(widget, value) + except settings.InvalidValueError, e: + common.show_error(_("Invalid setting value: %s") % e) + def _build_ui_group(self, group): def pack(widget, pos): self._table.attach(widget, pos, pos+1, self._index, self._index+1, @@ -139,6 +154,9 @@ widget = gtk.SpinButton() print "Digits: %i" % widget.get_digits() signal = "value-changed" + elif isinstance(value, settings.RadioSettingValueFloat): + widget = gtk.Entry() + signal = "focus-out-event" elif isinstance(value, settings.RadioSettingValueBoolean): widget = gtk.CheckButton(_("Enabled")) signal = "toggled" @@ -160,7 +178,11 @@ arraybox.pack_start(lalign, 1, 1, 1) widget.show() self._load_setting(value, widget) - widget.connect(signal, self._save_setting, value) + if signal == "focus-out-event": + widget.connect(signal, lambda w, e, v: + self._save_setting(w, v), value) + else: + widget.connect(signal, self._save_setting, value)
self._index += 1
# HG changeset patch # User Jim Unroe rock.unroe@gmail.com # Date 1359934996 18000 # Node ID f6ef3fde290991edb31f13f4cdb03370cb0955bb # Parent 41b8c8a428c3136a49ba9742b79752a6f764602d [uv5r] add workmode vfo presets #467
This was quite an undertaking.. Thanks for doing it :)
diff -r 41b8c8a428c3 -r f6ef3fde2909 chirp/settings.py --- a/chirp/settings.py Mon Jan 28 20:30:01 2013 -0500 +++ b/chirp/settings.py Sun Feb 03 18:43:16 2013 -0500
So, I had intended for the patch that I sent with the UI stuff to go in separately. It's much nicer for the version history if patches and changesets are small and self-contained. Since the UI stuff is not exactly small and also not specific to the UV5, I'd prefer it to be separate.
That being said, I understand if it's harder for you to slice it up at this point. If you don't want to, and don't mind, I might try to do that before I apply the patch.
@@ -644,7 +644,7 @@ return int(version_tag[idx:idx+3]) raise Exception("Unrecognized firmware version string")
- def _get_settings(self):
- def get_settings(self):
You reverted one of my changes here, probably because I made it while you were working on this and it got merged into your patch without you realizing it. It would be good if you could avoid this, which may just be a bit of manual tweaking so that the code after your patch looks like the code before (minus your changes).
The patch was:
http://chirp.danplanet.com/projects/chirp/repository/revisions/5f4fff6266ab/...
val1a = RadioSettingValueInteger(13600000, 52000000,
I know this isn't what you want to do, but at least it works. Maybe we should leave it as-is and I can help you make it format like a float after we get the core functionality into the tree.
Otherwise, I think it looks good.
Seriously, what's left to do? When can we start making fun of the folks that still use the icky OEM software? :)
So, I had intended for the patch that I sent with the UI stuff to go in separately. It's much nicer for the version history if patches and changesets are small and self-contained. Since the UI stuff is not exactly small and also not specific to the UV5, I'd prefer it to be separate.
No problem. Separate it will be.
That being said, I understand if it's harder for you to slice it up at this point. If you don't want to, and don't mind, I might try to do that before I apply the patch.
I still have the original patch that you sent me. I would appreciate it if you add it since it is UI stuff? Do you need need me to email it back? I'll take care of of the uv5r part.
@@ -644,7 +644,7 @@ return int(version_tag[idx:idx+3]) raise Exception("Unrecognized firmware version string")
- def _get_settings(self):
- def get_settings(self):
You reverted one of my changes here, probably because I made it while you were working on this and it got merged into your patch without you realizing it. It would be good if you could avoid this, which may just be a bit of manual tweaking so that the code after your patch looks like the code before (minus your changes).
The patch was:
http://chirp.danplanet.com/projects/chirp/repository/revisions/5f4fff6266ab/...
Sorry. I don't remember how that came about. But I would be happy change what I have to not affect this.
val1a = RadioSettingValueInteger(13600000, 52000000,
I know this isn't what you want to do, but at least it works. Maybe we should leave it as-is and I can help you make it format like a float after we get the core functionality into the tree.
I think this great. I would like to get it to look like a float, though. It is really nice to have both VFOs set to a frequency after a programming session.
Otherwise, I think it looks good.
Seriously, what's left to do? When can we start making fun of the folks that still use the icky OEM software? :)
I still have quite a few things on my list. I thought BCL would be a big
hurdle. It turned out to be nothing more than a speed bump. I am very close to be able to say that there is no longer a need to use the OEM software.
Jim
I still have the original patch that you sent me. I would appreciate it if you add it since it is UI stuff? Do you need need me to email it back? I'll take care of of the uv5r part.
I can put it in myself easily. One of the reasons to keep them separate is that I couldn't easily tell if you had tweaked it at all. If not, I'll shove it in straight away.
Sorry. I don't remember how that came about. But I would be happy change what I have to not affect this.
Cool, thanks.
I still have quite a few things on my list. I thought BCL would be a big hurdle. It turned out to be nothing more than a speed bump. I am very close to be able to say that there is no longer a need to use the OEM software.
Sweet!
participants (2)
-
Dan Smith
-
Jim Unroe