Developers
Threads by month
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
June 2014
- 8 participants
- 14 discussions
[chirp_devel] [PATCH] [RFC] Abstract Bank and BankModel to MemoryMapping and MappingModel
by Dan Smith 24 Aug '16
by Dan Smith 24 Aug '16
24 Aug '16
# HG changeset patch
# User Dan Smith <dsmith(a)danplanet.com>
# Date 1364678018 25200
# Node ID bf1c92a33bfd4c730dcc49095ff9a737b30c33c0
# Parent ede5a4ccfd6efbaed4883c86d93be92509fde8da
[RFC] Abstract Bank and BankModel to MemoryMapping and MappingModel
This is mostly just a search-and-replace for the above names, but makes
way for supporting things like scan lists that behave exactly the same
way.
diff -r ede5a4ccfd6e -r bf1c92a33bfd chirp/chirp_common.py
--- a/chirp/chirp_common.py Sat Mar 30 13:51:51 2013 -0700
+++ b/chirp/chirp_common.py Sat Mar 30 14:13:38 2013 -0700
@@ -543,8 +543,8 @@
except Exception:
self.dv_code = 0
-class Bank:
- """Base class for a radio's Bank"""
+class MemoryMapping(object):
+ """Base class for a memory mapping"""
def __init__(self, model, index, name):
self._model = model
self._index = index
@@ -554,76 +554,84 @@
return self.get_name()
def __repr__(self):
- return "Bank-%s" % self._index
+ return "%s-%s" % (self.__class__.__name__, self._index)
def get_name(self):
- """Returns the static or user-adjustable bank name"""
+ """Returns the mapping name"""
return self._name
def get_index(self):
- """Returns the immutable bank index (string or int)"""
+ """Returns the immutable index (string or int)"""
return self._index
def __eq__(self, other):
return self.get_index() == other.get_index()
+class MappingModel(object):
+ """Base class for a memory mapping model"""
+
+ def __init__(self, radio):
+ self._radio = radio
+
+ def get_num_mappings(self):
+ """Returns the number of mappings in the model (should be
+ callable without consulting the radio"""
+ raise NotImplementedError()
+
+ def get_mappings(self):
+ """Return a list of mappings"""
+ raise NotImplementedError()
+
+ def add_memory_to_mapping(self, memory, mapping):
+ """Add @memory to @mapping."""
+ raise NotImplementedError()
+
+ def remove_memory_from_mapping(self, memory, mapping):
+ """Remove @memory from @mapping.
+ Shall raise exception if @memory is not in @bank"""
+ raise NotImplementedError()
+
+ def get_mapping_memories(self, mapping):
+ """Return a list of memories in @mapping"""
+ raise NotImplementedError()
+
+ def get_memory_mappings(self, memory):
+ """Return a list of mappings that @memory is in"""
+ raise NotImplementedError()
+
+class Bank(MemoryMapping):
+ """Base class for a radio's Bank"""
+ pass
+
class NamedBank(Bank):
"""A bank that can have a name"""
def set_name(self, name):
"""Changes the user-adjustable bank name"""
self._name = name
-class BankModel:
+class BankModel(MappingModel):
"""A bank model where one memory is in zero or one banks at any point"""
- def __init__(self, radio):
- self._radio = radio
+ pass
- def get_num_banks(self):
- """Returns the number of banks (should be callable without
- consulting the radio"""
+class MappingModelIndexInterface:
+ """Interface for mappings with index capabilities"""
+ def get_index_bounds(self):
+ """Returns a tuple (lo,hi) of the min and max mapping indices"""
raise Exception("Not implemented")
- def get_banks(self):
- """Return a list of banks"""
+ def get_memory_index(self, memory, mapping):
+ """Returns the index of @memory in @mapping"""
raise Exception("Not implemented")
- def add_memory_to_bank(self, memory, bank):
- """Add @memory to @bank."""
+ def set_memory_index(self, memory, mapping, index):
+ """Sets the index of @memory in @mapping to @index"""
raise Exception("Not implemented")
- def remove_memory_from_bank(self, memory, bank):
- """Remove @memory from @bank.
- Shall raise exception if @memory is not in @bank."""
- raise Exception("Not implemented")
-
- def get_bank_memories(self, bank):
- """Return a list of memories in @bank"""
- raise Exception("Not implemented")
-
- def get_memory_banks(self, memory):
- """Returns a list of the banks that @memory is in"""
- raise Exception("Not implemented")
-
-class BankIndexInterface:
- """Interface for banks with index capabilities"""
- def get_index_bounds(self):
- """Returns a tuple (lo,hi) of the minimum and maximum bank indices"""
- raise Exception("Not implemented")
-
- def get_memory_index(self, memory, bank):
- """Returns the index of @memory in @bank"""
- raise Exception("Not implemented")
-
- def set_memory_index(self, memory, bank, index):
- """Sets the index of @memory in @bank to @index"""
- raise Exception("Not implemented")
-
- def get_next_bank_index(self, bank):
- """Returns the next available bank index in @bank, or raises
+ def get_next_mapping_index(self, mapping):
+ """Returns the next available mapping index in @mapping, or raises
Exception if full"""
raise Exception("Not implemented")
-
class MTOBankModel(BankModel):
"""A bank model where one memory can be in multiple banks at once """
pass
diff -r ede5a4ccfd6e -r bf1c92a33bfd chirp/ft7800.py
--- a/chirp/ft7800.py Sat Mar 30 13:51:51 2013 -0700
+++ b/chirp/ft7800.py Sat Mar 30 14:13:38 2013 -0700
@@ -336,7 +336,7 @@
class FT7800BankModel(chirp_common.BankModel):
"""Yaesu FT-7800/7900 bank model"""
def __init__(self, radio):
- chirp_common.BankModel.__init__(self, radio)
+ super(FT7800BankModel, self).__init__(radio)
self.__b2m_cache = defaultdict(list)
self.__m2b_cache = defaultdict(list)
@@ -344,24 +344,24 @@
if self.__b2m_cache:
return
- for bank in self.get_banks():
+ for bank in self.get_mappings():
self.__b2m_cache[bank.index] = self._get_bank_memories(bank)
for memnum in self.__b2m_cache[bank.index]:
self.__m2b_cache[memnum].append(bank.index)
- def get_num_banks(self):
+ def get_num_mappings(self):
return 20
- def get_banks(self):
+ def get_mappings(self):
banks = []
- for i in range(0, self.get_num_banks()):
+ for i in range(0, self.get_num_mappings()):
bank = chirp_common.Bank(self, "%i" % i, "BANK-%i" % (i + 1))
bank.index = i
banks.append(bank)
return banks
- def add_memory_to_bank(self, memory, bank):
+ def add_memory_to_mapping(self, memory, bank):
self.__precache()
index = memory.number - 1
@@ -371,7 +371,7 @@
self.__m2b_cache[memory.number].append(bank.index)
self.__b2m_cache[bank.index].append(memory.number)
- def remove_memory_from_bank(self, memory, bank):
+ def remove_memory_from_mapping(self, memory, bank):
self.__precache()
index = memory.number - 1
@@ -395,16 +395,16 @@
memories.append(i + 1)
return memories
- def get_bank_memories(self, bank):
+ def get_mapping_memories(self, bank):
self.__precache()
return [self._radio.get_memory(n)
for n in self.__b2m_cache[bank.index]]
- def get_memory_banks(self, memory):
+ def get_memory_mappings(self, memory):
self.__precache()
- _banks = self.get_banks()
+ _banks = self.get_mappings()
return [_banks[b] for b in self.__m2b_cache[memory.number]]
@directory.register
@@ -473,7 +473,7 @@
"""
class FT8800BankModel(FT7800BankModel):
- def get_num_banks(self):
+ def get_num_mappings(self):
return 10
@directory.register
diff -r ede5a4ccfd6e -r bf1c92a33bfd chirp/icf.py
--- a/chirp/icf.py Sat Mar 30 13:51:51 2013 -0700
+++ b/chirp/icf.py Sat Mar 30 14:13:38 2013 -0700
@@ -485,10 +485,10 @@
central implementation can, with a few icom-specific radio interfaces
serve most/all of them"""
- def get_num_banks(self):
+ def get_num_mappings(self):
return self._radio._num_banks
- def get_banks(self):
+ def get_mappings(self):
banks = []
for i in range(0, self._radio._num_banks):
@@ -498,31 +498,32 @@
banks.append(bank)
return banks
- def add_memory_to_bank(self, memory, bank):
+ def add_memory_to_mapping(self, memory, bank):
self._radio._set_bank(memory.number, bank.index)
- def remove_memory_from_bank(self, memory, bank):
+ def remove_memory_from_mapping(self, memory, bank):
if self._radio._get_bank(memory.number) != bank.index:
raise Exception("Memory %i not in bank %s. Cannot remove." % \
(memory.number, bank))
self._radio._set_bank(memory.number, None)
- def get_bank_memories(self, bank):
+ def get_bank_mappings(self, bank):
memories = []
for i in range(*self._radio.get_features().memory_bounds):
if self._radio._get_bank(i) == bank.index:
memories.append(self._radio.get_memory(i))
return memories
- def get_memory_banks(self, memory):
+ def get_memory_mappings(self, memory):
index = self._radio._get_bank(memory.number)
if index is None:
return []
else:
- return [self.get_banks()[index]]
+ return [self.get_mappings()[index]]
-class IcomIndexedBankModel(IcomBankModel, chirp_common.BankIndexInterface):
+class IcomIndexedBankModel(IcomBankModel,
+ chirp_common.MappingModelIndexInterface):
"""Generic bank model for Icom radios with indexed banks"""
def get_index_bounds(self):
return self._radio._bank_index_bounds
@@ -531,7 +532,7 @@
return self._radio._get_bank_index(memory.number)
def set_memory_index(self, memory, bank, index):
- if bank not in self.get_memory_banks(memory):
+ if bank not in self.get_memory_mappings(memory):
raise Exception("Memory %i is not in bank %s" % (memory.number,
bank))
@@ -539,7 +540,7 @@
raise Exception("Invalid index")
self._radio._set_bank_index(memory.number, index)
- def get_next_bank_index(self, bank):
+ def get_next_mapping_index(self, bank):
indexes = []
for i in range(*self._radio.get_features().memory_bounds):
if self._radio._get_bank(i) == bank.index:
diff -r ede5a4ccfd6e -r bf1c92a33bfd chirp/vx3.py
--- a/chirp/vx3.py Sat Mar 30 13:51:51 2013 -0700
+++ b/chirp/vx3.py Sat Mar 30 14:13:38 2013 -0700
@@ -110,10 +110,10 @@
class VX3BankModel(chirp_common.BankModel):
"""A VX-3 bank model"""
- def get_num_banks(self):
+ def get_num_mappings(self):
return 24
- def get_banks(self):
+ def get_mappings(self):
_banks = self._radio._memobj.bank_names
banks = []
diff -r ede5a4ccfd6e -r bf1c92a33bfd chirp/vx5.py
--- a/chirp/vx5.py Sat Mar 30 13:51:51 2013 -0700
+++ b/chirp/vx5.py Sat Mar 30 14:13:38 2013 -0700
@@ -82,18 +82,18 @@
chirp_common.PowerLevel("L1", watts=0.05)]
class VX5BankModel(chirp_common.BankModel):
- def get_num_banks(self):
+ def get_num_mappings(self):
return 5
- def get_banks(self):
+ def get_mappings(self):
banks = []
- for i in range(0, self.get_num_banks()):
+ for i in range(0, self.get_num_mappings()):
bank = chirp_common.Bank(self, "%i" % (i+1), "MG%i" % (i+1))
bank.index = i
banks.append(bank)
return banks
- def add_memory_to_bank(self, memory, bank):
+ def add_memory_to_mapping(self, memory, bank):
_members = self._radio._memobj.bank_groups[bank.index].members
_bank_used = self._radio._memobj.bank_used[bank.index]
for i in range(0, len(_members)):
@@ -107,7 +107,7 @@
return True
raise Exception(_("{bank} is full").format(bank=bank))
- def remove_memory_from_bank(self, memory, bank):
+ def remove_memory_from_mapping(self, memory, bank):
_members = self._radio._memobj.bank_groups[bank.index].members
_bank_used = self._radio._memobj.bank_used[bank.index]
@@ -128,7 +128,7 @@
if not remaining_members:
_bank_used.current_member = 0xFF
- def get_bank_memories(self, bank):
+ def get_mapping_memories(self, bank):
memories = []
_members = self._radio._memobj.bank_groups[bank.index].members
@@ -143,10 +143,11 @@
memories.append(self._radio.get_memory(member.channel+1))
return memories
- def get_memory_banks(self, memory):
+ def get_memory_mappings(self, memory):
banks = []
- for bank in self.get_banks():
- if memory.number in [x.number for x in self.get_bank_memories(bank)]:
+ for bank in self.get_mappings():
+ if memory.number in [x.number for x in
+ self.get_mapping_memories(bank)]:
banks.append(bank)
return banks
diff -r ede5a4ccfd6e -r bf1c92a33bfd chirp/vx7.py
--- a/chirp/vx7.py Sat Mar 30 13:51:51 2013 -0700
+++ b/chirp/vx7.py Sat Mar 30 14:13:38 2013 -0700
@@ -103,18 +103,18 @@
class VX7BankModel(chirp_common.BankModel):
"""A VX-7 Bank model"""
- def get_num_banks(self):
+ def get_num_mappings(self):
return 9
- def get_banks(self):
+ def get_mappings(self):
banks = []
- for i in range(0, self.get_num_banks()):
+ for i in range(0, self.get_num_mappings()):
bank = chirp_common.Bank(self, "%i" % (i+1), "MG%i" % (i+1))
bank.index = i
banks.append(bank)
return banks
- def add_memory_to_bank(self, memory, bank):
+ def add_memory_to_mapping(self, memory, bank):
_members = self._radio._memobj.bank_members[bank.index]
_bank_used = self._radio._memobj.bank_used[bank.index]
for i in range(0, 48):
@@ -123,7 +123,7 @@
_bank_used.in_use = 0x0000
break
- def remove_memory_from_bank(self, memory, bank):
+ def remove_memory_from_mapping(self, memory, bank):
_members = self._radio._memobj.bank_members[bank.index].members
_bank_used = self._radio._memobj.bank_used[bank.index]
@@ -143,7 +143,7 @@
if not remaining_members:
_bank_used.in_use = 0xFFFF
- def get_bank_memories(self, bank):
+ def get_mapping_memories(self, bank):
memories = []
_members = self._radio._memobj.bank_members[bank.index].members
@@ -158,11 +158,11 @@
memories.append(self._radio.get_memory(number+1))
return memories
- def get_memory_banks(self, memory):
+ def get_memory_mappings(self, memory):
banks = []
- for bank in self.get_banks():
+ for bank in self.get_mappings():
if memory.number in [x.number for x in
- self.get_bank_memories(bank)]:
+ self.get_mapping_memories(bank)]:
banks.append(bank)
return banks
diff -r ede5a4ccfd6e -r bf1c92a33bfd chirp/vx8.py
--- a/chirp/vx8.py Sat Mar 30 13:51:51 2013 -0700
+++ b/chirp/vx8.py Sat Mar 30 14:13:38 2013 -0700
@@ -151,10 +151,10 @@
class VX8BankModel(chirp_common.BankModel):
"""A VX-8 bank model"""
- def get_num_banks(self):
+ def get_num_mappings(self):
return 24
- def get_banks(self):
+ def get_mappings(self):
banks = []
_banks = self._radio._memobj.bank_info
@@ -174,7 +174,7 @@
flags = self._radio._memobj.flag
# Find a suitable bank and MR for VFO A and B.
- for bank in self.get_banks():
+ for bank in self.get_mappings():
bank_used = self._radio._memobj.bank_used[bank.index]
if bank_used != 0xFFFF:
members = self._radio._memobj.bank_members[bank.index]
@@ -213,7 +213,7 @@
vfo_bak.mr_index = vfo.mr_index
vfo_bak.bank_enable = vfo.bank_enable
- def add_memory_to_bank(self, memory, bank):
+ def add_memory_to_mapping(self, memory, bank):
_members = self._radio._memobj.bank_members[bank.index]
_bank_used = self._radio._memobj.bank_used[bank.index]
for i in range(0, 100):
@@ -224,7 +224,7 @@
self.update_vfo()
- def remove_memory_from_bank(self, memory, bank):
+ def remove_memory_from_mapping(self, memory, bank):
_members = self._radio._memobj.bank_members[bank.index]
_bank_used = self._radio._memobj.bank_used[bank.index]
@@ -246,7 +246,7 @@
self.update_vfo()
- def get_bank_memories(self, bank):
+ def get_mapping_memories(self, bank):
memories = []
_members = self._radio._memobj.bank_members[bank.index]
_bank_used = self._radio._memobj.bank_used[bank.index]
@@ -260,11 +260,11 @@
return memories
- def get_memory_banks(self, memory):
+ def get_memory_mappings(self, memory):
banks = []
- for bank in self.get_banks():
+ for bank in self.get_mappings():
if memory.number in \
- [x.number for x in self.get_bank_memories(bank)]:
+ [x.number for x in self.get_mapping_memories(bank)]:
banks.append(bank)
return banks
diff -r ede5a4ccfd6e -r bf1c92a33bfd chirpui/bankedit.py
--- a/chirpui/bankedit.py Sat Mar 30 13:51:51 2013 -0700
+++ b/chirpui/bankedit.py Sat Mar 30 14:13:38 2013 -0700
@@ -22,68 +22,70 @@
from chirp import chirp_common
from chirpui import common, miscwidgets
-class BankNamesJob(common.RadioJob):
- def __init__(self, bm, editor, cb):
+class MappingNamesJob(common.RadioJob):
+ def __init__(self, model, editor, cb):
common.RadioJob.__init__(self, cb, None)
- self.__bm = bm
+ self.__model = model
self.__editor = editor
def execute(self, radio):
- self.__editor.banks = []
+ self.__editor.mappings = []
- banks = self.__bm.get_banks()
- for bank in banks:
- self.__editor.banks.append((bank, bank.get_name()))
+ mappings = self.__model.get_mappings()
+ for mapping in mappings:
+ self.__editor.mappings.append((mapping, mapping.get_name()))
gobject.idle_add(self.cb, *self.cb_args)
-class BankNameEditor(common.Editor):
+class MappingNameEditor(common.Editor):
+ TYPE = _("Mapping")
+
def refresh(self):
- def got_banks():
+ def got_mappings():
self._keys = []
- for bank, name in self.banks:
- self._keys.append(bank.get_index())
- self.listw.set_item(bank.get_index(),
- bank.get_index(),
+ for mapping, name in self.mappings:
+ self._keys.append(mapping.get_index())
+ self.listw.set_item(mapping.get_index(),
+ mapping.get_index(),
name)
- self.listw.connect("item-set", self.bank_changed)
+ self.listw.connect("item-set", self.mapping_changed)
- job = BankNamesJob(self._bm, self, got_banks)
- job.set_desc(_("Retrieving bank information"))
+ job = MappingNamesJob(self._model, self, got_mappings)
+ job.set_desc(_("Retrieving %s information") % self.TYPE)
self.rthread.submit(job)
- def get_bank_list(self):
- banks = []
+ def get_mapping_list(self):
+ mappings = []
keys = self.listw.get_keys()
for key in keys:
- banks.append(self.listw.get_item(key)[2])
+ mappings.append(self.listw.get_item(key)[2])
- return banks
-
- def bank_changed(self, listw, key):
+ return mappings
+
+ def mapping_changed(self, listw, key):
def cb(*args):
self.emit("changed")
name = self.listw.get_item(key)[2]
- bank, oldname = self.banks[self._keys.index(key)]
+ mapping, oldname = self.mappings[self._keys.index(key)]
def trigger_changed(*args):
self.emit("changed")
job = common.RadioJob(trigger_changed, "set_name", name)
- job.set_target(bank)
- job.set_desc(_("Setting name on bank"))
+ job.set_target(mapping)
+ job.set_desc(_("Setting name on %s") % self.TYPE.lower())
self.rthread.submit(job)
return True
- def __init__(self, rthread):
- super(BankNameEditor, self).__init__(rthread)
- self._bm = rthread.radio.get_bank_model()
+ def __init__(self, rthread, model):
+ super(MappingNameEditor, self).__init__(rthread)
+ self._model = model
types = [(gobject.TYPE_STRING, "key"),
- (gobject.TYPE_STRING, _("Bank")),
+ (gobject.TYPE_STRING, self.TYPE),
(gobject.TYPE_STRING, _("Name"))]
self.listw = miscwidgets.KeyedListWidget(types)
@@ -92,7 +94,7 @@
self.listw.set_sort_column(1, -1)
self.listw.show()
- self.banks = []
+ self.mappings = []
sw = gtk.ScrolledWindow()
sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
@@ -108,51 +110,61 @@
self.refresh()
self._loaded = True
-class MemoryBanksJob(common.RadioJob):
- def __init__(self, bm, cb, number):
+class BankNameEditor(MappingNameEditor):
+ TYPE = _("Bank")
+
+ def __init__(self, rthread):
+ model = rthread.radio.get_bank_model()
+ super(BankNameEditor, self).__init__(rthread, model)
+
+class MemoryMappingsJob(common.RadioJob):
+ def __init__(self, model, cb, number):
common.RadioJob.__init__(self, cb, None)
- self.__bm = bm
+ self.__model = model
self.__number = number
def execute(self, radio):
mem = radio.get_memory(self.__number)
if mem.empty:
- banks = []
+ mappings = []
indexes = []
else:
- banks = self.__bm.get_memory_banks(mem)
+ mappings = self.__model.get_memory_mappings(mem)
indexes = []
- if isinstance(self.__bm, chirp_common.BankIndexInterface):
- for bank in banks:
- indexes.append(self.__bm.get_memory_index(mem, bank))
- self.cb(mem, banks, indexes, *self.cb_args)
+ if isinstance(self.__model,
+ chirp_common.MappingModelIndexInterface):
+ for mapping in mappings:
+ indexes.append(self.__model.get_memory_index(mem, mapping))
+ self.cb(mem, mappings, indexes, *self.cb_args)
-class BankMembershipEditor(common.Editor):
+class MappingMembershipEditor(common.Editor):
+ TYPE = _("Mapping")
+
def _number_to_path(self, number):
return (number - self._rf.memory_bounds[0],)
- def _get_next_bank_index(self, bank):
- # NB: Only works for one-to-one bank models right now!
+ def _get_next_mapping_index(self, mapping):
+ # NB: Only works for one-to-one models right now!
iter = self._store.get_iter_first()
indexes = []
- ncols = len(self._cols) + len(self.banks)
+ ncols = len(self._cols) + len(self.mappings)
while iter:
vals = self._store.get(iter, *tuple([n for n in range(0, ncols)]))
loc = vals[self.C_LOC]
index = vals[self.C_INDEX]
- banks = vals[self.C_BANKS:]
- if True in banks and banks.index(True) == bank:
+ mappings = vals[self.C_MAPPINGS:]
+ if True in mappings and mappings.index(True) == mapping:
indexes.append(index)
iter = self._store.iter_next(iter)
- index_bounds = self._bm.get_index_bounds()
+ index_bounds = self._model.get_index_bounds()
num_indexes = index_bounds[1] - index_bounds[0]
indexes.sort()
for i in range(0, num_indexes):
if i not in indexes:
return i + index_bounds[0] # In case not zero-origin index
- return 0 # If the bank is full, just wrap around!
+ return 0 # If the mapping is full, just wrap around!
def _toggled_cb(self, rend, path, colnum):
try:
@@ -164,56 +176,60 @@
if not self._store.get(iter, self.C_FILLED)[0]:
return
- # The bank index is the column number, minus the 3 label columns
- bank, name = self.banks[colnum - len(self._cols)]
+ # The mapping index is the column number, minus the 3 label columns
+ mapping, name = self.mappings[colnum - len(self._cols)]
loc, = self._store.get(self._store.get_iter(path), self.C_LOC)
+ is_indexed = isinstance(self._model,
+ chirp_common.MappingModelIndexInterface)
+
if rend.get_active():
# Changing from True to False
- fn = "remove_memory_from_bank"
+ fn = "remove_memory_from_mapping"
index = None
else:
# Changing from False to True
- fn = "add_memory_to_bank"
- if self._rf.has_bank_index:
- index = self._get_next_bank_index(colnum - len(self._cols))
+ fn = "add_memory_to_mapping"
+ if is_indexed:
+ index = self._get_next_mapping_index(colnum - len(self._cols))
else:
index = None
def do_refresh_memory(*args):
- # Step 2: Update our notion of the memory's bank information
+ # Step 2: Update our notion of the memory's mapping information
self.refresh_memory(loc)
- def do_bank_index(result, memory):
+ def do_mapping_index(result, memory):
if isinstance(result, Exception):
- common.show_error("Failed to add {mem} to bank: {err}"
+ common.show_error("Failed to add {mem} to mapping: {err}"
.format(mem=memory.number,
err=str(result)),
parent=self.editorset.parent_window)
return
self.emit("changed")
- # Step 3: Set the memory's bank index (maybe)
- if not self._rf.has_bank_index or index is None:
+ # Step 3: Set the memory's mapping index (maybe)
+ if not is_indexed or index is None:
return do_refresh_memory()
job = common.RadioJob(do_refresh_memory,
- "set_memory_index", memory, bank, index)
- job.set_target(self._bm)
- job.set_desc(_("Updating bank index "
- "for memory {num}").format(num=memory.number))
+ "set_memory_index", memory, mapping, index)
+ job.set_target(self._model)
+ job.set_desc(_("Updating {type} index "
+ "for memory {num}").format(type=self.TYPE,
+ num=memory.number))
self.rthread.submit(job)
- def do_bank_adjustment(memory):
- # Step 1: Do the bank add/remove
- job = common.RadioJob(do_bank_index, fn, memory, bank)
- job.set_target(self._bm)
+ def do_mapping_adjustment(memory):
+ # Step 1: Do the mapping add/remove
+ job = common.RadioJob(do_mapping_index, fn, memory, mapping)
+ job.set_target(self._model)
job.set_cb_args(memory)
- job.set_desc(_("Updating bank information "
+ job.set_desc(_("Updating mapping information "
"for memory {num}").format(num=memory.number))
self.rthread.submit(job)
# Step 0: Fetch the memory
- job = common.RadioJob(do_bank_adjustment, "get_memory", loc)
+ job = common.RadioJob(do_mapping_adjustment, "get_memory", loc)
job.set_desc(_("Getting memory {num}").format(num=loc))
self.rthread.submit(job)
@@ -223,36 +239,37 @@
def refresh_memory(*args):
self.refresh_memory(loc)
- def set_index(banks, memory):
+ def set_index(mappings, memory):
self.emit("changed")
# Step 2: Set the index
job = common.RadioJob(refresh_memory, "set_memory_index",
- memory, banks[0], int(new))
- job.set_target(self._bm)
+ memory, mappings[0], int(new))
+ job.set_target(self._model)
job.set_desc(_("Setting index "
"for memory {num}").format(num=memory.number))
self.rthread.submit(job)
- def get_bank(memory):
- # Step 1: Get the first/only bank
- job = common.RadioJob(set_index, "get_memory_banks", memory)
+ def get_mapping(memory):
+ # Step 1: Get the first/only mapping
+ job = common.RadioJob(set_index, "get_memory_mappings", memory)
job.set_cb_args(memory)
- job.set_target(self._bm)
- job.set_desc(_("Getting bank for "
- "memory {num}").format(num=memory.number))
+ job.set_target(self._model)
+ job.set_desc(_("Getting {type} for "
+ "memory {num}").format(type=self.TYPE,
+ num=memory.number))
self.rthread.submit(job)
# Step 0: Get the memory
- job = common.RadioJob(get_bank, "get_memory", loc)
+ job = common.RadioJob(get_mapping, "get_memory", loc)
job.set_desc(_("Getting memory {num}").format(num=loc))
self.rthread.submit(job)
- def __init__(self, rthread, editorset):
- super(BankMembershipEditor, self).__init__(rthread)
+ def __init__(self, rthread, editorset, model):
+ super(MappingMembershipEditor, self).__init__(rthread)
self.editorset = editorset
self._rf = rthread.radio.get_features()
- self._bm = rthread.radio.get_bank_model()
+ self._model = model
self._view_cols = [
(_("Loc"), TYPE_INT, gtk.CellRendererText, ),
@@ -270,19 +287,22 @@
self.C_FREQ = 2
self.C_NAME = 3
self.C_INDEX = 4
- self.C_BANKS = 5 # and beyond
+ self.C_MAPPINGS = 5 # and beyond
cols = list(self._cols)
self._index_cache = []
- for i in range(0, self._bm.get_num_banks()):
- label = "Bank %i" % (i+1)
+ for i in range(0, self._model.get_num_mappings()):
+ label = "%s %i" % (self.TYPE, (i+1))
cols.append((label, TYPE_BOOLEAN, gtk.CellRendererToggle))
self._store = gtk.ListStore(*tuple([y for x,y,z in cols]))
self._view = gtk.TreeView(self._store)
+ is_indexed = isinstance(self._model,
+ chirp_common.MappingModelIndexInterface)
+
colnum = 0
for label, dtype, rtype in cols:
if not rtype:
@@ -305,7 +325,7 @@
elif colnum == self.C_INDEX:
rend.set_property("editable", True)
rend.connect("edited", self._index_edited_cb)
- col.set_visible(self._rf.has_bank_index)
+ col.set_visible(is_indexed)
colnum += 1
# A non-rendered column to absorb extra space in the row
@@ -329,7 +349,7 @@
self._loaded = False
def refresh_memory(self, number):
- def got_mem(memory, banks, indexes):
+ def got_mem(memory, mappings, indexes):
iter = self._store.get_iter(self._number_to_path(memory.number))
row = [self.C_FILLED, not memory.empty,
self.C_LOC, memory.number,
@@ -338,29 +358,30 @@
# Hack for only one index right now
self.C_INDEX, indexes and indexes[0] or 0,
]
- for i in range(0, len(self.banks)):
+ for i in range(0, len(self.mappings)):
row.append(i + len(self._cols))
- row.append(self.banks[i][0] in banks)
+ row.append(self.mappings[i][0] in mappings)
self._store.set(iter, *tuple(row))
if memory.number == self._rf.memory_bounds[1] - 1:
- print "Got all bank info in %s" % (time.time() - self._start)
+ print "Got all %s info in %s" % (self.TYPE,
+ (time.time() - self._start))
- job = MemoryBanksJob(self._bm, got_mem, number)
- job.set_desc(_("Getting bank information "
- "for memory {num}").format(num=number))
+ job = MemoryMappingsJob(self._model, got_mem, number)
+ job.set_desc(_("Getting {type} information "
+ "for memory {num}").format(type=self.TYPE, num=number))
self.rthread.submit(job)
def refresh_all_memories(self):
for i in range(*self._rf.memory_bounds):
self.refresh_memory(i)
- def refresh_banks(self, and_memories=False):
- def got_banks():
+ def refresh_mappings(self, and_memories=False):
+ def got_mappings():
for i in range(len(self._cols) - len(self._view_cols) - 1,
- len(self.banks)):
+ len(self.mappings)):
col = self._view.get_column(i + len(self._view_cols))
- bank, name = self.banks[i]
+ mapping, name = self.mappings[i]
if name:
col.set_title(name)
else:
@@ -368,8 +389,8 @@
if and_memories:
self.refresh_all_memories()
- job = BankNamesJob(self._bm, self, got_banks)
- job.set_desc(_("Getting bank information"))
+ job = MappingNamesJob(self._model, self, got_mappings)
+ job.set_desc(_("Getting %s information") % self.TYPE)
self.rthread.submit(job)
def focus(self):
@@ -378,7 +399,7 @@
return
self._start = time.time()
- self.refresh_banks(True)
+ self.refresh_mappings(True)
self._loaded = True
@@ -387,5 +408,15 @@
if self.is_focused():
self.refresh_all_memories()
+ def mappings_changed(self):
+ self.refresh_mappings()
+
+class BankMembershipEditor(MappingMembershipEditor):
+ TYPE = _("Bank")
+
+ def __init__(self, rthread, editorset):
+ model = rthread.radio.get_bank_model()
+ super(BankMembershipEditor, self).__init__(rthread, editorset, model)
+
def banks_changed(self):
- self.refresh_banks()
+ self.mappings_changed()
2
3
Re: [chirp_devel] I'd like to add some features to the developer tools
by chirp.cordless@xoxy.net 17 Sep '14
by chirp.cordless@xoxy.net 17 Sep '14
17 Sep '14
Tom, thanks for responding.
On Jun 4, 2014, at 12:42 PM, Tom Hayward - esarfl(a)gmail.com
> I'm not sure I understand everything you're suggesting. If you have
> already implemented this, can send the changes in patch format so I
> can try them myself?
Yes, implemented and working for several months now.
I will do that today. Privately, just to keep the noise level down.
> Most of the time, I like having full context in the memory diff. It's
> not like it's very long.
> I don't understand why a negative channel number was chosen to enable
> this feature. Wouldn't a checkbox be more appropriate?
Well, channel -1 to enable the diff was what was built into Chirp to enable
the diff when I showed up here. It's not advertised, I discovered it from
browsing the code. See mainapp.py line 212.
Using -2 for the "diffs-only" version seemed like a reasonable
extension.
In fact, one of the changes I've made is to advertise the function.
>> Added some help text to the "Diff Radios" dialog explaining the
>> hex dumps available with mem # = -1 and -2.
I agree about wanting the context a lot of the time, and I'm not
proposing to eliminate that, at all. But twiddling some radio buttons
and dumping state, and wanting to be sure I notice ALL the changes,
get's pretty hairy when the scroll is ~3600 lines as in the FT-60.
I disagree that it's not very long, and I found myself wanting a
tool that allows me to be sure I got them all. So I built it.
That's also the focus of the diff_charflag mode. I just want to
be sure I see ALL the differences.
> Can you read the font size from the operating system default? I think
> this is the appropriate way to do it, but I don't know specifics.
> Ability to override this is reasonable, but maybe the problem is that
> you have your OS configured the way you like and Chirp isn't honoring
> it. That sounds more critical than implementing a font size override.
My eyesight is what you might expect for late 60s. I probably have
most apps configured to a slightly larger font than the majority, but in
actual practice, I switch them larger or smaller within apps (e.g. browser,
mail, pdf viewer, ...) pretty dynamically so I can see detail when needed,
and more context when not.
Just importing a "system font size" is not what I want.
I've worked out what I want the Chirp diffs and browser to be so
I can work with them, and I'd like to be able to set that directly,
not futz with inheriting some system property that I'd have to set
globally to get Chirp how I want it, that might make other apps
not behave as I'd like.
Not to mention introducing system dependencies. All I have is a Mac.
If you or someone wants to import a system font size as the default,
fine with me. I note that in the existing code, the browser and diff
sizes are different, so someone thought they needed to be.
Just allow me to override the default, however it's set.
> These sound like a number of small, atomic features. Each distinct
> feature should be its own patch and we can discuss it independently if
> needed. If one feature is dependent on another, just make sure the
> order of your patches is appropriate.
Groan. Yeah, I know the rules. Look over the changes and see if
they're trivial enough to do some lumping. But whatever it takes.
Patch equivalent coming soon.
-dan
4
4
[chirp_devel] [developer] Control fontsize of file browser display - #1697
by chirp.cordless@xoxy.net 11 Jul '14
by chirp.cordless@xoxy.net 11 Jul '14
11 Jul '14
Patch attached.
-dan
2
4
# HG changeset patch
# User Jim Unroe <rock.unroe(a)gmail.com>
# Date 1403439006 14400
# Node ID 8d54d97bd2667b2f6919fff177e68b43cbd745ed
# Parent 796b6bf2476a0f0f0e8dc208f11df2298d09e67b
[UV-82] UV-82X 220MHz Problem
the "rf.valid_bands" override in the "class" for the UV-82 was breaking
the vhf/220 functionality of the uv5r.py driver for this model.
support for varying band ranges by model was reworked to be similar to
how it is done in the th8102.py driver.
related to bug #1695
diff -r 796b6bf2476a -r 8d54d97bd266 chirp/uv5r.py
--- a/chirp/uv5r.py Thu May 22 18:44:42 2014 -0400
+++ b/chirp/uv5r.py Sun Jun 22 08:10:06 2014 -0400
@@ -540,6 +540,9 @@
_idents = [UV5R_MODEL_291,
UV5R_MODEL_ORIG
]
+ _vhf_range = (136000000, 174000000)
+ _220_range = (220000000, 260000000)
+ _uhf_range = (400000000, 520000000)
_mem_params = ( 0x1828 # poweron_msg offset
)
# offset of fw version in image file
@@ -589,8 +592,8 @@
rf.valid_duplexes = ["", "-", "+", "split", "off"]
rf.valid_modes = ["FM", "NFM"]
- normal_bands = [(136000000, 174000000), (400000000, 520000000)]
- rax_bands = [(136000000, 174000000), (220000000, 260000000)]
+ normal_bands = [self._vhf_range, self._uhf_range]
+ rax_bands = [self._vhf_range, self._220_range]
if self._mmap is None:
rf.valid_bands = [normal_bands[0], rax_bands[1], normal_bands[1]]
@@ -1511,11 +1514,8 @@
MODEL = "UV-82"
_basetype = BASETYPE_UV82
_idents = [UV5R_MODEL_UV82]
-
- def get_features(self):
- rf = BaofengUV5R.get_features(self)
- rf.valid_bands = [(130000000, 176000000), (400000000, 521000000)]
- return rf
+ _vhf_range = (130000000, 176000000)
+ _uhf_range = (400000000, 521000000)
def _is_orig(self):
# Override this for UV82 to always return False
@@ -1556,11 +1556,12 @@
MODEL = "KT-980HP"
_basetype = BASETYPE_KT980HP
_idents = [UV5R_MODEL_291]
+ _vhf_range = (130000000, 180000000)
+ _uhf_range = (400000000, 521000000)
def get_features(self):
rf = BaofengUV5R.get_features(self)
rf.valid_power_levels = UV5R_POWER_LEVELS3
- rf.valid_bands = [(130000000, 180000000), (400000000, 521000000)]
return rf
def _is_orig(self):
1
0
18 Jun '14
# HG changeset patch
# User David Fannin <dfannin(a)sushisoft.com>
# Date 1402177529 25200
# Sat Jun 07 14:45:29 2014 -0700
# Node ID a510b95c0a987a269cb29faf10ff0803e48f6ed2
# Parent 796b6bf2476a0f0f0e8dc208f11df2298d09e67b
[new model] new model tyt th9000 patch 004 #1035
TYT TH9000 VHF (2meter) Radio
alpha version 4
Features working:
Download/Upload to radio
Display and Edit Memories
Save image file
Modes: None, Tone, TSQL
Global Setting
APO
BG Color and Brightness
Squelch Level
TOT
Radio Max Transmit Power
Startup/Welcome Message
TBST Freq
TX/RX Freq Range
Beep
Memory Setting
Freq, Offset, Skip, Step, Ch Width, Name, Power, Mode, Tone-PL, TSQL-PL
Not Working
DCS, Cross and Reverse Modes
Display Mode (VFO/Mem)
VFO MR
Channel Lock
Voice Prompt
Tail Elim Type
Bootup Password
Memory: Reverse, TX Off, Compander, Talk Around, Scrambler
diff -r 796b6bf2476a -r a510b95c0a98 chirp/th9000vhf.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/chirp/th9000vhf.py Sat Jun 07 14:45:29 2014 -0700
@@ -0,0 +1,824 @@
+# Copyright 2012 Dan Smith <dsmith(a)danplanet.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 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/>.
+
+import os
+import struct
+import time
+
+from chirp import chirp_common
+from chirp import directory
+from chirp import memmap
+from chirp import bitwise
+from chirp import errors
+from chirp import util
+from chirp.settings import RadioSetting, RadioSettingGroup, \
+ RadioSettingValueInteger, RadioSettingValueList, \
+ RadioSettingValueBoolean, RadioSettingValueString, \
+ RadioSettingValueFloat, InvalidValueError
+
+#
+# Chirp Driver for TYT TH-9000 VHF (2 meter) Model
+# by David Fannin <dfannin(a)sushisoft.com>, KK6DF
+#
+# Version 0.4 (Experimental - Known Bugs and Issues)
+# Use for development purposes only!
+# Features working:
+# - Download from Radio
+# - Display Memories (only None, Tone, TSQL signalling supported)
+# - Save image file
+# - memory map decoded (about 90%)
+# - Upload to radio
+# - Modification of memories
+# - feature settings
+# - added Startup ID label
+#
+# Features not working:
+# - DCS , Cross Signaling
+# - Skip channels
+
+
+#
+# Global Parameters
+#
+MMAPSIZE = 16128
+TONES = [62.5] + list(chirp_common.TONES)
+TMODES = ['','Tone','DTCS']
+DUPLEXES = ['','err','-','+'] # index 2 not used
+MODES = ['WFM','FM','NFM'] # 25k, 20k,15k bw
+TUNING_STEPS=[ 5.0, 6.25, 8.33, 10.0, 12.5, 15.0, 20.0, 25.0, 30.0, 50.0 ] # index 0-9
+POWER_LEVELS=[chirp_common.PowerLevel("High", watts=65),
+ chirp_common.PowerLevel("Mid", watts=25),
+ chirp_common.PowerLevel("Low", watts=10)]
+
+CROSS_MODES = chirp_common.CROSS_MODES
+VALID_MODEL = ['TH-9000']
+
+APO_LIST = [ "Off","30 min","1 hr","2 hrs" ]
+BGCOLOR_LIST = ["Blue","Orange","Purple"]
+BGBRIGHT_LIST = ["%s" % x for x in range(1,32)]
+SQUELCH_LIST = ["Off"] + ["Level %s" % x for x in range(1,20)]
+TIMEOUT_LIST = ["Off"] + ["%s min" % x for x in range(1,30)]
+TXPWR_LIST = ["60W","25W"] # maximum power for Hi setting
+TBSTFREQ_LIST = ["1750Hz","2100Hz","1000Hz","1450Hz"]
+BEEP_LIST = ["Off","On"]
+
+SETTING_LISTS = {
+ "auto_power_off": APO_LIST,
+ "bg_color" : BGCOLOR_LIST,
+ "bg_brightness" : BGBRIGHT_LIST,
+ "squelch" : SQUELCH_LIST,
+ "timeout_timer" : TIMEOUT_LIST,
+ "choose_tx_power": TXPWR_LIST,
+ "tbst_freq" : TBSTFREQ_LIST,
+ "voice_prompt" : BEEP_LIST
+}
+
+
+#
+#
+#
+"""
+Overall Memory Map:
+
+ Memory Map (Range 0x0100-3FF0, step 0x10):
+
+ Field Start End Size
+ (hex) (hex) (hex)
+
+ 1 Channel Set Flag 0100 011F 20
+ 2 Channel Skip Flag 0120 013F 20
+ 3 Blank/Unknown 0140 01EF B0
+ 4 Unknown 01F0 01FF 10
+ 5 TX/RX Range 0200 020F 10
+ 6 Bootup Passwd 0210 021F 10
+ 7 Options, Radio 0220 023F 20
+ 8 Unknown 0240 019F
+ 8B Startup Label 03E0 03E7 07
+ 9 Channel Bank 2000 38FF 1900
+ Channel 000 2000 201F 20
+ Channel 001 2020 202F 20
+ ...
+ Channel 199 38E0 38FF 20
+ 10 Blank/Unknown 3900 3FFF 6FF 14592 16383 1792
+ Total Map Size 16128 (2^8 = 16384)
+
+
+"""
+
+"""
+ TH9000/VHF memory map
+ section: 1 and 2: Channel Set/Skip Flags
+
+ Channel Set (starts 0x100) : Channel Set bit is value 0 if a memory location in the channel bank is active.
+ Channel Skip (starts 0x120): Channel Skip bit is value 0 if a memory location in the channel bank is active.
+
+ Both flag maps are a total 24 bytes in length, aligned on 32 byte records.
+ bit = 0 channel set/no skip, 1 is channel not set/skip
+
+ to index a channel:
+ cbyte = channel / 8 ;
+ cbit = channel % 8 ;
+ setflag = csetflag[cbyte].c[cbit] ;
+ skipflag = cskipflag[cbyte].c[cbit] ;
+
+ channel range is 0-199, range is 32 bytes (last 7 unknown)
+"""
+
+
+MEM_FORMAT = """
+#seekto 0x0100;
+struct {
+ bit c[8];
+} csetflag[32];
+
+struct {
+ u8 unknown0100[7];
+} ropt0100;
+
+#seekto 0x0120;
+struct {
+ bit c[8];
+} cskipflag[32];
+
+struct {
+ u8 unknown0120[7];
+} ropt0120;
+"""
+
+"""
+ TH9000/VHF memory map
+ section: 5 TX/RX Range
+ used to set the TX/RX range of the radio (e.g. 144-148Mhz for 2 meter)
+ possible to set range to 136-172Mhz for tx/rx
+
+"""
+
+
+MEM_FORMAT = MEM_FORMAT + """
+#seekto 0x0200;
+struct {
+ bbcd txrangelow[4];
+ bbcd txrangehi[4];
+ bbcd rxrangelow[4];
+ bbcd rxrangehi[4];
+} freqrange;
+"""
+
+"""
+ TH9000/VHF memory map
+ section: 6 bootup_passwd
+ used to set bootup passwd (see boot_passwd checkbox option)
+
+ options - bootup password
+
+ bytes:bit type description
+ ---------------------------------------------------------------------------
+ 6 u8 bootup_passwd[6] bootup passwd, 6 chars, numberic chars 30-39 , see boot_passwd checkbox to set
+ 10 u8 unknown;
+
+"""
+
+MEM_FORMAT = MEM_FORMAT + """
+#seekto 0x0210;
+struct {
+ u8 bootup_passwd[6];
+ u8 unknown2010[10];
+} ropt0210;
+"""
+
+"""
+ TH9000/VHF memory map
+ section: 7 Radio Options
+ used to set a number of radio options
+
+ bytes:bit type description
+ ---------------------------------------------------------------------------
+ 1 u8 display_mode display mode, range 0-2, 0=freq,1=channel,2=name (selecting name affects vfo_mr)
+ 1 u8 vfo_mr; vfo_mr , 0=vfo, mr=1
+ 1 u8 unknown;
+ 1 u8 squelch; squelch level, range 0-19, hex for menu
+ 1 u8 unknown[2];
+ 1 u8 channel_lock; if display_mode[channel] selected, then lock=1,no lock =0
+ 1 u8 unknown;
+ 1 u8 bg_brightness ; background brightness, range 0-21, hex, menu index
+ 1 u8 unknown;
+ 1 u8 bg_color ; bg color, menu index, blue 0 , orange 1, purple 2
+ 1 u8 tbst_freq ; tbst freq , menu 0 = 1750Hz, 1=2100 , 2=1000 , 3=1450hz
+ 1 u8 timeout_timer; timeout timer, hex, value = minutes, 0= no timeout
+ 1 u8 unknown;
+ 1 u8 auto_power_off; auto power off, range 0-3, off,30min, 1hr, 2hr, hex menu index
+ 1 u8 voice_prompt; voice prompt, value 0,1 , Beep ON = 1, Beep Off = 2
+
+ description of function setup options, starting at 0x0230
+
+ bytes:bit type description
+ ---------------------------------------------------------------------------
+ 1 u8 // 0
+ :4 unknown:6
+ :1 elim_sql_tail:1 eliminate squelsh tail when no ctcss checkbox (1=checked)
+ :1 sql_key_function "squelch off" 1 , "squelch momentary off" 0 , menu index
+ 2 u8 unknown[2] /1-2
+ 1 u8 // 3
+ :4 unknown:4
+ :1 inhibit_init_ops:1 //bit 5
+ :1 unknownD:1
+ :1 inhibit_setup_bg_chk:1 //bit 7
+ :1 unknown:1
+ 1 u8 tail_elim_type menu , (off=0,120=1,180=2), // 4
+ 1 u8 choose_tx_power menu , (60w=0,25w=1) // 5
+ 2 u8 unknown[2]; // 6-7
+ 1 u8 bootup_passwd_flag checkbox 1=on, 0=off // 8
+ 7 u8 unknown[7]; // 9-F
+
+"""
+
+MEM_FORMAT = MEM_FORMAT + """
+#seekto 0x0220;
+struct {
+ u8 display_mode;
+ u8 vfo_mr;
+ u8 unknown0220A;
+ u8 squelch;
+ u8 unknown0220B[2];
+ u8 channel_lock;
+ u8 unknown0220C;
+ u8 bg_brightness;
+ u8 unknown0220D;
+ u8 bg_color;
+ u8 tbst_freq;
+ u8 timeout_timer;
+ u8 unknown0220E;
+ u8 auto_power_off;
+ u8 voice_prompt;
+ u8 unknown0230A:6,
+ elim_sql_tail:1,
+ sql_key_function:1;
+ u8 unknown0230B[2];
+ u8 unknown0230C:4,
+ inhibit_init_ops:1,
+ unknown0230D:1,
+ inhibit_setup_bg_chk:1,
+ unknown0230E:1;
+ u8 tail_elim_type;
+ u8 choose_tx_power;
+ u8 unknown0230F[2];
+ u8 bootup_passwd_flag;
+ u8 unknown0230G[7];
+} settings;
+"""
+
+"""
+ TH9000/VHF memory map
+ section: 8B Startup Label
+
+ bytes:bit type description
+ ---------------------------------------------------------------------------
+ 7 char start_label[7] label displayed at startup (usually your call sign)
+"""
+MEM_FORMAT = MEM_FORMAT + """
+#seekto 0x03E0;
+struct {
+ char startname[7];
+} slabel;
+"""
+
+"""
+ TH9000/VHF memory map
+ section: 9 Channel Bank
+ description of channel bank (200 channels , range 0-199)
+ Each 32 Byte (0x20 hex) record:
+ bytes:bit type description
+ ---------------------------------------------------------------------------
+ 4 bbcd freq[4] receive frequency in packed binary coded decimal
+ 4 bbcd offset[4] transmit offset in packed binary coded decimal (note: plus/minus direction set by 'duplex' field)
+ 1 u8
+ :4 unknown:4
+ :4 tuning_step:4 tuning step, menu index value from 0-9
+ 5,6.25,8.33,10,12.5,15,20,25,30,50
+ 1 u8
+ :4 unknown:4 not yet decoded, used for DCS coding?
+ :2 channel_width:2 channel spacing, menu index value from 0-3
+ 25,20,12.5
+ :1 reverse:1 reverse flag, 0=off, 1=on (reverses tx and rx freqs)
+ :1 txoff:1 transmitt off flag, 0=transmit , 1=do not transmit
+ 1 u8
+ :1 talkaround:1 talkaround flag, 0=off, 1=on (bypasses repeater)
+ :1 compander:1 compander flag, 0=off, 1=on (turns on/off voice compander option)
+ :2 unknown:2
+ :2 power:2 tx power setting, value range 0-2, 0=hi,1=med,2=lo
+ :2 duplex:2 duplex settings, 0=simplex,2= minus(-) offset, 3= plus (+) offset (see offset field)
+
+ 1 u8
+ :4 unknown:4
+ :2 rxtmode:2 rx tone mode, value range 0-2, 0=none, 1=CTCSS, 2=DCS (ctcss tone in field rxtone)
+ :2 txtmode:2 tx tone mode, value range 0-2, 0=none, 1=CTCSS, 3=DCS (ctcss tone in field txtone)
+ 1 u8
+ :2 unknown:2
+ :6 txtone:6 tx ctcss tone, menu index
+ 1 u8
+ :2 unknown:2
+ :6 rxtone:6 rx ctcss tone, menu index
+ 1 u8 txcode ?, not used for ctcss
+ 1 u8 rxcode ?, not used for ctcss
+ 3 u8 unknown[3]
+ 7 char name[7] 7 byte char string for channel name
+ 1 u8
+ :6 unknown:6,
+ :2 busychannellockout:2 busy channel lockout option , 0=off, 1=repeater, 2=busy (lock out tx if channel busy)
+ 4 u8 unknownI[4];
+ 1 u8
+ :7 unknown:7
+ :1 scrambler:1 scrambler flag, 0=off, 1=on (turns on tyt scrambler option)
+"""
+
+
+
+MEM_FORMAT = MEM_FORMAT + """
+#seekto 0x2000;
+struct {
+ bbcd freq[4];
+ bbcd offset[4];
+ u8 unknown2000A:4,
+ tuning_step:4;
+ u8 unknown2000B:4,
+ channel_width:2,
+ reverse:1,
+ txoff:1;
+ u8 talkaround:1,
+ compander:1,
+ unknown2000C:2,
+ power:2,
+ duplex:2;
+ u8 unknown2000D:4,
+ rxtmode:2,
+ txtmode:2;
+ u8 unknown2000E:2,
+ txtone:6;
+ u8 unknown2000F:2,
+ rxtone:6;
+ u8 txcode;
+ u8 rxcode;
+ u8 unknown2000G[3];
+ char name[7];
+ u8 unknown2000H:6,
+ busychannellockout:2;
+ u8 unknown2000I[4];
+ u8 unknown2000J:7,
+ scrambler:1;
+} memory[200] ;
+"""
+
+
+def _debug(string):
+ if "CHIRP_DEBUG" in os.environ or True:
+ print string
+
+def _echo_write(radio, data):
+ try:
+ radio.pipe.write(data)
+ radio.pipe.read(len(data))
+ except Exception, e:
+ print "Error writing to radio: %s" % e
+ raise errors.RadioError("Unable to write to radio")
+
+
+def _checksum(data):
+ cs = 0
+ for byte in data:
+ cs += ord(byte)
+ return cs % 256
+
+def _read(radio, length):
+ try:
+ data = radio.pipe.read(length)
+ except Exception, e:
+ print "Error reading from radio: %s" % e
+ raise errors.RadioError("Unable to read from radio")
+
+ if len(data) != length:
+ print "Short read from radio (%i, expected %i)" % (len(data),
+ length)
+ print util.hexprint(data)
+ raise errors.RadioError("Short read from radio")
+ return data
+
+
+
+def _ident(radio):
+ radio.pipe.setTimeout(1)
+ _echo_write(radio,"PROGRAM")
+ response = radio.pipe.read(3)
+ if response != "QX\06":
+ print "Response was :\n%s" % util.hexprint(response)
+ raise errors.RadioError("Unsupported model")
+ _echo_write(radio, "\x02")
+ response = radio.pipe.read(16)
+ _debug(util.hexprint(response))
+ if response[1:8] != "TH-9000":
+ print "Looking for:\n%s" % util.hexprint("TH-9000")
+ print "Response was:\n%s" % util.hexprint(response)
+ raise errors.RadioError("Unsupported model")
+
+def _send(radio, cmd, addr, length, data=None):
+ frame = struct.pack(">cHb", cmd, addr, length)
+ if data:
+ frame += data
+ frame += chr(_checksum(frame[1:]))
+ frame += "\x06"
+ _echo_write(radio, frame)
+ _debug("Sent:\n%s" % util.hexprint(frame))
+ if data:
+ result = radio.pipe.read(1)
+ if result != "\x06":
+ print "Ack was: %s" % repr(result)
+ raise errors.RadioError("Radio did not accept block at %04x" % addr)
+ return
+ result = _read(radio, length + 6)
+ _debug("Got:\n%s" % util.hexprint(result))
+ header = result[0:4]
+ data = result[4:-2]
+ ack = result[-1]
+ if ack != "\x06":
+ print "Ack was: %s" % repr(ack)
+ raise errors.RadioError("Radio NAK'd block at %04x" % addr)
+ _cmd, _addr, _length = struct.unpack(">cHb", header)
+ if _addr != addr or _length != _length:
+ print "Expected/Received:"
+ print " Length: %02x/%02x" % (length, _length)
+ print " Addr: %04x/%04x" % (addr, _addr)
+ raise errors.RadioError("Radio send unexpected block")
+ cs = _checksum(result[1:-2])
+ if cs != ord(result[-2]):
+ print "Calculated: %02x" % cs
+ print "Actual: %02x" % ord(result[-2])
+ raise errors.RadioError("Block at 0x%04x failed checksum" % addr)
+ return data
+
+
+def _finish(radio):
+ endframe = "\x45\x4E\x44"
+ _echo_write(radio, endframe)
+ result = radio.pipe.read(1)
+ if result != "\x06":
+ print "Got:\n%s" % util.hexprint(result)
+ raise errors.RadioError("Radio did not finish cleanly")
+
+def do_download(radio):
+
+ _ident(radio)
+
+ _memobj = None
+ data = ""
+
+ for start,end in radio._ranges:
+ for addr in range(start,end,0x10):
+ block = _send(radio,'R',addr,0x10)
+ data += block
+ status = chirp_common.Status()
+ status.cur = len(data)
+ status.max = end
+ status.msg = "Downloading from radio"
+ radio.status_fn(status)
+
+ _finish(radio)
+
+ return memmap.MemoryMap(data)
+
+def do_upload(radio):
+
+ _ident(radio)
+
+ for start,end in radio._ranges:
+ for addr in range(start,end,0x10):
+ if addr < 0x0100:
+ continue
+ block = radio._mmap[addr:addr+0x10]
+ _send(radio,'W',addr,len(block),block)
+ status = chirp_common.Status()
+ status.cur = addr
+ status.max = end
+ status.msg = "Uploading to Radio"
+ radio.status_fn(status)
+
+ _finish(radio)
+
+
+
+(a)directory.register
+class Th9000VHFRadio(chirp_common.CloneModeRadio):
+ """TYT TH-9000 VHF"""
+ VENDOR = "TYT"
+ MODEL = "TH9000"
+ BAUD_RATE = 9600
+ _file_ident = "TH-9000"
+
+ _memsize = MMAPSIZE
+ _ranges = [(0x0000,0x4000)]
+
+ @classmethod
+ def get_prompts(cls):
+ rp = chirp_common.RadioPrompts()
+ rp.experimental = ("The TYT TH-9000 driver is an alpha version."
+ "Use only for testing and development"
+ "Proceed with Caution and backup your data"
+ "as you may lose it using this driver!")
+ return rp
+
+ def get_features(self):
+ rf = chirp_common.RadioFeatures()
+ rf.has_settings = True
+ rf.has_bank = False
+ rf.has_cross = True
+ rf.has_tuning_step = False
+ rf.has_rx_dtcs = True
+ rf.valid_skips = ["","S"]
+ rf.memory_bounds = (0, 199)
+ rf.valid_name_length = 7
+ rf.valid_characters = chirp_common.CHARSET_UPPER_NUMERIC + "-"
+ rf.valid_modes = MODES
+ rf.valid_tmodes = chirp_common.TONE_MODES
+ rf.valid_cross_modes = CROSS_MODES
+ rf.valid_power_levels = POWER_LEVELS
+ rf.valid_dtcs_codes = chirp_common.ALL_DTCS_CODES
+ rf.valid_bands = [(136000000, 174000000)]
+ return rf
+
+ # Do a download of the radio from the serial port
+ def sync_in(self):
+ self._mmap = do_download(self)
+ self.process_mmap()
+
+ # Do an upload of the radio to the serial port
+ def sync_out(self):
+ do_upload(self)
+
+ def process_mmap(self):
+ self._memobj = bitwise.parse(MEM_FORMAT, self._mmap)
+
+
+ # Return a raw representation of the memory object, which
+ # is very helpful for development
+ def get_raw_memory(self, number):
+ return repr(self._memobj.memory[number])
+
+
+ # not working
+ def _get_dcs_index(self, _mem,which):
+ base = getattr(_mem, '%scode' % which)
+ extra = getattr(_mem, '%sdcsextra' % which)
+ return (int(extra) << 8) | int(base)
+
+ def _set_dcs_index(self, _mem, which, index):
+ base = getattr(_mem, '%scode' % which)
+ extra = getattr(_mem, '%sdcsextra' % which)
+ base.set_value(index & 0xFF)
+ extra.set_value(index >> 8)
+
+
+ # Extract a high-level memory object from the low-level memory map
+ # This is called to populate a memory in the UI
+ def get_memory(self, number):
+ # Get a low-level memory object mapped to the image
+ _mem = self._memobj.memory[number]
+
+ # get flag info
+ cbyte = number / 8 ;
+ cbit = 7 - (number % 8) ;
+ setflag = self._memobj.csetflag[cbyte].c[cbit];
+ skipflag = self._memobj.cskipflag[cbyte].c[cbit];
+
+ mem = chirp_common.Memory()
+
+ mem.number = number # Set the memory number
+
+ if setflag == 1:
+ mem.empty = True
+ return mem
+
+ mem.freq = int(_mem.freq) * 100
+ mem.offset = int(_mem.offset) * 100
+ mem.name = str(_mem.name).rstrip() # Set the alpha tag
+ mem.duplex = DUPLEXES[_mem.duplex]
+ mem.mode = MODES[_mem.channel_width]
+ mem.power = POWER_LEVELS[_mem.power]
+
+ rxtone = txtone = None
+
+
+ rxmode = TMODES[_mem.rxtmode]
+ txmode = TMODES[_mem.txtmode]
+
+
+ rxpol = txpol = ""
+
+ # doesn't work
+ if rxmode == "Tone":
+ rxpol = ""
+ rxtone = TONES[_mem.rxtone]
+ elif rxmode == "DTCS":
+ rxpol = "N"
+ rxtone = chirp_common.ALL_DTCS_CODES[self._get_dcs_index(_mem,'rx')]
+
+ if txmode == "Tone":
+ txpol = ""
+ txtone = TONES[_mem.txtone]
+ elif txmode == "DTCS":
+ txpol = "N"
+ txtone = chirp_common.ALL_DTCS_CODES[self._get_dcs_index(_mem,'tx')]
+
+
+ chirp_common.split_tone_decode(mem,
+ (txmode, txtone, txpol),
+ (rxmode, rxtone, rxpol))
+
+ mem.skip = "S" if skipflag == 1 else ""
+
+
+ # We'll consider any blank (i.e. 0MHz frequency) to be empty
+ if mem.freq == 0:
+ mem.empty = True
+
+ return mem
+
+ # Store details about a high-level memory to the memory map
+ # This is called when a user edits a memory in the UI
+ def set_memory(self, mem):
+ # Get a low-level memory object mapped to the image
+
+ _mem = self._memobj.memory[mem.number]
+
+ cbyte = mem.number / 8
+ cbit = 7 - (mem.number % 8)
+
+ if mem.empty:
+ self._memobj.csetflag[cbyte].c[cbit] = 1
+ self._memobj.cskipflag[cbyte].c[cbit] = 1
+ return
+
+ self._memobj.csetflag[cbyte].c[cbit] = 0
+ self._memobj.cskipflag[cbyte].c[cbit] = 1 if (mem.skip == "S") else 0
+
+ _mem.set_raw("\x00" * 32)
+
+ _mem.freq = mem.freq / 100 # Convert to low-level frequency
+ _mem.offset = mem.offset / 100 # Convert to low-level frequency
+
+ _mem.name = mem.name.ljust(7)[:7] # Store the alpha tag
+ _mem.duplex = DUPLEXES.index(mem.duplex)
+
+
+ try:
+ _mem.channel_width = MODES.index(mem.mode)
+ except ValueError:
+ _mem.channel_width = 0
+
+ ((txmode, txtone, txpol),
+ (rxmode, rxtone, rxpol)) = chirp_common.split_tone_encode(mem)
+
+ _mem.txtmode = TMODES.index(txmode)
+ _mem.rxtmode = TMODES.index(rxmode)
+
+ if txmode == "Tone":
+ _mem.txtone = TONES.index(txtone)
+ elif txmode == "DTCS":
+ self._set_dcs_index(_mem,'tx',chirp_common.ALL_DTCS_CODES.index(txtone))
+
+ if rxmode == "Tone":
+ _mem.rxtone = TONES.index(rxtone)
+ elif rxmode == "DTCS":
+ self._set_dcs_index(_mem, 'rx', chirp_common.ALL_DTCS_CODES.index(rxtone))
+
+ #_mem.txinv = txpol == "N"
+ #_mem.rxinv = rxpol == "N"
+
+
+ if mem.power:
+ _mem.power = POWER_LEVELS.index(mem.power)
+ else:
+ _mem.power = 0
+
+ def _get_settings(self):
+ _settings = self._memobj.settings
+ _freqrange = self._memobj.freqrange
+ _slabel = self._memobj.slabel
+
+ basic = RadioSettingGroup("basic","Global Settings")
+ freqrange = RadioSettingGroup("freqrange","Frequency Ranges")
+ top = RadioSettingGroup("top","All Settings",basic,freqrange)
+
+ def _filter(name):
+ filtered = ""
+ for char in str(name):
+ if char in chirp_common.CHARSET_ASCII:
+ filtered += char
+ else:
+ filtered += ""
+ return filtered
+
+ val = RadioSettingValueString(0,7,_filter(_slabel.startname))
+ rs = RadioSetting("startname","Startup Label",val)
+ basic.append(rs)
+
+ rs = RadioSetting("bg_color","LCD Color",
+ RadioSettingValueList(BGCOLOR_LIST, BGCOLOR_LIST[_settings.bg_color]))
+ basic.append(rs)
+
+ rs = RadioSetting("bg_brightness","LCD Brightness",
+ RadioSettingValueList(BGBRIGHT_LIST, BGBRIGHT_LIST[_settings.bg_brightness]))
+ basic.append(rs)
+
+ rs = RadioSetting("squelch","Squelch Level",
+ RadioSettingValueList(SQUELCH_LIST, SQUELCH_LIST[_settings.squelch]))
+ basic.append(rs)
+
+ rs = RadioSetting("timeout_timer","Timeout Timer (TOT)",
+ RadioSettingValueList(TIMEOUT_LIST, TIMEOUT_LIST[_settings.timeout_timer]))
+ basic.append(rs)
+
+ rs = RadioSetting("auto_power_off","Auto Power Off (APO)",
+ RadioSettingValueList(APO_LIST, APO_LIST[_settings.auto_power_off]))
+ basic.append(rs)
+
+ rs = RadioSetting("voice_prompt","Beep Prompt",
+ RadioSettingValueList(BEEP_LIST, BEEP_LIST[_settings.voice_prompt]))
+ basic.append(rs)
+
+ rs = RadioSetting("tbst_freq","Tone Burst Frequency",
+ RadioSettingValueList(TBSTFREQ_LIST, TBSTFREQ_LIST[_settings.tbst_freq]))
+ basic.append(rs)
+
+ rs = RadioSetting("choose_tx_power","Max Level of TX Power",
+ RadioSettingValueList(TXPWR_LIST, TXPWR_LIST[_settings.choose_tx_power]))
+ basic.append(rs)
+
+ rs = RadioSetting("txrangelow","TX Freq, Lower Limit (khz)", RadioSettingValueInteger(136000,144000, int(_freqrange.txrangelow)/10))
+ freqrange.append(rs)
+
+ rs = RadioSetting("txrangehi","TX Freq, Upper Limit (khz)", RadioSettingValueInteger(148000,174000,int(_freqrange.txrangehi)/10))
+ freqrange.append(rs)
+
+ rs = RadioSetting("rxrangelow","RX Freq, Lower Limit (khz)", RadioSettingValueInteger(136000,144000, int(_freqrange.rxrangelow)/10))
+ freqrange.append(rs)
+
+ rs = RadioSetting("rxrangehi","RX Freq, Upper Limit (khz)", RadioSettingValueInteger(148000,174000,int(_freqrange.rxrangehi)/10))
+ freqrange.append(rs)
+
+ return top
+
+ def get_settings(self):
+ try:
+ return self._get_settings()
+ except:
+ import traceback
+ print "failed to parse settings"
+ traceback.print_exc()
+ return None
+
+ def set_settings(self,settings):
+ _settings = self._memobj.settings
+ for element in settings:
+ if not isinstance(element,RadioSetting):
+ self.set_settings(element)
+ continue
+ else:
+ try:
+ name = element.get_name()
+
+ if name in ["txrangelow","txrangehi","rxrangelow","rxrangehi"]:
+ print "setting %s = %s" % (name,int(element.value)*10)
+ setattr(self._memobj.freqrange,name,int(element.value)*10)
+ continue
+
+ if name in ["startname"]:
+ print "setting %s = %s" % (name, element.value)
+ setattr(self._memobj.slabel,name,element.value)
+ continue
+
+ obj = _settings
+ setting = element.get_name()
+
+ if element.has_apply_callback():
+ print "using apply callback"
+ element.run_apply_callback()
+ else:
+ print "Setting %s = %s" % (setting, element.value)
+ setattr(obj, setting, element.value)
+ except Exception, e:
+ print element.get_name()
+ raise
+
+ @classmethod
+ def match_model(cls, filedata, filename):
+ return cls._file_ident in filedata[0x10:0x20]
2
1
Tested changes:
[Dan Drogichen <chirp.cordless(a)xoxy.net>] [developer] Control fontsize of hex diff/dump display - #1681
Add user specification of the font size to use for the hex diff/dump
display, without affecting any other Chirp displays.
This is done with a new chirp.config integer property diff_fontsize
in a new [developer] section. The default is unchanged at 11.
Values between 4 and 144 are accepted; others result in the default.
Add a new file README.developers at the top level of the repository
to document chirp.config [developer] section properties.
#1681
Full log:
[...truncated 25 lines...]
test_type_u16 (tests.unit.test_bitwise.TestBitwiseBaseIntTypes) ... ok
test_type_u24 (tests.unit.test_bitwise.TestBitwiseBaseIntTypes) ... ok
test_type_u32 (tests.unit.test_bitwise.TestBitwiseBaseIntTypes) ... ok
test_type_u8 (tests.unit.test_bitwise.TestBitwiseBaseIntTypes) ... ok
test_type_ul16 (tests.unit.test_bitwise.TestBitwiseBaseIntTypes) ... ok
test_type_ul24 (tests.unit.test_bitwise.TestBitwiseBaseIntTypes) ... ok
test_type_ul32 (tests.unit.test_bitwise.TestBitwiseBaseIntTypes) ... ok
test_char (tests.unit.test_bitwise.TestBitwiseCharTypes) ... ok
test_string (tests.unit.test_bitwise.TestBitwiseCharTypes) ... ok
test_string_invalid_chars (tests.unit.test_bitwise.TestBitwiseCharTypes) ... ok
test_string_wrong_length (tests.unit.test_bitwise.TestBitwiseCharTypes) ... ok
test_comment_cppstyle (tests.unit.test_bitwise.TestBitwiseComments) ... ok
test_comment_inline_cppstyle (tests.unit.test_bitwise.TestBitwiseComments) ... ok
test_missing_semicolon (tests.unit.test_bitwise.TestBitwiseErrors) ... ok
test_seek (tests.unit.test_bitwise.TestBitwiseSeek) ... ok
test_seekto (tests.unit.test_bitwise.TestBitwiseSeek) ... ok
test_struct_one_element (tests.unit.test_bitwise.TestBitwiseStructTypes) ... ok
test_struct_two_elements (tests.unit.test_bitwise.TestBitwiseStructTypes) ... ok
test_struct_writes (tests.unit.test_bitwise.TestBitwiseStructTypes) ... ok
split_tone_encode_test_cross_dtcs_tone (tests.unit.test_chirp_common.TestSplitTone) ... ok
split_tone_encode_test_cross_none_dtcs (tests.unit.test_chirp_common.TestSplitTone) ... ok
split_tone_encode_test_cross_none_tone (tests.unit.test_chirp_common.TestSplitTone) ... ok
split_tone_encode_test_cross_tone_dtcs (tests.unit.test_chirp_common.TestSplitTone) ... ok
split_tone_encode_test_cross_tone_tone (tests.unit.test_chirp_common.TestSplitTone) ... ok
split_tone_encode_test_dtcs (tests.unit.test_chirp_common.TestSplitTone) ... ok
split_tone_encode_test_none (tests.unit.test_chirp_common.TestSplitTone) ... ok
split_tone_encode_test_tone (tests.unit.test_chirp_common.TestSplitTone) ... ok
split_tone_encode_test_tsql (tests.unit.test_chirp_common.TestSplitTone) ... ok
test_split_tone_decode_cross_dtcs_dtcs (tests.unit.test_chirp_common.TestSplitTone) ... ok
test_split_tone_decode_cross_dtcs_tone (tests.unit.test_chirp_common.TestSplitTone) ... ok
test_split_tone_decode_cross_none_dtcs (tests.unit.test_chirp_common.TestSplitTone) ... ok
test_split_tone_decode_cross_none_tone (tests.unit.test_chirp_common.TestSplitTone) ... ok
test_split_tone_decode_cross_tone_dtcs (tests.unit.test_chirp_common.TestSplitTone) ... ok
test_split_tone_decode_cross_tone_tone (tests.unit.test_chirp_common.TestSplitTone) ... ok
test_split_tone_decode_dtcs (tests.unit.test_chirp_common.TestSplitTone) ... ok
test_split_tone_decode_none (tests.unit.test_chirp_common.TestSplitTone) ... ok
test_split_tone_decode_tone (tests.unit.test_chirp_common.TestSplitTone) ... ok
test_split_tone_decode_tsql (tests.unit.test_chirp_common.TestSplitTone) ... ok
test_fix_rounded_step_250 (tests.unit.test_chirp_common.TestStepFunctions) ... ok
test_fix_rounded_step_500 (tests.unit.test_chirp_common.TestStepFunctions) ... ok
test_fix_rounded_step_750 (tests.unit.test_chirp_common.TestStepFunctions) ... ok
test_is_12_5 (tests.unit.test_chirp_common.TestStepFunctions) ... ok
test_is_2_5 (tests.unit.test_chirp_common.TestStepFunctions) ... ok
test_is_5_0 (tests.unit.test_chirp_common.TestStepFunctions) ... ok
test_is_6_25 (tests.unit.test_chirp_common.TestStepFunctions) ... ok
test_is_fractional_step (tests.unit.test_chirp_common.TestStepFunctions) ... ok
test_required_step (tests.unit.test_chirp_common.TestStepFunctions) ... ok
test_required_step_fail (tests.unit.test_chirp_common.TestStepFunctions) ... ok
test_format_freq (tests.unit.test_chirp_common.TestUtilityFunctions) ... ok
test_parse_freq_bad (tests.unit.test_chirp_common.TestUtilityFunctions) ... ok
test_parse_freq_decimal (tests.unit.test_chirp_common.TestUtilityFunctions) ... ok
test_parse_freq_whitespace (tests.unit.test_chirp_common.TestUtilityFunctions) ... ok
test_parse_freq_whole (tests.unit.test_chirp_common.TestUtilityFunctions) ... ok
test_ensure_has_calls_almost_full (tests.unit.test_import_logic.DstarTests) ... ok
test_ensure_has_calls_empty (tests.unit.test_import_logic.DstarTests) ... ok
test_ensure_has_calls_partial (tests.unit.test_import_logic.DstarTests) ... ok
test_ensure_has_calls_rptcall_full1 (tests.unit.test_import_logic.DstarTests) ... ok
test_ensure_has_calls_rptcall_full2 (tests.unit.test_import_logic.DstarTests) ... ok
test_ensure_has_calls_urcall_full (tests.unit.test_import_logic.DstarTests) ... ok
test_import_bank (tests.unit.test_import_logic.ImportFieldTests) ... ok
test_import_dtcs_diffA_dtcs (tests.unit.test_import_logic.ImportFieldTests) ... ok
test_import_dtcs_diffB_dtcs (tests.unit.test_import_logic.ImportFieldTests) ... ok
test_import_duplex_negative (tests.unit.test_import_logic.ImportFieldTests) ... ok
test_import_duplex_too_big_vhf (tests.unit.test_import_logic.ImportFieldTests) ... ok
test_import_duplex_uhf (tests.unit.test_import_logic.ImportFieldTests) ... ok
test_import_duplex_vhf (tests.unit.test_import_logic.ImportFieldTests) ... ok
test_import_mem (tests.unit.test_import_logic.ImportFieldTests) ... ok
test_import_mem_with_errors (tests.unit.test_import_logic.ImportFieldTests) ... ok
test_import_mem_with_warnings (tests.unit.test_import_logic.ImportFieldTests) ... ok
test_import_mode_invalid (tests.unit.test_import_logic.ImportFieldTests) ... ok
test_import_mode_valid_am (tests.unit.test_import_logic.ImportFieldTests) ... ok
test_import_mode_valid_fm (tests.unit.test_import_logic.ImportFieldTests) ... ok
test_import_name (tests.unit.test_import_logic.ImportFieldTests) ... ok
test_import_power_closest (tests.unit.test_import_logic.ImportFieldTests) ... ok
test_import_power_no_dst (tests.unit.test_import_logic.ImportFieldTests) ... ok
test_import_power_no_src (tests.unit.test_import_logic.ImportFieldTests) ... ok
test_import_power_same (tests.unit.test_import_logic.ImportFieldTests) ... ok
test_import_tone_diffA_tsql (tests.unit.test_import_logic.ImportFieldTests) ... ok
test_import_tone_diffB_tsql (tests.unit.test_import_logic.ImportFieldTests) ... ok
test_mapping (tests.unit.test_mappingmodel.TestBaseBank) ... ok
test_mapping_eq (tests.unit.test_mappingmodel.TestBaseBank) ... ok
test_base_class (tests.unit.test_mappingmodel.TestBaseBankModel) ... ok
test_get_name (tests.unit.test_mappingmodel.TestBaseBankModel) ... ok
test_mapping (tests.unit.test_mappingmodel.TestBaseMapping) ... ok
test_mapping_eq (tests.unit.test_mappingmodel.TestBaseMapping) ... ok
test_base_class (tests.unit.test_mappingmodel.TestBaseMappingModel) ... ok
test_get_name (tests.unit.test_mappingmodel.TestBaseMappingModel) ... ok
test_base_class (tests.unit.test_mappingmodel.TestBaseMappingModelIndexInterface) ... ok
test_add_memory_to_mapping (tests.unit.test_mappingmodel.TestIcomBankModel) ... ok
test_get_mapping_memories (tests.unit.test_mappingmodel.TestIcomBankModel) ... ok
test_get_mappings (tests.unit.test_mappingmodel.TestIcomBankModel) ... ok
test_get_memory_mappings (tests.unit.test_mappingmodel.TestIcomBankModel) ... ok
test_get_num_mappings (tests.unit.test_mappingmodel.TestIcomBankModel) ... ok
test_remove_memory_from_mapping (tests.unit.test_mappingmodel.TestIcomBankModel) ... ok
test_remove_memory_from_mapping_no_bank (tests.unit.test_mappingmodel.TestIcomBankModel) ... ok
test_remove_memory_from_mapping_wrong_bank (tests.unit.test_mappingmodel.TestIcomBankModel) ... ok
test_icom_bank (tests.unit.test_mappingmodel.TestIcomBanks) ... ok
test_mapping (tests.unit.test_mappingmodel.TestIcomBanks) ... ok
test_mapping_eq (tests.unit.test_mappingmodel.TestIcomBanks) ... ok
test_add_memory_to_mapping (tests.unit.test_mappingmodel.TestIcomIndexedBankModel) ... ok
test_get_index_bounds (tests.unit.test_mappingmodel.TestIcomIndexedBankModel) ... ok
test_get_mapping_memories (tests.unit.test_mappingmodel.TestIcomIndexedBankModel) ... ok
test_get_mappings (tests.unit.test_mappingmodel.TestIcomIndexedBankModel) ... ok
test_get_memory_index (tests.unit.test_mappingmodel.TestIcomIndexedBankModel) ... ok
test_get_memory_mappings (tests.unit.test_mappingmodel.TestIcomIndexedBankModel) ... ok
test_get_next_mapping_index (tests.unit.test_mappingmodel.TestIcomIndexedBankModel) ... ok
test_get_num_mappings (tests.unit.test_mappingmodel.TestIcomIndexedBankModel) ... ok
test_remove_memory_from_mapping (tests.unit.test_mappingmodel.TestIcomIndexedBankModel) ... ok
test_remove_memory_from_mapping_no_bank (tests.unit.test_mappingmodel.TestIcomIndexedBankModel) ... ok
test_remove_memory_from_mapping_wrong_bank (tests.unit.test_mappingmodel.TestIcomIndexedBankModel) ... ok
test_set_memory_index (tests.unit.test_mappingmodel.TestIcomIndexedBankModel) ... ok
test_set_memory_index_bad_bank (tests.unit.test_mappingmodel.TestIcomIndexedBankModel) ... ok
test_set_memory_index_bad_index (tests.unit.test_mappingmodel.TestIcomIndexedBankModel) ... ok
test_auto_tone_mode_cross (tests.unit.test_memedit_edits.TestEdits) ... ok
test_auto_tone_mode_dtcs (tests.unit.test_memedit_edits.TestEdits) ... ok
test_auto_tone_mode_dtcs_pol (tests.unit.test_memedit_edits.TestEdits) ... ok
test_auto_tone_mode_dtcs_rx (tests.unit.test_memedit_edits.TestEdits) ... ok
test_auto_tone_mode_tone (tests.unit.test_memedit_edits.TestEdits) ... ok
test_auto_tone_mode_tsql (tests.unit.test_memedit_edits.TestEdits) ... ok
test_init (tests.unit.test_platform.Win32PlatformTest) ... ok
test_serial_ports_bad_portnames (tests.unit.test_platform.Win32PlatformTest) ... ok
test_serial_ports_sorted (tests.unit.test_platform.Win32PlatformTest) ... ok
test_apply_callback (tests.unit.test_settings.TestSettingContainers) ... ok
test_radio_setting (tests.unit.test_settings.TestSettingContainers) ... ok
test_radio_setting_group (tests.unit.test_settings.TestSettingContainers) ... ok
test_radio_setting_multi (tests.unit.test_settings.TestSettingContainers) ... ok
test_changed (tests.unit.test_settings.TestSettingValues) ... ok
test_radio_setting_value_boolean (tests.unit.test_settings.TestSettingValues) ... ok
test_radio_setting_value_float (tests.unit.test_settings.TestSettingValues) ... ok
test_radio_setting_value_integer (tests.unit.test_settings.TestSettingValues) ... ok
test_radio_setting_value_list (tests.unit.test_settings.TestSettingValues) ... ok
test_radio_setting_value_string (tests.unit.test_settings.TestSettingValues) ... ok
test_validate_callback (tests.unit.test_settings.TestSettingValues) ... ok
test_delete_hole_with_all (tests.unit.test_shiftdialog.ShiftDialogTest) ... ok
test_delete_hole_with_all_full (tests.unit.test_shiftdialog.ShiftDialogTest) ... ok
test_delete_hole_with_hole (tests.unit.test_shiftdialog.ShiftDialogTest) ... ok
test_delete_hole_without_hole (tests.unit.test_shiftdialog.ShiftDialogTest) ... ok
test_insert_hole_with_space (tests.unit.test_shiftdialog.ShiftDialogTest) ... ok
test_insert_hole_without_space (tests.unit.test_shiftdialog.ShiftDialogTest) ... ok
----------------------------------------------------------------------
Ran 151 tests in 0.072s
OK
Registered Icom_IC-2820H = IC2820Radio
Registered TYT_TH-UVF8D = TYTUVF8DRadio
Registered AnyTone_5888UV = AnyTone5888UVRadio
Registered Intek_HR-2040 = IntekHR2040Radio
Registered Polmar_DB-50M = PolmarDB50MRadio
Registered Powerwerx_DB-750X = PowerwerxDB750XRadio
Registered Icom_IC-2200H = IC2200Radio
Registered Yaesu_FT-2800M = FT2800Radio
Registered Yaesu_VX-3 = VX3Radio
Registered Icom_IC-2100H = IC2100Radio
Registered Yaesu_FTM-350 = FTM350Radio
Registered Icom_IC-V82_U82 = ICx8xRadio
Registered Yaesu_VX-6 = VX6Radio
Registered Yaesu_VX-5 = VX5Radio
Registered Yaesu_FT-60 = FT60Radio
Registered Yaesu_VX-7 = VX7Radio
Registered Baofeng_UV-5R = BaofengUV5R
Registered Baofeng_F-11 = BaofengF11Radio
Registered Baofeng_UV-82 = BaofengUV82Radio
Registered Baofeng_UV-6 = BaofengUV6Radio
Registered Intek_KT-980HP = IntekKT980Radio
Registered Yaesu_FT-1802M = FT1802Radio
Registered Kenwood_TK-7102 = KenwoodTK7102Radio
Registered Kenwood_TK-8102 = KenwoodTK8102Radio
Registered Kenwood_TK-7108 = KenwoodTK7108Radio
Registered Kenwood_TK-8108 = KenwoodTK8108Radio
Registered Icom_ID-31A = ID31Radio
Registered Icom_ID-51A = ID51Radio
Registered Icom_IC-2720H = IC2720Radio
Registered Icom_IC-T8A = ICT8ARadio
Registered Wouxun_KG-UVD1P = KGUVD1PRadio
Registered Wouxun_KG-UV6 = KGUV6DRadio
Registered Wouxun_KG-816 = KG816Radio
Registered Wouxun_KG-818 = KG818Radio
Registered TYT_TH-UVF1 = TYTTHUVF1Radio
Registered Yaesu_FT-90 = FT90Radio
Registered Generic_CSV = CSVRadio
Registered Commander_KG-UV = CommanderCSVRadio
Registered RT_Systems_CSV = RTCSVRadio
Registered Kenwood_ITM = ITMRadio
Registered Alinco_DR03T = DR03Radio
Registered Alinco_DR06T = DR06Radio
Registered Alinco_DR135T = DR135Radio
Registered Alinco_DR235T = DR235Radio
Registered Alinco_DR435T = DR435Radio
Registered Alinco_DJ596 = DJ596Radio
Registered Jetstream_JT220M = JT220MRadio
Registered Alinco_DJ175 = DJ175Radio
Registered Kenwood_TH-D7 = THD7Radio
Registered Kenwood_TH-D7G = THD7GRadio
Registered Kenwood_TM-D700 = TMD700Radio
Registered Kenwood_TM-V7 = TMV7Radio
Registered Kenwood_TM-G707 = TMG707Radio
Registered Kenwood_TH-G71 = THG71Radio
Registered Kenwood_TH-F6 = THF6ARadio
Registered Kenwood_TH-F7 = THF7ERadio
Registered Kenwood_TM-D710 = TMD710Radio
Registered Kenwood_TH-D72_live_mode = THD72Radio
Registered Kenwood_TM-V71 = TMV71Radio
Registered Kenwood_TH-K2 = THK2Radio
Registered Kenwood_TM-271 = TM271Radio
Registered Kenwood_TM-281 = TM281Radio
Registered Kenwood_TM-471 = TM471Radio
Registered Yaesu_VX-8_R = VX8Radio
Registered Yaesu_VX-8_DR = VX8DRadio
Registered Yaesu_VX-8_GE = VX8GERadio
Registered Icom_IC-T7H = ICT7HRadio
Registered Icom_IC-Q7A = ICQ7Radio
Registered Baofeng_UV-B5 = BaofengUVB5
Registered Generic_XML = XMLRadio
Registered Kenwood_HMK = HMKRadio
Registered Kenwood_TH-D72_clone_mode = THD72Radio
Registered Icom_IC-91_92AD = IC9xRadio
Registered Icom_IC-T70 = ICT70Radio
Registered Icom_IC-208H = IC208Radio
Registered Icom_ID-800H_v2 = ID800v2Radio
Registered Icom_7200 = Icom7200Radio
Registered Icom_7000 = Icom7000Radio
Registered Icom_746 = Icom746Radio
Registered ARRL_Travel_Plus = TpeRadio
Registered Vertex_Standard_VXA-700 = VXA700Radio
Registered Icom_IC-W32A = ICW32ARadio
Registered Baofeng_UV-3R = UV3RRadio
Registered Yaesu_VX-2 = VX2Radio
Registered Puxing_PX-777 = Puxing777Radio
Registered Puxing_PX-2R = Puxing2RRadio
Registered Baojie_BJ-UV55 = BaojieBJUV55Radio
Registered Baofeng_BF-888 = H777Radio
Registered Yaesu_FT-7800_7900 = FT7800Radio
Registered Yaesu_FT-8800 = FT8800Radio
Registered Yaesu_FT-8900 = FT8900Radio
Registered KYD_NC-630A = NC630aRadio
Registered Yaesu_FT-817 = FT817Radio
Registered Yaesu_FT-817ND = FT817NDRadio
Registered Yaesu_FT-817ND_US = FT817NDUSRadio
Registered Yaesu_FT-857_897 = FT857Radio
Registered Yaesu_FT-857_897_US = FT857USRadio
Registered Yaesu_VX-170 = VX170Radio
Registered Icom_ID-880H = ID880Radio
Registered Icom_ID-80H = ID80Radio
Registered TYT_TH-UV3R = TYTUV3RRadio
Alinco DJ175 Detect PASSED: All tests
Alinco DJ175 CopyAll PASSED: All tests
Alinco DJ175 Clone PASSED: All tests
Alinco DJ175 BruteForce PASSED: All tests
Alinco DJ175 Edges PASSED: All tests
Alinco DJ175 Banks SKIPPED: Banks not supported
Alinco DJ596 Detect PASSED: All tests
Alinco DJ596 CopyAll PASSED: All tests
Alinco DJ596 Clone PASSED: All tests
Alinco DJ596 BruteForce PASSED: All tests
Alinco DJ596 Edges PASSED: All tests
Alinco DJ596 Banks SKIPPED: Banks not supported
Alinco DR235T Detect PASSED: All tests
Alinco DR235T CopyAll PASSED: All tests
Alinco DR235T Clone PASSED: All tests
Alinco DR235T BruteForce PASSED: All tests
Alinco DR235T Edges PASSED: All tests
Alinco DR235T Banks SKIPPED: Banks not supported
Baofeng BF-888 Detect PASSED: All tests
Baofeng BF-888 CopyAll PASSED: All tests
Baofeng BF-888 Clone PASSED: All tests
Baofeng BF-888 BruteForce PASSED: All tests
Baofeng BF-888 Edges PASSED: All tests
Baofeng BF-888 Banks SKIPPED: Banks not supported
Baofeng F-11 Detect PASSED: All tests
Baofeng F-11 CopyAll PASSED: All tests
Baofeng F-11 Clone PASSED: All tests
Baofeng F-11 BruteForce PASSED: All tests
Baofeng F-11 Edges PASSED: All tests
Baofeng F-11 Banks SKIPPED: Banks not supported
Baofeng UV-3R Detect PASSED: All tests
Baofeng UV-3R CopyAll PASSED: All tests
Baofeng UV-3R Clone PASSED: All tests
Baofeng UV-3R BruteForce PASSED: All tests
Baofeng UV-3R Edges PASSED: All tests
Baofeng UV-3R Banks SKIPPED: Banks not supported
Baofeng UV-5R Detect PASSED: All tests
Baofeng UV-5R CopyAll PASSED: All tests
Baofeng UV-5R Clone PASSED: All tests
Baofeng UV-5R BruteForce PASSED: All tests
Baofeng UV-5R Edges PASSED: All tests
Baofeng UV-5R Banks SKIPPED: Banks not supported
Baofeng UV-B5 Detect PASSED: All tests
Baofeng UV-B5 CopyAll PASSED: All tests
Baofeng UV-B5 Clone PASSED: All tests
Baofeng UV-B5 BruteForce PASSED: All tests
Baofeng UV-B5 Edges PASSED: All tests
Baofeng UV-B5 Banks SKIPPED: Banks not supported
Icom IC-208H Detect PASSED: All tests
Icom IC-208H CopyAll PASSED: All tests
Icom IC-208H Clone PASSED: All tests
Icom IC-208H BruteForce PASSED: All tests
Icom IC-208H Edges PASSED: All tests
Icom IC-208H Banks PASSED: All tests
Icom IC-2100H Detect PASSED: All tests
Icom IC-2100H CopyAll PASSED: All tests
Icom IC-2100H Clone PASSED: All tests
Icom IC-2100H BruteForce PASSED: All tests
Icom IC-2100H Edges PASSED: All tests
Icom IC-2100H Banks SKIPPED: Banks not supported
Icom IC-2200H Detect PASSED: All tests
Icom IC-2200H CopyAll PASSED: All tests
Icom IC-2200H Clone PASSED: All tests
Icom IC-2200H BruteForce PASSED: All tests
Icom IC-2200H Edges PASSED: All tests
Icom IC-2200H Banks PASSED: All tests
Icom IC-2720H Detect PASSED: All tests
Icom IC-2720H CopyAll PASSED: All tests
Icom IC-2720H Clone PASSED: All tests
Icom IC-2720H BruteForce PASSED: All tests
Icom IC-2720H Edges PASSED: All tests
Icom IC-2720H Banks PASSED: All tests
Icom IC-2820H Detect PASSED: All tests
Icom IC-2820H CopyAll PASSED: All tests
Icom IC-2820H Clone PASSED: All tests
Icom IC-2820H BruteForce PASSED: All tests
Icom IC-2820H Edges PASSED: All tests
Icom IC-2820H Banks PASSED: All tests
Icom IC-Q7A Detect PASSED: All tests
Icom IC-Q7A CopyAll PASSED: All tests
Icom IC-Q7A Clone PASSED: All tests
Icom IC-Q7A BruteForce PASSED: All tests
Icom IC-Q7A Edges PASSED: All tests
Icom IC-Q7A Banks SKIPPED: Banks not supported
Icom IC-T70 Detect PASSED: All tests
Icom IC-T70 CopyAll PASSED: All tests
Icom IC-T70 Clone PASSED: All tests
Icom IC-T70 BruteForce PASSED: All tests
Icom IC-T70 Edges PASSED: All tests
Icom IC-T70 Banks PASSED: All tests
Icom IC-T7H Detect PASSED: All tests
Icom IC-T7H CopyAll PASSED: All tests
Icom IC-T7H Clone PASSED: All tests
Icom IC-T7H BruteForce PASSED: All tests
Icom IC-T7H Edges PASSED: All tests
Icom IC-T7H Banks SKIPPED: Banks not supported
Icom IC-T8A Detect PASSED: All tests
Icom IC-T8A CopyAll PASSED: All tests
Icom IC-T8A Clone PASSED: All tests
Icom IC-T8A BruteForce PASSED: All tests
Icom IC-T8A Edges PASSED: All tests
Icom IC-T8A Banks SKIPPED: Banks not supported
Icom IC-V82/U82 Detect PASSED: All tests
Icom IC-V82/U82 CopyAll PASSED: All tests
Icom IC-V82/U82 Clone PASSED: All tests
Icom IC-V82/U82 BruteForce PASSED: All tests
Icom IC-V82/U82 Edges PASSED: All tests
Icom IC-V82/U82 Banks PASSED: All tests
Icom IC-W32A VHF Detect PASSED: All tests
Icom IC-W32A VHF CopyAll PASSED: All tests
Icom IC-W32A VHF Clone PASSED: All tests
Icom IC-W32A VHF BruteForce PASSED: All tests
Icom IC-W32A VHF Edges PASSED: All tests
Icom IC-W32A VHF Banks SKIPPED: Banks not supported
Icom IC-W32A UHF Detect PASSED: All tests
Icom IC-W32A UHF CopyAll PASSED: All tests
Icom IC-W32A UHF Clone PASSED: All tests
Icom IC-W32A UHF BruteForce PASSED: All tests
Icom IC-W32A UHF Edges PASSED: All tests
Icom IC-W32A UHF Banks SKIPPED: Banks not supported
Icom ID-31A Detect PASSED: All tests
Icom ID-31A CopyAll PASSED: All tests
Icom ID-31A Clone PASSED: All tests
Icom ID-31A BruteForce PASSED: All tests
Icom ID-31A Edges PASSED: All tests
Icom ID-31A Banks PASSED: All tests
Icom ID-51A Detect PASSED: All tests
Icom ID-51A CopyAll PASSED: All tests
Icom ID-51A Clone PASSED: All tests
Icom ID-51A BruteForce PASSED: All tests
Icom ID-51A Edges PASSED: All tests
Icom ID-51A Banks PASSED: All tests
Icom ID-800H v2 Detect PASSED: All tests
Icom ID-800H v2 CopyAll PASSED: All tests
Icom ID-800H v2 Clone PASSED: All tests
Icom ID-800H v2 BruteForce PASSED: All tests
Icom ID-800H v2 Edges PASSED: All tests
Icom ID-800H v2 Banks PASSED: All tests
Icom ID-880H Detect PASSED: All tests
Icom ID-880H CopyAll PASSED: All tests
Icom ID-880H Clone PASSED: All tests
Icom ID-880H BruteForce PASSED: All tests
Icom ID-880H Edges PASSED: All tests
Icom ID-880H Banks PASSED: All tests
Jetstream JT220M Detect PASSED: All tests
Jetstream JT220M CopyAll PASSED: All tests
Jetstream JT220M Clone PASSED: All tests
Jetstream JT220M BruteForce PASSED: All tests
Jetstream JT220M Edges PASSED: All tests
Jetstream JT220M Banks SKIPPED: Banks not supported
Kenwood TH-D72 (clone Detect PASSED: All tests
Kenwood TH-D72 (clone CopyAll PASSED: All tests
Kenwood TH-D72 (clone Clone PASSED: All tests
Kenwood TH-D72 (clone BruteForce PASSED: All tests
Kenwood TH-D72 (clone Edges PASSED: All tests
Kenwood TH-D72 (clone Banks SKIPPED: Banks not supported
Kenwood TK-8102 Detect PASSED: All tests
Kenwood TK-8102 CopyAll PASSED: All tests
Kenwood TK-8102 Clone PASSED: All tests
Kenwood TK-8102 BruteForce PASSED: All tests
Kenwood TK-8102 Edges PASSED: All tests
Kenwood TK-8102 Banks SKIPPED: Banks not supported
Polmar DB-50M Detect PASSED: All tests
Polmar DB-50M CopyAll PASSED: All tests
Polmar DB-50M Clone PASSED: All tests
Polmar DB-50M BruteForce PASSED: All tests
Polmar DB-50M Edges PASSED: All tests
Polmar DB-50M Banks SKIPPED: Banks not supported
Puxing PX-2R Detect PASSED: All tests
Puxing PX-2R CopyAll PASSED: All tests
Puxing PX-2R Clone PASSED: All tests
Puxing PX-2R BruteForce PASSED: All tests
Puxing PX-2R Edges PASSED: All tests
Puxing PX-2R Banks SKIPPED: Banks not supported
Puxing PX-777 Detect PASSED: All tests
Puxing PX-777 CopyAll PASSED: All tests
Puxing PX-777 Clone PASSED: All tests
Puxing PX-777 BruteForce PASSED: All tests
Puxing PX-777 Edges PASSED: All tests
Puxing PX-777 Banks SKIPPED: Banks not supported
TYT TH-UV3R Detect PASSED: All tests
TYT TH-UV3R CopyAll PASSED: All tests
TYT TH-UV3R Clone PASSED: All tests
TYT TH-UV3R BruteForce PASSED: All tests
TYT TH-UV3R Edges PASSED: All tests
TYT TH-UV3R Banks SKIPPED: Banks not supported
TYT TH-UVF1 Detect PASSED: All tests
TYT TH-UVF1 CopyAll PASSED: All tests
TYT TH-UVF1 Clone PASSED: All tests
TYT TH-UVF1 BruteForce PASSED: All tests
TYT TH-UVF1 Edges PASSED: All tests
TYT TH-UVF1 Banks SKIPPED: Banks not supported
Vertex VXA-700 Detect PASSED: All tests
Vertex VXA-700 CopyAll PASSED: All tests
Vertex VXA-700 Clone PASSED: All tests
Vertex VXA-700 BruteForce PASSED: All tests
Vertex VXA-700 Edges PASSED: All tests
Vertex VXA-700 Banks SKIPPED: Banks not supported
Wouxun KG-816 Detect PASSED: All tests
Wouxun KG-816 CopyAll PASSED: All tests
Wouxun KG-816 Clone PASSED: All tests
Wouxun KG-816 BruteForce PASSED: All tests
Wouxun KG-816 Edges PASSED: All tests
Wouxun KG-816 Banks SKIPPED: Banks not supported
Wouxun KG-818 Detect PASSED: All tests
Wouxun KG-818 CopyAll PASSED: All tests
Wouxun KG-818 Clone PASSED: All tests
Wouxun KG-818 BruteForce PASSED: All tests
Wouxun KG-818 Edges PASSED: All tests
Wouxun KG-818 Banks SKIPPED: Banks not supported
Wouxun KG-UV6 Detect PASSED: All tests
Wouxun KG-UV6 CopyAll PASSED: All tests
Wouxun KG-UV6 Clone PASSED: All tests
Wouxun KG-UV6 BruteForce PASSED: All tests
Wouxun KG-UV6 Edges PASSED: All tests
Wouxun KG-UV6 Banks SKIPPED: Banks not supported
Wouxun KG-UVD1P Detect PASSED: All tests
Wouxun KG-UVD1P CopyAll PASSED: All tests
Wouxun KG-UVD1P Clone PASSED: All tests
Wouxun KG-UVD1P BruteForce PASSED: All tests
Wouxun KG-UVD1P Edges PASSED: All tests
Wouxun KG-UVD1P Banks SKIPPED: Banks not supported
Yaesu FT-1802M Detect PASSED: All tests
Yaesu FT-1802M CopyAll PASSED: All tests
Yaesu FT-1802M Clone PASSED: All tests
Yaesu FT-1802M BruteForce PASSED: All tests
Yaesu FT-1802M Edges PASSED: All tests
Yaesu FT-1802M Banks SKIPPED: Banks not supported
Yaesu FT-2800M Detect PASSED: All tests
Yaesu FT-2800M CopyAll PASSED: All tests
Yaesu FT-2800M Clone PASSED: All tests
Yaesu FT-2800M BruteForce PASSED: All tests
Yaesu FT-2800M Edges PASSED: All tests
Yaesu FT-2800M Banks SKIPPED: Banks not supported
Yaesu FT-60 Detect PASSED: All tests
Yaesu FT-60 CopyAll PASSED: All tests
Yaesu FT-60 Clone PASSED: All tests
Yaesu FT-60 BruteForce PASSED: All tests
Yaesu FT-60 Edges PASSED: All tests
Yaesu FT-60 Banks SKIPPED: Banks not supported
Yaesu FT-7800/7900 Detect PASSED: All tests
Yaesu FT-7800/7900 CopyAll PASSED: All tests
Yaesu FT-7800/7900 Clone PASSED: All tests
Yaesu FT-7800/7900 BruteForce PASSED: All tests
Yaesu FT-7800/7900 Edges PASSED: All tests
Yaesu FT-7800/7900 Banks PASSED: All tests
Yaesu FT-817 Detect PASSED: All tests
Yaesu FT-817 CopyAll PASSED: All tests
Yaesu FT-817 Clone PASSED: All tests
Yaesu FT-817 BruteForce PASSED: All tests
Yaesu FT-817 Edges PASSED: All tests
Yaesu FT-817 Banks SKIPPED: Banks not supported
Yaesu FT-817ND Detect PASSED: All tests
Yaesu FT-817ND CopyAll PASSED: All tests
Yaesu FT-817ND Clone PASSED: All tests
Yaesu FT-817ND BruteForce PASSED: All tests
Yaesu FT-817ND Edges PASSED: All tests
Yaesu FT-817ND Banks SKIPPED: Banks not supported
Yaesu FT-817ND (US) Detect PASSED: All tests
Yaesu FT-817ND (US) CopyAll PASSED: All tests
Yaesu FT-817ND (US) Clone PASSED: All tests
Yaesu FT-817ND (US) BruteForce PASSED: All tests
Yaesu FT-817ND (US) Edges PASSED: All tests
Yaesu FT-817ND (US) Banks SKIPPED: Banks not supported
Yaesu FT-857/897 Detect PASSED: All tests
Yaesu FT-857/897 CopyAll PASSED: All tests
Yaesu FT-857/897 Clone PASSED: All tests
Yaesu FT-857/897 BruteForce PASSED: All tests
Yaesu FT-857/897 Edges PASSED: All tests
Yaesu FT-857/897 Banks SKIPPED: Banks not supported
Yaesu FT-857/897 (U Detect PASSED: All tests
Yaesu FT-857/897 (U CopyAll PASSED: All tests
Yaesu FT-857/897 (U Clone PASSED: All tests
Yaesu FT-857/897 (U BruteForce PASSED: All tests
Yaesu FT-857/897 (U Edges PASSED: All tests
Yaesu FT-857/897 (U Banks SKIPPED: Banks not supported
Yaesu FT-8800 Left Detect PASSED: All tests
Yaesu FT-8800 Left CopyAll PASSED: All tests
Yaesu FT-8800 Left Clone PASSED: All tests
Yaesu FT-8800 Left BruteForce PASSED: All tests
Yaesu FT-8800 Left Edges PASSED: All tests
Yaesu FT-8800 Left Banks PASSED: All tests
Yaesu FT-8800 Right Detect PASSED: All tests
Yaesu FT-8800 Right CopyAll PASSED: All tests
Yaesu FT-8800 Right Clone PASSED: All tests
Yaesu FT-8800 Right BruteForce PASSED: All tests
Yaesu FT-8800 Right Edges PASSED: All tests
Yaesu FT-8800 Right Banks PASSED: All tests
Yaesu FT-8900 Detect PASSED: All tests
Yaesu FT-8900 CopyAll PASSED: All tests
Yaesu FT-8900 Clone PASSED: All tests
Yaesu FT-8900 BruteForce PASSED: All tests
Yaesu FT-8900 Edges PASSED: All tests
Yaesu FT-8900 Banks SKIPPED: Banks not supported
Yaesu FTM-350 Left Detect PASSED: All tests
Yaesu FTM-350 Left CopyAll PASSED: All tests
Yaesu FTM-350 Left Clone PASSED: All tests
Yaesu FTM-350 Left BruteForce PASSED: All tests
Yaesu FTM-350 Left Edges PASSED: All tests
Yaesu FTM-350 Left Banks SKIPPED: Banks not supported
Yaesu FTM-350 Right Detect PASSED: All tests
Yaesu FTM-350 Right CopyAll PASSED: All tests
Yaesu FTM-350 Right Clone PASSED: All tests
Yaesu FTM-350 Right BruteForce PASSED: All tests
Yaesu FTM-350 Right Edges PASSED: All tests
Yaesu FTM-350 Right Banks SKIPPED: Banks not supported
Yaesu VX-2 Detect PASSED: All tests
Yaesu VX-2 CopyAll PASSED: All tests
Yaesu VX-2 Clone PASSED: All tests
Yaesu VX-2 BruteForce PASSED: All tests
Yaesu VX-2 Edges PASSED: All tests
Yaesu VX-2 Banks PASSED: All tests
Yaesu VX-3 Detect PASSED: All tests
Yaesu VX-3 CopyAll PASSED: All tests
Yaesu VX-3 Clone PASSED: All tests
Yaesu VX-3 BruteForce PASSED: All tests
Yaesu VX-3 Edges PASSED: All tests
Yaesu VX-3 Banks PASSED: All tests
Yaesu VX-5 Detect PASSED: All tests
Yaesu VX-5 CopyAll PASSED: All tests
Yaesu VX-5 Clone PASSED: All tests
Yaesu VX-5 BruteForce PASSED: All tests
Yaesu VX-5 Edges PASSED: All tests
Yaesu VX-5 Banks PASSED: All tests
Yaesu VX-6 Detect PASSED: All tests
Yaesu VX-6 CopyAll PASSED: All tests
Yaesu VX-6 Clone PASSED: All tests
Yaesu VX-6 BruteForce PASSED: All tests
Yaesu VX-6 Edges PASSED: All tests
Yaesu VX-6 Banks PASSED: All tests
Yaesu VX-7 Detect PASSED: All tests
Yaesu VX-7 CopyAll PASSED: All tests
Yaesu VX-7 Clone PASSED: All tests
Yaesu VX-7 BruteForce PASSED: All tests
Yaesu VX-7 Edges PASSED: All tests
Yaesu VX-7 Banks PASSED: All tests
Yaesu VX-8 R Detect PASSED: All tests
Yaesu VX-8 R CopyAll PASSED: All tests
Yaesu VX-8 R Clone PASSED: All tests
Yaesu VX-8 R BruteForce PASSED: All tests
Yaesu VX-8 R Edges PASSED: All tests
Yaesu VX-8 R Banks PASSED: All tests
----------------------------------------------------------------------
Results:
TOTAL : 342
FAILED : 0
SKIPPED: 38
PASSED : 304
CRASHED: 0
Patch 'tip' is OK
================================================
Tests OK
Email was triggered for: Success
Sending email for trigger: Success
1
0
18 Jun '14
I've updated the TYT TH9000 new model radio ticket with my latest patch.
It's ready for review and/or others to test. I would still consider it an
alpha version.
What's the process to get this included in trunk?
The hg qpatch file and details are listed in NewModel Ticket #1035.
Thanks,
Dave KK6DF
Here's the qlog message from the latest patch:
-----------------------------------------------------------
Update for TYT TH9000 Radio (new model)
Features working:
Download/Upload to radio
Display and Edit Memories
Save image file
Modes: None, Tone, TSQL
Global Setting
APO
BG Color and Brightness
Squelch Level
TOT
Radio Max Transmit Power
Startup/Welcome Message
TBST Freq
TX/RX Freq Range
Beep
Memory Setting
Freq, Offset, Skip, Step, Ch Width, Name, Power, Mode, Tone-PL,
TSQL-PL
Not Working
DCS, Cross and Reverse Modes
Display Mode (VFO/Mem)
VFO MR
Channel Lock
Voice Prompt
Tail Elim Type
Bootup Password
Memory: Reverse, TX Off, Compander, Talk Around, Scrambler
I executed the unit tests, and its failing on one test:
TYT TH9000 BruteForce FAILED: Field `tmode' is `', expected `TSQL-R'
----------------------------------------------------
2
1
All,
I got my hands on some Wouxun mobile radios that I thought I would see if I
could develop support for. Specifically the KG-UV920P-A dual band mobile
and the KG-UV950P quad band mobile.
I thought when I captured the serial port of a download using PortMon, I
would see something similar to what I was used to working with
handi-talkies. Well that wasn't the case.
So I have attached the logs from both radios in the hope that a few might
be able to assist me (or at least guide me) with getting started. Thanks in
advance.
Jim KC9HI
3
7
[chirp_devel] [developer] Control fontsize of hex diff/dumpdisplay - #1681
by chirp.cordless@xoxy.net 07 Jun '14
by chirp.cordless@xoxy.net 07 Jun '14
07 Jun '14
Resubmitted patch attached.
-dan
1
0
Re: [chirp_devel] [developer] Control fontsize of hex diff/dumpdisplay - #1681
by chirp.cordless@xoxy.net 07 Jun '14
by chirp.cordless@xoxy.net 07 Jun '14
07 Jun '14
Well, not quite what I expected. I have tried font sizes of 400, 300000, 0,
-12, and -1234 and Pango does not generate an exception, it fact is seems
to render what was asked for, mostly.
0 was a blank screen. 300000 actually seemed to be realized;
scrolling about the window I was able to find some glyph edges.
Of course, it's completely unusable, but there's no exception to handle.
Doing some reading about Pango on the web, I think this is what
it's built to do.
The negative values were readable, but variable-width, making me
nervous that something got mangled. But no exception generated.
That's on a Mac, so Windows or linux might behave differently, but
there's no exception I can generate and thus handle.
Then out of whimsy I tried "twelve" (no quotes), expecting that would
generate an exception from CONF.get_int(). Nope. It returned 0, no
exception, resulting in an empty window. I suspect that's related to
> However, I see that the ChirpConfigProxy wrapper is not going to raise a
> sane exception for the case you're going to hit here.
So between the odd behavior for negative fontsizes, and the lack of
exception for non-integer, I've added some bounds checking, accepting
[4, 144]. The values were chosen as marginally absurd, or more specifically,
exceeding anything I expect is useful, but rendering recognizably so the
developer-user can see they got what they asked for but probably not
what they want. And minimal chance that someone will request
larger/smaller down the line, even with 4k displays.
Resubmitted patch to follow shortly. If you still want refinements
I remain open to that, but I can't see what else to do at the moment.
-dan
On Jun 6, 2014, at 3:39 PM, Dan Smith - dsmith(a)danplanet.com wrote:
>> For the first, what you're suggesting would be
>> except:
>> fontsize = 11
>> ??
>> I did test what happens if diff_fontsize is not there in chirp.config
>> and what I submitted handles it. Does that cover your concern?
>
> Well, you can ignore this for the moment. In general, it's bad form to
> catch Exception, which will swallow anything. It's better to catch the
> actual thing you're expecting, so that if anything unexpected happens,
> it bubbles up and gets noticed.
>
> However, I see that the ChirpConfigProxy wrapper is not going to raise a
> sane exception for the case you're going to hit here. So, I'll retract
> my comment on the grounds that my code you're calling is kinda broken :)
>
>> I'll look at specifying some weird fontsize and see if I can get
>> an exception generated and make sure it's handled.
>> I thought about bounds checking, but I figured the users are
>> developers and could deal with the results of specifying something strange.
>> But if it's just a try/except clause, seems worth it.
>
> Well, just see what happens. If it's something we can just log to the
> debug log that the size was unsupported and default back to 11, that
> seems like a good idea.
>
> --Dan
1
0