[chirp_devel] Update to IC-2730A Driver
Rick DeWitt AA0RD
Wed Jun 26 07:38:31 PDT 2019
Attached is the update to the IC-2730A driver that incorporates all the
Settings tabs and fixes the C0/C1 special channels lookup error.
The referenced issue is #6711, which duplicated 2745, 4085 and 4147.
--
Rick DeWitt
AA0RD
Sequim, Washington, USA 98382
(360) 681-3494
-------------- next part --------------
# HG changeset patch
# User Rick DeWitt <aa0rd at yahoo.com>
# Date 1561559439 25200
# Wed Jun 26 07:30:39 2019 -0700
# Node ID c31a96e2f689aa038ac66343783151347e326883
# Parent bc8b50e0e189286bd57d96cf50e322ffdcbe84c5
[IC-2730a] Update to Icom IC-2730A Issue #6711
Adding settings and fixing special channels.Issue #6711
diff -r bc8b50e0e189 -r c31a96e2f689 chirp/drivers/ic2730.py
--- a/chirp/drivers/ic2730.py Thu May 30 10:06:52 2019 -0400
+++ b/chirp/drivers/ic2730.py Wed Jun 26 07:30:39 2019 -0700
@@ -1,294 +1,1284 @@
-# Copyright 2018 Rhett Robinson <rrhett at gmail.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
-# the Free Software Foundation, either version 3 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/>.
-
-from chirp.drivers import icf
-from chirp import chirp_common, util, directory, bitwise, memmap
-
-
-# Still missing:
-# - scan edges
-# - priority watch
-# - hope channel beep
-# - DTMF memory
-# - weather channel alert
-MEM_FORMAT = """
-struct {
- u24 freq_flags:6
- freq:18;
- u16 offset;
- u8 tune_step:4,
- unknown5:2,
- mode:2;
- u8 unknown6:2,
- rtone:6;
- u8 unknown7:2,
- ctone:6;
- u8 unknown8;
- u8 dtcs;
- u8 tmode:4,
- duplex:2,
- dtcs_polarity:2;
- char name[6];
-} memory[1002];
-
-#seekto 0x42c0;
-u8 used_flags[125];
-
-#seekto 0x433e;
-u8 skip_flags[125];
-u8 pskip_flags[125];
-
-#seekto 0x4440;
-struct {
- u8 bank;
- u8 index;
-} bank_info[1000];
-
-#seekto 0x4c50;
-struct {
- char name[6];
-} bank_names[10];
-
-#seekto 0x5004;
-u8 unknown12:4,
- autorptr:2,
- unknown13:2;
-
-#seekto 0x5030;
-u8 unknown14:6,
- backlight:2;
-
-#seekto 0x5056;
-u8 unknown15:6,
- power:2;
-
-#seekto 0x5220;
-u16 left_memory;
-u16 right_memory;
-
-#seekto 0x5280;
-u16 mem_writes_count;
-"""
-
-# Guessing some of these intermediate values are with the Pocket Beep function,
-# but I haven't reliably reproduced these.
-TMODES = ["", "Tone", "??0", "TSQL", "??1", "DTCS", "TSQL-R", "DTCS-R",
- "DTC.OFF", "TON.DTC", "DTC.TSQ", "TON.TSQ"]
-DUPLEX = ["", "-", "+"]
-MODES = ["FM", "NFM", "AM", "NAM"]
-DTCSP = ["NN", "NR", "RN", "RR"]
-
-AUTOREPEATER = ["OFF", "DUP", "DUP.TON"]
-
-
-class IC2730Bank(icf.IcomNamedBank):
- """An IC2730 bank"""
- def get_name(self):
- _banks = self._model._radio._memobj.bank_names
- return str(_banks[self.index].name).rstrip()
-
- def set_name(self, name):
- _banks = self._model._radio._memobj.bank_names
- _banks[self.index].name = str(name).ljust(6)[:6]
-
-
-def _get_special():
- special = {"C0": 1000,
- "C1": 1001}
- return special
-
-
-def _resolve_memory_number(number):
- if isinstance(number, str):
- return _get_special()[number]
- else:
- return number
-
-
-def _wipe_memory(mem, char):
- mem.set_raw(char * (mem.size() / 8))
-
-
- at directory.register
-class IC2730Radio(icf.IcomRawCloneModeRadio):
- """Icom IC-2730A"""
- VENDOR = "Icom"
- MODEL = "IC-2730A"
-
- _model = "\x35\x98\x00\x01"
- _memsize = 21312 # 0x5340
- _endframe = "Icom Inc\x2e4E"
-
- _ranges = [(0x0000, 0x5300, 64),
- (0x5300, 0x5310, 16),
- (0x5310, 0x5340, 48),
- ]
-
- _num_banks = 10
- _bank_class = IC2730Bank
- _can_hispeed = True
-
- def _get_bank(self, loc):
- _bank = self._memobj.bank_info[loc]
- if _bank.bank == 0x1F:
- return None
- else:
- return _bank.bank
-
- def _set_bank(self, loc, bank):
- _bank = self._memobj.bank_info[loc]
- if bank is None:
- _bank.bank = 0x1F
- else:
- _bank.bank = bank
-
- def _get_bank_index(self, loc):
- _bank = self._memobj.bank_info[loc]
- return _bank.index
-
- def _set_bank_index(self, loc, index):
- _bank = self._memobj.bank_info[loc]
- _bank.index = index
-
- def get_features(self):
- rf = chirp_common.RadioFeatures()
- rf.has_settings = True
- rf.has_bank_index = True
- rf.has_bank_names = True
- rf.requires_call_lists = False
- rf.memory_bounds = (0, 999)
- rf.valid_modes = list(MODES)
- rf.valid_tmodes = list(TMODES)
- rf.valid_duplexes = list(set(DUPLEX))
- rf.valid_tuning_steps = list(chirp_common.TUNING_STEPS[0:9])
- rf.valid_bands = [(118000000, 174000000),
- (375000000, 550000000),
- ]
- rf.valid_skips = ["", "S", "P"]
- rf.valid_characters = chirp_common.CHARSET_ASCII
- rf.valid_name_length = 6
- rf.valid_special_chans = sorted(_get_special().keys())
-
- return rf
-
- def process_mmap(self):
- 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 = 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
-
- # _mem.freq is stored as a multiple of a tuning step
- frequency_flags = int(_mem.freq_flags)
- frequency_multiplier = 5000
- offset_multiplier = 5000
- if frequency_flags & 0x08:
- 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
-
- mem.freq = int(_mem.freq) * frequency_multiplier
- 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]
- mem.duplex = DUPLEX[_mem.duplex]
- mem.mode = MODES[_mem.mode]
- mem.dtcs = chirp_common.DTCS_CODES[_mem.dtcs]
- mem.dtcs_polarity = DTCSP[_mem.dtcs_polarity]
- if _mem.tune_step > 8:
- mem.tuning_step = 5.0 # Sometimes TS is garbage?
- else:
- mem.tuning_step = chirp_common.TUNING_STEPS[_mem.tune_step]
- mem.name = str(_mem.name).rstrip()
-
- return mem
-
- def set_memory(self, mem):
- bitpos = (1 << (mem.number % 8))
- bytepos = mem.number / 8
-
- _mem = self._memobj.memory[mem.number]
- _used = self._memobj.used_flags[bytepos]
-
- 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
-
- 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")
-
- 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
- if mem.offset % 5000 != 0 and mem.offset % 6250 == 0:
- frequency_flags |= 0x01
- offset_multiplier = 6250
- _mem.freq = mem.freq / frequency_multiplier
- _mem.offset = mem.offset / offset_multiplier
- _mem.freq_flags = frequency_flags
- _mem.rtone = chirp_common.TONES.index(mem.rtone)
- _mem.ctone = chirp_common.TONES.index(mem.ctone)
- _mem.tmode = TMODES.index(mem.tmode)
- _mem.duplex = DUPLEX.index(mem.duplex)
- _mem.mode = MODES.index(mem.mode)
- _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])
+# 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
+# the Free Software Foundation, either version 3 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/>.
+
+import struct
+import logging
+
+LOG = logging.getLogger(__name__)
+
+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
+
+MEM_FORMAT = """
+struct {
+ u24 freq_flags:6
+ freq:18;
+ u16 offset;
+ u8 tune_step:4,
+ unknown5:2,
+ mode:2;
+ u8 unknown6:2,
+ rtone:6;
+ u8 unknown7:2,
+ ctone:6;
+ u8 unknown8;
+ u8 dtcs;
+ u8 tmode:4,
+ duplex:2,
+ dtcs_polarity:2;
+ char name[6];
+} memory[1002];
+
+#seekto 0x42c0;
+u8 used_flags[125];
+
+#seekto 0x433e;
+u8 skip_flags[125];
+u8 pskip_flags[125];
+
+#seekto 0x4440;
+struct {
+u8 bank;
+u8 index;
+} bank_info[1000];
+
+#seekto 0x4c40;
+struct {
+char com[16];
+} comment;
+
+#seekto 0x4c50;
+struct {
+char name[6];
+} bank_names[10];
+
+#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 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;
+"""
+
+# Guessing some of these intermediate values are with the Pocket Beep function,
+# but I haven't reliably reproduced these.
+TMODES = ["", "Tone", "??0", "TSQL", "??1", "DTCS", "TSQL-R", "DTCS-R",
+ "DTC.OFF", "TON.DTC", "DTC.TSQ", "TON.TSQ"]
+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):
+ """An IC2730 bank"""
+ def get_name(self):
+ _banks = self._model._radio._memobj.bank_names
+ return str(_banks[self.index].name).rstrip()
+
+ def set_name(self, name):
+ _banks = self._model._radio._memobj.bank_names
+ _banks[self.index].name = str(name).ljust(6)[:6]
+
+def _get_special():
+ special = {"C0": 1000, "C1": 1001}
+ return special
+
+def _resolve_memory_number(number):
+ if isinstance(number, str):
+ return _get_special()[number]
+ else:
+ return number
+
+def _wipe_memory(mem, char):
+ mem.set_raw(char * (mem.size() / 8))
+
+
+ at directory.register
+class IC2730Radio(icf.IcomRawCloneModeRadio):
+ """Icom IC-2730A"""
+ VENDOR = "Icom"
+ MODEL = "IC-2730A"
+
+ _model = "\x35\x98\x00\x01"
+ _memsize = 21312 # 0x5340
+ _endframe = "Icom Inc\x2e4E"
+
+ _ranges = [(0x0000, 0x5300, 64),
+ (0x5300, 0x5310, 16),
+ (0x5310, 0x5340, 48)]
+
+ _num_banks = 10
+ _bank_class = IC2730Bank
+ _can_hispeed = True
+
+ @classmethod
+ def get_prompts(cls):
+ rp = chirp_common.RadioPrompts()
+ rp.info = \
+ ('NOTE 1: Click the Special Channels tab on the main screen to '
+ 'view the C0 and C1 frequencies as channels 1000 and 1001.\n'
+ 'NOTE 2: CI-V is the control inteface protocol used to both'
+ ' clone and control the rig. The factory-standard CI-V address'
+ ' for the IC-2730a is hex 90.\n'
+ 'NOTE 3: If there is no audio from the B-side, check that the '
+ 'programming interface cable is removed from speaker jack 2.\n'
+ 'NOTE 4: Enabling Weather Alert will cause an interupt every '
+ '5 seconds when the band is recieving non-weather signals.\n'
+ 'Note 5: Bank names can only be editted in the radio menu.\n'
+ 'Note 6: CLONE ERROR on upload is usaually the result of an '
+ 'invalid frequency.\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:
+ return None
+ else:
+ return _bank.bank
+
+ def _set_bank(self, loc, bank):
+ _bank = self._memobj.bank_info[loc]
+ if bank is None:
+ _bank.bank = 0x1F
+ else:
+ _bank.bank = bank
+
+ def _get_bank_index(self, loc):
+ _bank = self._memobj.bank_info[loc]
+ return _bank.index
+
+ def _set_bank_index(self, loc, index):
+ _bank = self._memobj.bank_info[loc]
+ _bank.index = index
+
+ def get_features(self):
+ rf = chirp_common.RadioFeatures()
+ rf.has_settings = True
+ rf.has_bank_index = True
+ rf.has_bank_names = True
+ rf.requires_call_lists = False
+ rf.memory_bounds = (0, 999)
+ rf.valid_modes = list(MODES)
+ rf.valid_tmodes = list(TMODES)
+ rf.valid_duplexes = list(set(DUPLEX))
+ rf.valid_tuning_steps = list(chirp_common.TUNING_STEPS[0:9])
+ rf.valid_bands = [(118000000, 174000000),
+ (375000000, 550000000)]
+ rf.valid_skips = ["", "S", "P"]
+ rf.valid_characters = chirp_common.CHARSET_ASCII
+ rf.valid_name_length = 6
+ rf.valid_special_chans = sorted(_get_special().keys())
+
+ return rf
+
+ def process_mmap(self):
+ self._memobj = bitwise.parse(MEM_FORMAT, self._mmap)
+
+ def get_memory(self, number):
+ mem = chirp_common.Memory()
+ mem.number = _resolve_memory_number(number)
+ _mem = self._memobj.memory[mem.number]
+ if mem.number < 1000:
+ bitpos = (1 << (number % 8))
+ bytepos = number / 8
+ _used = self._memobj.used_flags[bytepos]
+ is_used = ((_used & bitpos) == 0)
+
+ _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
+
+ # _mem.freq is stored as a multiple of a tuning step
+ frequency_flags = int(_mem.freq_flags)
+ frequency_multiplier = 5000
+ offset_multiplier = 5000
+ if frequency_flags & 0x08:
+ frequency_multiplier = 6250
+ if frequency_flags & 0x01:
+ offset_multiplier = 6250
+ if frequency_flags & 0x10:
+ frequency_multiplier = 8333.3333
+ if frequency_flags & 0x02:
+ offset_multiplier = 8333.3333
+
+ 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]
+ mem.duplex = DUPLEX[_mem.duplex]
+ mem.mode = MODES[_mem.mode]
+ mem.dtcs = chirp_common.DTCS_CODES[_mem.dtcs]
+ mem.dtcs_polarity = DTCSP[_mem.dtcs_polarity]
+ if _mem.tune_step > 8:
+ mem.tuning_step = 5.0 # Sometimes TS is garbage?
+ else:
+ mem.tuning_step = chirp_common.TUNING_STEPS[_mem.tune_step]
+ mem.name = str(_mem.name).rstrip()
+ if mem.number == 1000: mem.name = "C0"
+ if mem.number == 1001: mem.name = "C1"
+
+ return mem
+
+ def set_memory(self, mem):
+ bitpos = (1 << (mem.number % 8))
+ bytepos = mem.number / 8
+
+ _mem = self._memobj.memory[mem.number]
+ _used = self._memobj.used_flags[bytepos]
+
+ 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
+
+ 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")
+
+ 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.3333 == 0:
+ frequency_flags |= 0x10
+ frequency_multiplier = 8333.3333
+ if mem.offset % 5000 != 0 and mem.offset % 6250 == 0:
+ frequency_flags |= 0x01
+ offset_multiplier = 6250
+ elif mem.offset % 8333.3333 == 0:
+ frequency_flags |= 0x02
+ offset_multiplier = 8333.3333
+ _mem.freq = mem.freq / frequency_multiplier
+ _mem.offset = mem.offset / offset_multiplier
+ _mem.freq_flags = frequency_flags
+ _mem.rtone = chirp_common.TONES.index(mem.rtone)
+ _mem.ctone = chirp_common.TONES.index(mem.ctone)
+ _mem.tmode = TMODES.index(mem.tmode)
+ _mem.duplex = DUPLEX.index(mem.duplex)
+ _mem.mode = MODES.index(mem.mode)
+ _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:
+ #stx += str(int(val(codestr[i]), 16)[2:])
+ 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, uooercase 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.3333)
+ 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:
+ 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.3333
+ 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.3333
+ 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
+
More information about the chirp_devel
mailing list