[chirp_devel] [KYD IP-620] Add support for KYD IP-620 radio - issue #2033
Alex K
Wed Oct 7 14:01:41 PDT 2015
# HG changeset patch
# User Alexey K <lepik.stv at gmail.com>
# Date 1444251379 -10800
# Wed Oct 07 23:56:19 2015 +0300
# Node ID 6213e68e50e323221bf1939101bfc4169621a8cd
# Parent 39ec1a8bc0b04f90f47e8e76795a7abbe5b1af40
[KYD IP-620] Add support for KYD IP-620 radio - issue #2033
diff -r 39ec1a8bc0b0 -r 6213e68e50e3 chirp/drivers/kyd_IP620.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/chirp/drivers/kyd_IP620.py Wed Oct 07 23:56:19 2015 +0300
@@ -0,0 +1,619 @@
+# Copyright 2015 Lepik.stv <lepik.stv at gmail.com>
+# based on modification of Dan Smith's and Jim Unroe original work
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+"""KYD IP-620 radios management module"""
+
+# TODO: Power on message
+# TODO: Channel name
+# TODO: Tuning step
+
+import struct
+import time
+import os
+import logging
+from chirp import util, chirp_common, bitwise, memmap, errors, directory
+from chirp.settings import RadioSetting, RadioSettingGroup, \
+ RadioSettingValueBoolean, RadioSettingValueList, \
+ RadioSettingValueInteger, RadioSettingValueString, \
+ RadioSettings
+
+LOG = logging.getLogger(__name__)
+
+IP620_MEM_FORMAT = """
+#seekto 0x0000;
+struct { // Channel memory structure
+ lbcd rx_freq[4]; // RX frequency
+ lbcd tx_freq[4]; // TX frequency
+ ul16 rx_tone; // RX tone
+ ul16 tx_tone; // TX tone
+ u8 unknown_1:4 // n-a
+ busy_loc:2, // NO-00, Crrier wave-01, SM-10
+ n_a:2; // n-a
+ u8 unknown_2:1 // n-a
+ scan_add:1, // Scan add
+ n_a:1, // n-a
+ w_n:1, // Narrow-0 Wide-1
+ lout:1, // LOCKOUT OFF-0 ON-1
+ n_a_:1, // n-a
+ power:2; // Power low-00 middle-01 high-10
+ u8 unknown_3; // n-a
+ u8 unknown_4; // n-a
+} memory[200];
+
+#seekto 0x1000;
+struct {
+ u8 chan_name[6]; //Channel name
+ u8 unknown_1[10];
+} chan_names[200];
+
+#seekto 0x0C80;
+struct { // Settings memory structure ( A-Frequency mode )
+ lbcd freq_a_rx[4];
+ lbcd freq_a_tx[4];
+ ul16 freq_a_rx_tone; // RX tone
+ ul16 freq_a_tx_tone; // TX tone
+ u8 unknown_1_5:4
+ freq_a_busy_loc:2,
+ n_a:2;
+ u8 unknown_1_6:3
+ freq_a_w_n:1,
+ n_a:1,
+ na:1,
+ freq_a_power:2;
+ u8 unknown_1_7;
+ u8 unknown_1_8;
+} settings_freq_a;
+
+#seekto 0x0E20;
+struct {
+ u8 chan_disp_way; // Channel display way
+ u8 step_freq; // Step frequency KHz
+ u8 rf_sql; // Squelch level
+ u8 bat_save; // Battery Saver
+ u8 chan_pri; // Channel PRI
+ u8 end_beep; // End beep
+ u8 tot; // Time-out timer
+ u8 vox; // VOX Gain
+ u8 chan_pri_num; // Channel PRI time Sec
+ u8 n_a_2;
+ u8 ch_mode; // CH mode
+ u8 n_a_3;
+ u8 call_tone; // Call tone
+ u8 beep; // Beep
+ u8 unknown_1_1[2];
+ u8 unknown_1_2[8];
+ u8 scan_rev; // Scan rev
+ u8 unknown_1_3[2];
+ u8 enc; // Frequency lock
+ u8 vox_dly; // VOX Delay
+ u8 wait_back_light;// Wait back light
+ u8 unknown_1_4[2];
+} settings;
+
+#seekto 0x0E40;
+struct {
+ u8 fm_radio; // FM radio
+ u8 auto_lock; // Auto lock
+ u8 unknown_1[8];
+ u8 pon_msg[6]; //Power on msg
+} settings_misc;
+
+#seekto 0x1C80;
+struct {
+ u8 unknown_1[16];
+ u8 unknown_2[16];
+} settings_radio_3;
+"""
+
+CMD_ACK = "\x06"
+WRITE_BLOCK_SIZE = 0x10
+READ_BLOCK_SIZE = 0x40
+
+CHAR_LENGTH_MAX = 6
+
+OFF_ON_LIST = ["OFF", "ON"]
+ON_OFF_LIST = ["ON", "OFF"]
+NO_YES_LIST = ["NO", "YES"]
+STEP_LIST = ["5.0", "6.25", "10.0", "12.5", "25.0"]
+BAT_SAVE_LIST = ["OFF", "0.2 Sec", "0.4 Sec", "0.6 Sec", "0.8 Sec","1.0
Sec"]
+SHIFT_LIST = ["", "-", "+"]
+SCANM_LIST = ["Time", "Carrier wave", "Search"]
+ENDBEEP_LIST = ["OFF", "Begin", "End", "Begin/End"]
+POWER_LEVELS = [chirp_common.PowerLevel("Low", watts=1.00),
chirp_common.PowerLevel("Medium", watts=2.50),
chirp_common.PowerLevel("High", watts=5.00)]
+TIMEOUT_LIST = ["OFF", "1 Min", "3 Min", "10 Min"]
+TOTALERT_LIST = ["", "OFF"] + ["%s seconds" % x for x in range(1, 11)]
+VOX_LIST = ["OFF"] + ["%s" % x for x in range(1, 17)]
+VOXDELAY_LIST = ["0.3 Sec", "0.5 Sec", "1.0 Sec", "1.5 Sec", "2.0 Sec",
"3.0 Sec", "4.0 Sec", "5.0 Sec"]
+PRI_NUM = [3, 5, 8, 10]
+PRI_NUM_LIST = [str(x) for x in PRI_NUM]
+CH_FLAG_LIST = ["Channel+Freq", "Channel+Name"]
+BACKLIGHT_LIST = ["Always Off", "Auto", "Always On"]
+BUSYLOCK_LIST = ["NO", "Carrier", "SM"]
+KEYBLOCK_LIST = ["Manual", "Auto"]
+CALLTONE_LIST = ["OFF", "1", "2", "3", "4", "5", "6", "7", "8", "1750"]
+RFSQL_LIST = ["OFF", "S-1", "S-2", "S-3", "S-4", "S-5", "S-6","S-7",
"S-8", "S-FULL"]
+
+IP620_CHARSET = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ?+-* "
+
+IP620_BANDS = [
+ (136000000, 174000000),
+ (200000000, 260000000),
+ (300000000, 340000000), # <--- this band supports only Russian model
(ARGUT A-36)
+ (350000000, 390000000),
+ (400000000, 480000000),
+ (420000000, 510000000),
+ (450000000, 520000000),
+]
+
+ at directory.register
+class IP620Radio(chirp_common.CloneModeRadio,
+ chirp_common.ExperimentalRadio):
+ """KYD IP-620"""
+ VENDOR = "KYD"
+ MODEL = "IP-620"
+ BAUD_RATE = 9600
+
+ _ranges = [
+ (0x0000, 0x2000),
+ ]
+ _memsize = 0x2000
+
+ def _ip620_exit_programming_mode(self):
+ try:
+ self.pipe.write("\x06")
+ except errors.RadioError:
+ raise
+ except Exception, e:
+ raise errors.RadioError("Radio refused to exit programming
mode: %s" % e)
+
+ def _ip620_enter_programming_mode(self):
+ try:
+ self.pipe.write("iUHOUXUN")
+ self.pipe.write("\x02")
+ time.sleep(0.2)
+ _ack = self.pipe.read(1)
+ except errors.RadioError:
+ raise
+ except Exception, e:
+ raise errors.RadioError("Error communicating with radio: %s" %
e)
+ if not _ack:
+ raise errors.RadioError("No response from radio")
+ elif _ack != CMD_ACK:
+ raise errors.RadioError("Radio refused to enter programming
mode")
+ try:
+ self.pipe.write("\x02")
+ _ident = self.pipe.read(8)
+ except errors.RadioError:
+ raise
+ except Exception, e:
+ raise errors.RadioError("Error communicating with radio: %s" %
e)
+ if not _ident.startswith("\x06\x4B\x47\x36\x37\x01\x56\xF8"):
+ print util.hexprint(_ident)
+ raise errors.RadioError("Radio returned unknown identification
string")
+ try:
+ self.pipe.write(CMD_ACK)
+ _ack = self.pipe.read(1)
+ except errors.RadioError:
+ raise
+ except Exception, e:
+ raise errors.RadioError("Error communicating with radio: %s" %
e)
+ if _ack != CMD_ACK:
+ raise errors.RadioError("Radio refused to enter programming
mode")
+
+ def _ip620_write_block(self, block_addr):
+ _cmd = struct.pack(">cHb", 'W', block_addr, WRITE_BLOCK_SIZE)
+ _data = self.get_mmap()[block_addr:block_addr + WRITE_BLOCK_SIZE]
+ LOG.debug("Writing Data:")
+ LOG.debug(util.hexprint(_cmd + _data))
+ try:
+ self.pipe.write(_cmd + _data)
+ if self.pipe.read(1) != CMD_ACK:
+ raise Exception("No ACK")
+ except:
+ raise errors.RadioError("Failed to send block "
+ "to radio at %04x" % block_addr)
+
+ def _ip620_read_block(self, block_addr):
+ _cmd = struct.pack(">cHb", 'R', block_addr, READ_BLOCK_SIZE)
+ _expectedresponse = "W" + _cmd[1:]
+ LOG.debug("Reading block %04x..." % (block_addr))
+ try:
+ self.pipe.write(_cmd)
+ _response = self.pipe.read(4 + READ_BLOCK_SIZE)
+ if _response[:4] != _expectedresponse:
+ raise Exception("Error reading block %04x." % (block_addr))
+ _block_data = _response[4:]
+ self.pipe.write(CMD_ACK)
+ _ack = self.pipe.read(1)
+ except:
+ raise errors.RadioError("Failed to read block at %04x" %
block_addr)
+ if _ack != CMD_ACK:
+ raise Exception("No ACK reading block %04x." % (block_addr))
+ return _block_data
+
+ def _do_download(self):
+ self._ip620_enter_programming_mode()
+ _data = ""
+ _status = chirp_common.Status()
+ _status.msg = "Cloning from radio"
+ _status.cur = 0
+ _status.max = self._memsize
+ for _addr in range(0, self._memsize, READ_BLOCK_SIZE):
+ _status.cur = _addr + READ_BLOCK_SIZE
+ self.status_fn(_status)
+ _block = self._ip620_read_block(_addr)
+ _data += _block
+ LOG.debug("Address: %04x" % _addr)
+ LOG.debug(util.hexprint(_block))
+ self._ip620_exit_programming_mode()
+ return memmap.MemoryMap(_data)
+
+ def _do_upload(self):
+ _status = chirp_common.Status()
+ _status.msg = "Uploading to radio"
+ self._ip620_enter_programming_mode()
+ _status.cur = 0
+ _status.max = self._memsize
+ for _start_addr, _end_addr in self._ranges:
+ for _addr in range(_start_addr, _end_addr, WRITE_BLOCK_SIZE):
+ _status.cur = _addr + WRITE_BLOCK_SIZE
+ self.status_fn(_status)
+ self._ip620_write_block(_addr)
+ self._ip620_exit_programming_mode()
+
+ @classmethod
+ def get_prompts(cls):
+ rp = chirp_common.RadioPrompts()
+ rp.experimental = ("This radio driver is currently under
development. "
+ "There are no known issues with it, but you
should "
+ "proceed with caution. However, proceed at your
own risk!")
+ return rp
+
+ def get_features(self):
+ rf = chirp_common.RadioFeatures()
+ rf.has_settings = True
+ rf.has_bank = False
+ rf.has_ctone = True
+ rf.has_cross = False
+ rf.has_rx_dtcs = True
+ rf.has_tuning_step = False
+ rf.can_odd_split = False
+ rf.has_name = False
+ rf.valid_skips = []
+ rf.valid_tmodes = ["", "Tone", "TSQL", "DTCS"]
+ rf.valid_power_levels = POWER_LEVELS
+ rf.valid_duplexes = SHIFT_LIST
+ rf.valid_modes = ["FM", "NFM"]
+ rf.memory_bounds = (1, 200)
+ rf.valid_bands = IP620_BANDS
+ rf.valid_characters = ''.join(set(IP620_CHARSET))
+ rf.valid_name_length = CHAR_LENGTH_MAX
+ return rf
+
+ def process_mmap(self):
+ self._memobj = bitwise.parse(IP620_MEM_FORMAT, self._mmap)
+
+ def sync_in(self):
+ try:
+ self._mmap = self._do_download()
+ except errors.RadioError:
+ raise
+ except Exception, e:
+ raise errors.RadioError("Failed to communicate with radio: %s"
% e)
+ self.process_mmap()
+
+ def sync_out(self):
+ self._do_upload()
+
+ def get_raw_memory(self, number):
+ return repr(self._memobj.memory[number - 1])
+
+ def _get_tone(self, _mem, mem):
+ def _get_dcs(val):
+ code = int("%03o" % (val & 0x07FF))
+ pol = (val & 0x8000) and "R" or "N"
+ return code, pol
+
+ if _mem.tx_tone != 0xFFFF and _mem.tx_tone > 0x2800:
+ tcode, tpol = _get_dcs(_mem.tx_tone)
+ mem.dtcs = tcode
+ txmode = "DTCS"
+ elif _mem.tx_tone != 0xFFFF:
+ mem.rtone = _mem.tx_tone / 10.0
+ txmode = "Tone"
+ else:
+ txmode = ""
+
+ if _mem.rx_tone != 0xFFFF and _mem.rx_tone > 0x2800:
+ rcode, rpol = _get_dcs(_mem.rx_tone)
+ mem.rx_dtcs = rcode
+ rxmode = "DTCS"
+ elif _mem.rx_tone != 0xFFFF:
+ mem.ctone = _mem.rx_tone / 10.0
+ rxmode = "Tone"
+ else:
+ rxmode = ""
+
+ if txmode == "Tone" and not rxmode:
+ mem.tmode = "Tone"
+ elif txmode == rxmode and txmode == "Tone" and mem.rtone ==
mem.ctone:
+ mem.tmode = "TSQL"
+ elif txmode == rxmode and txmode == "DTCS" and mem.dtcs ==
mem.rx_dtcs:
+ mem.tmode = "DTCS"
+ elif rxmode or txmode:
+ mem.tmode = "Cross"
+ mem.cross_mode = "%s->%s" % (txmode, rxmode)
+
+ if mem.tmode == "DTCS":
+ mem.dtcs_polarity = "%s%s" % (tpol, rpol)
+
+ LOG.debug("Got TX %s (%i) RX %s (%i)" % (txmode, _mem.tx_tone,
+ rxmode, _mem.rx_tone))
+
+ def get_memory(self, number):
+ _mem = self._memobj.memory[number - 1]
+ _nam = self._memobj.chan_names[number - 1]
+
+ def _is_empty():
+ for i in range(0, 4):
+ if _mem.rx_freq[i].get_raw() != "\xFF":
+ return False
+ return True
+
+ mem = chirp_common.Memory()
+ mem.number = number
+
+ if _is_empty():
+ mem.empty = True
+ return mem
+
+ mem.freq = int(_mem.rx_freq) * 10
+
+ if int(_mem.rx_freq) == int(_mem.tx_freq):
+ mem.duplex = ""
+ mem.offset = 0
+ else:
+ mem.duplex = int(_mem.rx_freq) > int(_mem.tx_freq) and "-" or
"+"
+ mem.offset = abs(int(_mem.rx_freq) - int(_mem.tx_freq)) * 10
+
+ mem.mode = _mem.w_n and "FM" or "NFM"
+ self._get_tone(_mem, mem)
+ mem.power = POWER_LEVELS[_mem.power]
+
+ mem.extra = RadioSettingGroup("Extra", "extra")
+ rs = RadioSetting("lout", "Lock out",
+ RadioSettingValueList(OFF_ON_LIST,
+ OFF_ON_LIST[_mem.lout]))
+ mem.extra.append(rs)
+
+ rs = RadioSetting("busy_loc", "Busy lock",
+ RadioSettingValueList(BUSYLOCK_LIST,
+ BUSYLOCK_LIST[_mem.busy_loc]))
+ mem.extra.append(rs)
+
+ rs = RadioSetting("scan_add", "Scan add",
+ RadioSettingValueList(NO_YES_LIST,
+ NO_YES_LIST[_mem.scan_add]))
+ mem.extra.append(rs)
+ #TODO: Show name channel
+## count = 0
+## for i in _nam.chan_name:
+## if i == 0xFF:
+## break
+## try:
+## mem.name += IP620_CHARSET[i]
+## except Exception:
+## LOG.error("Unknown name char %i: 0x%02x (mem %i)" %
+## (count, i, number - 1))
+## mem.name += " "
+## count += 1
+## mem.name = mem.name.rstrip()
+
+ return mem
+
+ def _set_tone(self, mem, _mem):
+ def _set_dcs(code, pol):
+ val = int("%i" % code, 8) + 0x2800
+ if pol == "R":
+ val += 0x8000
+ return val
+
+ if mem.tmode == "Cross":
+ tx_mode, rx_mode = mem.cross_mode.split("->")
+ elif mem.tmode == "Tone":
+ tx_mode = mem.tmode
+ rx_mode = None
+ else:
+ tx_mode = rx_mode = mem.tmode
+
+ if tx_mode == "DTCS":
+ _mem.tx_tone = mem.tmode != "DTCS" and \
+ _set_dcs(mem.dtcs, mem.dtcs_polarity[0]) or \
+ _set_dcs(mem.rx_dtcs, mem.dtcs_polarity[0])
+ elif tx_mode:
+ _mem.tx_tone = tx_mode == "Tone" and \
+ int(mem.rtone * 10) or int(mem.ctone * 10)
+ else:
+ _mem.tx_tone = 0xFFFF
+
+ if rx_mode == "DTCS":
+ _mem.rx_tone = _set_dcs(mem.rx_dtcs, mem.dtcs_polarity[1])
+ elif rx_mode:
+ _mem.rx_tone = int(mem.ctone * 10)
+ else:
+ _mem.rx_tone = 0xFFFF
+
+ LOG.debug("Set TX %s (%i) RX %s (%i)" % (tx_mode, _mem.tx_tone,
+ rx_mode, _mem.rx_tone))
+
+ def set_memory(self, mem):
+ _mem = self._memobj.memory[mem.number - 1]
+ if mem.empty:
+ _mem.set_raw("\xFF" * (_mem.size() / 8))
+ return
+
+ _mem.rx_freq = mem.freq / 10
+ if mem.duplex == "OFF":
+ for i in range(0, 4):
+ _mem.tx_freq[i].set_raw("\xFF")
+ elif mem.duplex == "+":
+ _mem.tx_freq = (mem.freq + mem.offset) / 10
+ elif mem.duplex == "-":
+ _mem.tx_freq = (mem.freq - mem.offset) / 10
+ else:
+ _mem.tx_freq = mem.freq / 10
+
+ _mem.w_n = mem.mode == "FM"
+ self._set_tone(mem, _mem)
+ _mem.power = mem.power == POWER_LEVELS[1]
+
+ for setting in mem.extra:
+ setattr(_mem, setting.get_name(), setting.value)
+
+ def get_settings(self):
+ _settings = self._memobj.settings
+ _settings_misc = self._memobj.settings_misc
+ basic = RadioSettingGroup("basic", "Basic Settings")
+ top = RadioSettings(basic)
+
+ rs = RadioSetting("rf_sql", "Squelch level (SQL)",
+ RadioSettingValueList(RFSQL_LIST,
+ RFSQL_LIST[_settings.rf_sql]))
+ basic.append(rs)
+
+ rs = RadioSetting("step_freq", "Step frequency KHz (STP)",
+ RadioSettingValueList(STEP_LIST,
+ STEP_LIST[_settings.step_freq]))
+ basic.append(rs)
+
+ rs = RadioSetting("fm_radio", "FM radio (DW)",
+ RadioSettingValueList(OFF_ON_LIST,
+ OFF_ON_LIST[_settings_misc.fm_radio]))
+ basic.append(rs)
+
+ rs = RadioSetting("call_tone", "Call tone (CK)",
+ RadioSettingValueList(CALLTONE_LIST,
+ CALLTONE_LIST[_settings.call_tone]))
+ basic.append(rs)
+
+ rs = RadioSetting("tot", "Time-out timer (TOT)",
+ RadioSettingValueList(TIMEOUT_LIST,
+ TIMEOUT_LIST[_settings.tot]))
+ basic.append(rs)
+
+ rs = RadioSetting("chan_disp_way", "Channel display way",
+ RadioSettingValueList(CH_FLAG_LIST,
+ CH_FLAG_LIST[_settings.chan_disp_way]))
+ basic.append(rs)
+
+ rs = RadioSetting("vox", "VOX Gain (VOX)",
+ RadioSettingValueList(VOX_LIST,
+ VOX_LIST[_settings.vox]))
+ basic.append(rs)
+
+ rs = RadioSetting("vox_dly", "VOX Delay",
+ RadioSettingValueList(VOXDELAY_LIST,
+ VOXDELAY_LIST[_settings.vox_dly]))
+ basic.append(rs)
+
+ rs = RadioSetting("beep", "Beep (BP)",
+ RadioSettingValueList(OFF_ON_LIST,
+ OFF_ON_LIST[_settings.beep]))
+ basic.append(rs)
+
+ rs = RadioSetting("auto_lock", "Auto lock (KY)",
+ RadioSettingValueList(NO_YES_LIST,
+ NO_YES_LIST[_settings_misc.auto_lock]))
+ basic.append(rs)
+
+ rs = RadioSetting("bat_save", "Battery Saver (SAV)",
+ RadioSettingValueList(BAT_SAVE_LIST,
+ BAT_SAVE_LIST[_settings.bat_save]))
+ basic.append(rs)
+
+ rs = RadioSetting("chan_pri", "Channel PRI (PRI)",
+ RadioSettingValueList(OFF_ON_LIST,
+ OFF_ON_LIST[_settings.chan_pri]))
+ basic.append(rs)
+
+ rs = RadioSetting("chan_pri_num", "Channel PRI time Sec (PRI)",
+ RadioSettingValueList(PRI_NUM_LIST,
+ PRI_NUM_LIST[_settings.chan_pri_num]))
+ basic.append(rs)
+
+ rs = RadioSetting("end_beep", "End beep (ET)",
+ RadioSettingValueList(ENDBEEP_LIST,
+ ENDBEEP_LIST[_settings.end_beep]))
+ basic.append(rs)
+
+ rs = RadioSetting("ch_mode", "CH mode",
+ RadioSettingValueList(ON_OFF_LIST,
+ ON_OFF_LIST[_settings.ch_mode]))
+ basic.append(rs)
+
+ rs = RadioSetting("scan_rev", "Scan rev (SCAN)",
+ RadioSettingValueList(SCANM_LIST,
+ SCANM_LIST[_settings.scan_rev]))
+ basic.append(rs)
+
+ rs = RadioSetting("enc", "Frequency lock (ENC)",
+ RadioSettingValueList(OFF_ON_LIST,
+ OFF_ON_LIST[_settings.enc]))
+ basic.append(rs)
+
+ rs = RadioSetting("wait_back_light", "Wait back light (LED)",
+ RadioSettingValueList(BACKLIGHT_LIST,
+ BACKLIGHT_LIST[_settings.wait_back_light]))
+ basic.append(rs)
+
+ return top
+
+ def _set_misc_settings(self, settings):
+ for element in settings:
+ try:
+ setattr(self._memobj.settings_misc,
+ element.get_name(),
+ element.value)
+ except Exception, e:
+ LOG.debug(element.get_name())
+ raise
+
+ def set_settings(self, settings):
+ _settings = self._memobj.settings
+ _settings_misc = self._memobj.settings_misc
+ for element in settings:
+ if not isinstance(element, RadioSetting):
+ self.set_settings(element)
+ continue
+ if not element.changed():
+ continue
+ try:
+ setting = element.get_name()
+ if setting in ["auto_lock","fm_radio"]:
+ oldval = getattr(_settings_misc, setting)
+ else:
+ oldval = getattr(_settings, setting)
+
+ newval = element.value
+
+ LOG.debug("Setting %s(%s) <= %s" % (setting, oldval,
newval))
+ if setting in ["auto_lock","fm_radio"]:
+ setattr(_settings_misc, setting, newval)
+ else:
+ setattr(_settings, setting, newval)
+ except Exception, e:
+ LOG.debug(element.get_name())
+ raise
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://intrepid.danplanet.com/pipermail/chirp_devel/attachments/20151008/553d59a0/attachment-0001.html
More information about the chirp_devel
mailing list