[chirp_devel] IC-2730 FINAL Update patch
Rick DeWitt AA0RD
Fri Jun 28 08:55:42 PDT 2019
OK, the perfect IC-2730 patch is attached, along with an updated image file.
--
Rick DeWitt
AA0RD
Sequim, Washington, USA 98382
(360) 681-3494
-------------- next part --------------
# HG changeset patch
# User Rick DeWitt <aa0rd at yahoo.com>
# Date 1561736831 25200
# Fri Jun 28 08:47:11 2019 -0700
# Node ID d35b3cf6f047ec19fd655b02d71aef00fe4a179e
# Parent 1bcc885b00d0d62be639c1f8b080ec1ffa7e76f1
[IC-2730a] Update to Icom IC-2730A Issue #6711
Adding settings and fixing special channels.Issue #6711
diff -r 1bcc885b00d0 -r d35b3cf6f047 chirp/drivers/ic2730.py
--- a/chirp/drivers/ic2730.py Fri Jun 28 08:43:07 2019 -0700
+++ b/chirp/drivers/ic2730.py Fri Jun 28 08:47:11 2019 -0700
@@ -1,4 +1,5 @@
# Copyright 2018 Rhett Robinson <rrhett at gmail.com>
+# Added Settings support, 6/2019 Rick DeWitt <aa0rd at yahoo.com>
#
# 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
@@ -13,16 +14,19 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
+import struct
+import logging
from chirp.drivers import icf
from chirp import chirp_common, util, directory, bitwise, memmap
-
+from chirp import errors
+from chirp.settings import RadioSettingGroup, RadioSetting, \
+ RadioSettingValueBoolean, RadioSettingValueList, \
+ RadioSettingValueString, RadioSettingValueInteger, \
+ RadioSettingValueFloat, RadioSettings, InvalidValueError
+from textwrap import dedent
-# Still missing:
-# - scan edges
-# - priority watch
-# - hope channel beep
-# - DTMF memory
-# - weather channel alert
+LOG = logging.getLogger(__name__)
+
MEM_FORMAT = """
struct {
u24 freq_flags:6
@@ -52,31 +56,164 @@
#seekto 0x4440;
struct {
- u8 bank;
- u8 index;
+u8 bank;
+u8 index;
} bank_info[1000];
+#seekto 0x4c40;
+struct {
+char com[16];
+} comment;
+
#seekto 0x4c50;
struct {
- char name[6];
+char name[6];
} bank_names[10];
-#seekto 0x5004;
-u8 unknown12:4,
- autorptr:2,
- unknown13:2;
+#seekto 0x4cc8;
+struct{
+u8 codes[24];
+} dtmfcode[16];
+
+#seekto 0x4c8c;
+struct {
+char nam[6];
+} pslnam[10];
+
+#seekto 0x4e80;
+struct {
+u24 loflags:6
+ lofreq:18;
+u24 hiflags:6
+ hifreq:18;
+u8 flag:4
+ mode:4;
+u8 tstp;
+char name[6];
+} pgmscanedge[25];
-#seekto 0x5030;
-u8 unknown14:6,
- backlight:2;
-
-#seekto 0x5056;
-u8 unknown15:6,
- power:2;
+#seekto 0x5000;
+struct {
+u8 aprichn;
+u8 bprichn;
+u8 autopwr;
+u8 unk5003;
+u8 autorptr;
+u8 rmtmic; // 0x05005
+u8 pttlock;
+u8 bcl;
+u8 tot;
+u8 actband;
+u8 unk500a;
+u8 dialspdup;
+u8 toneburst;
+u8 micgain;
+u8 unk500e;
+u8 civaddr;
+u8 civbaud;
+u8 civtcvr;
+u8 sqlatt;
+u8 sqldly;
+u8 unk5014a:4
+ fanspeed:4;
+u8 unk5015;
+u8 bthvox;
+u8 bthvoxlvl;
+u8 bthvoxdly;
+u8 bthvoxtot; // 0x05019
+u8 btoothon;
+u8 btoothauto;
+u8 bthdset;
+u8 bthhdpsav;
+u8 bth1ptt; // 0x0501e
+u8 bthpttbeep;
+u8 bthcustbeep; // 0x05020
+u8 ascanpause;
+u8 bscanpause;
+u8 ascanresume;
+u8 bscanresume;
+u8 dtmfspd;
+u8 unk5026;
+u8 awxalert;
+u8 bwxalert;
+u8 aprgskpscn;
+u8 bprgskpscn;
+u8 memname;
+u8 contrast;
+u8 autodimtot;
+u8 autodim;
+u8 unk502f;
+u8 backlight;
+u8 unk5031;
+u8 unk5032;
+u8 openmsg;
+u8 beeplvl; // 0x05034
+u8 keybeep;
+u8 scanstpbeep;
+u8 bandedgbeep;
+u8 subandmute;
+u8 atmpskiptym;
+u8 btmpskiptym;
+u32 vfohome;
+u8 vfohomeset;
+u16 homech;
+u8 mickyrxf1;
+u8 mickyrxf2;
+u8 mickyrxup;
+u8 mickyrxdn; // 0x05045
+u8 bthplaykey;
+u8 bthfwdkey;
+u8 bthrwdkey;
+u8 mickytxf1;
+u8 mickytxf2;
+u8 mickytxup;
+u8 mickytxdn;
+u8 unk504d;
+u8 unk504e;
+u8 unk504f;
+u8 homebeep;
+u8 bthfctn;
+u8 unk5052;
+u8 unk5053;
+u8 ifxchg;
+u8 airbandch;
+u8 vhfpower;
+u8 uhfpower;
+u8 unk5058;
+u8 unk5059;
+u8 unk505a;
+u8 unk505b;
+u8 unk505c;
+u8 unk505d;
+u8 unk505e:6
+ rpthangup:1
+ unk505e2:1;
+u8 unk505f;
+} settings;
#seekto 0x5220;
+struct {
u16 left_memory;
u16 right_memory;
+} initmem;
+
+#seekto 0x523e;
+struct {
+u8 awxchan;
+u8 bwxchan;
+} abwx;
+
+#seekto 0x5250;
+struct {
+u8 alnk[2];
+u16 unk5252;
+u8 blnk[2];
+} banklink;
+
+#seekto 0x5258;
+struct {
+u8 msk[4];
+} pslgrps[25];
#seekto 0x5280;
u16 mem_writes_count;
@@ -89,8 +226,14 @@
DUPLEX = ["", "-", "+"]
MODES = ["FM", "NFM", "AM", "NAM"]
DTCSP = ["NN", "NR", "RN", "RR"]
-
+DTMF_CHARS = list("0123456789ABCD*#")
+BANKLINK_CHARS = list("ABCDEFGHIJ")
AUTOREPEATER = ["OFF", "DUP", "DUP.TON"]
+MICKEYOPTS = ["Off", "Up", "Down", "Vol Up", "Vol Down", "SQL Up",
+ "SQL Down", "Monitor", "Call", "MR (Ch 0)", "MR (Ch 1)",
+ "VFO/MR", "Home Chan", "Band/Bank", "Scan", "Temp Skip",
+ "Main", "Mode", "Low", "Dup", "Priority", "Tone", "MW", "Mute",
+ "T-Call", "DTMF Direct"]
class IC2730Bank(icf.IcomNamedBank):
@@ -105,8 +248,7 @@
def _get_special():
- special = {"C0": 1000,
- "C1": 1001}
+ special = {"C0": -2, "C1": -1}
return special
@@ -133,13 +275,41 @@
_ranges = [(0x0000, 0x5300, 64),
(0x5300, 0x5310, 16),
- (0x5310, 0x5340, 48),
- ]
+ (0x5310, 0x5340, 48)]
_num_banks = 10
_bank_class = IC2730Bank
_can_hispeed = True
+ @classmethod
+ def get_prompts(cls):
+ rp = chirp_common.RadioPrompts()
+ rp.info = ('Click the Special Channels tab on the main screen to '
+ 'access the C0 and C1 frequencies.\n')
+
+ rp.pre_download = _(dedent("""\
+ Follow these instructions to download your config:
+
+ 1 - Turn off your radio
+ 2 - Connect your interface cable to the Speaker-2 jack
+ 3 - Turn on your radio
+ 4 - Radio > Download from radio
+ 5 - Disconnect the interface cable! Otherwise there will be
+ no right-side audio!
+ """))
+ rp.pre_upload = _(dedent("""\
+ Follow these instructions to upload your config:
+
+ 1 - Turn off your radio
+ 2 - Connect your interface cable to the Speaker-2 jack
+ 3 - Turn on your radio
+ 4 - Radio > Upload to radio
+ 5 - Disconnect the interface cable, otherwise there will be
+ no right-side audio!
+ 6 - Cycle power on the radio to exit clone mode
+ """))
+ return rp
+
def _get_bank(self, loc):
_bank = self._memobj.bank_info[loc]
if _bank.bank == 0x1F:
@@ -174,8 +344,7 @@
rf.valid_duplexes = list(set(DUPLEX))
rf.valid_tuning_steps = list(chirp_common.TUNING_STEPS[0:9])
rf.valid_bands = [(118000000, 174000000),
- (375000000, 550000000),
- ]
+ (375000000, 550000000)]
rf.valid_skips = ["", "S", "P"]
rf.valid_characters = chirp_common.CHARSET_ASCII
rf.valid_name_length = 6
@@ -187,28 +356,26 @@
self._memobj = bitwise.parse(MEM_FORMAT, self._mmap)
def get_memory(self, number):
- bitpos = (1 << (number % 8))
- bytepos = number / 8
-
- _mem = self._memobj.memory[number]
- _used = self._memobj.used_flags[bytepos]
-
- is_used = ((_used & bitpos) == 0)
-
mem = chirp_common.Memory()
+ mem.number = _resolve_memory_number(number)
+ if mem.number >= 0:
+ _mem = self._memobj.memory[mem.number]
+ bitpos = (1 << (number % 8))
+ bytepos = number / 8
+ _used = self._memobj.used_flags[bytepos]
+ is_used = ((_used & bitpos) == 0)
- mem.number = number
-
- _skip = self._memobj.skip_flags[bytepos]
- _pskip = self._memobj.pskip_flags[bytepos]
- if _skip & bitpos:
- mem.skip = "S"
- elif _pskip & bitpos:
- mem.skip = "P"
-
- if not is_used:
- mem.empty = True
- return mem
+ _skip = self._memobj.skip_flags[bytepos]
+ _pskip = self._memobj.pskip_flags[bytepos]
+ if _skip & bitpos:
+ mem.skip = "S"
+ elif _pskip & bitpos:
+ mem.skip = "P"
+ if not is_used:
+ mem.empty = True
+ return mem
+ else: # C0, C1 specials
+ _mem = self._memobj.memory[1002 + mem.number]
# _mem.freq is stored as a multiple of a tuning step
frequency_flags = int(_mem.freq_flags)
@@ -218,11 +385,21 @@
frequency_multiplier = 6250
if frequency_flags & 0x01:
offset_multiplier = 6250
- # flag of 0x10 is related to tuning step of 25./3, but it is not exact,
- # so skip this for now
+ if frequency_flags & 0x10:
+ frequency_multiplier = 8333
+ if frequency_flags & 0x02:
+ offset_multiplier = 8333
- mem.freq = int(_mem.freq) * frequency_multiplier
- mem.offset = int(_mem.offset) * offset_multiplier
+ if frequency_flags & 0x10: # fix underflow
+ val = int(_mem.freq) * frequency_multiplier
+ mem.freq = round(val)
+ else:
+ mem.freq = int(_mem.freq) * frequency_multiplier
+ if frequency_flags & 0x02:
+ val = int(_mem.offset) * offset_multiplier
+ mem.offset = round(val)
+ else:
+ mem.offset = int(_mem.offset) * offset_multiplier
mem.rtone = chirp_common.TONES[_mem.rtone]
mem.ctone = chirp_common.TONES[_mem.ctone]
mem.tmode = TMODES[_mem.tmode]
@@ -235,48 +412,65 @@
else:
mem.tuning_step = chirp_common.TUNING_STEPS[_mem.tune_step]
mem.name = str(_mem.name).rstrip()
+ if mem.number == -2:
+ mem.name = "C0"
+ mem.extd_number = "C0"
+ if mem.number == -1:
+ mem.name = "C1"
+ mem.extd_number = "C1"
return mem
def set_memory(self, mem):
- bitpos = (1 << (mem.number % 8))
- bytepos = mem.number / 8
+ if mem.number >= 0: # Normal
+ bitpos = (1 << (mem.number % 8))
+ bytepos = mem.number / 8
- _mem = self._memobj.memory[mem.number]
- _used = self._memobj.used_flags[bytepos]
+ _mem = self._memobj.memory[mem.number]
+ _used = self._memobj.used_flags[bytepos]
- was_empty = _used & bitpos
+ was_empty = _used & bitpos
- skip = self._memobj.skip_flags[bytepos]
- pskip = self._memobj.pskip_flags[bytepos]
- if mem.skip == "S":
- skip |= bitpos
- else:
- skip &= ~bitpos
- if mem.skip == "P":
- pskip |= bitpos
- else:
- pskip &= ~bitpos
+ skip = self._memobj.skip_flags[bytepos]
+ pskip = self._memobj.pskip_flags[bytepos]
+ if mem.skip == "S":
+ skip |= bitpos
+ else:
+ skip &= ~bitpos
+ if mem.skip == "P":
+ pskip |= bitpos
+ else:
+ pskip &= ~bitpos
- if mem.empty:
- _used |= bitpos
- _wipe_memory(_mem, "\xFF")
- self._set_bank(mem.number, None)
- return
+ if mem.empty:
+ _used |= bitpos
+ _wipe_memory(_mem, "\xFF")
+ self._set_bank(mem.number, None)
+ return
- _used &= ~bitpos
- if was_empty:
- _wipe_memory(_mem, "\x00")
+ _used &= ~bitpos
+ if was_empty:
+ _wipe_memory(_mem, "\x00")
+ _mem.name = mem.name.ljust(6)
+ else: # Specials: -2 and -1
+ _mem = self._memobj.memory[1002 + mem.number]
+ # Common to both types
frequency_flags = 0x00
frequency_multiplier = 5000
offset_multiplier = 5000
if mem.freq % 5000 != 0 and mem.freq % 6250 == 0:
frequency_flags |= 0x08
frequency_multiplier = 6250
+ elif mem.freq % 8333 == 0:
+ frequency_flags |= 0x10
+ frequency_multiplier = 8333
if mem.offset % 5000 != 0 and mem.offset % 6250 == 0:
frequency_flags |= 0x01
offset_multiplier = 6250
+ elif mem.offset % 8333 == 0:
+ frequency_flags |= 0x02
+ offset_multiplier = 8333
_mem.freq = mem.freq / frequency_multiplier
_mem.offset = mem.offset / offset_multiplier
_mem.freq_flags = frequency_flags
@@ -288,7 +482,809 @@
_mem.dtcs = chirp_common.DTCS_CODES.index(mem.dtcs)
_mem.dtcs_polarity = DTCSP.index(mem.dtcs_polarity)
_mem.tune_step = chirp_common.TUNING_STEPS.index(mem.tuning_step)
- _mem.name = mem.name.ljust(6)
def get_raw_memory(self, number):
return repr(self._memobj.memory[number])
+
+ def get_settings(self):
+ """Translate the MEM_FORMAT structs into settings in the UI"""
+ # Define mem struct write-back shortcuts
+ _sets = self._memobj.settings
+ _cmnt = self._memobj.comment
+ _wxch = self._memobj.abwx
+ _dtm = self._memobj.dtmfcode
+ _pses = self._memobj.pgmscanedge
+ _bklk = self._memobj.banklink
+
+ basic = RadioSettingGroup("basic", "Basic Settings")
+ mickey = RadioSettingGroup("mickey", "Microphone Keys")
+ bluet = RadioSettingGroup("bluet", "Bluetooth")
+ disp = RadioSettingGroup("disp", "Display")
+ sound = RadioSettingGroup("sound", "Sounds")
+ dtmf = RadioSettingGroup("dtmf", "DTMF Codes")
+ abset = RadioSettingGroup("abset", "A/B Band Settings")
+ edges = RadioSettingGroup("edges", "Program Scan Edges")
+ pslnk = RadioSettingGroup("pslnk", "Program Scan Links")
+ other = RadioSettingGroup("other", "Other Settings")
+
+ group = RadioSettings(basic, disp, sound, mickey, dtmf,
+ abset, bluet, edges, pslnk, other)
+
+ def mic_keys(setting, obj, atrb):
+ """ Callback to set subset of mic key options """
+ stx = str(setting.value)
+ value = MICKEYOPTS.index(stx)
+ setattr(obj, atrb, value)
+ return
+
+ def hex_val(setting, obj, atrb):
+ """ Callback to store string as hex values """
+ value = int(str(setting.value), 16)
+ setattr(obj, atrb, value)
+ return
+
+ def unpack_str(codestr):
+ """Convert u8 DTMF array to a string: NOT a callback."""
+ stx = ""
+ for i in range(0, 24): # unpack up to ff
+ if codestr[i] != 0xff:
+ if codestr[i] == 0x0E:
+ stx += "#"
+ elif codestr[i] == 0x0F:
+ stx += "*"
+ else:
+ stx += format(int(codestr[i]), '0X')
+ return stx
+
+ def pack_chars(setting, obj, atrb, ndx):
+ """Callback to build 0-9,A-D,*# nibble array from string"""
+ # String will be f padded to 24 bytes
+ # Chars are stored as hex values
+ ary = []
+ stx = str(setting.value).upper()
+ stx = stx.strip() # trim spaces
+ # Remove illegal characters first
+ sty = ""
+ for j in range(0, len(stx)):
+ if stx[j] in DTMF_CHARS:
+ sty += stx[j]
+ for j in range(0, 24):
+ if j < len(sty):
+ if sty[j] == "#":
+ chrv = 0xE
+ elif sty[j] == "*":
+ chrv = 0xF
+ else:
+ chrv = int(sty[j], 16)
+ else: # pad to 24 bytes
+ chrv = 0xFF
+ ary.append(chrv) # append byte
+ setattr(obj[ndx], atrb, ary)
+ return
+
+ def myset_comment(setting, obj, atrb, knt):
+ """ Callback to create space-padded char array"""
+ stx = str(setting.value)
+ for i in range(0, knt):
+ if i > len(stx):
+ str.append(0x20)
+ setattr(obj, atrb, stx)
+ return
+
+ def myset_psnam(setting, obj, ndx, atrb, knt):
+ """ Callback to generate space-padded, uppercase char array """
+ # This sub also is specific to object arrays
+ stx = str(setting.value).upper()
+ for i in range(0, knt):
+ if i > len(stx):
+ str.append(0x20)
+ setattr(obj[ndx], atrb, stx)
+ return
+
+ def myset_frqflgs(setting, obj, ndx, flg, frq):
+ """ Callback to gen flag/freq pairs """
+ vfrq = float(str(setting.value))
+ vfrq = int(vfrq * 1000000)
+ vflg = 0x10
+ if vfrq % 6250 == 0:
+ vflg = 0x08
+ vfrq = int(vfrq / 6250)
+ elif vfrq % 5000 == 0:
+ vflg = 0
+ vfrq = int(vfrq / 5000)
+ else:
+ vfrq = int(vfrq / 8333)
+ setattr(obj[ndx], flg, vflg)
+ setattr(obj[ndx], frq, vfrq)
+ return
+
+ def banklink(ary):
+ """ Sub to generate A-J string from 2-byte bit pattern """
+ stx = ""
+ for kx in range(0, 10):
+ if kx < 8:
+ val = ary[0]
+ msk = 1 << kx
+ else:
+ val = ary[1]
+ msk = 1 << (kx - 8)
+ if val & msk:
+ stx += chr(kx + 65)
+ else:
+ stx += "_"
+ return stx
+
+ def myset_banklink(setting, obj, atrb):
+ """Callback to create 10-bit, u8[2] array from 10 char string"""
+ stx = str(setting.value).upper()
+ ary = [0, 0]
+ for kx in range(0, 10):
+ if stx[kx] == chr(kx + 65):
+ if kx < 8:
+ ary[0] = ary[0] + (1 << kx)
+ else:
+ ary[1] = ary[1] + (1 << (kx - 8))
+ setattr(obj, atrb, ary)
+ return
+
+ def myset_tsopt(setting, obj, ndx, atrb, bx):
+ """ Callback to set scan Edge tstep """
+ stx = str(setting.value)
+ flg = 0
+ if stx == "-":
+ val = 0xff
+ else:
+ if bx == 1: # Air band
+ if stx == "Auto":
+ val = 0xe
+ elif stx == "25k":
+ val = 8
+ elif stx == "8.33k":
+ val = 2
+ else: # VHF or UHF
+ optx = ["-", "5k", "6.25k", "10k", "12.5k", "15k",
+ "20k", "25k", "30k", "50k"]
+ val = optx.index(stx) + 1
+ setattr(obj[ndx], atrb, val)
+ # and set flag
+ setattr(obj[ndx], "flag", flg)
+ return
+
+ def myset_mdopt(setting, obj, ndx, atrb, bx):
+ """ Callback to set Scan Edge mode """
+ stx = str(setting.value)
+ if stx == "-":
+ val = 0xf
+ elif stx == "FM":
+ val = 0
+ else:
+ val = 1
+ setattr(obj[ndx], atrb, val)
+ return
+
+ def myset_bitmask(setting, obj, ndx, atrb, knt):
+ """ Callback to gnerate byte-array bitmask from string"""
+ # knt is BIT count to process
+ lsx = str(setting.value).strip().split(",")
+ for kx in range(0, len(lsx)):
+ try:
+ lsx[kx] = int(lsx[kx])
+ except Exception:
+ lsx[kx] = -99 # will nop
+ ary = [0, 0, 0, 0xfe]
+ for kx in range(0, knt):
+ if kx < 8:
+ if kx in lsx:
+ ary[0] += 1 << kx
+ elif kx >= 8 and kx < 16:
+ if kx in lsx:
+ ary[1] += 1 << (kx - 8)
+ elif kx >= 16 and kx < 24:
+ if kx in lsx:
+ ary[2] += 1 << (kx - 16)
+ else:
+ if kx in lsx: # only bit 25
+ ary[3] += 1
+ setattr(obj[ndx], atrb, ary)
+ return
+
+ # --- Basic
+ options = ["Off", "S-Meter Squelch", "ATT"]
+ rx = RadioSettingValueList(options, options[_sets.sqlatt])
+ rset = RadioSetting("settings.sqlatt", "Squelch/ATT", rx)
+ basic.append(rset)
+
+ options = ["Short", "Long"]
+ rx = RadioSettingValueList(options, options[_sets.sqldly])
+ rset = RadioSetting("settings.sqldly", "Squelch Delay", rx)
+ basic.append(rset)
+
+ rx = RadioSettingValueBoolean(bool(_sets.pttlock))
+ rset = RadioSetting("settings.pttlock", "PTT Lockout", rx)
+ basic.append(rset)
+
+ rx = RadioSettingValueBoolean(bool(_sets.bcl))
+ rset = RadioSetting("settings.bcl", "Busy Channel Lockout", rx)
+ basic.append(rset)
+
+ options = ["Off", "1m", "3m", "5m", "10m", "15m", "30m"]
+ rx = RadioSettingValueList(options, options[_sets.tot])
+ rset = RadioSetting("settings.tot", "Tx Timeout", rx)
+ basic.append(rset)
+
+ val = int(_sets.vfohome)
+ if val == 0xffff:
+ val = 0
+ val = val / 1000000.0
+ rx = RadioSettingValueFloat(0.0, 550.0, val, 0.005, 4)
+ rx.set_mutable(False)
+ rset = RadioSetting("settings.vfohome", "Home VFO (Read-Only)", rx)
+ basic.append(rset)
+
+ val = _sets.homech
+ if val == 0xffff:
+ val = -1
+ rx = RadioSettingValueInteger(-1, 999, val)
+ rx.set_mutable(False)
+ rset = RadioSetting("settings.homech",
+ "Home Channel (Read-Only)", rx)
+ basic.append(rset)
+
+ options = ["1", "2", "3", "4"]
+ rx = RadioSettingValueList(options, options[_sets.micgain])
+ rset = RadioSetting("settings.micgain", "Microphone Gain", rx)
+ basic.append(rset)
+
+ _bmem = self._memobj.initmem
+ rx = RadioSettingValueInteger(0, 999, _bmem.left_memory)
+ rset = RadioSetting("initmem.left_memory",
+ "Left Bank Initial Mem Chan", rx)
+ basic.append(rset)
+
+ rx = RadioSettingValueInteger(0, 999, _bmem.right_memory)
+ rset = RadioSetting("initmem.right_memory",
+ "Right Bank Initial Mem Chan", rx)
+ basic.append(rset)
+
+ stx = ""
+ for i in range(0, 16):
+ stx += chr(_cmnt.com[i])
+ stx = stx.rstrip()
+ rx = RadioSettingValueString(0, 16, stx)
+ rset = RadioSetting("comment.com", "Comment (16 chars)", rx)
+ rset.set_apply_callback(myset_comment, _cmnt, "com", 16)
+ basic.append(rset)
+
+ # --- Other
+ rset = RadioSetting("drv_clone_speed", "Use Hi-Speed Clone",
+ RadioSettingValueBoolean(self._can_hispeed))
+ other.append(rset)
+
+ options = ["Single", "All", "Ham"]
+ rx = RadioSettingValueList(options, options[_sets.actband])
+ rset = RadioSetting("settings.actband", "Active Band", rx)
+ other.append(rset)
+
+ options = ["Slow", "Mid", "Fast", "Auto"]
+ rx = RadioSettingValueList(options, options[_sets.fanspeed])
+ rset = RadioSetting("settings.fanspeed", "Fan Speed", rx)
+ other.append(rset)
+
+ rx = RadioSettingValueBoolean(bool(_sets.dialspdup))
+ rset = RadioSetting("settings.dialspdup", "Dial Speed-Up", rx)
+ other.append(rset)
+
+ options = ["Off", "On(Dup)", "On(Dup+Tone)"]
+ rx = RadioSettingValueList(options, options[_sets.autorptr])
+ rset = RadioSetting("settings.autorptr", "Auto Repeater", rx)
+ other.append(rset)
+
+ rx = RadioSettingValueBoolean(bool(_sets.rmtmic))
+ rset = RadioSetting("settings.rmtmic",
+ "One-Touch PTT (Remote Mic)", rx)
+ other.append(rset)
+
+ options = ["Low", "Mid", "High"]
+ rx = RadioSettingValueList(options, options[_sets.vhfpower])
+ rset = RadioSetting("settings.vhfpower", "VHF Power Default", rx)
+ other.append(rset)
+
+ rx = RadioSettingValueList(options, options[_sets.uhfpower])
+ rset = RadioSetting("settings.uhfpower", "UHF Power Default", rx)
+ other.append(rset)
+
+ rx = RadioSettingValueBoolean(bool(_sets.toneburst))
+ rset = RadioSetting("settings.toneburst", "1750 Htz Tone Burst", rx)
+ other.append(rset)
+
+ rx = RadioSettingValueBoolean(bool(_sets.ifxchg))
+ rset = RadioSetting("settings.ifxchg", "IF Exchange", rx)
+ other.append(rset)
+
+ rx = RadioSettingValueBoolean(bool(_sets.rpthangup))
+ rset = RadioSetting("settings.rpthangup",
+ "Repeater Hang up Timeout", rx)
+ other.append(rset)
+
+ stx = str(_sets.civaddr)[2:] # Hex value
+ rx = RadioSettingValueString(1, 2, stx)
+ rset = RadioSetting("settings.civaddr", "CI-V Address (90)", rx)
+ rset.set_apply_callback(hex_val, _sets, "civaddr")
+ other.append(rset)
+
+ options = ["1200", "2400", "4800", "9600", "19200", "Auto"]
+ rx = RadioSettingValueList(options, options[_sets.civbaud])
+ rset = RadioSetting("settings.civbaud", "CI-V Baud Rate (bps)", rx)
+ other.append(rset)
+
+ rx = RadioSettingValueBoolean(bool(_sets.civtcvr))
+ rset = RadioSetting("settings.civtcvr", "CI-V Transceive", rx)
+ other.append(rset)
+
+ # A/B Band Settings
+ options = ["Off", "On", "Bell"]
+ rx = RadioSettingValueList(options, options[_sets.aprichn])
+ rset = RadioSetting("settings.aprichn",
+ "A Band: VFO Priority Watch Mode", rx)
+ abset.append(rset)
+
+ options = ["2", "4", "6", "8", "10", "12", "14",
+ "16", "18", "20", "Hold"]
+ rx = RadioSettingValueList(options, options[_sets.ascanpause])
+ rset = RadioSetting("settings.ascanpause",
+ "-- A Band: Scan Pause Time (Secs)", rx)
+ abset.append(rset)
+
+ options = ["0", "1", "2", "3", "4", "5", "Hold"]
+ rx = RadioSettingValueList(options, options[_sets.ascanresume])
+ rset = RadioSetting("settings.ascanresume",
+ "-- A Band: Scan Resume Time (Secs)", rx)
+ abset.append(rset)
+
+ options = ["5", "10", "15"]
+ rx = RadioSettingValueList(options, options[_sets.atmpskiptym])
+ rset = RadioSetting("settings.atmpskiptym",
+ "-- A Band: Temp Skip Time (Secs)", rx)
+ abset.append(rset)
+
+ rx = RadioSettingValueBoolean(bool(_sets.aprgskpscn))
+ rset = RadioSetting("settings.aprgskpscn",
+ "-- A Band: Program Skip Scan", rx)
+ abset.append(rset)
+
+ rx = RadioSettingValueString(10, 10, banklink(_bklk.alnk))
+ rset = RadioSetting("banklink.alnk",
+ "-- A Band Banklink (use _ to skip)", rx)
+ rset.set_apply_callback(myset_banklink, _bklk, "alnk")
+ abset.append(rset)
+
+ rx = RadioSettingValueBoolean(bool(_sets.awxalert))
+ rset = RadioSetting("settings.awxalert",
+ "-- A Band: Weather Alert", rx)
+ abset.append(rset)
+
+ # Use list for Wx chans since chan 1 = index 0
+ options = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"]
+ rx = RadioSettingValueList(options, options[_wxch.awxchan])
+ rset = RadioSetting("abwx.awxchan", "-- A Band: Weather Channel", rx)
+ abset.append(rset)
+
+ options = ["Off", "On", "Bell"]
+ rx = RadioSettingValueList(options, options[_sets.bprichn])
+ rset = RadioSetting("settings.bprichn",
+ "B Band: VFO Priority Watch Mode", rx)
+ abset.append(rset)
+
+ options = ["2", "4", "6", "8", "10", "12", "14",
+ "16", "18", "20", "Hold"]
+ rx = RadioSettingValueList(options, options[_sets.bscanpause])
+ rset = RadioSetting("settings.bscanpause",
+ "-- B Band: Scan Pause Time (Secs)", rx)
+ abset.append(rset)
+
+ options = ["0", "1", "2", "3", "4", "5", "Hold"]
+ rx = RadioSettingValueList(options, options[_sets.bscanresume])
+ rset = RadioSetting("settings.bscanresume",
+ "-- B Band: Scan Resume Time (Secs)", rx)
+ abset.append(rset)
+
+ options = ["5", "10", "15"]
+ rx = RadioSettingValueList(options, options[_sets.btmpskiptym])
+ rset = RadioSetting("settings.btmpskiptym",
+ "-- B Band: Temp Skip Time (Secs)", rx)
+ abset.append(rset)
+
+ rx = RadioSettingValueBoolean(bool(_sets.bprgskpscn))
+ rset = RadioSetting("settings.bprgskpscn",
+ "-- B Band: Program Skip Scan", rx)
+ abset.append(rset)
+
+ rx = RadioSettingValueString(10, 10, banklink(_bklk.blnk))
+ rset = RadioSetting("banklink.blnk",
+ "-- B Band Banklink (use _ to skip)", rx)
+ rset.set_apply_callback(myset_banklink, _bklk, "blnk")
+ abset.append(rset)
+
+ rx = RadioSettingValueBoolean(bool(_sets.bwxalert))
+ rset = RadioSetting("settings.bwxalert",
+ "-- B Band: Weather Alert", rx)
+ abset.append(rset)
+
+ options = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"]
+ rx = RadioSettingValueList(options, options[_wxch.bwxchan])
+ rset = RadioSetting("abwx.bwxchan", "-- B Band: Weather Channel", rx)
+ abset.append(rset)
+
+ # --- Microphone Keys
+ # The Mic keys get wierd: stored values are indecis to the full
+ # options list, but only a subset is valid...
+ shortopts = ["Off", "Monitor", "MR (Ch 0)", "MR (Ch 1)", "Band/Bank",
+ "Scan", "Temp Skip", "Mode", "Low", "Dup", "Priority",
+ "Tone", "MW", "Mute", "DTMF Direct", "T-Call"]
+ ptr = shortopts.index(MICKEYOPTS[_sets.mickyrxf1])
+ rx = RadioSettingValueList(shortopts, shortopts[ptr])
+ rset = RadioSetting("settings.mickyrxf1",
+ "During Rx/Standby [F-1]", rx)
+ rset.set_apply_callback(mic_keys, _sets, "mickyrxf1")
+ mickey.append(rset)
+
+ ptr = shortopts.index(MICKEYOPTS[_sets.mickyrxf2])
+ rx = RadioSettingValueList(shortopts, shortopts[ptr])
+ rset = RadioSetting("settings.mickyrxf2",
+ "During Rx/Standby [F-2]", rx)
+ rset.set_apply_callback(mic_keys, _sets, "mickyrxf2")
+ mickey.append(rset)
+
+ options = ["Off", "Low", "T-Call"] # NOT a subset of MICKEYOPTS
+ rx = RadioSettingValueList(options, options[_sets.mickytxf1])
+ rset = RadioSetting("settings.mickytxf1", "During Tx [F-1]", rx)
+ mickey.append(rset)
+
+ rx = RadioSettingValueList(options, options[_sets.mickytxf2])
+ rset = RadioSetting("settings.mickytxf2", "During Tx [F-2]", rx)
+ mickey.append(rset)
+
+ # These next two get the full options list
+ rx = RadioSettingValueList(MICKEYOPTS, MICKEYOPTS[_sets.mickyrxup])
+ rset = RadioSetting("settings.mickyrxup",
+ "During Rx/Standby [Up]", rx)
+ mickey.append(rset)
+
+ rx = RadioSettingValueList(MICKEYOPTS, MICKEYOPTS[_sets.mickyrxdn])
+ rset = RadioSetting("settings.mickyrxdn",
+ "During Rx/Standby [Down]", rx)
+ mickey.append(rset)
+
+ options = ["Off", "Low", "T-Call"]
+ rx = RadioSettingValueList(options, options[_sets.mickytxup])
+ rset = RadioSetting("settings.mickytxup", "During Tx [Up]", rx)
+ mickey.append(rset)
+
+ rx = RadioSettingValueList(options, options[_sets.mickytxdn])
+ rset = RadioSetting("settings.mickytxdn", "During Tx [Down]", rx)
+ mickey.append(rset)
+
+ # --- Bluetooth
+ rx = RadioSettingValueBoolean(bool(_sets.btoothon))
+ rset = RadioSetting("settings.btoothon", "Bluetooth", rx)
+ bluet.append(rset)
+
+ rx = RadioSettingValueBoolean(bool(_sets.btoothauto))
+ rset = RadioSetting("settings.btoothauto", "Auto Connect", rx)
+ bluet.append(rset)
+
+ options = ["Headset Only", "Headset & Speaker"]
+ rx = RadioSettingValueList(options, options[_sets.bthdset])
+ rset = RadioSetting("settings.bthdset", "Headset Audio", rx)
+ bluet.append(rset)
+
+ options = ["Normal", "Microphone", "PTT (Audio:Main)",
+ "PTT(Audio:Controller)"]
+ rx = RadioSettingValueList(options, options[_sets.bthfctn])
+ rset = RadioSetting("settings.bthfctn", "Headset Function", rx)
+ bluet.append(rset)
+
+ rx = RadioSettingValueBoolean(bool(_sets.bthvox))
+ rset = RadioSetting("settings.bthvox", "Vox", rx)
+ bluet.append(rset)
+
+ options = ["Off", "1.0", "2", "3", "4", "5", "6", "7", "8", "9", "10"]
+ rx = RadioSettingValueList(options, options[_sets.bthvoxlvl])
+ rset = RadioSetting("settings.bthvoxlvl", "Vox Level", rx)
+ bluet.append(rset)
+
+ options = ["0.5", "1.0", "1.5", "2.0", "2.5", "3.0"]
+ rx = RadioSettingValueList(options, options[_sets.bthvoxdly])
+ rset = RadioSetting("settings.bthvoxdly", "Vox Delay (Secs)", rx)
+ bluet.append(rset)
+
+ options = ["Off", "1", "2", "3", "4", "5", "10", "15"]
+ rx = RadioSettingValueList(options, options[_sets.bthvoxtot])
+ rset = RadioSetting("settings.bthvoxtot", "Vox Time-Out (Mins)", rx)
+ bluet.append(rset)
+
+ rx = RadioSettingValueBoolean(bool(_sets.bthhdpsav))
+ rset = RadioSetting("settings.bthhdpsav",
+ "ICOM Headset Power-Save", rx)
+ bluet.append(rset)
+
+ rx = RadioSettingValueBoolean(bool(_sets.bth1ptt))
+ rset = RadioSetting("settings.bth1ptt",
+ "ICOM Headset One-Touch PTT", rx)
+ bluet.append(rset)
+
+ rx = RadioSettingValueBoolean(bool(_sets.bthpttbeep))
+ rset = RadioSetting("settings.bthpttbeep",
+ "ICOM Headset PTT Beep", rx)
+ bluet.append(rset)
+
+ rx = RadioSettingValueBoolean(bool(_sets.bthcustbeep))
+ rset = RadioSetting("settings.bthcustbeep",
+ "ICOM Headset Custom Key Beep", rx)
+ bluet.append(rset)
+
+ rx = RadioSettingValueList(MICKEYOPTS, MICKEYOPTS[_sets.bthplaykey])
+ rset = RadioSetting("settings.bthplaykey",
+ "ICOM Headset Custom Key [Play]", rx)
+ bluet.append(rset)
+
+ rx = RadioSettingValueList(MICKEYOPTS, MICKEYOPTS[_sets.bthfwdkey])
+ rset = RadioSetting("settings.bthfwdkey",
+ "ICOM Headset Custom Key [Fwd]", rx)
+ bluet.append(rset)
+
+ rx = RadioSettingValueList(MICKEYOPTS, MICKEYOPTS[_sets.bthrwdkey])
+ rset = RadioSetting("settings.bthrwdkey",
+ "ICOM Headset Custom Key [Rwd]", rx)
+ bluet.append(rset)
+
+ # ---- Display
+ options = ["1: Dark", "2", "3", "4: Bright"]
+ rx = RadioSettingValueList(options, options[_sets.backlight])
+ rset = RadioSetting("settings.backlight", "Backlight Level", rx)
+ disp.append(rset)
+
+ options = ["Off", "Auto-Off", "Auto-1", "Auto-2", "Auto-3"]
+ rx = RadioSettingValueList(options, options[_sets.autodim])
+ rset = RadioSetting("settings.autodim", "Auto Dimmer", rx)
+ disp.append(rset)
+
+ options = ["5", "10"]
+ rx = RadioSettingValueList(options, options[_sets.autodimtot])
+ rset = RadioSetting("settings.autodimtot",
+ "Auto-Dimmer Timeout (Secs)", rx)
+ disp.append(rset)
+
+ options = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"]
+ rx = RadioSettingValueList(options, options[_sets.contrast])
+ rset = RadioSetting("settings.contrast", "LCD Contrast", rx)
+ disp.append(rset)
+
+ rx = RadioSettingValueBoolean(bool(_sets.openmsg))
+ rset = RadioSetting("settings.openmsg", "Opening Message", rx)
+ disp.append(rset)
+
+ rx = RadioSettingValueBoolean(bool(_sets.memname))
+ rset = RadioSetting("settings.memname", "Memory Names", rx)
+ disp.append(rset)
+
+ options = ["CH ID", "Frequency"]
+ rx = RadioSettingValueList(options, options[_sets.airbandch])
+ rset = RadioSetting("settings.airbandch", "Air Band Display", rx)
+ disp.append(rset)
+
+ # -- Sounds
+ rx = RadioSettingValueInteger(0, 9, _sets.beeplvl)
+ rset = RadioSetting("settings.beeplvl", "Beep Level", rx)
+ sound.append(rset)
+
+ rx = RadioSettingValueBoolean(bool(_sets.homebeep))
+ rset = RadioSetting("settings.homebeep", "Home Chan Beep", rx)
+ sound.append(rset)
+
+ rx = RadioSettingValueBoolean(bool(_sets.keybeep))
+ rset = RadioSetting("settings.keybeep", "Key Touch Beep", rx)
+ sound.append(rset)
+
+ rx = RadioSettingValueBoolean(bool(_sets.bandedgbeep))
+ rset = RadioSetting("settings.bandedgbeep", "Band Edge Beep", rx)
+ sound.append(rset)
+
+ rx = RadioSettingValueBoolean(bool(_sets.scanstpbeep))
+ rset = RadioSetting("settings.scanstpbeep", "Scan Stop Beep", rx)
+ sound.append(rset)
+
+ options = ["Off", "Mute", "Beep", "Mute & Beep"]
+ rx = RadioSettingValueList(options, options[_sets.subandmute])
+ rset = RadioSetting("settings.subandmute", "Sub Band Mute", rx)
+ sound.append(rset)
+
+ # --- DTMF Codes
+ options = ["100", "200", "300", "500"]
+ rx = RadioSettingValueList(options, options[_sets.dtmfspd])
+ rset = RadioSetting("settings.dtmfspd", "DTMF Speed (mSecs)", rx)
+ dtmf.append(rset)
+
+ for kx in range(0, 16):
+ stx = unpack_str(_dtm[kx].codes)
+ rx = RadioSettingValueString(0, 24, stx)
+ # NOTE the / to indicate indexed array
+ rset = RadioSetting("dtmfcode/%d.codes" % kx,
+ "DTMF Code %X" % kx, rx)
+ rset.set_apply_callback(pack_chars, _dtm, "codes", kx)
+ dtmf.append(rset)
+
+ # --- Program Scan Edges
+ for kx in range(0, 25):
+ stx = ""
+ for i in range(0, 6):
+ stx += chr(_pses[kx].name[i])
+ stx = stx.rstrip()
+ rx = RadioSettingValueString(0, 6, stx)
+ rset = RadioSetting("pgmscanedge/%d.name" % kx,
+ "Program Scan %d Name" % kx, rx)
+ rset.set_apply_callback(myset_psnam, _pses, kx, "name", 6)
+ edges.append(rset)
+
+ # Freq's use the multiplier flags
+ fmult = 5000.0
+ if _pses[kx].loflags == 0x10:
+ fmult = 8333
+ if _pses[kx].loflags == 0x08:
+ fmult = 6250.0
+ flow = (int(_pses[kx].lofreq) * fmult) / 1000000.0
+ flow = round(flow, 4)
+
+ fmult = 5000.0
+ if _pses[kx].hiflags == 0x10:
+ fmult = 8333
+ if _pses[kx].hiflags == 0x08:
+ fmult = 6250.0
+ fhigh = (int(_pses[kx].hifreq) * fmult) / 1000000.0
+ fhigh = round(fhigh, 4)
+ if (flow > 0) and (flow >= fhigh): # reverse em
+ val = flow
+ flow = fhigh
+ fhigh = val
+ rx = RadioSettingValueFloat(0, 550.0, flow, 0.010, 3)
+ rset = RadioSetting("pgmscanedge/%d.lofreq" % kx,
+ "-- Scan %d Low Limit" % kx, rx)
+ rset.set_apply_callback(myset_frqflgs, _pses, kx, "loflags",
+ "lofreq")
+ edges.append(rset)
+
+ rx = RadioSettingValueFloat(0, 550.0, fhigh, 0.010, 3)
+ rset = RadioSetting("pgmscanedge/%d.hifreq" % kx,
+ "-- Scan %d High Limit" % kx, rx)
+ rset.set_apply_callback(myset_frqflgs, _pses, kx, "hiflags",
+ "hifreq")
+ edges.append(rset)
+
+ # Tstep and Mode depend on the bands
+ ndxt = 0
+ ndxm = 0
+ bxnd = 0
+ tsopt = ["-", "5k", "6.25k", "10k", "12.5k", "15k",
+ "20k", "25k", "30k", "50k"]
+ mdopt = ["-", "FM", "FM-N"]
+ if fhigh > 0:
+ if fhigh < 135.0: # Air band
+ bxnd = 1
+ tsopt = ["-", "8.33k", "25k", "Auto"]
+ ndxt = _pses[kx].tstp
+ if ndxt == 0xe: # Auto
+ ndxt = 3
+ elif ndxt == 8: # 25k
+ ndxt = 2
+ elif ndxt == 2: # 8.33k
+ ndxt = 1
+ else:
+ ndxt = 0
+ mdopt = ["-"]
+ elif (flow >= 137.0) and (fhigh <= 174.0): # VHF
+ ndxt = _pses[kx].tstp - 1
+ ndxm = _pses[kx].mode + 1
+ bxnd = 2
+ elif (flow >= 375.0) and (fhigh <= 550.0): # UHF
+ ndxt = _pses[kx].tstp - 1
+ ndxm = _pses[kx].mode + 1
+ bxnd = 3
+ else: # Mixed, ndx's = 0 default
+ tsopt = ["-"]
+ mdopt = ["-"]
+ bxnd = 4
+ if (ndxt > 9) or (ndxt < 0):
+ ndxt = 0 # trap ff
+ if ndxm > 2:
+ ndxm = 0
+ # end if fhigh > 0
+ rx = RadioSettingValueList(tsopt, tsopt[ndxt])
+ rset = RadioSetting("pgmscanedge/%d.tstp" % kx,
+ "-- Scan %d Freq Step" % kx, rx)
+ rset.set_apply_callback(myset_tsopt, _pses, kx, "tstp", bxnd)
+ edges.append(rset)
+
+ rx = RadioSettingValueList(mdopt, mdopt[ndxm])
+ rset = RadioSetting("pgmscanedge/%d.mode" % kx,
+ "-- Scan %d Mode" % kx, rx)
+ rset.set_apply_callback(myset_mdopt, _pses, kx, "mode", bxnd)
+ edges.append(rset)
+ # End for kx
+
+ # --- Program Scan Links
+ _psln = self._memobj.pslnam
+ _pslg = self._memobj.pslgrps
+ for kx in range(0, 10):
+ stx = ""
+ for i in range(0, 6):
+ stx += chr(_psln[kx].nam[i])
+ stx = stx.rstrip()
+ rx = RadioSettingValueString(0, 6, stx)
+ rset = RadioSetting("pslnam/%d.nam" % kx,
+ "Program Scan Link %d Name" % kx, rx)
+ rset.set_apply_callback(myset_psnam, _psln, kx, "nam", 6)
+ pslnk.append(rset)
+
+ for px in range(0, 25):
+ # Generate string numeric representation of 4-byte bitmask
+ stx = ""
+ for nx in range(0, 25):
+ if nx < 8:
+ if (_pslg[kx].msk[0] & (1 << nx)):
+ stx += "%0d, " % nx
+ elif (nx >= 8) and (nx < 16):
+ if (_pslg[kx].msk[1] & (1 << (nx - 8))):
+ sstx += "%0d, " % nx
+ elif (nx >= 16) and (nx < 24):
+ if (_pslg[kx].msk[2] & (1 << (nx - 16))):
+ stx += "%0d, " % nx
+ elif (nx >= 24):
+ if (_pslg[kx].msk[3] & (1 << (nx - 24))):
+ stx += "%0d, " % nx
+ rx = RadioSettingValueString(0, 80, stx)
+ rset = RadioSetting("pslgrps/%d.msk" % kx,
+ "--- Scan Link %d Scans" % kx, rx)
+ rset.set_apply_callback(myset_bitmask, _pslg,
+ kx, "msk", 25)
+ pslnk.append(rset)
+ # end for px
+ # End for kx
+ return group # END get_settings()
+
+ def set_settings(self, settings):
+ _settings = self._memobj.settings
+ _mem = self._memobj
+ for element in settings:
+ if not isinstance(element, RadioSetting):
+ self.set_settings(element)
+ continue
+ else:
+ try:
+ name = element.get_name()
+ if "." in name:
+ bits = name.split(".")
+ obj = self._memobj
+ for bit in bits[:-1]:
+ if "/" in bit:
+ bit, index = bit.split("/", 1)
+ index = int(index)
+ obj = getattr(obj, bit)[index]
+ else:
+ obj = getattr(obj, bit)
+ setting = bits[-1]
+ else:
+ obj = _settings
+ setting = element.get_name()
+
+ if element.has_apply_callback():
+ LOG.debug("Using apply callback")
+ element.run_apply_callback()
+ elif element.get_name() == "drv_clone_speed":
+ val = element.value.get_value()
+ self.__class__._can_hispeed = val
+ elif element.value.get_mutable():
+ LOG.debug("Setting %s = %s" % (setting, element.value))
+ setattr(obj, setting, element.value)
+ except Exception, e:
+ LOG.debug(element.get_name())
+ raise
diff -r 1bcc885b00d0 -r d35b3cf6f047 tests/images/Icom_IC-2730A.img
Binary file tests/images/Icom_IC-2730A.img has changed
-------------- next part --------------
A non-text attachment was scrubbed...
Name: Icom_IC-2730A.img
Type: application/octet-stream
Size: 21477 bytes
Desc: not available
Url : http://intrepid.danplanet.com/pipermail/chirp_devel/attachments/20190628/ad23ce94/attachment-0001.img
More information about the chirp_devel
mailing list