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
May 2021
- 7 participants
- 12 discussions
# HG changeset patch
# User Angus Ainslie <angus(a)akkea.ca>
# Date 1592188302 25200
# Sun Jun 14 19:31:42 2020 -0700
# Branch py3
# Node ID eb35a46c5f7e43518f6adc88768107efc0a3d402
# Parent b1e01577ff2505de7fcca665bf3d6af296f0f7ca
[thd74] Add a Kenwood d74 driver
Based on code from
Tom Hayward, Eric Wolak, William McKeehan
https://chirp.danplanet.com/issues/4129
This works with python3 no idea about python2
diff --git a/chirp/drivers/thd74.py b/chirp/drivers/thd74.py
new file mode 100644
--- /dev/null
+++ b/chirp/drivers/thd74.py
@@ -0,0 +1,571 @@
+import logging
+import struct
+import binascii
+
+import time
+
+from chirp import directory, bitwise, errors, chirp_common, memmap
+from chirp.settings import RadioSettingGroup, RadioSetting, RadioSettings, \
+ RadioSettingValueInteger, RadioSettingValueString, \
+ RadioSettingValueList, RadioSettingValueBoolean, \
+ InvalidValueError
+
+from . import thd72
+from chirp.util import hexprint
+
+LOG = logging.getLogger(__name__)
+
+# Save files from MCP-D74 have a 256-byte header, and possibly some oddness
+# TH-D74 memory map
+
+# 0x02000: memory flags, 4 bytes per memory
+# 0x04000: memories, each 40 bytes long
+# 0x10000: names, each 16 bytes long, null padded, ascii encoded
+
+# memory channel
+# 0 1 2 3 4 5 6 7 8 9 a b c d e f
+# [freq ] ? mode tmode/duplex rtone ctone dtcs cross_mode [offset] ?
+
+# frequency is 32-bit unsigned little-endian Hz
+
+DEFAULT_PROG_VFO = (
+ (136000000, 174000000),
+ (410000000, 470000000),
+ (118000000, 136000000),
+ (136000000, 174000000),
+ (320000000, 400000000),
+ (400000000, 524000000),
+)
+
+# Some of the blocks written by MCP have a length set of less than 0x00/256
+BLOCK_SIZES = {
+ 0x0003: 0x00B4,
+ 0x0007: 0x0068,
+}
+
+mem_format = """
+// TODO: find lockout
+
+#seekto 0x10c0;
+struct {
+ char power_on_msg[16];
+ char modem_name[16];
+} onmsg_name;
+
+#seekto 0x1200;
+struct {
+ char callsign[8];
+} callsign;
+
+#seekto 0x02000;
+struct {
+// 4 bytes long
+ u8 disabled;
+ u8 unk;
+ u8 group;
+ u8 unk2;
+} flag[1032];
+
+#seekto 0x04000;
+// TODO: deal with the 16-byte trailers of every block
+struct {
+ struct {
+ ul32 freq;
+ ul32 offset;
+
+ u8 tuning_step:4,
+ unk:4;
+ u8 mode:4,
+ unk1:4;
+ u8 tone_mode:4,
+ duplex:4;
+ u8 rtone;
+
+ u8 ctone;
+ u8 dtcs;
+ u8 cross_mode:4
+ digital_squelch:4;
+ char urcall[8];
+ char rpt1[8];
+ char rpt2[8];
+
+ u8 digital_squelch_code;
+
+ } mem[6];
+
+ u8 pad[16];
+} memory[1167]; // TODO: correct number of memories
+
+#seekto 0x10000;
+struct {
+ char name[16];
+} channel_name[1000];
+
+#seekto 0x14700;
+struct {
+ char name[16];
+} wx_name[10];
+
+#seekto 0x144d0;
+struct {
+ char name[16];
+} call_name[6];
+
+#seekto 0x14800;
+struct {
+ char name[16];
+} group_name[31];
+"""
+
+STEPS = [5.0, 6.25, None, None, 10.0, 12.5, 15.0, 20.0, 25.0, 50.0, 100.0, 9.0]
+MODES = [
+ "FM",
+ "DV",
+ "AM",
+ "LSB",
+ "USB",
+ "CW",
+ "NFM",
+ "DV"
+]
+
+def hex(data):
+ data_txt = ""
+ for idx in range(0, len(data), 16):
+ bytes = binascii.hexlify(str(data[idx:idx+16]).encode('utf8')).upper()
+ for idx in range(0, len(bytes), 2):
+ data_txt += str(bytes[idx:idx+2]) + " "
+ data_txt += "\n"
+ return data_txt.strip()
+
+class SProxy(object):
+ def __init__(self, delegate):
+ self.delegate = delegate
+
+ def read(self, len):
+ r = self.delegate.read(len)
+ LOG.debug("READ\n" + hex(r))
+ return r
+
+ def write(self, data):
+ LOG.debug("WRITE\n" + hex(data))
+ return self.delegate.write(str(data))
+
+ @property
+ def timeout(self):
+ return self.delegate.timeout
+
+ @timeout.setter
+ def timeout(self, timeout):
+ self.delegate.timeout = timeout
+
+
+
+(a)directory.register
+class THD74Radio(thd72.THD72Radio):
+ MODEL = "TH-D74 (clone mode)"
+ #MODEL = "TH-D74"
+ _memsize = 500480
+ # I think baud rate might be ignored by USB-Serial stack of the D74's
+ # on-board FTDI chip, but it doesn't seem to hurt.
+ BAUD_RATE = 115200
+
+
+ #def __init__(self, pipe):
+ # pipe = SProxy(pipe)
+ # super(THD74Radio, self).__init__(pipe)
+
+ def get_features(self):
+ rf = super(THD74Radio, self).get_features()
+ rf.has_tuning_step = True
+ return rf
+
+ def process_mmap(self):
+ self._memobj = bitwise.parse(mem_format, self._mmap)
+ self._dirty_blocks = []
+
+ def sync_in(self):
+ # self._detect_baud()
+ self._mmap = self.download()
+ self.process_mmap()
+
+ def sync_out(self):
+ if len(self._dirty_blocks):
+ self.upload(self._dirty_blocks)
+ else:
+ self.upload()
+
+ def read_block(self, block, count=256):
+ cmd = struct.pack(">cHH", b"R", block, count%256)
+ print( "Read cmd %s" % cmd )
+ self.pipe.write(''.join(chr(b) for b in cmd))
+
+ r = self.pipe.read(5)
+ if len(r) != 5:
+ raise Exception("Did not receive block response")
+
+ print( "Read input %s %i %i %i %i" % ( r, ord(r[1]), ord(r[2]), ord(r[3]), ord(r[4] )))
+
+ #cmd, _block, _ = struct.unpack(">cHH", b''.join(ord(b) for b in r))
+ cmd = r[0]
+ _block = (ord(r[1]) << 8) + ord(r[2])
+ if cmd != 'W' or _block != block:
+ raise Exception("Invalid response: %s %i %i" % (cmd, block, _block))
+
+ data = ""
+ while len(data) < count:
+ data += self.pipe.read(count - len(data))
+
+ self.pipe.write(chr(0x06))
+ if self.pipe.read(1) != chr(0x06):
+ raise Exception("Did not receive post-block ACK!")
+
+ return data
+
+ def write_block(self, block, map, count=256):
+ #print("Write block ", block )
+ c = struct.pack(">cHH", b"W", block, count%256)
+ base = block * 256
+ data = map[base:base + count]
+ # It's crucial that these are written together. Otherwise the radio
+ # will fail to ACK under some conditions.
+ c_d = ''.join(chr(b) for b in c) + data
+ self.pipe.write(c_d)
+
+ ack = self.pipe.read(1)
+
+ if len(ack) == 0:
+ print("read timed out block %d - trying again" % block )
+ time.sleep(0.5)
+ ack = self.pipe.read(1)
+
+ if ack != chr(0x06):
+ print("Block %d write failed %d" % ( block, ord(ack)))
+
+ return ack == chr(0x06)
+
+ def _unlock(self):
+ """Voodoo sequence of operations to get the radio to accept our programming."""
+
+ h = self.read_block(0, 6)
+
+ unlock = ("\x57\x00\x00\x00\x30\xff\x01\xff\x00\x00\xff\xff\xff\xff\xff\x01" +
+ "\x00\x00\x00\x03\x01\x00\x00\x00\x00\x02\x00\x30\x30\x30\x00\xff" +
+ "\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff" +
+ "\xff\xff\xff\xff\xff")
+
+ self.pipe.write(unlock)
+
+ ack = self.pipe.read(1)
+
+ if ack != chr(0x06):
+ raise errors.RadioError("Expected ack but got {} ({})".format(ord(ack), type(ack)))
+
+ c = struct.pack(">cHH", b"W", 0, 0x38C8)
+ self.pipe.write(''.join(chr(b) for b in c))
+ # magic unlock sequence
+ unlock = [0xFF] * 8 + [0] * 160 + [0xFF] * 32
+ unlock = "".join([chr(x) for x in unlock])
+ self.pipe.write(unlock)
+
+ time.sleep(0.01)
+ ack = self.pipe.read(1)
+
+ if ack != chr(0x06):
+ raise errors.RadioError("Expected ack but got {} ({})".format(ord(ack), type(ack)))
+
+ def download(self, raw=False, blocks=None):
+ if blocks is None:
+ blocks = list(range(int(self._memsize / 256)))
+ else:
+ blocks = [b for b in blocks if b < int(self._memsize / 256)]
+
+ if self.command("0M PROGRAM", 2, timeout=1.5) != "0M":
+ raise errors.RadioError("Radio didn't go into PROGRAM mode")
+
+ allblocks = list(range(int(self._memsize / 256)))
+ self.pipe.baudrate = 57600
+ try:
+ self.pipe.setRTS()
+ except AttributeError:
+ self.pipe.rts = True
+ self.pipe.read(1)
+ data = ""
+ LOG.debug("reading blocks %d..%d" % (blocks[0], blocks[-1]))
+ total = len(blocks)
+ count = 0
+ for i in allblocks:
+ if i not in blocks:
+ data += 256 * '\xff'
+ continue
+ data += self.read_block(i)
+ count += 1
+ if self.status_fn:
+ s = chirp_common.Status()
+ s.msg = "Cloning from radio"
+ s.max = total
+ s.cur = count
+ self.status_fn(s)
+
+
+ self.pipe.write("E")
+ if raw:
+ return data
+ return memmap.MemoryMap(data)
+
+ def upload(self, blocks=None):
+ # MCP-D74 sets DTR, so we should too
+ try:
+ self.pipe.setDTR()
+ except AttributeError:
+ self.pipe.dtr = True
+
+ if blocks is None:
+ blocks = list(range((int(self._memsize / 256)) - 2))
+ else:
+ blocks = [b for b in blocks if b < int(self._memsize / 256)]
+
+ if self.command("0M PROGRAM", 2, timeout=1.5) != "0M":
+ raise errors.RadioError("Radio didn't go into PROGRAM mode")
+
+ if self._unlock():
+ raise errors.RadioError("Unlock failed")
+
+ # This block definitely isn't written conventionally, so we let _unlock
+ # handle it and skip.
+ if 0 in blocks:
+ blocks.remove(0)
+
+ # For some reason MCP-D74 skips this block. If we don't, we'll get a NACK
+ # on the next one. There is also a more than 500 ms delay for the ACK.
+ if 1279 in blocks:
+ blocks.remove(1279)
+
+ print("writing blocks %d..%d" % (blocks[0], blocks[-1]))
+ total = len(blocks)
+ count = 0
+ for i in blocks:
+ time.sleep(0.001)
+ r = self.write_block(i, self._mmap, BLOCK_SIZES.get(i, 256))
+ count += 1
+ if not r:
+ raise errors.RadioError("write of block %i failed" % i)
+ if self.status_fn:
+ s = chirp_common.Status()
+ s.msg = "Cloning to radio"
+ s.max = total
+ s.cur = count
+ self.status_fn(s)
+
+ lock = ("\x57\x00\x00\x00\x06\x02\x01\xff\x00\x00\xff")
+ self.pipe.write(lock)
+
+ self.pipe.write("F")
+ # clear out blocks we uploaded from the dirty blocks list
+ self._dirty_blocks = [b for b in self._dirty_blocks if b not in blocks]
+
+ def command(self, cmd, response_length, timeout=0.5):
+ start = time.time()
+
+ LOG.debug("PC->D72: %s" % cmd)
+ default_timeout = self.pipe.timeout
+ self.pipe.write(cmd + "\r")
+ self.pipe.timeout = timeout
+ try:
+ data = self.pipe.read(response_length + 1)
+ LOG.debug("D72->PC: %s" % data.strip())
+ finally:
+ self.pipe.timeout = default_timeout
+ return data.strip()
+
+ def get_raw_memory(self, number):
+ bank = number // 6
+ idx = number % 6
+
+ _mem = self._memobj.memory[bank].mem[idx]
+ return repr(_mem) + \
+ repr(self._memobj.flag[number])
+
+ def get_id(self):
+ r = self.command("ID", 9)
+ if r.startswith("ID "):
+ return r.split(" ")[1]
+ else:
+ raise errors.RadioError("No response to ID command")
+
+ def set_channel_name(self, number, name):
+ name = name[:16] + '\x00' * 16
+ if number < 999:
+ self._memobj.channel_name[number].name = name[:16]
+ self.add_dirty_block(self._memobj.channel_name[number])
+ elif number >= 1020 and number < 1030:
+ number -= 1020
+ self._memobj.wx_name[number].name = name[:16]
+ self.add_dirty_block(self._memobj.wx_name[number])
+
+ def get_memory(self, number):
+ if isinstance(number, str):
+ try:
+ number = thd72.THD72_SPECIAL[number]
+ except KeyError:
+ raise errors.InvalidMemoryLocation("Unknown channel %s" %
+ number)
+
+ if number < 0 or number > (max(thd72.THD72_SPECIAL.values()) + 1):
+ raise errors.InvalidMemoryLocation(
+ "Number must be between 0 and 999")
+
+ bank = number // 6
+ idx = number % 6
+
+ #print("reading memory #%d bank %d entry %d" %(number, bank, idx))
+ _mem = self._memobj.memory[bank].mem[idx]
+ flag = self._memobj.flag[number]
+
+ #print("Memory mode %d" % _mem.mode)
+ if _mem.mode < len( MODES ) and MODES[_mem.mode] == "DV":
+ mem = chirp_common.DVMemory()
+ else:
+ mem = chirp_common.Memory()
+
+ mem.number = number
+
+ if number > 999:
+ mem.extd_number = thd72.THD72_SPECIAL_REV[number]
+ if flag.disabled == 0xFF:
+ mem.empty = True
+ return mem
+
+ mem.name = self.get_channel_name(number)
+ mem.freq = int(_mem.freq)
+ mem.tmode = thd72.TMODES[int(_mem.tone_mode)]
+ mem.rtone = chirp_common.TONES[_mem.rtone]
+ mem.ctone = chirp_common.TONES[_mem.ctone]
+ mem.dtcs = chirp_common.DTCS_CODES[_mem.dtcs]
+ mem.duplex = thd72.DUPLEX[int(_mem.duplex)]
+ mem.offset = _mem.offset
+ mem.mode = MODES[int(_mem.mode)]
+ mem.tuning_step = STEPS[_mem.tuning_step]
+
+ if mem.mode == "DV":
+ mem.dv_urcall = _mem.urcall
+ mem.dv_rpt1call = _mem.rpt1
+ mem.dv_rpt2call = _mem.rpt2
+ mem.dv_code = _mem.digital_squelch_code
+
+ if number < 999:
+ # mem.skip = chirp_common.SKIP_VALUES[int(flag.skip)]
+ mem.cross_mode = chirp_common.CROSS_MODES[_mem.cross_mode]
+ if number > 999:
+ mem.cross_mode = chirp_common.CROSS_MODES[0]
+ mem.immutable = ["number", "bank", "extd_number", "cross_mode"]
+ if number >= 1020 and number < 1030:
+ mem.immutable += ["freq", "offset", "tone", "mode",
+ "tmode", "ctone", "skip"] # FIXME: ALL
+ else:
+ mem.immutable += ["name"]
+
+ return mem
+
+ def set_memory(self, mem):
+ LOG.debug("set_memory(%d)" % mem.number)
+ if mem.number < 0 or mem.number > (max(thd72.THD72_SPECIAL.values()) + 1):
+ raise errors.InvalidMemoryLocation(
+ "Number must be between 0 and 999")
+
+ # weather channels can only change name, nothing else
+ if mem.number >= 1020 and mem.number < 1030:
+ self.set_channel_name(mem.number, mem.name)
+ return
+
+ flag = self._memobj.flag[mem.number]
+ self.add_dirty_block(self._memobj.flag[mem.number])
+
+ # only delete non-WX channels
+ was_empty = flag.disabled == 0xf
+ if mem.empty:
+ flag.disabled = 0xf
+ return
+ flag.disabled = 0
+
+ bank = mem.number // 6
+ idx = mem.number % 6
+
+ print("seting memory #%d bank %d entry %d" %(mem.number, bank, idx))
+ _mem = self._memobj.memory[bank].mem[idx]
+ self.add_dirty_block(_mem)
+ if was_empty:
+ self.initialize(_mem)
+
+ _mem.freq = mem.freq
+
+ if mem.number < 999:
+ self.set_channel_name(mem.number, mem.name)
+
+ _mem.tone_mode = thd72.TMODES_REV[mem.tmode]
+ _mem.rtone = chirp_common.TONES.index(mem.rtone)
+ _mem.ctone = chirp_common.TONES.index(mem.ctone)
+ _mem.dtcs = chirp_common.DTCS_CODES.index(mem.dtcs)
+ _mem.cross_mode = chirp_common.CROSS_MODES.index(mem.cross_mode)
+ _mem.duplex = thd72.DUPLEX_REV[mem.duplex]
+ _mem.offset = mem.offset
+ _mem.mode = thd72.MODES_REV[mem.mode]
+
+ prog_vfo = thd72.get_prog_vfo(mem.freq)
+ #flag.prog_vfo = prog_vfo
+
+ #if mem.number < 999:
+ # flag.skip = chirp_common.SKIP_VALUES.index(mem.skip)
+
+
+ @staticmethod
+ def _add_00_pad(val, length):
+ return val.ljust(length, "\x00")[:length]
+
+
+ @classmethod
+ def apply_callsign(cls, setting, obj):
+ callsign = setting.value.get_value().upper()
+ setattr(obj, "callsign", cls._add_00_pad(callsign, 8))
+
+
+ @classmethod
+ def apply_power_on_msg(cls, setting, obj):
+ msg = setting.value.get_value()
+ setattr(obj, "power_on_msg", cls._add_00_pad(msg, 16))
+
+
+ def _get_general_settings(self):
+ menu = RadioSettingGroup("general", "General")
+ cs = self._memobj.callsign
+
+ val = RadioSettingValueString(
+ 0, 6, str(cs.callsign).rstrip("\x00"))
+ rs = RadioSetting("cs.callsign", "Callsign", val)
+ rs.set_apply_callback(self.apply_callsign, cs)
+ menu.append(rs)
+
+ msg = self._memobj.onmsg_name
+
+ val = RadioSettingValueString(
+ 0, 16, str(msg.power_on_msg).rstrip("\x00"))
+ rs = RadioSetting("msg.power_on_msg", "Power on message", val)
+ rs.set_apply_callback(self.apply_power_on_msg, msg)
+ menu.append(rs)
+
+ return menu
+
+
+ def _get_settings(self):
+ top = RadioSettings(self._get_general_settings())
+ return top
+
+
+ def get_settings(self):
+ try:
+ return self._get_settings()
+ except:
+ import traceback
+ LOG.error("Failed to parse settings: %s", traceback.format_exc())
+ return None
+
4
4
[chirp_devel] [PATCH] [csv] Optimize generic csv files load times. Fixes #8991
by Kosta A. 13 Jun '21
by Kosta A. 13 Jun '21
13 Jun '21
# HG changeset patch
# User Kosta A. <ve7kcy(a)gmail.com>
# Date 1618643404 25200
# Sat Apr 17 00:10:04 2021 -0700
# Node ID cd3e2444040876b4a19b41c6cfecedb79ff4a8fe
# Parent 42c5ae551170c33b04f997e3a07a9e1857bdb504
[csv] Optimize generic csv files load times. Fixes #8991
diff --git a/chirp/chirp_common.py b/chirp/chirp_common.py
--- a/chirp/chirp_common.py
+++ b/chirp/chirp_common.py
@@ -268,11 +268,11 @@
# or an empty list if none
extra = []
- def __init__(self):
+ def __init__(self, number=0, empty=False, name=""):
self.freq = 0
- self.number = 0
+ self.number = number
self.extd_number = ""
- self.name = ""
+ self.name = name
self.vfo = 0
self.rtone = 88.5
self.ctone = 88.5
@@ -290,7 +290,7 @@
self.comment = ""
- self.empty = False
+ self.empty = empty
self.immutable = []
diff --git a/chirp/drivers/generic_csv.py b/chirp/drivers/generic_csv.py
--- a/chirp/drivers/generic_csv.py
+++ b/chirp/drivers/generic_csv.py
@@ -47,7 +47,7 @@
@directory.register
-class CSVRadio(chirp_common.FileBackedRadio, chirp_common.IcomDstarSupport):
+class CSVRadio(chirp_common.FileBackedRadio):
"""A driver for Generic CSV files"""
VENDOR = "Generic"
MODEL = "CSV"
@@ -67,20 +67,15 @@
"Mode": (str, "mode"),
"TStep": (float, "tuning_step"),
"Skip": (str, "skip"),
- "URCALL": (str, "dv_urcall"),
- "RPT1CALL": (str, "dv_rpt1call"),
- "RPT2CALL": (str, "dv_rpt2call"),
"Comment": (str, "comment"),
}
- def _blank(self):
+ def _blank(self, defaults=False):
self.errors = []
- self.memories = []
- for i in range(0, 1000):
- mem = chirp_common.Memory()
- mem.number = i
- mem.empty = True
- self.memories.append(mem)
+ self.memories = [chirp_common.Memory(i, True) for i in range(0, 1000)]
+ if (defaults):
+ self.memories[0].empty = False
+ self.memories[0].freq = 146010000
def __init__(self, pipe):
chirp_common.FileBackedRadio.__init__(self, None)
@@ -92,14 +87,14 @@
if self._filename and os.path.exists(self._filename):
self.load()
else:
- self._blank()
+ self._blank(True)
def get_features(self):
rf = chirp_common.RadioFeatures()
rf.has_bank = False
rf.requires_call_lists = False
rf.has_implicit_calls = False
- rf.memory_bounds = (0, len(self.memories))
+ rf.memory_bounds = (0, len(self.memories)-1)
rf.has_infinite_number = True
rf.has_nostep_tuning = True
rf.has_comment = True
diff --git a/chirp/drivers/ic2200.py b/chirp/drivers/ic2200.py
--- a/chirp/drivers/ic2200.py
+++ b/chirp/drivers/ic2200.py
@@ -217,7 +217,6 @@
return mem
def get_memories(self, lo=0, hi=199):
-
return [m for m in self._memories if m.number >= lo and m.number <= hi]
def set_memory(self, mem):
diff --git a/chirp/ui/bandplans.py b/chirp/ui/bandplans.py
--- a/chirp/ui/bandplans.py
+++ b/chirp/ui/bandplans.py
@@ -47,7 +47,7 @@
# Check for duplicates.
duplicates = [x for x in plan.BANDS if x == band]
if len(duplicates) > 1:
- LOG.warn("Bandplan %s has duplicates %s" %
+ LOG.info("Bandplan %s has duplicates %s" %
(name, duplicates))
# Add repeater inputs.
rpt_input = band.inverse()
diff --git a/chirp/ui/editorset.py b/chirp/ui/editorset.py
--- a/chirp/ui/editorset.py
+++ b/chirp/ui/editorset.py
@@ -386,19 +386,6 @@
"export: {error}").format(error=e),
self)
- def prime(self):
- # NOTE: this is only called to prime new CSV files, so assume
- # only one memory editor for now
- mem = chirp_common.Memory()
- mem.freq = 146010000
-
- def cb(*args):
- gobject.idle_add(self.editors["memedit0"].prefill)
-
- job = common.RadioJob(cb, "set_memory", mem)
- job.set_desc(_("Priming memory"))
- self.rthread.submit(job)
-
def tab_selected(self, notebook, foo, pagenum):
widget = notebook.get_nth_page(pagenum)
for k, v in self.editors.items():
diff --git a/chirp/ui/mainapp.py b/chirp/ui/mainapp.py
--- a/chirp/ui/mainapp.py
+++ b/chirp/ui/mainapp.py
@@ -271,7 +271,6 @@
def do_new(self):
eset = editorset.EditorSet(_("Untitled") + ".csv", self)
self._connect_editorset(eset)
- eset.prime()
eset.show()
tab = self.tabs.append_page(eset, eset.get_tab_label())
diff --git a/chirp/ui/memedit.py b/chirp/ui/memedit.py
--- a/chirp/ui/memedit.py
+++ b/chirp/ui/memedit.py
@@ -1062,10 +1062,7 @@
if not mem.empty or self.show_empty:
gobject.idle_add(self.set_memory, mem)
else:
- mem = chirp_common.Memory()
- mem.number = number
- mem.name = "ERROR"
- mem.empty = True
+ mem = chirp_common.Memory(number, True, "Error")
gobject.idle_add(self.set_memory, mem)
for i in range(lo, hi+1):
3
4
Factory CHIRP Radio Images (*.img) file attached: Retevis_RT76P.img
---------- Forwarded message ---------
From: Jim Unroe <kc9hi(a)comcast.net>
Date: Sun, May 30, 2021 at 10:44 PM
Subject: [PATCH] [RT76P] Add Retevis RT76P
To: <Rock.Unroe(a)gmail.com>
# HG changeset patch
# User Jim Unroe <rock.unroe(a)gmail.com>
# Date 1622428761 14400
# Sun May 30 22:39:21 2021 -0400
# Node ID f8aa35624ba03d4c6d5480dcaec3aed10c1af897
# Parent b62aebea801d5d8a4996046287d50e94a1483660
[RT76P] Add Retevis RT76P
This patch adds support for the Retevis RT76P GMRS handheld radio.
#8681
diff -r b62aebea801d -r f8aa35624ba0 chirp/drivers/retevis_rt76p.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/chirp/drivers/retevis_rt76p.py Sun May 30 22:39:21 2021 -0400
@@ -0,0 +1,1043 @@
+# Copyright 2021 Jim Unroe <rock.unroe(a)gmail.com>
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 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 logging
+import os
+import struct
+import time
+
+from chirp import (
+ bitwise,
+ chirp_common,
+ directory,
+ errors,
+ memmap,
+ util,
+)
+from chirp.settings import (
+ RadioSetting,
+ RadioSettingGroup,
+ RadioSettings,
+ RadioSettingValueBoolean,
+ RadioSettingValueFloat,
+ RadioSettingValueInteger,
+ RadioSettingValueList,
+ RadioSettingValueString,
+)
+
+LOG = logging.getLogger(__name__)
+
+MEM_FORMAT = """
+#seekto 0x0000;
+struct {
+ lbcd rxfreq[4]; // 0-3
+ lbcd txfreq[4]; // 4-7
+ ul16 rxtone; // 8-9
+ ul16 txtone; // A-B
+ u8 unknown1:4, // C
+ scode:4; // Signal
+ u8 unknown2:6, // D
+ pttid:2; // PTT-ID
+ u8 unknown3:7, // E
+ lowpower:1; // Power Level 0 = High, 1 = Low
+ u8 ani:1, // F ANI
+ narrow:1, // Bandwidth 0 = Wide, 1 = Narrow
+ unknown4:2,
+ bcl:1, // BCL
+ scan:1, // Scan 0 = Skip, 1 = Scan
+ unknown5:1,
+ compand:1; // Compand
+} memory[30];
+
+#seekto 0x0C00;
+struct {
+ char name[10]; // 10-character Alpha Tag
+ u8 unused[6];
+} names[30];
+
+#seekto 0x1A00;
+struct {
+ u8 unknown:4, // 1A00
+ squelch:4; // Squelch Level
+ u8 unknown_1a01:7, // 1A01
+ save:1; // Save Mode
+ u8 unknown_1a02:4, // 1A04
+ vox:4; // 1A02 VOX Level
+ u8 unknown_1a03:4, // 1A03
+ abr:4; // Auto Backlight Time-out
+ u8 unknown_1a04:7, // 1A04
+ tdr:1; // Dual Standby
+ u8 tot; // 1A05 Time-out Timer
+ u8 unknown_1a06:7, // 1A06
+ beep:1; // Beep
+ u8 unknown_1a07:7, // 1A07
+ voice:1; // Voice Switch
+ u8 unknown_1a08:7, // 1A08
+ language:1; // Language
+ u8 unknown_1a09:6, // 1A09
+ dtmfst:2; // DTMF ST
+ u8 unknown_101a:6, // 1A0A
+ scmode:2; // Scan Mode
+ u8 unknown_1a0a; // 1A0B
+ u8 pttlt; // 1A0C PTT Delay
+ u8 unknown_1a0d:6, // 1A0D
+ mdfa:2; // Channle A Display
+ u8 unknown_1a0e:6, // 1A0E
+ mdfb:2; // Channle B Display
+ u8 unknown_1a0f:7, // 1A0F
+ bcl:1; // BCL
+ u8 unknown_1a10:7, // 1A10
+ autolock:1; // AutoLock
+ u8 unknown_1a11:6, // 1A11
+ almod:2; // Alarm Mode
+ u8 unknown_1a12:7, // 1A12
+ alarm:1; // Alarm Sound
+ u8 unknown_1a13:6, // 1A13
+ tdrab:2; // Tx Under TDR Start
+ u8 unknown_1a14:7, // 1A14
+ ste:1; // Tail Noise Clear
+ u8 unknown_1a15:4, // 1A15
+ rpste:4; // Pass Repet Noise
+ u8 unknown_1a16:4, // 1A16
+ rptrl:4; // Pass Repet Noise
+ u8 unknown_1a17:7, // 1A17
+ roger:1; // Roger
+ u8 unknown_1a18; // 1A18
+ u8 unknown_1a19:7, // 1A19
+ fmradio:1; // FM Radio (inverted)
+ u8 unknown_1a1a:7, // 1A1A
+ workmode:1; // Work Mode
+ u8 unknown_1a1b:7, // 1A1B
+ kblock:1; // KB_Lock
+ u8 unknown_1a1c:6, // 1A1C
+ pwronmsg:2; // Pwr On Msg
+ u8 unknown_1a1d; // 1A1D
+ u8 unknown_1a1e:6, // 1A1E
+ tone:2; // Tone
+ u8 unknown_1a1f; // 1A1F
+ u8 unknown_1a20[7]; // 1A20-1A26
+ u8 unknown_1a27:6, // 1A27
+ wtled:2; // Wait Backlight Color
+ u8 unknown_1a28:6, // 1A28
+ rxled:2; // Rx Backlight Color
+ u8 unknown_1a29:6, // 1A29
+ txled:2; // Tx Backlight Color
+} settings;
+
+#seekto 0x1A80;
+struct {
+ u8 shortp; // 1A80 Skey Short
+ u8 longp; // 1A81 Skey Long
+} skey;
+
+#seekto 0x1B00;
+struct {
+ u8 code[6]; // 6-character PTT-ID Code
+ u8 unused[10];
+} pttid[15];
+
+#seekto 0x1BF0;
+struct {
+ u8 code[6]; // ANI Code
+ u8 unknown111;
+ u8 dtmfon; // DTMF Speed (on time)
+ u8 dtmfoff; // DTMR Speed (off time)
+ u8 unused222[7];
+ u8 killword[6]; // Kill Word
+ u8 unused333[2];
+ u8 revive[6]; // Revive
+ u8 unused444[2];
+} dtmf;
+
+#seekto 0x1FE0;
+struct {
+ char line1[16]; // Power-on Message Line 1
+ char line2[16]; // Power-on Message Line 2
+} poweron_msg;
+"""
+
+
+CMD_ACK = "\x06"
+
+RT76P_DTCS = sorted(chirp_common.DTCS_CODES + [645])
+
+DTMF_CHARS = "0123456789 *#ABCD"
+
+ALMOD_LIST = ["On Site", "Send Sound", "Send Code"]
+BACKLIGHT_LIST = ["Off", "Blue", "Orange", "Purple"]
+DTMFSPEED_LIST = ["%s ms" % x for x in range(50, 2010, 10)]
+DTMFST_LIST = ["Off", "KeyBboard Side Tone", "ANI Side Tone", "KB ST + ANI ST"]
+LANGUAGE_LIST = ["English", "China"]
+MDF_LIST = ["Name", "Frequency", "Number"]
+OFF1TO10_LIST = ["Off"] + ["%s" % x for x in range(1, 11)]
+PTTID_LIST = ["Off", "BOT", "EOT", "Both"]
+PTTIDCODE_LIST = ["%s" % x for x in range(1, 16)]
+PWRONMSG_LIST = ["Picture", "Message", "Voltage"]
+RPSTE_LIST = ["Off"] + ["%s" % x for x in range(100, 1100, 100)]
+SCMODE_LIST = ["Time (TO)", "Carrier (CO)", "Search (SE)"]
+TDRAB_LIST = ["Off", "A Band", "B Band"]
+TIMEOUTTIMER_LIST = ["%s seconds" % x for x in range(15, 615, 15)]
+TONE_LIST = ["1000Hz", "1450Hz", "1750Hz", "2100Hz"]
+VOICE_LIST = ["Off", "On"]
+WORKMODE_LIST = ["VFO Mode", "Channel Mode"]
+
+SKEY_CHOICES = ["FM", "Tx Power", "Moni", "Scan", "Offline", "Weather"]
+SKEY_VALUES = [0x07, 0x0A, 0x05, 0x1C, 0x0B, 0x0C]
+
+
+SETTING_LISTS = {
+ "abr": OFF1TO10_LIST,
+ "almod": ALMOD_LIST,
+ "dtmfspeed": DTMFSPEED_LIST,
+ "language": LANGUAGE_LIST,
+ "mdfa": MDF_LIST,
+ "mdfb": MDF_LIST,
+ "pttid": PTTID_LIST,
+ "rpste": RPSTE_LIST,
+ "rptrl": RPSTE_LIST,
+ "rxled": BACKLIGHT_LIST,
+ "scode": PTTIDCODE_LIST,
+ "scmode": SCMODE_LIST,
+ "tdrab": TDRAB_LIST,
+ "tot": TIMEOUTTIMER_LIST,
+ "tone": TONE_LIST,
+ "txled": BACKLIGHT_LIST,
+ "voice": VOICE_LIST,
+ "vox": OFF1TO10_LIST,
+ "workmode": WORKMODE_LIST,
+ "wtled": BACKLIGHT_LIST,
+ }
+
+GMRS_FREQS1 = [462.5625, 462.5875, 462.6125, 462.6375, 462.6625,
+ 462.6875, 462.7125]
+GMRS_FREQS2 = [467.5625, 467.5875, 467.6125, 467.6375, 467.6625,
+ 467.6875, 467.7125]
+GMRS_FREQS3 = [462.5500, 462.5750, 462.6000, 462.6250, 462.6500,
+ 462.6750, 462.7000, 462.7250]
+GMRS_FREQS = GMRS_FREQS1 + GMRS_FREQS2 + GMRS_FREQS3 * 2
+
+
+def _rt76p_enter_programming_mode(radio):
+ serial = radio.pipe
+
+ exito = False
+ for i in range(0, 5):
+ serial.write(radio._magic)
+ ack = serial.read(1)
+
+ try:
+ if ack == CMD_ACK:
+ exito = True
+ break
+ except:
+ LOG.debug("Attempt #%s, failed, trying again" % i)
+ pass
+
+ # check if we had EXITO
+ if exito is False:
+ msg = "The radio did not accept program mode after five tries.\n"
+ msg += "Check you interface cable and power cycle your radio."
+ raise errors.RadioError(msg)
+
+ try:
+ serial.write("F")
+ ident = serial.read(8)
+ except:
+ raise errors.RadioError("Error communicating with radio")
+
+ if not ident == radio._fingerprint:
+ LOG.debug(util.hexprint(ident))
+ raise errors.RadioError("Radio returned unknown identification string")
+
+
+def _rt76p_exit_programming_mode(radio):
+ serial = radio.pipe
+ try:
+ serial.write("E")
+ except:
+ raise errors.RadioError("Radio refused to exit programming mode")
+
+
+def _rt76p_read_block(radio, block_addr, block_size):
+ serial = radio.pipe
+
+ cmd = struct.pack(">cHb", 'R', block_addr, block_size)
+ expectedresponse = "R" + cmd[1:]
+ LOG.debug("Reading block %04x..." % (block_addr))
+
+ try:
+ serial.write(cmd)
+ response = serial.read(4 + block_size)
+ if response[:4] != expectedresponse:
+ raise Exception("Error reading block %04x." % (block_addr))
+
+ block_data = response[4:]
+ except:
+ raise errors.RadioError("Failed to read block at %04x" % block_addr)
+
+ return block_data
+
+
+def _rt76p_write_block(radio, block_addr, block_size):
+ serial = radio.pipe
+
+ cmd = struct.pack(">cHb", 'W', block_addr, block_size)
+ data = radio.get_mmap()[block_addr:block_addr + block_size]
+
+ LOG.debug("Writing Data:")
+ LOG.debug(util.hexprint(cmd + data))
+
+ try:
+ serial.write(cmd + data)
+ if serial.read(1) != CMD_ACK:
+ raise Exception("No ACK")
+ except:
+ raise errors.RadioError("Failed to send block "
+ "to radio at %04x" % block_addr)
+
+
+def do_download(radio):
+ serial = radio.pipe
+ LOG.debug("download")
+ _rt76p_enter_programming_mode(radio)
+
+ data = ""
+
+ status = chirp_common.Status()
+ status.msg = "Cloning from radio"
+
+ status.cur = 0
+ status.max = radio._memsize
+
+ for addr in range(0, radio._memsize, radio.BLOCK_SIZE):
+ status.cur = addr + radio.BLOCK_SIZE
+ radio.status_fn(status)
+
+ block = _rt76p_read_block(radio, addr, radio.BLOCK_SIZE)
+ data += block
+
+ LOG.debug("Address: %04x" % addr)
+ LOG.debug(util.hexprint(block))
+
+ _rt76p_exit_programming_mode(radio)
+
+ return memmap.MemoryMap(data)
+
+
+def do_upload(radio):
+ status = chirp_common.Status()
+ status.msg = "Uploading to radio"
+
+ _rt76p_enter_programming_mode(radio)
+
+ status.cur = 0
+ status.max = radio._memsize
+
+ for start_addr, end_addr in radio._ranges:
+ for addr in range(start_addr, end_addr, radio.BLOCK_SIZE_UP):
+ status.cur = addr + radio.BLOCK_SIZE_UP
+ radio.status_fn(status)
+ _rt76p_write_block(radio, addr, radio.BLOCK_SIZE_UP)
+
+ _rt76p_exit_programming_mode(radio)
+
+
+(a)directory.register
+class RT76PRadio(chirp_common.CloneModeRadio):
+ """RETEVIS RT76P"""
+ VENDOR = "Retevis"
+ MODEL = "RT76P"
+ BAUD_RATE = 9600
+ BLOCK_SIZE = 0x40
+ BLOCK_SIZE_UP = 0x20
+
+ RT76P_POWER_LEVELS = [chirp_common.PowerLevel("High", watts=5.00),
+ chirp_common.PowerLevel("Low", watts=0.50)]
+
+ _magic = "PROGROMCD2U"
+ _fingerprint = "\x01\x36\x01\x74\x04\x00\x05\x20"
+
+ _ranges = [
+ (0x0000, 0x0820),
+ (0x0C00, 0x1400),
+ (0x1A00, 0x1E00),
+ (0x1FE0, 0x2000),
+ ]
+ _memsize = 0x2000
+
+ def get_features(self):
+ rf = chirp_common.RadioFeatures()
+ rf.has_settings = True
+ rf.has_bank = False
+ rf.has_ctone = True
+ rf.has_cross = True
+ rf.has_rx_dtcs = True
+ rf.has_tuning_step = False
+ rf.can_odd_split = True
+ rf.has_name = True
+ rf.valid_name_length = 10
+ rf.valid_skips = ["", "S"]
+ rf.valid_tmodes = ["", "Tone", "TSQL", "DTCS", "Cross"]
+ rf.valid_cross_modes = ["Tone->Tone", "Tone->DTCS", "DTCS->Tone",
+ "->Tone", "->DTCS", "DTCS->", "DTCS->DTCS"]
+ rf.valid_power_levels = self.RT76P_POWER_LEVELS
+ rf.valid_duplexes = ["", "-", "+", "split", "off"]
+ rf.valid_modes = ["FM", "NFM"] # 25 kHz, 12.5 KHz.
+ rf.valid_dtcs_codes = RT76P_DTCS
+ rf.memory_bounds = (1, 30)
+ rf.valid_tuning_steps = [2.5, 5., 6.25, 10., 12.5, 20., 25., 50.]
+ rf.valid_bands = [(400000000, 480000000)]
+ return rf
+
+ def process_mmap(self):
+ self._memobj = bitwise.parse(MEM_FORMAT, self._mmap)
+
+ def validate_memory(self, mem):
+ msgs = ""
+ msgs = chirp_common.CloneModeRadio.validate_memory(self, mem)
+
+ _msg_freq = 'Memory location cannot change frequency'
+ _msg_simplex = 'Memory location only supports Duplex:(None)'
+ _msg_duplex = 'Memory location only supports Duplex: +'
+ _msg_offset = 'Memory location only supports Offset: 5.000000'
+ _msg_nfm = 'Memory location only supports Mode: NFM'
+ _msg_txp = 'Memory location only supports Power: Low'
+
+ # GMRS models
+ # range of memories with values set by FCC rules
+ if mem.freq != int(GMRS_FREQS[mem.number - 1] * 1000000):
+ # warn user can't change frequency
+ msgs.append(chirp_common.ValidationError(_msg_freq))
+
+ # channels 1 - 22 are simplex only
+ if mem.number <= 22:
+ if str(mem.duplex) != "":
+ # warn user can't change duplex
+ msgs.append(chirp_common.ValidationError(_msg_simplex))
+
+ # channels 23 - 30 are +5 MHz duplex only
+ if mem.number >= 23:
+ if str(mem.duplex) != "+":
+ # warn user can't change duplex
+ msgs.append(chirp_common.ValidationError(_msg_duplex))
+
+ if str(mem.offset) != "5000000":
+ # warn user can't change offset
+ msgs.append(chirp_common.ValidationError(_msg_offset))
+
+ # channels 8 - 14 are low power NFM only
+ if mem.number >= 8 and mem.number <= 14:
+ if mem.mode != "NFM":
+ # warn user can't change mode
+ msgs.append(chirp_common.ValidationError(_msg_nfm))
+
+ if mem.power != "Low":
+ # warn user can't change power
+ msgs.append(chirp_common.ValidationError(_msg_txp))
+
+ return msgs
+
+ def sync_in(self):
+ """Download from radio"""
+ try:
+ data = do_download(self)
+ except errors.RadioError:
+ # Pass through any real errors we raise
+ raise
+ except:
+ # If anything unexpected happens, make sure we raise
+ # a RadioError and log the problem
+ LOG.exception('Unexpected error during download')
+ raise errors.RadioError('Unexpected error communicating '
+ 'with the radio')
+ self._mmap = data
+ self.process_mmap()
+
+ def sync_out(self):
+ """Upload to radio"""
+ try:
+ do_upload(self)
+ except:
+ # If anything unexpected happens, make sure we raise
+ # a RadioError and log the problem
+ LOG.exception('Unexpected error during upload')
+ raise errors.RadioError('Unexpected error communicating '
+ 'with the radio')
+
+ def get_memory(self, number):
+ _mem = self._memobj.memory[number - 1]
+ _nam = self._memobj.names[number - 1]
+
+ mem = chirp_common.Memory()
+
+ mem.number = number
+ mem.freq = int(_mem.rxfreq) * 10
+
+ # We'll consider any blank (i.e. 0MHz frequency) to be empty
+ if mem.freq == 0:
+ mem.empty = True
+ return mem
+
+ if _mem.rxfreq.get_raw() == "\xFF\xFF\xFF\xFF":
+ mem.freq = 0
+ mem.empty = True
+ return mem
+
+ if _mem.get_raw() == ("\xFF" * 16):
+ LOG.debug("Initializing empty memory")
+ _mem.set_raw("\x00" * 13 + "\x30\x8F\xF8")
+
+ if int(_mem.rxfreq) == int(_mem.txfreq):
+ mem.duplex = ""
+ mem.offset = 0
+ else:
+ mem.duplex = int(_mem.rxfreq) > int(_mem.txfreq) and "-" or "+"
+ mem.offset = abs(int(_mem.rxfreq) - int(_mem.txfreq)) * 10
+
+ for char in _nam.name:
+ if str(char) == "\xFF":
+ char = " " # may have 0xFF mid-name
+ mem.name += str(char)
+ mem.name = mem.name.rstrip()
+
+ dtcs_pol = ["N", "N"]
+
+ if _mem.txtone in [0, 0xFFFF]:
+ txmode = ""
+ elif _mem.txtone >= 0x0258:
+ txmode = "Tone"
+ mem.rtone = int(_mem.txtone) / 10.0
+ elif _mem.txtone <= 0x0258:
+ txmode = "DTCS"
+ if _mem.txtone > 0x69:
+ index = _mem.txtone - 0x6A
+ dtcs_pol[0] = "R"
+ else:
+ index = _mem.txtone - 1
+ mem.dtcs = RT76P_DTCS[index]
+ else:
+ LOG.warn("Bug: txtone is %04x" % _mem.txtone)
+
+ if _mem.rxtone in [0, 0xFFFF]:
+ rxmode = ""
+ elif _mem.rxtone >= 0x0258:
+ rxmode = "Tone"
+ mem.ctone = int(_mem.rxtone) / 10.0
+ elif _mem.rxtone <= 0x0258:
+ rxmode = "DTCS"
+ if _mem.rxtone >= 0x6A:
+ index = _mem.rxtone - 0x6A
+ dtcs_pol[1] = "R"
+ else:
+ index = _mem.rxtone - 1
+ mem.rx_dtcs = RT76P_DTCS[index]
+ else:
+ LOG.warn("Bug: rxtone is %04x" % _mem.rxtone)
+
+ if txmode == "Tone" and not rxmode:
+ mem.tmode = "Tone"
+ elif txmode == rxmode and txmode == "Tone" and mem.rtone == mem.ctone:
+ mem.tmode = "TSQL"
+ elif txmode == rxmode and txmode == "DTCS" and mem.dtcs == mem.rx_dtcs:
+ mem.tmode = "DTCS"
+ elif rxmode or txmode:
+ mem.tmode = "Cross"
+ mem.cross_mode = "%s->%s" % (txmode, rxmode)
+
+ mem.dtcs_polarity = "".join(dtcs_pol)
+
+ if not _mem.scan:
+ mem.skip = "S"
+
+ mem.power = self.RT76P_POWER_LEVELS[_mem.lowpower]
+
+ mem.mode = _mem.narrow and "NFM" or "FM"
+
+ mem.extra = RadioSettingGroup("Extra", "extra")
+
+ # BCL (Busy Channel Lockout)
+ rs = RadioSettingValueBoolean(_mem.bcl)
+ rset = RadioSetting("bcl", "BCL", rs)
+ mem.extra.append(rset)
+
+ # PTT-ID
+ rs = RadioSettingValueList(PTTID_LIST, PTTID_LIST[_mem.pttid])
+ rset = RadioSetting("pttid", "PTT ID", rs)
+ mem.extra.append(rset)
+
+ # Signal (DTMF Encoder Group #)
+ rs = RadioSettingValueList(PTTIDCODE_LIST, PTTIDCODE_LIST[_mem.scode])
+ rset = RadioSetting("scode", "PTT ID Code", rs)
+ mem.extra.append(rset)
+
+ # Compand
+ rs = RadioSettingValueBoolean(_mem.compand)
+ rset = RadioSetting("compand", "Compand", rs)
+ mem.extra.append(rset)
+
+ # ANI
+ rs = RadioSettingValueBoolean(_mem.ani)
+ rset = RadioSetting("ani", "ANI", rs)
+ mem.extra.append(rset)
+
+ return mem
+
+ def set_memory(self, mem):
+ _mem = self._memobj.memory[mem.number - 1]
+ _nam = self._memobj.names[mem.number - 1]
+
+ if mem.empty:
+ _mem.set_raw("\xff" * 8 + "\x00" * 8)
+
+ GMRS_FREQ = int(GMRS_FREQS[mem.number - 1] * 100000)
+ _mem.narrow = True
+ _mem.scan = True
+ if mem.number > 22:
+ _mem.rxfreq = GMRS_FREQ
+ _mem.txfreq = int(_mem.rxfreq) + 500000
+ else:
+ _mem.rxfreq = _mem.txfreq = GMRS_FREQ
+ if mem.number >= 8 and mem.number <= 14:
+ _mem.lowpower = True
+
+ _nam.set_raw("\xff" * 16)
+ return
+
+ _mem.set_raw("\x00" * 16)
+
+ _mem.rxfreq = mem.freq / 10
+
+ if mem.duplex == "off":
+ for i in range(0, 4):
+ _mem.txfreq[i].set_raw("\xFF")
+ elif mem.duplex == "split":
+ _mem.txfreq = mem.offset / 10
+ elif mem.duplex == "+":
+ _mem.txfreq = (mem.freq + mem.offset) / 10
+ elif mem.duplex == "-":
+ _mem.txfreq = (mem.freq - mem.offset) / 10
+ else:
+ _mem.txfreq = mem.freq / 10
+
+ _namelength = self.get_features().valid_name_length
+ for i in range(_namelength):
+ try:
+ _nam.name[i] = mem.name[i]
+ except IndexError:
+ _nam.name[i] = "\xFF"
+
+ rxmode = txmode = ""
+ if mem.tmode == "Tone":
+ _mem.txtone = int(mem.rtone * 10)
+ _mem.rxtone = 0
+ elif mem.tmode == "TSQL":
+ _mem.txtone = int(mem.ctone * 10)
+ _mem.rxtone = int(mem.ctone * 10)
+ elif mem.tmode == "DTCS":
+ rxmode = txmode = "DTCS"
+ _mem.txtone = RT76P_DTCS.index(mem.dtcs) + 1
+ _mem.rxtone = RT76P_DTCS.index(mem.dtcs) + 1
+ elif mem.tmode == "Cross":
+ txmode, rxmode = mem.cross_mode.split("->", 1)
+ if txmode == "Tone":
+ _mem.txtone = int(mem.rtone * 10)
+ elif txmode == "DTCS":
+ _mem.txtone = RT76P_DTCS.index(mem.dtcs) + 1
+ else:
+ _mem.txtone = 0
+ if rxmode == "Tone":
+ _mem.rxtone = int(mem.ctone * 10)
+ elif rxmode == "DTCS":
+ _mem.rxtone = RT76P_DTCS.index(mem.rx_dtcs) + 1
+ else:
+ _mem.rxtone = 0
+ else:
+ _mem.rxtone = 0
+ _mem.txtone = 0
+
+ if txmode == "DTCS" and mem.dtcs_polarity[0] == "R":
+ _mem.txtone += 0x69
+ if rxmode == "DTCS" and mem.dtcs_polarity[1] == "R":
+ _mem.rxtone += 0x69
+
+ _mem.scan = mem.skip != "S"
+ _mem.narrow = mem.mode == "NFM"
+
+ _mem.lowpower = mem.power == self.RT76P_POWER_LEVELS[1]
+
+ for setting in mem.extra:
+ if setting.get_name() == "scramble_type":
+ setattr(_mem, setting.get_name(), int(setting.value) + 8)
+ setattr(_mem, "scramble_type2", int(setting.value) + 8)
+ else:
+ setattr(_mem, setting.get_name(), setting.value)
+
+ def get_settings(self):
+ _dtmf = self._memobj.dtmf
+ _settings = self._memobj.settings
+ _skey = self._memobj.skey
+ basic = RadioSettingGroup("basic", "Basic Settings")
+ group = RadioSettings(basic)
+
+ # Menu 00: Squelch (Squelch Level)
+ rs = RadioSettingValueInteger(0, 9, _settings.squelch)
+ rset = RadioSetting("squelch", "Squelch Level", rs)
+ basic.append(rset)
+
+ # Menu 01: Step (VFO setting)
+ # Menu 02: Tx Power (VFO setting - not available)
+
+ # Menu 03: Power save (Save Mode)
+ rs = RadioSettingValueBoolean(_settings.save)
+ rset = RadioSetting("save", "Power Save", rs)
+ basic.append(rset)
+
+ # Menu 04: Vox Level (VOX)
+ rs = RadioSettingValueList(OFF1TO10_LIST, OFF1TO10_LIST[_settings.vox])
+ rset = RadioSetting("vox", "VOX Level", rs)
+ basic.append(rset)
+
+ # Menu 05: Bandwidth
+
+ # Menu 06: Backlight (Auto Backlight)
+ rs = RadioSettingValueList(OFF1TO10_LIST,
+ OFF1TO10_LIST[_settings.abr])
+ rset = RadioSetting("abr", "Backlight Time-out", rs)
+ basic.append(rset)
+
+ # Menu 07: Dual Standby (TDR)
+ rs = RadioSettingValueBoolean(_settings.tdr)
+ rset = RadioSetting("tdr", "Dual Standby", rs)
+ basic.append(rset)
+
+ # Menu 08: Beep Prompt
+ rs = RadioSettingValueBoolean(_settings.beep)
+ rset = RadioSetting("beep", "Beep Prompt", rs)
+ basic.append(rset)
+
+ # Menu 09: Voice (Voice Switch)
+ rs = RadioSettingValueBoolean(_settings.voice)
+ rset = RadioSetting("voice", "Voice Prompts", rs)
+ basic.append(rset)
+
+ # Menu 10: Tx over time (Time Out)
+ rs = RadioSettingValueList(TIMEOUTTIMER_LIST,
+ TIMEOUTTIMER_LIST[_settings.tot - 1])
+ rset = RadioSetting("tot", "Time-out Timer", rs)
+ basic.append(rset)
+
+ # Menu 11: Rx DCS
+ # Menu 12: Rx CTCSS
+ # Menu 13: Tx DCS
+ # Menu 14: Tx CTCSS
+ # Menu 15: Voice Compand
+
+ # Menu 16: DTMFST (DTMF ST)
+ rs = RadioSettingValueList(DTMFST_LIST, DTMFST_LIST[_settings.dtmfst])
+ rset = RadioSetting("dtmfst", "DTMF Side Tone", rs)
+ basic.append(rset)
+
+ # Mneu 17: R-TONE (Tone)
+ rs = RadioSettingValueList(TONE_LIST, TONE_LIST[_settings.tone])
+ rset = RadioSetting("tone", "Tone-burst Frequency", rs)
+ basic.append(rset)
+
+ # Menu 18: S-CODE
+
+ # Menu 19: Scan Mode
+ rs = RadioSettingValueList(SCMODE_LIST, SCMODE_LIST[_settings.scmode])
+ rset = RadioSetting("scmode", "Scan Resume Method", rs)
+ basic.append(rset)
+
+ # Menu 20: ANI Match
+ # Menu 21: PTT-ID
+
+ # Menu 22: MDF-A (Channle_A Display)
+ rs = RadioSettingValueList(MDF_LIST, MDF_LIST[_settings.mdfa])
+ rset = RadioSetting("mdfa", "Memory Display Format A", rs)
+ basic.append(rset)
+
+ # Menu 23: MDF-B (Channle_B Display)
+ rs = RadioSettingValueList(MDF_LIST, MDF_LIST[_settings.mdfb])
+ rset = RadioSetting("mdfb", "Memory Display Format B", rs)
+ basic.append(rset)
+
+ # Menu 24: Busy Lockout
+
+ # Menu 25: Key Auto Lock (AutoLock)
+ rs = RadioSettingValueBoolean(_settings.autolock)
+ rset = RadioSetting("autolock", "Keypad Auto Lock", rs)
+ basic.append(rset)
+
+ # Menu 26: WT-LED (Wait Backlight)
+ rs = RadioSettingValueList(BACKLIGHT_LIST,
+ BACKLIGHT_LIST[_settings.wtled])
+ rset = RadioSetting("wtled", "Wait Backlight Color", rs)
+ basic.append(rset)
+
+ # Menu 27: RX-LED (Rx Backlight)
+ rs = RadioSettingValueList(BACKLIGHT_LIST,
+ BACKLIGHT_LIST[_settings.rxled])
+ rset = RadioSetting("rxled", "RX Backlight Color", rs)
+ basic.append(rset)
+
+ # Menu 28: TX-LED (Tx Backlight)
+ rs = RadioSettingValueList(BACKLIGHT_LIST,
+ BACKLIGHT_LIST[_settings.txled])
+ rset = RadioSetting("txled", "TX Backlight Color", rs)
+ basic.append(rset)
+
+ # Menu 29: Alarm Mode
+ rs = RadioSettingValueList(ALMOD_LIST, ALMOD_LIST[_settings.almod])
+ rset = RadioSetting("almod", "Alarm Mode", rs)
+ basic.append(rset)
+
+ # Menu 30: TAIL (Tail Noise Clear)
+ rs = RadioSettingValueBoolean(_settings.ste)
+ rset = RadioSetting("ste", "Squelch Tail Eliminate", rs)
+ basic.append(rset)
+
+ # Menu 31: PROGRE (Roger)
+ rs = RadioSettingValueBoolean(_settings.roger)
+ rset = RadioSetting("roger", "Roger Beep", rs)
+ basic.append(rset)
+
+ # Menu 32: Language
+ rs = RadioSettingValueList(LANGUAGE_LIST,
+ LANGUAGE_LIST[_settings.language])
+ rset = RadioSetting("language", "Language", rs)
+ basic.append(rset)
+
+ # Menu 33: OPENMGS (Pwr On Msg)
+ rs = RadioSettingValueList(PWRONMSG_LIST,
+ PWRONMSG_LIST[_settings.pwronmsg])
+ rset = RadioSetting("pwronmsg", "Power On Message", rs)
+ basic.append(rset)
+
+ dtmfchars = "0123456789ABCD*#"
+
+ # Menu 34: ANI ID (display only)
+ _codeobj = self._memobj.dtmf.code
+ print "_codeobj"
+ print _codeobj
+ _code = "".join([dtmfchars[x] for x in _codeobj if int(x) < 0x1F])
+ val = RadioSettingValueString(0, 6, _code, False)
+ val.set_charset(dtmfchars)
+ val.set_mutable(False)
+ rs = RadioSetting("dtmf.code", "Query ANI ID", val)
+ basic.append(rs)
+
+ # Menu 35: Reset
+
+ advanced = RadioSettingGroup("advanced", "Advanced Settings")
+ group.append(advanced)
+
+ # Work Mode
+ rs = RadioSettingValueList(WORKMODE_LIST,
+ WORKMODE_LIST[_settings.workmode])
+ rset = RadioSetting("workmode", "Work Mode", rs)
+ advanced.append(rset)
+
+ # PTT Delay
+ rs = RadioSettingValueInteger(0, 30, _settings.pttlt)
+ rset = RadioSetting("pttlt", "PTT ID Delay", rs)
+ advanced.append(rset)
+
+ def apply_skey_listvalue(setting, obj):
+ LOG.debug("Setting value: " + str(setting.value) + " from list")
+ val = str(setting.value)
+ index = SKEY_CHOICES.index(val)
+ val = SKEY_VALUES[index]
+ obj.set_value(val)
+
+ # Skey Short
+ if _skey.shortp in SKEY_VALUES:
+ idx = SKEY_VALUES.index(_skey.shortp)
+ else:
+ idx = SKEY_VALUES.index(0x0C)
+ rs = RadioSettingValueList(SKEY_CHOICES, SKEY_CHOICES[idx])
+ rset = RadioSetting("skey.shortp", "Side Key (Short Press)", rs)
+ rset.set_apply_callback(apply_skey_listvalue, _skey.shortp)
+ advanced.append(rset)
+
+ # Skey Long
+ if _skey.longp in SKEY_VALUES:
+ idx = SKEY_VALUES.index(_skey.longp)
+ else:
+ idx = SKEY_VALUES.index(0x0C)
+ rs = RadioSettingValueList(SKEY_CHOICES, SKEY_CHOICES[idx])
+ rset = RadioSetting("skey.longp", "Side Key (Long Press)", rs)
+ rset.set_apply_callback(apply_skey_listvalue, _skey.longp)
+ advanced.append(rset)
+
+ # Pass Repet Noise
+ rs = RadioSettingValueList(RPSTE_LIST, RPSTE_LIST[_settings.rpste])
+ rset = RadioSetting("rpste", "Squelch Tail Eliminate (repeater)", rs)
+ advanced.append(rset)
+
+ # Pass Repet Noise
+ rs = RadioSettingValueList(RPSTE_LIST, RPSTE_LIST[_settings.rptrl])
+ rset = RadioSetting("rptrl", "STE Repeater Delay", rs)
+ advanced.append(rset)
+
+ # KB_Lock
+ rs = RadioSettingValueBoolean(_settings.kblock)
+ rset = RadioSetting("kblock", "Keypad Lock", rs)
+ advanced.append(rset)
+
+ # FM Radio Enable
+ rs = RadioSettingValueBoolean(not _settings.fmradio)
+ rset = RadioSetting("fmradio", "Broadcast FM Radio", rs)
+ advanced.append(rset)
+
+ # Alarm Sound
+ rs = RadioSettingValueBoolean(_settings.alarm)
+ rset = RadioSetting("alarm", "Alarm Sound", rs)
+ advanced.append(rset)
+
+ # Tx Under TDR Start
+ rs = RadioSettingValueList(TDRAB_LIST, TDRAB_LIST[_settings.tdrab])
+ rset = RadioSetting("tdrab", "Dual Standby TX Priority", rs)
+ advanced.append(rset)
+
+ def _filter(name):
+ filtered = ""
+ for char in str(name):
+ if char in chirp_common.CHARSET_ASCII:
+ filtered += char
+ else:
+ filtered += " "
+ return filtered
+
+ _msg = self._memobj.poweron_msg
+ rs = RadioSetting("poweron_msg.line1", "Power-On Message 1",
+ RadioSettingValueString(
+ 0, 16, _filter(_msg.line1)))
+ advanced.append(rs)
+ rs = RadioSetting("poweron_msg.line2", "Power-On Message 2",
+ RadioSettingValueString(
+ 0, 16, _filter(_msg.line2)))
+ advanced.append(rs)
+
+ dtmf = RadioSettingGroup("dtmf", "DTMF Settings")
+ group.append(dtmf)
+
+ def apply_code(setting, obj, length):
+ code = []
+ for j in range(0, length):
+ try:
+ code.append(DTMF_CHARS.index(str(setting.value)[j]))
+ except IndexError:
+ code.append(0xFF)
+ obj.code = code
+
+ for i in range(0, 15):
+ _codeobj = self._memobj.pttid[i].code
+ _code = "".join([DTMF_CHARS[x] for x in _codeobj if int(x) < 0x1F])
+ val = RadioSettingValueString(0, 6, _code, False)
+ val.set_charset(DTMF_CHARS)
+ pttid = RadioSetting("pttid/%i.code" % i,
+ "Signal Code %i" % (i + 1), val)
+ pttid.set_apply_callback(apply_code, self._memobj.pttid[i], 6)
+ dtmf.append(pttid)
+
+ _codeobj = self._memobj.dtmf.killword
+ _code = "".join([DTMF_CHARS[x] for x in _codeobj if int(x) < 0x1F])
+ val = RadioSettingValueString(0, 6, _code, False)
+ val.set_charset(DTMF_CHARS)
+ rs = RadioSetting("dtmf.killword", "Kill Word", val)
+ rs.set_apply_callback(apply_code, self._memobj.dtmf, 6)
+ dtmf.append(rs)
+
+ _codeobj = self._memobj.dtmf.revive
+ _code = "".join([DTMF_CHARS[x] for x in _codeobj if int(x) < 0x1F])
+ val = RadioSettingValueString(0, 6, _code, False)
+ val.set_charset(DTMF_CHARS)
+ rs = RadioSetting("dtmf.revive", "Revive Word", val)
+ rs.set_apply_callback(apply_code, self._memobj.dtmf, 6)
+ dtmf.append(rs)
+
+ _codeobj = self._memobj.dtmf.code
+ _code = "".join([DTMF_CHARS[x] for x in _codeobj if int(x) < 0x1F])
+ val = RadioSettingValueString(0, 6, _code, False)
+ val.set_charset(DTMF_CHARS)
+ rs = RadioSetting("dtmf.code", "ANI Code", val)
+ rs.set_apply_callback(apply_code, self._memobj.dtmf, 6)
+ dtmf.append(rs)
+
+ if _dtmf.dtmfon > 0xC3:
+ val = 0x00
+ else:
+ val = _dtmf.dtmfon
+ rs = RadioSetting("dtmf.dtmfon", "DTMF Speed (on)",
+ RadioSettingValueList(DTMFSPEED_LIST,
+ DTMFSPEED_LIST[val]))
+ dtmf.append(rs)
+
+ if _dtmf.dtmfoff > 0xC3:
+ val = 0x00
+ else:
+ val = _dtmf.dtmfoff
+ rs = RadioSetting("dtmf.dtmfoff", "DTMF Speed (off)",
+ RadioSettingValueList(DTMFSPEED_LIST,
+ DTMFSPEED_LIST[val]))
+ dtmf.append(rs)
+
+ return group
+
+ def set_settings(self, settings):
+ _settings = self._memobj.settings
+ _mem = self._memobj
+ for element in settings:
+ if not isinstance(element, RadioSetting):
+ self.set_settings(element)
+ continue
+ else:
+ try:
+ name = element.get_name()
+ if "." in name:
+ bits = name.split(".")
+ obj = self._memobj
+ for bit in bits[:-1]:
+ if "/" in bit:
+ bit, index = bit.split("/", 1)
+ index = int(index)
+ obj = getattr(obj, bit)[index]
+ else:
+ obj = getattr(obj, bit)
+ setting = bits[-1]
+ else:
+ obj = _settings
+ setting = element.get_name()
+
+ if element.has_apply_callback():
+ LOG.debug("Using apply callback")
+ element.run_apply_callback()
+ elif setting == "fmradio":
+ setattr(obj, setting, not int(element.value))
+ elif setting == "tot":
+ setattr(obj, setting, int(element.value) + 1)
+ elif element.value.get_mutable():
+ LOG.debug("Setting %s = %s" % (setting, element.value))
+ setattr(obj, setting, element.value)
+ except Exception, e:
+ LOG.debug(element.get_name())
+ raise
+
+ @classmethod
+ def match_model(cls, filedata, filename):
+ # This radio has always been post-metadata, so never do
+ # old-school detection
+ return False
diff -r b62aebea801d -r f8aa35624ba0 tools/cpep8.manifest
--- a/tools/cpep8.manifest Fri May 28 14:25:48 2021 -0400
+++ b/tools/cpep8.manifest Sun May 30 22:39:21 2021 -0400
@@ -82,6 +82,7 @@
./chirp/drivers/retevis_rt22.py
./chirp/drivers/retevis_rt23.py
./chirp/drivers/retevis_rt26.py
+./chirp/drivers/retevis_rt76p.py
./chirp/drivers/rfinder.py
./chirp/drivers/tdxone_tdq8a.py
./chirp/drivers/template.py
1
0
[chirp_devel] Fwd: [PATCH] [KT8900] Add support for a new QYT KT-8900 MCU Version
by Jim Unroe 24 May '21
by Jim Unroe 24 May '21
24 May '21
---------- Forwarded message ---------
From: Jim Unroe <kc9hi(a)comcast.net>
Date: Mon, May 24, 2021 at 9:47 PM
Subject: [PATCH] [KT8900] Add support for a new QYT KT-8900 MCU Version
To: <Rock.Unroe(a)gmail.com>
# HG changeset patch
# User Jim Unroe <rock.unroe(a)gmail.com>
# Date 1621906990 14400
# Mon May 24 21:43:10 2021 -0400
# Node ID 890a42404b7c696fac2bf4a991c807b2dbbec366
# Parent 5415ba0656b31a97617d177d26fc4ddb813d8337
[KT8900] Add support for a new QYT KT-8900 MCU Version
This patch adds support for a new MCU version that has been discovered
in the QYT KT-8900 mobile radios.
Related to #9085
diff -r 5415ba0656b3 -r 890a42404b7c chirp/drivers/btech.py
--- a/chirp/drivers/btech.py Mon May 24 21:30:30 2021 -0400
+++ b/chirp/drivers/btech.py Mon May 24 21:43:10 2021 -0400
@@ -211,6 +211,7 @@
KT8900_fp3 = "M2G2F4"
KT8900_fp4 = "M2G304"
KT8900_fp5 = "M2G314"
+KT8900_fp6 = "M2G424"
# this radio has an extra ID
KT8900_id = "303688"
@@ -3475,7 +3476,8 @@
KT8900_fp2,
KT8900_fp3,
KT8900_fp4,
- KT8900_fp5]
+ KT8900_fp5,
+ KT8900_fp6]
_id2 = [KT8900_id, ]
# Clones
ALIASES = [JT6188Mini, SSGT890, ZastoneMP300]
1
0
[chirp_devel] Fwd: [PATCH 2 of 2] [RT22] Add BCL and Signal settings to Retevis RT22FRS and RT622 models
by Jim Unroe 24 May '21
by Jim Unroe 24 May '21
24 May '21
---------- Forwarded message ---------
From: Jim Unroe <kc9hi(a)comcast.net>
Date: Mon, May 24, 2021 at 9:47 PM
Subject: [PATCH 2 of 2] [RT22] Add BCL and Signal settings to Retevis
RT22FRS and RT622 models
To: <Rock.Unroe(a)gmail.com>
# HG changeset patch
# User Jim Unroe <rock.unroe(a)gmail.com>
# Date 1621906230 14400
# Mon May 24 21:30:30 2021 -0400
# Node ID 5415ba0656b31a97617d177d26fc4ddb813d8337
# Parent 05cad5ed5ef71ee0b7cd7555fd3f7fbeccc315ba
[RT22] Add BCL and Signal settings to Retevis RT22FRS and RT622 models
This patch adds support for the per-channel "BCL" and "Signal" settings.
related to #9043
diff -r 05cad5ed5ef7 -r 5415ba0656b3 chirp/drivers/retevis_rt22.py
--- a/chirp/drivers/retevis_rt22.py Mon May 24 21:19:57 2021 -0400
+++ b/chirp/drivers/retevis_rt22.py Mon May 24 21:30:30 2021 -0400
@@ -38,7 +38,9 @@
u8 unknown3:2,
highpower:1, // Power Level
wide:1, // Bandwidth
- unknown4:4;
+ unknown4:2,
+ signal:1, // Signal
+ bcl:1; // BCL
u8 unknown5[2];
} memory[16];
@@ -491,6 +493,17 @@
mem.skip = "" if (_skp & bitpos) else "S"
LOG.debug("mem.skip %s" % mem.skip)
+ mem.extra = RadioSettingGroup("Extra", "extra")
+
+ if self.MODEL == "RT22FRS" or self.MODEL == "RT622":
+ rs = RadioSettingValueBoolean(_mem.bcl)
+ rset = RadioSetting("bcl", "Busy Channel Lockout", rs)
+ mem.extra.append(rset)
+
+ rs = RadioSettingValueBoolean(_mem.signal)
+ rset = RadioSetting("signal", "Signal", rs)
+ mem.extra.append(rset)
+
return mem
def _set_tone(self, mem, _mem):
@@ -570,6 +583,9 @@
_skp &= ~bitpos
LOG.debug("_skp %s" % _skp)
+ for setting in mem.extra:
+ setattr(_mem, setting.get_name(), setting.value)
+
def get_settings(self):
_settings = self._memobj.settings
_message = self._memobj.embedded_msg
1
0
[chirp_devel] Fwd: [PATCH 1 of 2] [RT22] Address original RT22 block read errors
by Jim Unroe 24 May '21
by Jim Unroe 24 May '21
24 May '21
---------- Forwarded message ---------
From: Jim Unroe <kc9hi(a)comcast.net>
Date: Mon, May 24, 2021 at 9:46 PM
Subject: [PATCH 1 of 2] [RT22] Address original RT22 block read errors
To: <Rock.Unroe(a)gmail.com>
# HG changeset patch
# User Jim Unroe <rock.unroe(a)gmail.com>
# Date 1621905597 14400
# Mon May 24 21:19:57 2021 -0400
# Node ID 05cad5ed5ef71ee0b7cd7555fd3f7fbeccc315ba
# Parent 47a1e03308716b00c2a685c44bbf0ce395e69b41
[RT22] Address original RT22 block read errors
While investigating this issue, the original RT22 was often experiencing read
errors while cloning from the radio to CHIRP. It was eventually discovered
that the radio was eventually missing an ACK at some point during the download
which stopped the cloning process with an error.
This patch adds a small delay between the reading a block of data an the
sending of the ACK back to the radio indicating that the block of data was
received OK. The original RT22 radio now receives every ACK reliably.
related to #9043
diff -r 47a1e0330871 -r 05cad5ed5ef7 chirp/drivers/retevis_rt22.py
--- a/chirp/drivers/retevis_rt22.py Wed May 19 20:58:53 2021 -0400
+++ b/chirp/drivers/retevis_rt22.py Mon May 24 21:19:57 2021 -0400
@@ -216,6 +216,7 @@
block_data = response[4:]
+ time.sleep(0.005)
serial.write(CMD_ACK)
ack = serial.read(1)
except:
1
0
Hi All,
I've made a lot of progress on getting the latest py3 branch working across
multiple platforms. I'm maintaining all my working changes here for now:
https://github.com/mpoletiek/py3-CHIRP
I've even made a list of supported devices and am marking the ones I've
personally tested:
https://github.com/mpoletiek/py3-CHIRP/blob/main/RADIOS.md
Currently I only own a BF-F8HP so I've marked all the Radios that use that
driver `TESTED`.
I've been playing around with Tox and testing the other drivers that way
too. With a few changes I was able to get it working and run every test
against every driver. A lot of them passed every test just fine, but a lot
of them are failing here and there.
As expected the debug.log is quite long and I figured I'd go through the
drivers one by one that way, but the recommended syntax for doing that
doesn't seem to work as expected.
https://chirp.danplanet.com/projects/chirp/wiki/DevelopersProcess
`tox -e driver -- -d Icom_IC-2820H`
Running this command gives me the following in a Python3.7 environment:
`ERROR: MISSING test execution (tx) nodes: please specify --tx`
When I add '-n 2' or `--tx popen//python=python3.7` to the pytest
command it exits with `code: 5 (no tests run)`
Anyone familiar enough with tox to help me out with this?
There's also a py3driver env setup in the tox.ini file, but that
doesn't work either.
Thanks,
-------------------------------------------
Matthew Poletiek
303.810.9082
matthew.poletiek(a)gmail.com
www.matthewpoletiek.com
2
1
Tested changes:
Changes for Build #917
[Dan Smith <dsmith(a)danplanet.com>] Add Radioddity GT-5R
This is a special version of the UV-5R with a requirement around
enforcing tx-inhibit outside of the legal limits.
#9077
[Kosta A. <ve7kcy(a)gmail.com>] Modified icomciv probe_model to use directory based driver search pattern. #4547
[Tom Hayward <tom(a)tomh.us>] [id880] Fix typo in charset definition. #281
[Tom Hayward <tom(a)tomh.us>] [thf6a] Support full charset (ASCII). Fixes #141
[Tom Hayward <tom(a)tomh.us>] [id880] Support full charset. Fixes #281
[Tom Hayward <tom(a)tomh.us>] [vx5] Support full charset (ASCII). Fixes #292
[Tom Hayward <tom(a)tomh.us>] [id31a] set used bit when creating new memory, clear when deleting. Fixes #269
[Tom Hayward <tom(a)tomh.us>] Support PyGTK < 2.22 in bank edit. Fixes #231
[Tom Hayward <tom(a)tomh.us>] [d710] [v71] [d72] Fix tone list (not all tones are supported). Fixes #212
[Dan Smith <dsmith(a)danplanet.com>] [vx7] Fix setting memory power levels on 220MHz band
Fixes #214
[Dan Smith <dsmith(a)danplanet.com>] fips: Pennsylvania FIPS code was wrong. #117
[Marco Filippi <iz3gme.marco(a)gmail.com>] Consider lower bound frequency of each valid_band as valid
Fix bug #181
[Tom Hayward <tom(a)tomh.us>] tmd700: allow 8-char names. Fixes #176
[Dan Smith <dsmith(a)danplanet.com>] Fix the "blind deletion" problem, as well as properly direct copy/paste
Fixes #172
[David Griffith <dave(a)661.org>] Bug #155 fix: VX-7 1.25m power levels
[David Griffith <dave(a)661.org>] New INSTALL and README files
Fixes #122
[Tom Hayward <tom(a)tomh.us>] thd72: only use hardware flow on OS X. Fixes #166
[Marco Filippi <iz3gme.marco(a)gmail.com>] [FT817] Tone freq not set correctly
Same as #88 for FT857, to avoid code duplication fix code have been moved from
ft857 to its ancestor class
Fix bug #163
[Tom Hayward <tom(a)tomh.us>] Fix Mac .app so paths with spaces work. Fixes Bug #145
Full log:
[...truncated 1318 lines...]
test_copy_all (tests.TestCase_YaesuFT70D)
Testing Yaesu FT-70D copy all ... ok
test_detect (tests.TestCase_YaesuFT70D)
Testing Yaesu FT-70D detect ... ok
test_edges (tests.TestCase_YaesuFT70D)
Testing Yaesu FT-70D edges ... ok
test_settings (tests.TestCase_YaesuFT70D)
Testing Yaesu FT-70D settings ... ok
test_banks (tests.TestCase_YaesuVX3)
Testing Yaesu VX-3 banks ... ok
test_brute_force (tests.TestCase_YaesuVX3)
Testing Yaesu VX-3 brute force ... ok
test_clone (tests.TestCase_YaesuVX3)
Testing Yaesu VX-3 clone ... ok
test_copy_all (tests.TestCase_YaesuVX3)
Testing Yaesu VX-3 copy all ... ok
test_detect (tests.TestCase_YaesuVX3)
Testing Yaesu VX-3 detect ... ok
test_edges (tests.TestCase_YaesuVX3)
Testing Yaesu VX-3 edges ... ok
test_settings (tests.TestCase_YaesuVX3)
Testing Yaesu VX-3 settings ... ok
test_banks (tests.TestCase_WouxunKGUV9DPlus)
Testing Wouxun KG-UV9D Plus banks ... skipped 'Banks not supported'
test_brute_force (tests.TestCase_WouxunKGUV9DPlus)
Testing Wouxun KG-UV9D Plus brute force ... ok
test_clone (tests.TestCase_WouxunKGUV9DPlus)
Testing Wouxun KG-UV9D Plus clone ... ok
test_copy_all (tests.TestCase_WouxunKGUV9DPlus)
Testing Wouxun KG-UV9D Plus copy all ... ok
test_detect (tests.TestCase_WouxunKGUV9DPlus)
Testing Wouxun KG-UV9D Plus detect ... ok
test_edges (tests.TestCase_WouxunKGUV9DPlus)
Testing Wouxun KG-UV9D Plus edges ... ok
test_settings (tests.TestCase_WouxunKGUV9DPlus)
Testing Wouxun KG-UV9D Plus settings ... ok
test_banks (tests.TestCase_TYTTH7800)
Testing TYT TH-7800 banks ... skipped 'Banks not supported'
test_brute_force (tests.TestCase_TYTTH7800)
Testing TYT TH-7800 brute force ... ok
test_clone (tests.TestCase_TYTTH7800)
Testing TYT TH-7800 clone ... ok
test_copy_all (tests.TestCase_TYTTH7800)
Testing TYT TH-7800 copy all ... ok
test_detect (tests.TestCase_TYTTH7800)
Testing TYT TH-7800 detect ... ok
test_edges (tests.TestCase_TYTTH7800)
Testing TYT TH-7800 edges ... ok
test_settings (tests.TestCase_TYTTH7800)
Testing TYT TH-7800 settings ... ok
test_banks (tests.TestCase_RadioddityGA510)
Testing Radioddity GA-510 banks ... skipped 'Banks not supported'
test_brute_force (tests.TestCase_RadioddityGA510)
Testing Radioddity GA-510 brute force ... ok
test_clone (tests.TestCase_RadioddityGA510)
Testing Radioddity GA-510 clone ... ok
test_copy_all (tests.TestCase_RadioddityGA510)
Testing Radioddity GA-510 copy all ... ok
test_detect (tests.TestCase_RadioddityGA510)
Testing Radioddity GA-510 detect ... ok
test_edges (tests.TestCase_RadioddityGA510)
Testing Radioddity GA-510 edges ... ok
test_settings (tests.TestCase_RadioddityGA510)
Testing Radioddity GA-510 settings ... ok
test_banks (tests.TestCase_KenwoodTK8102)
Testing Kenwood TK-8102 banks ... skipped 'Banks not supported'
test_brute_force (tests.TestCase_KenwoodTK8102)
Testing Kenwood TK-8102 brute force ... ok
test_clone (tests.TestCase_KenwoodTK8102)
Testing Kenwood TK-8102 clone ... ok
test_copy_all (tests.TestCase_KenwoodTK8102)
Testing Kenwood TK-8102 copy all ... ok
test_detect (tests.TestCase_KenwoodTK8102)
Testing Kenwood TK-8102 detect ... ok
test_edges (tests.TestCase_KenwoodTK8102)
Testing Kenwood TK-8102 edges ... ok
test_settings (tests.TestCase_KenwoodTK8102)
Testing Kenwood TK-8102 settings ... ok
test_banks (tests.TestCase_IcomICV82U82)
Testing Icom IC-V82/U82 banks ... ok
test_brute_force (tests.TestCase_IcomICV82U82)
Testing Icom IC-V82/U82 brute force ... ok
test_clone (tests.TestCase_IcomICV82U82)
Testing Icom IC-V82/U82 clone ... ok
test_copy_all (tests.TestCase_IcomICV82U82)
Testing Icom IC-V82/U82 copy all ... ok
test_detect (tests.TestCase_IcomICV82U82)
Testing Icom IC-V82/U82 detect ... ok
test_edges (tests.TestCase_IcomICV82U82)
Testing Icom IC-V82/U82 edges ... ok
test_settings (tests.TestCase_IcomICV82U82)
Testing Icom IC-V82/U82 settings ... skipped 'Settings not supported'
test_banks (tests.TestCase_BTECHUV25X2)
Testing BTECH UV-25X2 banks ... skipped 'Banks not supported'
test_brute_force (tests.TestCase_BTECHUV25X2)
Testing BTECH UV-25X2 brute force ... ok
test_clone (tests.TestCase_BTECHUV25X2)
Testing BTECH UV-25X2 clone ... ok
test_copy_all (tests.TestCase_BTECHUV25X2)
Testing BTECH UV-25X2 copy all ... ok
test_detect (tests.TestCase_BTECHUV25X2)
Testing BTECH UV-25X2 detect ... ok
test_edges (tests.TestCase_BTECHUV25X2)
Testing BTECH UV-25X2 edges ... ok
test_settings (tests.TestCase_BTECHUV25X2)
Testing BTECH UV-25X2 settings ... ok
test_banks (tests.TestCase_CRTMicronUV)
Testing CRT Micron UV banks ... skipped 'Banks not supported'
test_brute_force (tests.TestCase_CRTMicronUV)
Testing CRT Micron UV brute force ... ok
test_clone (tests.TestCase_CRTMicronUV)
Testing CRT Micron UV clone ... ok
test_copy_all (tests.TestCase_CRTMicronUV)
Testing CRT Micron UV copy all ... ok
test_detect (tests.TestCase_CRTMicronUV)
Testing CRT Micron UV detect ... ok
test_edges (tests.TestCase_CRTMicronUV)
Testing CRT Micron UV edges ... ok
test_settings (tests.TestCase_CRTMicronUV)
Testing CRT Micron UV settings ... ok
test_banks (tests.TestCase_YaesuFT7100M)
Testing Yaesu FT-7100M banks ... skipped 'Banks not supported'
test_brute_force (tests.TestCase_YaesuFT7100M)
Testing Yaesu FT-7100M brute force ... ok
test_clone (tests.TestCase_YaesuFT7100M)
Testing Yaesu FT-7100M clone ... ok
test_copy_all (tests.TestCase_YaesuFT7100M)
Testing Yaesu FT-7100M copy all ... ok
test_detect (tests.TestCase_YaesuFT7100M)
Testing Yaesu FT-7100M detect ... ok
test_edges (tests.TestCase_YaesuFT7100M)
Testing Yaesu FT-7100M edges ... ok
test_settings (tests.TestCase_YaesuFT7100M)
Testing Yaesu FT-7100M settings ... ok
test_banks (tests.TestCase_RadioddityR2)
Testing Radioddity R2 banks ... skipped 'Banks not supported'
test_brute_force (tests.TestCase_RadioddityR2)
Testing Radioddity R2 brute force ... ok
test_clone (tests.TestCase_RadioddityR2)
Testing Radioddity R2 clone ... ok
test_copy_all (tests.TestCase_RadioddityR2)
Testing Radioddity R2 copy all ... ok
test_detect (tests.TestCase_RadioddityR2)
Testing Radioddity R2 detect ... ok
test_edges (tests.TestCase_RadioddityR2)
Testing Radioddity R2 edges ... ok
test_settings (tests.TestCase_RadioddityR2)
Testing Radioddity R2 settings ... ok
test_banks (tests.TestCase_YaesuVX5)
Testing Yaesu VX-5 banks ... ok
test_brute_force (tests.TestCase_YaesuVX5)
Testing Yaesu VX-5 brute force ... ok
test_clone (tests.TestCase_YaesuVX5)
Testing Yaesu VX-5 clone ... ok
test_copy_all (tests.TestCase_YaesuVX5)
Testing Yaesu VX-5 copy all ... ok
test_detect (tests.TestCase_YaesuVX5)
Testing Yaesu VX-5 detect ... ok
test_edges (tests.TestCase_YaesuVX5)
Testing Yaesu VX-5 edges ... ok
test_settings (tests.TestCase_YaesuVX5)
Testing Yaesu VX-5 settings ... skipped 'Settings not supported'
test_banks (tests.TestCase_WouxunKGUVD1P)
Testing Wouxun KG-UVD1P banks ... skipped 'Banks not supported'
test_brute_force (tests.TestCase_WouxunKGUVD1P)
Testing Wouxun KG-UVD1P brute force ... ok
test_clone (tests.TestCase_WouxunKGUVD1P)
Testing Wouxun KG-UVD1P clone ... ok
test_copy_all (tests.TestCase_WouxunKGUVD1P)
Testing Wouxun KG-UVD1P copy all ... ok
test_detect (tests.TestCase_WouxunKGUVD1P)
Testing Wouxun KG-UVD1P detect ... ok
test_edges (tests.TestCase_WouxunKGUVD1P)
Testing Wouxun KG-UVD1P edges ... ok
test_settings (tests.TestCase_WouxunKGUVD1P)
Testing Wouxun KG-UVD1P settings ... ok
test_banks (tests.TestCase_IcomICW32A)
Testing Icom IC-W32A banks ... skipped 'Banks not supported'
test_brute_force (tests.TestCase_IcomICW32A)
Testing Icom IC-W32A brute force ... ok
test_clone (tests.TestCase_IcomICW32A)
Testing Icom IC-W32A clone ... ok
test_copy_all (tests.TestCase_IcomICW32A)
Testing Icom IC-W32A copy all ... ok
test_detect (tests.TestCase_IcomICW32A)
Testing Icom IC-W32A detect ... ok
test_edges (tests.TestCase_IcomICW32A)
Testing Icom IC-W32A edges ... ok
test_settings (tests.TestCase_IcomICW32A)
Testing Icom IC-W32A settings ... skipped 'Settings not supported'
test_banks (tests.TestCase_TYTTH9800)
Testing TYT TH-9800 banks ... skipped 'Banks not supported'
test_brute_force (tests.TestCase_TYTTH9800)
Testing TYT TH-9800 brute force ... ok
test_clone (tests.TestCase_TYTTH9800)
Testing TYT TH-9800 clone ... ok
test_copy_all (tests.TestCase_TYTTH9800)
Testing TYT TH-9800 copy all ... ok
test_detect (tests.TestCase_TYTTH9800)
Testing TYT TH-9800 detect ... ok
test_edges (tests.TestCase_TYTTH9800)
Testing TYT TH-9800 edges ... ok
test_settings (tests.TestCase_TYTTH9800)
Testing TYT TH-9800 settings ... ok
test_banks (tests.TestCase_FeidaxinFD268A)
Testing Feidaxin FD-268A banks ... skipped 'Banks not supported'
test_brute_force (tests.TestCase_FeidaxinFD268A)
Testing Feidaxin FD-268A brute force ... ok
test_clone (tests.TestCase_FeidaxinFD268A)
Testing Feidaxin FD-268A clone ... ok
test_copy_all (tests.TestCase_FeidaxinFD268A)
Testing Feidaxin FD-268A copy all ... ok
test_detect (tests.TestCase_FeidaxinFD268A)
Testing Feidaxin FD-268A detect ... ok
test_edges (tests.TestCase_FeidaxinFD268A)
Testing Feidaxin FD-268A edges ... ok
test_settings (tests.TestCase_FeidaxinFD268A)
Testing Feidaxin FD-268A settings ... ok
test_banks (tests.TestCase_AlincoDJG7EG)
Testing Alinco DJ-G7EG banks ... skipped 'Banks not supported'
test_brute_force (tests.TestCase_AlincoDJG7EG)
Testing Alinco DJ-G7EG brute force ... ok
test_clone (tests.TestCase_AlincoDJG7EG)
Testing Alinco DJ-G7EG clone ... ok
test_copy_all (tests.TestCase_AlincoDJG7EG)
Testing Alinco DJ-G7EG copy all ... ok
test_detect (tests.TestCase_AlincoDJG7EG)
Testing Alinco DJ-G7EG detect ... ok
test_edges (tests.TestCase_AlincoDJG7EG)
Testing Alinco DJ-G7EG edges ... ok
test_settings (tests.TestCase_AlincoDJG7EG)
Testing Alinco DJ-G7EG settings ... skipped 'Settings not supported'
test_banks (tests.TestCase_BTECHUV25X4)
Testing BTECH UV-25X4 banks ... skipped 'Banks not supported'
test_brute_force (tests.TestCase_BTECHUV25X4)
Testing BTECH UV-25X4 brute force ... ok
test_clone (tests.TestCase_BTECHUV25X4)
Testing BTECH UV-25X4 clone ... ok
test_copy_all (tests.TestCase_BTECHUV25X4)
Testing BTECH UV-25X4 copy all ... ok
test_detect (tests.TestCase_BTECHUV25X4)
Testing BTECH UV-25X4 detect ... ok
test_edges (tests.TestCase_BTECHUV25X4)
Testing BTECH UV-25X4 edges ... ok
test_settings (tests.TestCase_BTECHUV25X4)
Testing BTECH UV-25X4 settings ... ok
test_banks (tests.TestCase_KenwoodTK8180)
Testing Kenwood TK-8180 banks ... skipped 'Banks not supported'
test_brute_force (tests.TestCase_KenwoodTK8180)
Testing Kenwood TK-8180 brute force ... ok
test_clone (tests.TestCase_KenwoodTK8180)
Testing Kenwood TK-8180 clone ... ok
test_copy_all (tests.TestCase_KenwoodTK8180)
Testing Kenwood TK-8180 copy all ... ok
test_detect (tests.TestCase_KenwoodTK8180)
Testing Kenwood TK-8180 detect ... ok
test_edges (tests.TestCase_KenwoodTK8180)
Testing Kenwood TK-8180 edges ... ok
test_settings (tests.TestCase_KenwoodTK8180)
Testing Kenwood TK-8180 settings ... ok
test_banks (tests.TestCase_YaesuFT78007900)
Testing Yaesu FT-7800/7900 banks ... ok
test_brute_force (tests.TestCase_YaesuFT78007900)
Testing Yaesu FT-7800/7900 brute force ... ok
test_clone (tests.TestCase_YaesuFT78007900)
Testing Yaesu FT-7800/7900 clone ... ok
test_copy_all (tests.TestCase_YaesuFT78007900)
Testing Yaesu FT-7800/7900 copy all ... ok
test_detect (tests.TestCase_YaesuFT78007900)
Testing Yaesu FT-7800/7900 detect ... ok
test_edges (tests.TestCase_YaesuFT78007900)
Testing Yaesu FT-7800/7900 edges ... ok
test_settings (tests.TestCase_YaesuFT78007900)
Testing Yaesu FT-7800/7900 settings ... ok
test_banks (tests.TestCase_RadtelT18)
Testing Radtel T18 banks ... skipped 'Banks not supported'
test_brute_force (tests.TestCase_RadtelT18)
Testing Radtel T18 brute force ... ok
test_clone (tests.TestCase_RadtelT18)
Testing Radtel T18 clone ... ok
test_copy_all (tests.TestCase_RadtelT18)
Testing Radtel T18 copy all ... ok
test_detect (tests.TestCase_RadtelT18)
Testing Radtel T18 detect ... ok
test_edges (tests.TestCase_RadtelT18)
Testing Radtel T18 edges ... ok
test_settings (tests.TestCase_RadtelT18)
Testing Radtel T18 settings ... ok
test_banks (tests.TestCase_YaesuFT1500M)
Testing Yaesu FT-1500M banks ... skipped 'Banks not supported'
test_brute_force (tests.TestCase_YaesuFT1500M)
Testing Yaesu FT-1500M brute force ... ok
test_clone (tests.TestCase_YaesuFT1500M)
Testing Yaesu FT-1500M clone ... ok
test_copy_all (tests.TestCase_YaesuFT1500M)
Testing Yaesu FT-1500M copy all ... ok
test_detect (tests.TestCase_YaesuFT1500M)
Testing Yaesu FT-1500M detect ... ok
test_edges (tests.TestCase_YaesuFT1500M)
Testing Yaesu FT-1500M edges ... ok
test_settings (tests.TestCase_YaesuFT1500M)
Testing Yaesu FT-1500M settings ... skipped 'Settings not supported'
test_banks (tests.TestCase_YaesuVX6)
Testing Yaesu VX-6 banks ... ok
test_brute_force (tests.TestCase_YaesuVX6)
Testing Yaesu VX-6 brute force ... ok
test_clone (tests.TestCase_YaesuVX6)
Testing Yaesu VX-6 clone ... ok
test_copy_all (tests.TestCase_YaesuVX6)
Testing Yaesu VX-6 copy all ... ok
test_detect (tests.TestCase_YaesuVX6)
Testing Yaesu VX-6 detect ... ok
test_edges (tests.TestCase_YaesuVX6)
Testing Yaesu VX-6 edges ... ok
test_settings (tests.TestCase_YaesuVX6)
Testing Yaesu VX-6 settings ... ok
test_banks (tests.TestCase_TYTTHUV3R25)
Testing TYT TH-UV3R-25 banks ... skipped 'Banks not supported'
test_brute_force (tests.TestCase_TYTTHUV3R25)
Testing TYT TH-UV3R-25 brute force ... ok
test_clone (tests.TestCase_TYTTHUV3R25)
Testing TYT TH-UV3R-25 clone ... ok
test_copy_all (tests.TestCase_TYTTHUV3R25)
Testing TYT TH-UV3R-25 copy all ... ok
test_detect (tests.TestCase_TYTTHUV3R25)
Testing TYT TH-UV3R-25 detect ... ok
test_edges (tests.TestCase_TYTTHUV3R25)
Testing TYT TH-UV3R-25 edges ... ok
test_settings (tests.TestCase_TYTTHUV3R25)
Testing TYT TH-UV3R-25 settings ... skipped 'Settings not supported'
test_banks (tests.TestCase_IcomICW32E)
Testing Icom IC-W32E banks ... skipped 'Banks not supported'
test_brute_force (tests.TestCase_IcomICW32E)
Testing Icom IC-W32E brute force ... ok
test_clone (tests.TestCase_IcomICW32E)
Testing Icom IC-W32E clone ... ok
test_copy_all (tests.TestCase_IcomICW32E)
Testing Icom IC-W32E copy all ... ok
test_detect (tests.TestCase_IcomICW32E)
Testing Icom IC-W32E detect ... ok
test_edges (tests.TestCase_IcomICW32E)
Testing Icom IC-W32E edges ... ok
test_settings (tests.TestCase_IcomICW32E)
Testing Icom IC-W32E settings ... skipped 'Settings not supported'
test_banks (tests.TestCase_FeidaxinFD268B)
Testing Feidaxin FD-268B banks ... skipped 'Banks not supported'
test_brute_force (tests.TestCase_FeidaxinFD268B)
Testing Feidaxin FD-268B brute force ... ok
test_clone (tests.TestCase_FeidaxinFD268B)
Testing Feidaxin FD-268B clone ... ok
test_copy_all (tests.TestCase_FeidaxinFD268B)
Testing Feidaxin FD-268B copy all ... ok
test_detect (tests.TestCase_FeidaxinFD268B)
Testing Feidaxin FD-268B detect ... ok
test_edges (tests.TestCase_FeidaxinFD268B)
Testing Feidaxin FD-268B edges ... ok
test_settings (tests.TestCase_FeidaxinFD268B)
Testing Feidaxin FD-268B settings ... ok
test_banks (tests.TestCase_AlincoDJ175)
Testing Alinco DJ175 banks ... skipped 'Banks not supported'
test_brute_force (tests.TestCase_AlincoDJ175)
Testing Alinco DJ175 brute force ... ok
test_clone (tests.TestCase_AlincoDJ175)
Testing Alinco DJ175 clone ... ok
test_copy_all (tests.TestCase_AlincoDJ175)
Testing Alinco DJ175 copy all ... ok
test_detect (tests.TestCase_AlincoDJ175)
Testing Alinco DJ175 detect ... ok
test_edges (tests.TestCase_AlincoDJ175)
Testing Alinco DJ175 edges ... ok
test_settings (tests.TestCase_AlincoDJ175)
Testing Alinco DJ175 settings ... skipped 'Settings not supported'
test_banks (tests.TestCase_BTECHUV5001)
Testing BTECH UV-5001 banks ... skipped 'Banks not supported'
test_brute_force (tests.TestCase_BTECHUV5001)
Testing BTECH UV-5001 brute force ... ok
test_clone (tests.TestCase_BTECHUV5001)
Testing BTECH UV-5001 clone ... ok
test_copy_all (tests.TestCase_BTECHUV5001)
Testing BTECH UV-5001 copy all ... ok
test_detect (tests.TestCase_BTECHUV5001)
Testing BTECH UV-5001 detect ... ok
test_edges (tests.TestCase_BTECHUV5001)
Testing BTECH UV-5001 edges ... ok
test_settings (tests.TestCase_BTECHUV5001)
Testing BTECH UV-5001 settings ... ok
test_banks (tests.TestCase_YaesuFT1802M)
Testing Yaesu FT-1802M banks ... skipped 'Banks not supported'
test_brute_force (tests.TestCase_YaesuFT1802M)
Testing Yaesu FT-1802M brute force ... ok
test_clone (tests.TestCase_YaesuFT1802M)
Testing Yaesu FT-1802M clone ... ok
test_copy_all (tests.TestCase_YaesuFT1802M)
Testing Yaesu FT-1802M copy all ... ok
test_detect (tests.TestCase_YaesuFT1802M)
Testing Yaesu FT-1802M detect ... ok
test_edges (tests.TestCase_YaesuFT1802M)
Testing Yaesu FT-1802M edges ... ok
test_settings (tests.TestCase_YaesuFT1802M)
Testing Yaesu FT-1802M settings ... skipped 'Settings not supported'
test_banks (tests.TestCase_RetevisRB17A)
Testing Retevis RB17A banks ... skipped 'Banks not supported'
test_brute_force (tests.TestCase_RetevisRB17A)
Testing Retevis RB17A brute force ... ok
test_clone (tests.TestCase_RetevisRB17A)
Testing Retevis RB17A clone ... ok
test_copy_all (tests.TestCase_RetevisRB17A)
Testing Retevis RB17A copy all ... ok
test_detect (tests.TestCase_RetevisRB17A)
Testing Retevis RB17A detect ... ok
test_edges (tests.TestCase_RetevisRB17A)
Testing Retevis RB17A edges ... skipped 'No mutable memory locations found'
test_settings (tests.TestCase_RetevisRB17A)
Testing Retevis RB17A settings ... ok
test_banks (tests.TestCase_YaesuFT817)
Testing Yaesu FT-817 banks ... skipped 'Banks not supported'
test_brute_force (tests.TestCase_YaesuFT817)
Testing Yaesu FT-817 brute force ... ok
test_clone (tests.TestCase_YaesuFT817)
Testing Yaesu FT-817 clone ... ok
test_copy_all (tests.TestCase_YaesuFT817)
Testing Yaesu FT-817 copy all ... ok
test_detect (tests.TestCase_YaesuFT817)
Testing Yaesu FT-817 detect ... ok
test_edges (tests.TestCase_YaesuFT817)
Testing Yaesu FT-817 edges ... ok
test_settings (tests.TestCase_YaesuFT817)
Testing Yaesu FT-817 settings ... ok
test_banks (tests.TestCase_YaesuVX7)
Testing Yaesu VX-7 banks ... ok
test_brute_force (tests.TestCase_YaesuVX7)
Testing Yaesu VX-7 brute force ... ok
test_clone (tests.TestCase_YaesuVX7)
Testing Yaesu VX-7 clone ... ok
test_copy_all (tests.TestCase_YaesuVX7)
Testing Yaesu VX-7 copy all ... ok
test_detect (tests.TestCase_YaesuVX7)
Testing Yaesu VX-7 detect ... ok
test_edges (tests.TestCase_YaesuVX7)
Testing Yaesu VX-7 edges ... ok
test_settings (tests.TestCase_YaesuVX7)
Testing Yaesu VX-7 settings ... skipped 'Settings not supported'
test_banks (tests.TestCase_TYTTHUV3R)
Testing TYT TH-UV3R banks ... skipped 'Banks not supported'
test_brute_force (tests.TestCase_TYTTHUV3R)
Testing TYT TH-UV3R brute force ... ok
test_clone (tests.TestCase_TYTTHUV3R)
Testing TYT TH-UV3R clone ... ok
test_copy_all (tests.TestCase_TYTTHUV3R)
Testing TYT TH-UV3R copy all ... ok
test_detect (tests.TestCase_TYTTHUV3R)
Testing TYT TH-UV3R detect ... ok
test_edges (tests.TestCase_TYTTHUV3R)
Testing TYT TH-UV3R edges ... ok
test_settings (tests.TestCase_TYTTHUV3R)
Testing TYT TH-UV3R settings ... skipped 'Settings not supported'
test_banks (tests.TestCase_AlincoDJ596)
Testing Alinco DJ596 banks ... skipped 'Banks not supported'
test_brute_force (tests.TestCase_AlincoDJ596)
Testing Alinco DJ596 brute force ... ok
test_clone (tests.TestCase_AlincoDJ596)
Testing Alinco DJ596 clone ... ok
test_copy_all (tests.TestCase_AlincoDJ596)
Testing Alinco DJ596 copy all ... ok
test_detect (tests.TestCase_AlincoDJ596)
Testing Alinco DJ596 detect ... ok
test_edges (tests.TestCase_AlincoDJ596)
Testing Alinco DJ596 edges ... ok
test_settings (tests.TestCase_AlincoDJ596)
Testing Alinco DJ596 settings ... skipped 'Settings not supported'
test_banks (tests.TestCase_FeidaxinFD288B)
Testing Feidaxin FD-288B banks ... skipped 'Banks not supported'
test_brute_force (tests.TestCase_FeidaxinFD288B)
Testing Feidaxin FD-288B brute force ... ok
test_clone (tests.TestCase_FeidaxinFD288B)
Testing Feidaxin FD-288B clone ... ok
test_copy_all (tests.TestCase_FeidaxinFD288B)
Testing Feidaxin FD-288B copy all ... ok
test_detect (tests.TestCase_FeidaxinFD288B)
Testing Feidaxin FD-288B detect ... ok
test_edges (tests.TestCase_FeidaxinFD288B)
Testing Feidaxin FD-288B edges ... ok
test_settings (tests.TestCase_FeidaxinFD288B)
Testing Feidaxin FD-288B settings ... ok
test_banks (tests.TestCase_KenwoodTMD710GCloneMode)
Testing Kenwood TM-D710G_CloneMode banks ... skipped 'Banks not supported'
test_brute_force (tests.TestCase_KenwoodTMD710GCloneMode)
Testing Kenwood TM-D710G_CloneMode brute force ... ok
test_clone (tests.TestCase_KenwoodTMD710GCloneMode)
Testing Kenwood TM-D710G_CloneMode clone ... ok
test_copy_all (tests.TestCase_KenwoodTMD710GCloneMode)
Testing Kenwood TM-D710G_CloneMode copy all ... ok
test_detect (tests.TestCase_KenwoodTMD710GCloneMode)
Testing Kenwood TM-D710G_CloneMode detect ... ok
test_edges (tests.TestCase_KenwoodTMD710GCloneMode)
Testing Kenwood TM-D710G_CloneMode edges ... ok
test_settings (tests.TestCase_KenwoodTMD710GCloneMode)
Testing Kenwood TM-D710G_CloneMode settings ... ok
test_banks (tests.TestCase_BTECHUV50X2)
Testing BTECH UV-50X2 banks ... skipped 'Banks not supported'
test_brute_force (tests.TestCase_BTECHUV50X2)
Testing BTECH UV-50X2 brute force ... ok
test_clone (tests.TestCase_BTECHUV50X2)
Testing BTECH UV-50X2 clone ... ok
test_copy_all (tests.TestCase_BTECHUV50X2)
Testing BTECH UV-50X2 copy all ... ok
test_detect (tests.TestCase_BTECHUV50X2)
Testing BTECH UV-50X2 detect ... ok
test_edges (tests.TestCase_BTECHUV50X2)
Testing BTECH UV-50X2 edges ... ok
test_settings (tests.TestCase_BTECHUV50X2)
Testing BTECH UV-50X2 settings ... ok
test_banks (tests.TestCase_RetevisRB26)
Testing Retevis RB26 banks ... skipped 'Banks not supported'
test_brute_force (tests.TestCase_RetevisRB26)
Testing Retevis RB26 brute force ... ok
test_clone (tests.TestCase_RetevisRB26)
Testing Retevis RB26 clone ... ok
test_copy_all (tests.TestCase_RetevisRB26)
Testing Retevis RB26 copy all ... ok
test_detect (tests.TestCase_RetevisRB26)
Testing Retevis RB26 detect ... ok
test_edges (tests.TestCase_RetevisRB26)
Testing Retevis RB26 edges ... skipped 'No mutable memory locations found'
test_settings (tests.TestCase_RetevisRB26)
Testing Retevis RB26 settings ... ok
test_banks (tests.TestCase_IcomID31A)
Testing Icom ID-31A banks ... ok
test_brute_force (tests.TestCase_IcomID31A)
Testing Icom ID-31A brute force ... ok
test_clone (tests.TestCase_IcomID31A)
Testing Icom ID-31A clone ... ok
test_copy_all (tests.TestCase_IcomID31A)
Testing Icom ID-31A copy all ... ok
test_detect (tests.TestCase_IcomID31A)
Testing Icom ID-31A detect ... ok
test_edges (tests.TestCase_IcomID31A)
Testing Icom ID-31A edges ... ok
test_settings (tests.TestCase_IcomID31A)
Testing Icom ID-31A settings ... ok
test_banks (tests.TestCase_YaesuFT817ND)
Testing Yaesu FT-817ND banks ... skipped 'Banks not supported'
test_brute_force (tests.TestCase_YaesuFT817ND)
Testing Yaesu FT-817ND brute force ... ok
test_clone (tests.TestCase_YaesuFT817ND)
Testing Yaesu FT-817ND clone ... ok
test_copy_all (tests.TestCase_YaesuFT817ND)
Testing Yaesu FT-817ND copy all ... ok
test_detect (tests.TestCase_YaesuFT817ND)
Testing Yaesu FT-817ND detect ... ok
test_edges (tests.TestCase_YaesuFT817ND)
Testing Yaesu FT-817ND edges ... ok
test_settings (tests.TestCase_YaesuFT817ND)
Testing Yaesu FT-817ND settings ... ok
test_banks (tests.TestCase_TYTTHUV8000)
Testing TYT TH-UV8000 banks ... skipped 'Banks not supported'
test_brute_force (tests.TestCase_TYTTHUV8000)
Testing TYT TH-UV8000 brute force ... ok
test_clone (tests.TestCase_TYTTHUV8000)
Testing TYT TH-UV8000 clone ... ok
test_copy_all (tests.TestCase_TYTTHUV8000)
Testing TYT TH-UV8000 copy all ... ok
test_detect (tests.TestCase_TYTTHUV8000)
Testing TYT TH-UV8000 detect ... ok
test_edges (tests.TestCase_TYTTHUV8000)
Testing TYT TH-UV8000 edges ... ok
test_settings (tests.TestCase_TYTTHUV8000)
Testing TYT TH-UV8000 settings ... ok
test_banks (tests.TestCase_IcomIC208H)
Testing Icom IC-208H banks ... ok
test_brute_force (tests.TestCase_IcomIC208H)
Testing Icom IC-208H brute force ... ok
test_clone (tests.TestCase_IcomIC208H)
Testing Icom IC-208H clone ... ok
test_copy_all (tests.TestCase_IcomIC208H)
Testing Icom IC-208H copy all ... ok
test_detect (tests.TestCase_IcomIC208H)
Testing Icom IC-208H detect ... ok
test_edges (tests.TestCase_IcomIC208H)
Testing Icom IC-208H edges ... ok
test_settings (tests.TestCase_IcomIC208H)
Testing Icom IC-208H settings ... skipped 'Settings not supported'
test_banks (tests.TestCase_RetevisRT1)
Testing Retevis RT1 banks ... skipped 'Banks not supported'
test_brute_force (tests.TestCase_RetevisRT1)
Testing Retevis RT1 brute force ... ok
test_clone (tests.TestCase_RetevisRT1)
Testing Retevis RT1 clone ... ok
test_copy_all (tests.TestCase_RetevisRT1)
Testing Retevis RT1 copy all ... ok
test_detect (tests.TestCase_RetevisRT1)
Testing Retevis RT1 detect ... ok
test_edges (tests.TestCase_RetevisRT1)
Testing Retevis RT1 edges ... ok
test_settings (tests.TestCase_RetevisRT1)
Testing Retevis RT1 settings ... ok
test_banks (tests.TestCase_YaesuVX8DR)
Testing Yaesu VX-8DR banks ... ok
test_brute_force (tests.TestCase_YaesuVX8DR)
Testing Yaesu VX-8DR brute force ... ok
test_clone (tests.TestCase_YaesuVX8DR)
Testing Yaesu VX-8DR clone ... ok
test_copy_all (tests.TestCase_YaesuVX8DR)
Testing Yaesu VX-8DR copy all ... ok
test_detect (tests.TestCase_YaesuVX8DR)
Testing Yaesu VX-8DR detect ... ok
test_edges (tests.TestCase_YaesuVX8DR)
Testing Yaesu VX-8DR edges ... ok
test_settings (tests.TestCase_YaesuVX8DR)
Testing Yaesu VX-8DR settings ... ok
test_banks (tests.TestCase_BTECHUV50X3)
Testing BTECH UV-50X3 banks ... skipped 'Banks not supported'
test_brute_force (tests.TestCase_BTECHUV50X3)
Testing BTECH UV-50X3 brute force ... ok
test_clone (tests.TestCase_BTECHUV50X3)
Testing BTECH UV-50X3 clone ... ok
test_copy_all (tests.TestCase_BTECHUV50X3)
Testing BTECH UV-50X3 copy all ... ok
test_detect (tests.TestCase_BTECHUV50X3)
Testing BTECH UV-50X3 detect ... ok
test_edges (tests.TestCase_BTECHUV50X3)
Testing BTECH UV-50X3 edges ... ok
test_settings (tests.TestCase_BTECHUV50X3)
Testing BTECH UV-50X3 settings ... ok
test_banks (tests.TestCase_KenwoodTMD710CloneMode)
Testing Kenwood TM-D710_CloneMode banks ... skipped 'Banks not supported'
test_brute_force (tests.TestCase_KenwoodTMD710CloneMode)
Testing Kenwood TM-D710_CloneMode brute force ... ok
test_clone (tests.TestCase_KenwoodTMD710CloneMode)
Testing Kenwood TM-D710_CloneMode clone ... ok
test_copy_all (tests.TestCase_KenwoodTMD710CloneMode)
Testing Kenwood TM-D710_CloneMode copy all ... ok
test_detect (tests.TestCase_KenwoodTMD710CloneMode)
Testing Kenwood TM-D710_CloneMode detect ... ok
test_edges (tests.TestCase_KenwoodTMD710CloneMode)
Testing Kenwood TM-D710_CloneMode edges ... ok
test_settings (tests.TestCase_KenwoodTMD710CloneMode)
Testing Kenwood TM-D710_CloneMode settings ... ok
test_banks (tests.TestCase_YaesuFT817NDUS)
Testing Yaesu FT-817ND (US) banks ... skipped 'Banks not supported'
test_brute_force (tests.TestCase_YaesuFT817NDUS)
Testing Yaesu FT-817ND (US) brute force ... ok
test_clone (tests.TestCase_YaesuFT817NDUS)
Testing Yaesu FT-817ND (US) clone ... ok
test_copy_all (tests.TestCase_YaesuFT817NDUS)
Testing Yaesu FT-817ND (US) copy all ... ok
test_detect (tests.TestCase_YaesuFT817NDUS)
Testing Yaesu FT-817ND (US) detect ... ok
test_edges (tests.TestCase_YaesuFT817NDUS)
Testing Yaesu FT-817ND (US) edges ... ok
test_settings (tests.TestCase_YaesuFT817NDUS)
Testing Yaesu FT-817ND (US) settings ... ok
test_banks (tests.TestCase_TYTTHUV88)
Testing TYT TH-UV88 banks ... skipped 'Banks not supported'
test_brute_force (tests.TestCase_TYTTHUV88)
Testing TYT TH-UV88 brute force ... ok
test_clone (tests.TestCase_TYTTHUV88)
Testing TYT TH-UV88 clone ... ok
test_copy_all (tests.TestCase_TYTTHUV88)
Testing TYT TH-UV88 copy all ... ok
test_detect (tests.TestCase_TYTTHUV88)
Testing TYT TH-UV88 detect ... ok
test_edges (tests.TestCase_TYTTHUV88)
Testing TYT TH-UV88 edges ... ok
test_settings (tests.TestCase_TYTTHUV88)
Testing TYT TH-UV88 settings ... ok
test_banks (tests.TestCase_YaesuFT1D)
Testing Yaesu FT-1D banks ... ok
test_brute_force (tests.TestCase_YaesuFT1D)
Testing Yaesu FT-1D brute force ... ok
test_clone (tests.TestCase_YaesuFT1D)
Testing Yaesu FT-1D clone ... ok
test_copy_all (tests.TestCase_YaesuFT1D)
Testing Yaesu FT-1D copy all ... ok
test_detect (tests.TestCase_YaesuFT1D)
Testing Yaesu FT-1D detect ... ok
test_edges (tests.TestCase_YaesuFT1D)
Testing Yaesu FT-1D edges ... ok
test_settings (tests.TestCase_YaesuFT1D)
Testing Yaesu FT-1D settings ... ok
test_banks (tests.TestCase_IcomIC2100H)
Testing Icom IC-2100H banks ... skipped 'Banks not supported'
test_brute_force (tests.TestCase_IcomIC2100H)
Testing Icom IC-2100H brute force ... ok
test_clone (tests.TestCase_IcomIC2100H)
Testing Icom IC-2100H clone ... ok
test_copy_all (tests.TestCase_IcomIC2100H)
Testing Icom IC-2100H copy all ... ok
test_detect (tests.TestCase_IcomIC2100H)
Testing Icom IC-2100H detect ... ok
test_edges (tests.TestCase_IcomIC2100H)
Testing Icom IC-2100H edges ... ok
test_settings (tests.TestCase_IcomIC2100H)
Testing Icom IC-2100H settings ... skipped 'Settings not supported'
test_banks (tests.TestCase_RetevisRT21)
Testing Retevis RT21 banks ... skipped 'Banks not supported'
test_brute_force (tests.TestCase_RetevisRT21)
Testing Retevis RT21 brute force ... ok
test_clone (tests.TestCase_RetevisRT21)
Testing Retevis RT21 clone ... ok
test_copy_all (tests.TestCase_RetevisRT21)
Testing Retevis RT21 copy all ... ok
test_detect (tests.TestCase_RetevisRT21)
Testing Retevis RT21 detect ... ok
test_edges (tests.TestCase_RetevisRT21)
Testing Retevis RT21 edges ... ok
test_settings (tests.TestCase_RetevisRT21)
Testing Retevis RT21 settings ... ok
test_banks (tests.TestCase_BTECHUV5X3)
Testing BTECH UV-5X3 banks ... skipped 'Banks not supported'
test_brute_force (tests.TestCase_BTECHUV5X3)
Testing BTECH UV-5X3 brute force ... ok
test_clone (tests.TestCase_BTECHUV5X3)
Testing BTECH UV-5X3 clone ... ok
test_copy_all (tests.TestCase_BTECHUV5X3)
Testing BTECH UV-5X3 copy all ... ok
test_detect (tests.TestCase_BTECHUV5X3)
Testing BTECH UV-5X3 detect ... ok
test_edges (tests.TestCase_BTECHUV5X3)
Testing BTECH UV-5X3 edges ... ok
test_settings (tests.TestCase_BTECHUV5X3)
Testing BTECH UV-5X3 settings ... ok
test_banks (tests.TestCase_KenwoodTS480CloneMode)
Testing Kenwood TS-480_CloneMode banks ... skipped 'Banks not supported'
test_brute_force (tests.TestCase_KenwoodTS480CloneMode)
Testing Kenwood TS-480_CloneMode brute force ... ok
test_clone (tests.TestCase_KenwoodTS480CloneMode)
Testing Kenwood TS-480_CloneMode clone ... ok
test_copy_all (tests.TestCase_KenwoodTS480CloneMode)
Testing Kenwood TS-480_CloneMode copy all ... ok
test_detect (tests.TestCase_KenwoodTS480CloneMode)
Testing Kenwood TS-480_CloneMode detect ... ok
test_edges (tests.TestCase_KenwoodTS480CloneMode)
Testing Kenwood TS-480_CloneMode edges ... ok
test_settings (tests.TestCase_KenwoodTS480CloneMode)
Testing Kenwood TS-480_CloneMode settings ... ok
test_banks (tests.TestCase_IcomIC2200H)
Testing Icom IC-2200H banks ... ok
test_brute_force (tests.TestCase_IcomIC2200H)
Testing Icom IC-2200H brute force ... ok
test_clone (tests.TestCase_IcomIC2200H)
Testing Icom IC-2200H clone ... ok
test_copy_all (tests.TestCase_IcomIC2200H)
Testing Icom IC-2200H copy all ... ok
test_detect (tests.TestCase_IcomIC2200H)
Testing Icom IC-2200H detect ... ok
test_edges (tests.TestCase_IcomIC2200H)
Testing Icom IC-2200H edges ... ok
test_settings (tests.TestCase_IcomIC2200H)
Testing Icom IC-2200H settings ... ok
test_banks (tests.TestCase_YaesuFT818)
Testing Yaesu FT-818 banks ... skipped 'Banks not supported'
test_brute_force (tests.TestCase_YaesuFT818)
Testing Yaesu FT-818 brute force ... ok
test_clone (tests.TestCase_YaesuFT818)
Testing Yaesu FT-818 clone ... ok
test_copy_all (tests.TestCase_YaesuFT818)
Testing Yaesu FT-818 copy all ... ok
test_detect (tests.TestCase_YaesuFT818)
Testing Yaesu FT-818 detect ... ok
test_edges (tests.TestCase_YaesuFT818)
Testing Yaesu FT-818 edges ... ok
test_settings (tests.TestCase_YaesuFT818)
Testing Yaesu FT-818 settings ... ok
test_banks (tests.TestCase_TYTTHUVF1)
Testing TYT TH-UVF1 banks ... skipped 'Banks not supported'
test_brute_force (tests.TestCase_TYTTHUVF1)
Testing TYT TH-UVF1 brute force ... ok
test_clone (tests.TestCase_TYTTHUVF1)
Testing TYT TH-UVF1 clone ... ok
test_copy_all (tests.TestCase_TYTTHUVF1)
Testing TYT TH-UVF1 copy all ... ok
test_detect (tests.TestCase_TYTTHUVF1)
Testing TYT TH-UVF1 detect ... ok
test_edges (tests.TestCase_TYTTHUVF1)
Testing TYT TH-UVF1 edges ... ok
test_settings (tests.TestCase_TYTTHUVF1)
Testing TYT TH-UVF1 settings ... ok
test_banks (tests.TestCase_YaesuVX8GE)
Testing Yaesu VX-8GE banks ... ok
test_brute_force (tests.TestCase_YaesuVX8GE)
Testing Yaesu VX-8GE brute force ... ok
test_clone (tests.TestCase_YaesuVX8GE)
Testing Yaesu VX-8GE clone ... ok
test_copy_all (tests.TestCase_YaesuVX8GE)
Testing Yaesu VX-8GE copy all ... ok
test_detect (tests.TestCase_YaesuVX8GE)
Testing Yaesu VX-8GE detect ... ok
test_edges (tests.TestCase_YaesuVX8GE)
Testing Yaesu VX-8GE edges ... ok
test_settings (tests.TestCase_YaesuVX8GE)
Testing Yaesu VX-8GE settings ... ok
test_banks (tests.TestCase_RetevisRT22)
Testing Retevis RT22 banks ... skipped 'Banks not supported'
test_brute_force (tests.TestCase_RetevisRT22)
Testing Retevis RT22 brute force ... ok
test_clone (tests.TestCase_RetevisRT22)
Testing Retevis RT22 clone ... ok
test_copy_all (tests.TestCase_RetevisRT22)
Testing Retevis RT22 copy all ... ok
test_detect (tests.TestCase_RetevisRT22)
Testing Retevis RT22 detect ... ok
test_edges (tests.TestCase_RetevisRT22)
Testing Retevis RT22 edges ... ok
test_settings (tests.TestCase_RetevisRT22)
Testing Retevis RT22 settings ... ok
test_banks (tests.TestCase_YaesuFT25R)
Testing Yaesu FT-25R banks ... ok
test_brute_force (tests.TestCase_YaesuFT25R)
Testing Yaesu FT-25R brute force ... ok
test_clone (tests.TestCase_YaesuFT25R)
Testing Yaesu FT-25R clone ... ok
test_copy_all (tests.TestCase_YaesuFT25R)
Testing Yaesu FT-25R copy all ... ok
test_detect (tests.TestCase_YaesuFT25R)
Testing Yaesu FT-25R detect ... ok
test_edges (tests.TestCase_YaesuFT25R)
Testing Yaesu FT-25R edges ... ok
test_settings (tests.TestCase_YaesuFT25R)
Testing Yaesu FT-25R settings ... ok
test_banks (tests.TestCase_IcomID51)
Testing Icom ID-51 banks ... ok
test_brute_force (tests.TestCase_IcomID51)
Testing Icom ID-51 brute force ... ok
test_clone (tests.TestCase_IcomID51)
Testing Icom ID-51 clone ... ok
test_copy_all (tests.TestCase_IcomID51)
Testing Icom ID-51 copy all ... ok
test_detect (tests.TestCase_IcomID51)
Testing Icom ID-51 detect ... ok
test_edges (tests.TestCase_IcomID51)
Testing Icom ID-51 edges ... ok
test_settings (tests.TestCase_IcomID51)
Testing Icom ID-51 settings ... ok
test_banks (tests.TestCase_IcomIC2300H)
Testing Icom IC-2300H banks ... ok
test_brute_force (tests.TestCase_IcomIC2300H)
Testing Icom IC-2300H brute force ... ok
test_clone (tests.TestCase_IcomIC2300H)
Testing Icom IC-2300H clone ... ok
test_copy_all (tests.TestCase_IcomIC2300H)
Testing Icom IC-2300H copy all ... ok
test_detect (tests.TestCase_IcomIC2300H)
Testing Icom IC-2300H detect ... ok
test_edges (tests.TestCase_IcomIC2300H)
Testing Icom IC-2300H edges ... ok
test_settings (tests.TestCase_IcomIC2300H)
Testing Icom IC-2300H settings ... ok
test_banks (tests.TestCase_BaofengBF888)
Testing Baofeng BF-888 banks ... skipped 'Banks not supported'
test_brute_force (tests.TestCase_BaofengBF888)
Testing Baofeng BF-888 brute force ... ok
test_clone (tests.TestCase_BaofengBF888)
Testing Baofeng BF-888 clone ... ok
test_copy_all (tests.TestCase_BaofengBF888)
Testing Baofeng BF-888 copy all ... ok
test_detect (tests.TestCase_BaofengBF888)
Testing Baofeng BF-888 detect ... ok
test_edges (tests.TestCase_BaofengBF888)
Testing Baofeng BF-888 edges ... ok
test_settings (tests.TestCase_BaofengBF888)
Testing Baofeng BF-888 settings ... ok
test_banks (tests.TestCase_KenwoodTS590SGCloneMode)
Testing Kenwood TS-590SG_CloneMode banks ... skipped 'Banks not supported'
test_brute_force (tests.TestCase_KenwoodTS590SGCloneMode)
Testing Kenwood TS-590SG_CloneMode brute force ... ok
test_clone (tests.TestCase_KenwoodTS590SGCloneMode)
Testing Kenwood TS-590SG_CloneMode clone ... ok
test_copy_all (tests.TestCase_KenwoodTS590SGCloneMode)
Testing Kenwood TS-590SG_CloneMode copy all ... ok
test_detect (tests.TestCase_KenwoodTS590SGCloneMode)
Testing Kenwood TS-590SG_CloneMode detect ... ok
test_edges (tests.TestCase_KenwoodTS590SGCloneMode)
Testing Kenwood TS-590SG_CloneMode edges ... ok
test_settings (tests.TestCase_KenwoodTS590SGCloneMode)
Testing Kenwood TS-590SG_CloneMode settings ... ok
test_banks (tests.TestCase_YaesuFT857897)
Testing Yaesu FT-857/897 banks ... skipped 'Banks not supported'
test_brute_force (tests.TestCase_YaesuFT857897)
Testing Yaesu FT-857/897 brute force ... ok
test_clone (tests.TestCase_YaesuFT857897)
Testing Yaesu FT-857/897 clone ... ok
test_copy_all (tests.TestCase_YaesuFT857897)
Testing Yaesu FT-857/897 copy all ... ok
test_detect (tests.TestCase_YaesuFT857897)
Testing Yaesu FT-857/897 detect ... ok
test_edges (tests.TestCase_YaesuFT857897)
Testing Yaesu FT-857/897 edges ... ok
test_settings (tests.TestCase_YaesuFT857897)
Testing Yaesu FT-857/897 settings ... ok
test_banks (tests.TestCase_TYTTH9000144)
Testing TYT TH9000_144 banks ... skipped 'Banks not supported'
test_brute_force (tests.TestCase_TYTTH9000144)
Testing TYT TH9000_144 brute force ... ok
test_clone (tests.TestCase_TYTTH9000144)
Testing TYT TH9000_144 clone ... ok
test_copy_all (tests.TestCase_TYTTH9000144)
Testing TYT TH9000_144 copy all ... ok
test_detect (tests.TestCase_TYTTH9000144)
Testing TYT TH9000_144 detect ... ok
test_edges (tests.TestCase_TYTTH9000144)
Testing TYT TH9000_144 edges ... ok
test_settings (tests.TestCase_TYTTH9000144)
Testing TYT TH9000_144 settings ... ok
test_banks (tests.TestCase_RetevisRT22FRS)
Testing Retevis RT22FRS banks ... skipped 'Banks not supported'
test_brute_force (tests.TestCase_RetevisRT22FRS)
Testing Retevis RT22FRS brute force ... ok
test_clone (tests.TestCase_RetevisRT22FRS)
Testing Retevis RT22FRS clone ... ok
test_copy_all (tests.TestCase_RetevisRT22FRS)
Testing Retevis RT22FRS copy all ... ok
test_detect (tests.TestCase_RetevisRT22FRS)
Testing Retevis RT22FRS detect ... ok
test_edges (tests.TestCase_RetevisRT22FRS)
Testing Retevis RT22FRS edges ... ok
test_settings (tests.TestCase_RetevisRT22FRS)
Testing Retevis RT22FRS settings ... ok
test_banks (tests.TestCase_IcomIC2720H)
Testing Icom IC-2720H banks ... ok
test_brute_force (tests.TestCase_IcomIC2720H)
Testing Icom IC-2720H brute force ... ok
test_clone (tests.TestCase_IcomIC2720H)
Testing Icom IC-2720H clone ... ok
test_copy_all (tests.TestCase_IcomIC2720H)
Testing Icom IC-2720H copy all ... ok
test_detect (tests.TestCase_IcomIC2720H)
Testing Icom IC-2720H detect ... ok
test_edges (tests.TestCase_IcomIC2720H)
Testing Icom IC-2720H edges ... ok
test_settings (tests.TestCase_IcomIC2720H)
Testing Icom IC-2720H settings ... skipped 'Settings not supported'
test_banks (tests.TestCase_YaesuFT2800M)
Testing Yaesu FT-2800M banks ... skipped 'Banks not supported'
test_brute_force (tests.TestCase_YaesuFT2800M)
Testing Yaesu FT-2800M brute force ... ok
test_clone (tests.TestCase_YaesuFT2800M)
Testing Yaesu FT-2800M clone ... ok
test_copy_all (tests.TestCase_YaesuFT2800M)
Testing Yaesu FT-2800M copy all ... ok
test_detect (tests.TestCase_YaesuFT2800M)
Testing Yaesu FT-2800M detect ... ok
test_edges (tests.TestCase_YaesuFT2800M)
Testing Yaesu FT-2800M edges ... ok
test_settings (tests.TestCase_YaesuFT2800M)
Testing Yaesu FT-2800M settings ... skipped 'Settings not supported'
test_banks (tests.TestCase_BaofengBFA58S)
Testing Baofeng BF-A58S banks ... skipped 'Banks not supported'
test_brute_force (tests.TestCase_BaofengBFA58S)
Testing Baofeng BF-A58S brute force ... ok
test_clone (tests.TestCase_BaofengBFA58S)
Testing Baofeng BF-A58S clone ... ok
test_copy_all (tests.TestCase_BaofengBFA58S)
Testing Baofeng BF-A58S copy all ... ok
test_detect (tests.TestCase_BaofengBFA58S)
Testing Baofeng BF-A58S detect ... ok
test_edges (tests.TestCase_BaofengBFA58S)
Testing Baofeng BF-A58S edges ... ok
test_settings (tests.TestCase_BaofengBFA58S)
Testing Baofeng BF-A58S settings ... ok
test_banks (tests.TestCase_YaesuFT857897US)
Testing Yaesu FT-857/897 (US) banks ... skipped 'Banks not supported'
test_brute_force (tests.TestCase_YaesuFT857897US)
Testing Yaesu FT-857/897 (US) brute force ... ok
test_clone (tests.TestCase_YaesuFT857897US)
Testing Yaesu FT-857/897 (US) clone ... ok
test_copy_all (tests.TestCase_YaesuFT857897US)
Testing Yaesu FT-857/897 (US) copy all ... ok
test_detect (tests.TestCase_YaesuFT857897US)
Testing Yaesu FT-857/897 (US) detect ... ok
test_edges (tests.TestCase_YaesuFT857897US)
Testing Yaesu FT-857/897 (US) edges ... ok
test_settings (tests.TestCase_YaesuFT857897US)
Testing Yaesu FT-857/897 (US) settings ... ok
test_banks (tests.TestCase_LUITONLT725UV)
Testing LUITON LT-725UV banks ... skipped 'Banks not supported'
test_brute_force (tests.TestCase_LUITONLT725UV)
Testing LUITON LT-725UV brute force ... ok
test_clone (tests.TestCase_LUITONLT725UV)
Testing LUITON LT-725UV clone ... ok
test_copy_all (tests.TestCase_LUITONLT725UV)
Testing LUITON LT-725UV copy all ... ok
test_detect (tests.TestCase_LUITONLT725UV)
Testing LUITON LT-725UV detect ... ok
test_edges (tests.TestCase_LUITONLT725UV)
Testing LUITON LT-725UV edges ... ok
test_settings (tests.TestCase_LUITONLT725UV)
Testing LUITON LT-725UV settings ... ok
test_banks (tests.TestCase_YaesuVX8R)
Testing Yaesu VX-8R banks ... ok
test_brute_force (tests.TestCase_YaesuVX8R)
Testing Yaesu VX-8R brute force ... ok
test_clone (tests.TestCase_YaesuVX8R)
Testing Yaesu VX-8R clone ... ok
test_copy_all (tests.TestCase_YaesuVX8R)
Testing Yaesu VX-8R copy all ... ok
test_detect (tests.TestCase_YaesuVX8R)
Testing Yaesu VX-8R detect ... ok
test_edges (tests.TestCase_YaesuVX8R)
Testing Yaesu VX-8R edges ... ok
test_settings (tests.TestCase_YaesuVX8R)
Testing Yaesu VX-8R settings ... ok
test_banks (tests.TestCase_RetevisRT23)
Testing Retevis RT23 banks ... skipped 'Banks not supported'
test_brute_force (tests.TestCase_RetevisRT23)
Testing Retevis RT23 brute force ... ok
test_clone (tests.TestCase_RetevisRT23)
Testing Retevis RT23 clone ... ok
test_copy_all (tests.TestCase_RetevisRT23)
Testing Retevis RT23 copy all ... ok
test_detect (tests.TestCase_RetevisRT23)
Testing Retevis RT23 detect ... ok
test_edges (tests.TestCase_RetevisRT23)
Testing Retevis RT23 edges ... ok
test_settings (tests.TestCase_RetevisRT23)
Testing Retevis RT23 settings ... ok
test_banks (tests.TestCase_VertexStandardVXA700)
Testing Vertex Standard VXA-700 banks ... skipped 'Banks not supported'
test_brute_force (tests.TestCase_VertexStandardVXA700)
Testing Vertex Standard VXA-700 brute force ... ok
test_clone (tests.TestCase_VertexStandardVXA700)
Testing Vertex Standard VXA-700 clone ... ok
test_copy_all (tests.TestCase_VertexStandardVXA700)
Testing Vertex Standard VXA-700 copy all ... ok
test_detect (tests.TestCase_VertexStandardVXA700)
Testing Vertex Standard VXA-700 detect ... ok
test_edges (tests.TestCase_VertexStandardVXA700)
Testing Vertex Standard VXA-700 edges ... ok
test_settings (tests.TestCase_VertexStandardVXA700)
Testing Vertex Standard VXA-700 settings ... skipped 'Settings not supported'
test_banks (tests.TestCase_IcomID51Plus)
Testing Icom ID-51 Plus banks ... ok
test_brute_force (tests.TestCase_IcomID51Plus)
Testing Icom ID-51 Plus brute force ... ok
test_clone (tests.TestCase_IcomID51Plus)
Testing Icom ID-51 Plus clone ... ok
test_copy_all (tests.TestCase_IcomID51Plus)
Testing Icom ID-51 Plus copy all ... ok
test_detect (tests.TestCase_IcomID51Plus)
Testing Icom ID-51 Plus detect ... ok
test_edges (tests.TestCase_IcomID51Plus)
Testing Icom ID-51 Plus edges ... ok
test_settings (tests.TestCase_IcomID51Plus)
Testing Icom ID-51 Plus settings ... ok
test_banks (tests.TestCase_IcomIC2730A)
Testing Icom IC-2730A banks ... ok
test_brute_force (tests.TestCase_IcomIC2730A)
Testing Icom IC-2730A brute force ... ok
test_clone (tests.TestCase_IcomIC2730A)
Testing Icom IC-2730A clone ... ok
test_copy_all (tests.TestCase_IcomIC2730A)
Testing Icom IC-2730A copy all ... ok
test_detect (tests.TestCase_IcomIC2730A)
Testing Icom IC-2730A detect ... ok
test_edges (tests.TestCase_IcomIC2730A)
Testing Icom IC-2730A edges ... ok
test_settings (tests.TestCase_IcomIC2730A)
Testing Icom IC-2730A settings ... ok
test_banks (tests.TestCase_YaesuFT8800)
Testing Yaesu FT-8800 banks ... ok
test_brute_force (tests.TestCase_YaesuFT8800)
Testing Yaesu FT-8800 brute force ... ok
test_clone (tests.TestCase_YaesuFT8800)
Testing Yaesu FT-8800 clone ... ok
test_copy_all (tests.TestCase_YaesuFT8800)
Testing Yaesu FT-8800 copy all ... ok
test_detect (tests.TestCase_YaesuFT8800)
Testing Yaesu FT-8800 detect ... ok
test_edges (tests.TestCase_YaesuFT8800)
Testing Yaesu FT-8800 edges ... ok
test_settings (tests.TestCase_YaesuFT8800)
Testing Yaesu FT-8800 settings ... skipped 'Settings not supported'
test_banks (tests.TestCase_YaesuFT2900R1900R)
Testing Yaesu FT-2900R/1900R banks ... ok
test_brute_force (tests.TestCase_YaesuFT2900R1900R)
Testing Yaesu FT-2900R/1900R brute force ... ok
test_clone (tests.TestCase_YaesuFT2900R1900R)
Testing Yaesu FT-2900R/1900R clone ... ok
test_copy_all (tests.TestCase_YaesuFT2900R1900R)
Testing Yaesu FT-2900R/1900R copy all ... ok
test_detect (tests.TestCase_YaesuFT2900R1900R)
Testing Yaesu FT-2900R/1900R detect ... ok
test_edges (tests.TestCase_YaesuFT2900R1900R)
Testing Yaesu FT-2900R/1900R edges ... ok
test_settings (tests.TestCase_YaesuFT2900R1900R)
Testing Yaesu FT-2900R/1900R settings ... ok
test_banks (tests.TestCase_RetevisRT26)
Testing Retevis RT26 banks ... skipped 'Banks not supported'
test_brute_force (tests.TestCase_RetevisRT26)
Testing Retevis RT26 brute force ... ok
test_clone (tests.TestCase_RetevisRT26)
Testing Retevis RT26 clone ... ok
test_copy_all (tests.TestCase_RetevisRT26)
Testing Retevis RT26 copy all ... ok
test_detect (tests.TestCase_RetevisRT26)
Testing Retevis RT26 detect ... ok
test_edges (tests.TestCase_RetevisRT26)
Testing Retevis RT26 edges ... ok
test_settings (tests.TestCase_RetevisRT26)
Testing Retevis RT26 settings ... ok
test_banks (tests.TestCase_LeixenVV898)
Testing Leixen VV-898 banks ... skipped 'Banks not supported'
test_brute_force (tests.TestCase_LeixenVV898)
Testing Leixen VV-898 brute force ... ok
test_clone (tests.TestCase_LeixenVV898)
Testing Leixen VV-898 clone ... ok
test_copy_all (tests.TestCase_LeixenVV898)
Testing Leixen VV-898 copy all ... ok
test_detect (tests.TestCase_LeixenVV898)
Testing Leixen VV-898 detect ... ok
test_edges (tests.TestCase_LeixenVV898)
Testing Leixen VV-898 edges ... ok
test_settings (tests.TestCase_LeixenVV898)
Testing Leixen VV-898 settings ... ok
test_banks (tests.TestCase_WACCOMMINI8900)
Testing WACCOM MINI-8900 banks ... skipped 'Banks not supported'
test_brute_force (tests.TestCase_WACCOMMINI8900)
Testing WACCOM MINI-8900 brute force ... ok
test_clone (tests.TestCase_WACCOMMINI8900)
Testing WACCOM MINI-8900 clone ... ok
test_copy_all (tests.TestCase_WACCOMMINI8900)
Testing WACCOM MINI-8900 copy all ... ok
test_detect (tests.TestCase_WACCOMMINI8900)
Testing WACCOM MINI-8900 detect ... ok
test_edges (tests.TestCase_WACCOMMINI8900)
Testing WACCOM MINI-8900 edges ... ok
test_settings (tests.TestCase_WACCOMMINI8900)
Testing WACCOM MINI-8900 settings ... ok
test_banks (tests.TestCase_IcomID800H)
Testing Icom ID-800H banks ... ok
test_brute_force (tests.TestCase_IcomID800H)
Testing Icom ID-800H brute force ... ok
test_clone (tests.TestCase_IcomID800H)
Testing Icom ID-800H clone ... ok
test_copy_all (tests.TestCase_IcomID800H)
Testing Icom ID-800H copy all ... ok
test_detect (tests.TestCase_IcomID800H)
Testing Icom ID-800H detect ... ok
test_edges (tests.TestCase_IcomID800H)
Testing Icom ID-800H edges ... ok
test_settings (tests.TestCase_IcomID800H)
Testing Icom ID-800H settings ... ok
test_banks (tests.TestCase_YaesuFT8900)
Testing Yaesu FT-8900 banks ... skipped 'Banks not supported'
test_brute_force (tests.TestCase_YaesuFT8900)
Testing Yaesu FT-8900 brute force ... ok
test_clone (tests.TestCase_YaesuFT8900)
Testing Yaesu FT-8900 clone ... ok
test_copy_all (tests.TestCase_YaesuFT8900)
Testing Yaesu FT-8900 copy all ... ok
test_detect (tests.TestCase_YaesuFT8900)
Testing Yaesu FT-8900 detect ... ok
test_edges (tests.TestCase_YaesuFT8900)
Testing Yaesu FT-8900 edges ... ok
test_settings (tests.TestCase_YaesuFT8900)
Testing Yaesu FT-8900 settings ... skipped 'Settings not supported'
test_banks (tests.TestCase_RetevisRT622)
Testing Retevis RT622 banks ... skipped 'Banks not supported'
test_brute_force (tests.TestCase_RetevisRT622)
Testing Retevis RT622 brute force ... ok
test_clone (tests.TestCase_RetevisRT622)
Testing Retevis RT622 clone ... ok
test_copy_all (tests.TestCase_RetevisRT622)
Testing Retevis RT622 copy all ... ok
test_detect (tests.TestCase_RetevisRT622)
Testing Retevis RT622 detect ... ok
test_edges (tests.TestCase_RetevisRT622)
Testing Retevis RT622 edges ... ok
test_settings (tests.TestCase_RetevisRT622)
Testing Retevis RT622 settings ... ok
test_banks (tests.TestCase_YaesuFT450D)
Testing Yaesu FT-450D banks ... skipped 'Banks not supported'
test_brute_force (tests.TestCase_YaesuFT450D)
Testing Yaesu FT-450D brute force ... ok
test_clone (tests.TestCase_YaesuFT450D)
Testing Yaesu FT-450D clone ... ok
test_copy_all (tests.TestCase_YaesuFT450D)
Testing Yaesu FT-450D copy all ... ok
test_detect (tests.TestCase_YaesuFT450D)
Testing Yaesu FT-450D detect ... ok
test_edges (tests.TestCase_YaesuFT450D)
Testing Yaesu FT-450D edges ... ok
test_settings (tests.TestCase_YaesuFT450D)
Testing Yaesu FT-450D settings ... ok
test_banks (tests.TestCase_LeixenVV898S)
Testing Leixen VV-898S banks ... skipped 'Banks not supported'
test_brute_force (tests.TestCase_LeixenVV898S)
Testing Leixen VV-898S brute force ... ok
test_clone (tests.TestCase_LeixenVV898S)
Testing Leixen VV-898S clone ... ok
test_copy_all (tests.TestCase_LeixenVV898S)
Testing Leixen VV-898S copy all ... ok
test_detect (tests.TestCase_LeixenVV898S)
Testing Leixen VV-898S detect ... ok
test_edges (tests.TestCase_LeixenVV898S)
Testing Leixen VV-898S edges ... ok
test_settings (tests.TestCase_LeixenVV898S)
Testing Leixen VV-898S settings ... ok
test_banks (tests.TestCase_WouxunKG816)
Testing Wouxun KG-816 banks ... skipped 'Banks not supported'
test_brute_force (tests.TestCase_WouxunKG816)
Testing Wouxun KG-816 brute force ... ok
test_clone (tests.TestCase_WouxunKG816)
Testing Wouxun KG-816 clone ... ok
test_copy_all (tests.TestCase_WouxunKG816)
Testing Wouxun KG-816 copy all ... ok
test_detect (tests.TestCase_WouxunKG816)
Testing Wouxun KG-816 detect ... ok
test_edges (tests.TestCase_WouxunKG816)
Testing Wouxun KG-816 edges ... ok
test_settings (tests.TestCase_WouxunKG816)
Testing Wouxun KG-816 settings ... ok
test_banks (tests.TestCase_IcomID880H)
Testing Icom ID-880H banks ... ok
test_brute_force (tests.TestCase_IcomID880H)
Testing Icom ID-880H brute force ... ok
test_clone (tests.TestCase_IcomID880H)
Testing Icom ID-880H clone ... ok
test_copy_all (tests.TestCase_IcomID880H)
Testing Icom ID-880H copy all ... ok
test_detect (tests.TestCase_IcomID880H)
Testing Icom ID-880H detect ... ok
test_edges (tests.TestCase_IcomID880H)
Testing Icom ID-880H edges ... ok
test_settings (tests.TestCase_IcomID880H)
Testing Icom ID-880H settings ... ok
test_banks (tests.TestCase_RetevisRT76)
Testing Retevis RT76 banks ... skipped 'Banks not supported'
test_brute_force (tests.TestCase_RetevisRT76)
Testing Retevis RT76 brute force ... ok
test_clone (tests.TestCase_RetevisRT76)
Testing Retevis RT76 clone ... ok
test_copy_all (tests.TestCase_RetevisRT76)
Testing Retevis RT76 copy all ... ok
test_detect (tests.TestCase_RetevisRT76)
Testing Retevis RT76 detect ... ok
test_edges (tests.TestCase_RetevisRT76)
Testing Retevis RT76 edges ... skipped 'No mutable memory locations found'
test_settings (tests.TestCase_RetevisRT76)
Testing Retevis RT76 settings ... ok
test_banks (tests.TestCase_YaesuFT4VR)
Testing Yaesu FT-4VR banks ... ok
test_brute_force (tests.TestCase_YaesuFT4VR)
Testing Yaesu FT-4VR brute force ... ok
test_clone (tests.TestCase_YaesuFT4VR)
Testing Yaesu FT-4VR clone ... ok
test_copy_all (tests.TestCase_YaesuFT4VR)
Testing Yaesu FT-4VR copy all ... ok
test_detect (tests.TestCase_YaesuFT4VR)
Testing Yaesu FT-4VR detect ... ok
test_edges (tests.TestCase_YaesuFT4VR)
Testing Yaesu FT-4VR edges ... ok
test_settings (tests.TestCase_YaesuFT4VR)
Testing Yaesu FT-4VR settings ... ok
test_banks (tests.TestCase_YaesuFT2D)
Testing Yaesu FT2D banks ... ok
test_brute_force (tests.TestCase_YaesuFT2D)
Testing Yaesu FT2D brute force ... ok
test_clone (tests.TestCase_YaesuFT2D)
Testing Yaesu FT2D clone ... ok
test_copy_all (tests.TestCase_YaesuFT2D)
Testing Yaesu FT2D copy all ... ok
test_detect (tests.TestCase_YaesuFT2D)
Testing Yaesu FT2D detect ... ok
test_edges (tests.TestCase_YaesuFT2D)
Testing Yaesu FT2D edges ... ok
test_settings (tests.TestCase_YaesuFT2D)
Testing Yaesu FT2D settings ... ok
test_banks (tests.TestCase_JetstreamJT220M)
Testing Jetstream JT220M banks ... skipped 'Banks not supported'
test_brute_force (tests.TestCase_JetstreamJT220M)
Testing Jetstream JT220M brute force ... ok
test_clone (tests.TestCase_JetstreamJT220M)
Testing Jetstream JT220M clone ... ok
test_copy_all (tests.TestCase_JetstreamJT220M)
Testing Jetstream JT220M copy all ... ok
test_detect (tests.TestCase_JetstreamJT220M)
Testing Jetstream JT220M detect ... ok
test_edges (tests.TestCase_JetstreamJT220M)
Testing Jetstream JT220M edges ... ok
test_settings (tests.TestCase_JetstreamJT220M)
Testing Jetstream JT220M settings ... skipped 'Settings not supported'
test_banks (tests.TestCase_WouxunKG818)
Testing Wouxun KG-818 banks ... skipped 'Banks not supported'
test_brute_force (tests.TestCase_WouxunKG818)
Testing Wouxun KG-818 brute force ... ok
test_clone (tests.TestCase_WouxunKG818)
Testing Wouxun KG-818 clone ... ok
test_copy_all (tests.TestCase_WouxunKG818)
Testing Wouxun KG-818 copy all ... ok
test_detect (tests.TestCase_WouxunKG818)
Testing Wouxun KG-818 detect ... ok
test_edges (tests.TestCase_WouxunKG818)
Testing Wouxun KG-818 edges ... ok
test_settings (tests.TestCase_WouxunKG818)
Testing Wouxun KG-818 settings ... ok
test_banks (tests.TestCase_JetstreamJT270M)
Testing Jetstream JT270M banks ... skipped 'Banks not supported'
test_brute_force (tests.TestCase_JetstreamJT270M)
Testing Jetstream JT270M brute force ... ok
test_clone (tests.TestCase_JetstreamJT270M)
Testing Jetstream JT270M clone ... ok
test_copy_all (tests.TestCase_JetstreamJT270M)
Testing Jetstream JT270M copy all ... ok
test_detect (tests.TestCase_JetstreamJT270M)
Testing Jetstream JT270M detect ... ok
test_edges (tests.TestCase_JetstreamJT270M)
Testing Jetstream JT270M edges ... ok
test_settings (tests.TestCase_JetstreamJT270M)
Testing Jetstream JT270M settings ... ok
test_banks (tests.TestCase_YaesuFT4XE)
Testing Yaesu FT-4XE banks ... ok
test_brute_force (tests.TestCase_YaesuFT4XE)
Testing Yaesu FT-4XE brute force ... ok
test_clone (tests.TestCase_YaesuFT4XE)
Testing Yaesu FT-4XE clone ... ok
test_copy_all (tests.TestCase_YaesuFT4XE)
Testing Yaesu FT-4XE copy all ... ok
test_detect (tests.TestCase_YaesuFT4XE)
Testing Yaesu FT-4XE detect ... ok
test_edges (tests.TestCase_YaesuFT4XE)
Testing Yaesu FT-4XE edges ... ok
test_settings (tests.TestCase_YaesuFT4XE)
Testing Yaesu FT-4XE settings ... ok
test_banks (tests.TestCase_WouxunKGUV6)
Testing Wouxun KG-UV6 banks ... skipped 'Banks not supported'
test_brute_force (tests.TestCase_WouxunKGUV6)
Testing Wouxun KG-UV6 brute force ... ok
test_clone (tests.TestCase_WouxunKGUV6)
Testing Wouxun KG-UV6 clone ... ok
test_copy_all (tests.TestCase_WouxunKGUV6)
Testing Wouxun KG-UV6 copy all ... ok
test_detect (tests.TestCase_WouxunKGUV6)
Testing Wouxun KG-UV6 detect ... ok
test_edges (tests.TestCase_WouxunKGUV6)
Testing Wouxun KG-UV6 edges ... ok
test_settings (tests.TestCase_WouxunKGUV6)
Testing Wouxun KG-UV6 settings ... ok
test_banks (tests.TestCase_MidlandDBR2500)
Testing Midland DBR2500 banks ... skipped 'Banks not supported'
test_brute_force (tests.TestCase_MidlandDBR2500)
Testing Midland DBR2500 brute force ... ok
test_clone (tests.TestCase_MidlandDBR2500)
Testing Midland DBR2500 clone ... ok
test_copy_all (tests.TestCase_MidlandDBR2500)
Testing Midland DBR2500 copy all ... ok
test_detect (tests.TestCase_MidlandDBR2500)
Testing Midland DBR2500 detect ... ok
test_edges (tests.TestCase_MidlandDBR2500)
Testing Midland DBR2500 edges ... ok
test_settings (tests.TestCase_MidlandDBR2500)
Testing Midland DBR2500 settings ... ok
test_banks (tests.TestCase_YaesuFT3D)
Testing Yaesu FT3D banks ... ok
test_brute_force (tests.TestCase_YaesuFT3D)
Testing Yaesu FT3D brute force ... ok
test_clone (tests.TestCase_YaesuFT3D)
Testing Yaesu FT3D clone ... ok
test_copy_all (tests.TestCase_YaesuFT3D)
Testing Yaesu FT3D copy all ... ok
test_detect (tests.TestCase_YaesuFT3D)
Testing Yaesu FT3D detect ... ok
test_edges (tests.TestCase_YaesuFT3D)
Testing Yaesu FT3D edges ... ok
test_settings (tests.TestCase_YaesuFT3D)
Testing Yaesu FT3D settings ... ok
test_banks (tests.TestCase_JetstreamJT270MH)
Testing Jetstream JT270MH banks ... skipped 'Banks not supported'
test_brute_force (tests.TestCase_JetstreamJT270MH)
Testing Jetstream JT270MH brute force ... ok
test_clone (tests.TestCase_JetstreamJT270MH)
Testing Jetstream JT270MH clone ... ok
test_copy_all (tests.TestCase_JetstreamJT270MH)
Testing Jetstream JT270MH copy all ... ok
test_detect (tests.TestCase_JetstreamJT270MH)
Testing Jetstream JT270MH detect ... ok
test_edges (tests.TestCase_JetstreamJT270MH)
Testing Jetstream JT270MH edges ... ok
test_settings (tests.TestCase_JetstreamJT270MH)
Testing Jetstream JT270MH settings ... ok
test_banks (tests.TestCase_YaesuFT4XR)
Testing Yaesu FT-4XR banks ... ok
test_brute_force (tests.TestCase_YaesuFT4XR)
Testing Yaesu FT-4XR brute force ... ok
test_clone (tests.TestCase_YaesuFT4XR)
Testing Yaesu FT-4XR clone ... ok
test_copy_all (tests.TestCase_YaesuFT4XR)
Testing Yaesu FT-4XR copy all ... ok
test_detect (tests.TestCase_YaesuFT4XR)
Testing Yaesu FT-4XR detect ... ok
test_edges (tests.TestCase_YaesuFT4XR)
Testing Yaesu FT-4XR edges ... ok
test_settings (tests.TestCase_YaesuFT4XR)
Testing Yaesu FT-4XR settings ... ok
test_banks (tests.TestCase_WouxunKGUV8D)
Testing Wouxun KG-UV8D banks ... skipped 'Banks not supported'
test_brute_force (tests.TestCase_WouxunKGUV8D)
Testing Wouxun KG-UV8D brute force ... ok
test_clone (tests.TestCase_WouxunKGUV8D)
Testing Wouxun KG-UV8D clone ... ok
test_copy_all (tests.TestCase_WouxunKGUV8D)
Testing Wouxun KG-UV8D copy all ... ok
test_detect (tests.TestCase_WouxunKGUV8D)
Testing Wouxun KG-UV8D detect ... ok
test_edges (tests.TestCase_WouxunKGUV8D)
Testing Wouxun KG-UV8D edges ... ok
test_settings (tests.TestCase_WouxunKGUV8D)
Testing Wouxun KG-UV8D settings ... ok
test_banks (tests.TestCase_KYDIP620)
Testing KYD IP-620 banks ... skipped 'Banks not supported'
test_brute_force (tests.TestCase_KYDIP620)
Testing KYD IP-620 brute force ... ok
test_clone (tests.TestCase_KYDIP620)
Testing KYD IP-620 clone ... ok
test_copy_all (tests.TestCase_KYDIP620)
Testing KYD IP-620 copy all ... ok
test_detect (tests.TestCase_KYDIP620)
Testing KYD IP-620 detect ... ok
test_edges (tests.TestCase_KYDIP620)
Testing KYD IP-620 edges ... ok
test_settings (tests.TestCase_KYDIP620)
Testing KYD IP-620 settings ... ok
test_banks (tests.TestCase_PolmarDB50M)
Testing Polmar DB-50M banks ... skipped 'Banks not supported'
test_brute_force (tests.TestCase_PolmarDB50M)
Testing Polmar DB-50M brute force ... ok
test_clone (tests.TestCase_PolmarDB50M)
Testing Polmar DB-50M clone ... ok
test_copy_all (tests.TestCase_PolmarDB50M)
Testing Polmar DB-50M copy all ... ok
test_detect (tests.TestCase_PolmarDB50M)
Testing Polmar DB-50M detect ... ok
test_edges (tests.TestCase_PolmarDB50M)
Testing Polmar DB-50M edges ... ok
test_settings (tests.TestCase_PolmarDB50M)
Testing Polmar DB-50M settings ... ok
test_banks (tests.TestCase_YaesuFTM3200D)
Testing Yaesu FTM-3200D banks ... skipped 'Banks not supported'
test_brute_force (tests.TestCase_YaesuFTM3200D)
Testing Yaesu FTM-3200D brute force ... ok
test_clone (tests.TestCase_YaesuFTM3200D)
Testing Yaesu FTM-3200D clone ... ok
test_copy_all (tests.TestCase_YaesuFTM3200D)
Testing Yaesu FTM-3200D copy all ... ok
test_detect (tests.TestCase_YaesuFTM3200D)
Testing Yaesu FTM-3200D detect ... ok
test_edges (tests.TestCase_YaesuFTM3200D)
Testing Yaesu FTM-3200D edges ... ok
test_settings (tests.TestCase_YaesuFTM3200D)
Testing Yaesu FTM-3200D settings ... skipped 'Settings not supported'
test_banks (tests.TestCase_YaesuFT50)
Testing Yaesu FT-50 banks ... skipped 'Banks not supported'
test_brute_force (tests.TestCase_YaesuFT50)
Testing Yaesu FT-50 brute force ... ok
test_clone (tests.TestCase_YaesuFT50)
Testing Yaesu FT-50 clone ... ok
test_copy_all (tests.TestCase_YaesuFT50)
Testing Yaesu FT-50 copy all ... ok
test_detect (tests.TestCase_YaesuFT50)
Testing Yaesu FT-50 detect ... ok
test_edges (tests.TestCase_YaesuFT50)
Testing Yaesu FT-50 edges ... ok
test_settings (tests.TestCase_YaesuFT50)
Testing Yaesu FT-50 settings ... ok
test_banks (tests.TestCase_PuxingPX2R)
Testing Puxing PX-2R banks ... skipped 'Banks not supported'
test_brute_force (tests.TestCase_PuxingPX2R)
Testing Puxing PX-2R brute force ... ok
test_clone (tests.TestCase_PuxingPX2R)
Testing Puxing PX-2R clone ... ok
test_copy_all (tests.TestCase_PuxingPX2R)
Testing Puxing PX-2R copy all ... ok
test_detect (tests.TestCase_PuxingPX2R)
Testing Puxing PX-2R detect ... ok
test_edges (tests.TestCase_PuxingPX2R)
Testing Puxing PX-2R edges ... ok
test_settings (tests.TestCase_PuxingPX2R)
Testing Puxing PX-2R settings ... skipped 'Settings not supported'
test_banks (tests.TestCase_YaesuFTM350)
Testing Yaesu FTM-350 banks ... skipped 'Banks not supported'
test_brute_force (tests.TestCase_YaesuFTM350)
Testing Yaesu FTM-350 brute force ... ok
test_clone (tests.TestCase_YaesuFTM350)
Testing Yaesu FTM-350 clone ... ok
test_copy_all (tests.TestCase_YaesuFTM350)
Testing Yaesu FTM-350 copy all ... ok
test_detect (tests.TestCase_YaesuFTM350)
Testing Yaesu FTM-350 detect ... ok
test_edges (tests.TestCase_YaesuFTM350)
Testing Yaesu FTM-350 edges ... ok
test_settings (tests.TestCase_YaesuFTM350)
Testing Yaesu FTM-350 settings ... skipped 'Settings not supported'
test_banks (tests.TestCase_YaesuFT60)
Testing Yaesu FT-60 banks ... ok
test_brute_force (tests.TestCase_YaesuFT60)
Testing Yaesu FT-60 brute force ... ok
test_clone (tests.TestCase_YaesuFT60)
Testing Yaesu FT-60 clone ... ok
test_copy_all (tests.TestCase_YaesuFT60)
Testing Yaesu FT-60 copy all ... ok
test_detect (tests.TestCase_YaesuFT60)
Testing Yaesu FT-60 detect ... ok
test_edges (tests.TestCase_YaesuFT60)
Testing Yaesu FT-60 edges ... ok
test_settings (tests.TestCase_YaesuFT60)
Testing Yaesu FT-60 settings ... ok
test_banks (tests.TestCase_YaesuFTM7250D)
Testing Yaesu FTM-7250D banks ... skipped 'Banks not supported'
test_brute_force (tests.TestCase_YaesuFTM7250D)
Testing Yaesu FTM-7250D brute force ... ok
test_clone (tests.TestCase_YaesuFTM7250D)
Testing Yaesu FTM-7250D clone ... ok
test_copy_all (tests.TestCase_YaesuFTM7250D)
Testing Yaesu FTM-7250D copy all ... ok
test_detect (tests.TestCase_YaesuFTM7250D)
Testing Yaesu FTM-7250D detect ... ok
test_edges (tests.TestCase_YaesuFTM7250D)
Testing Yaesu FTM-7250D edges ... ok
test_settings (tests.TestCase_YaesuFTM7250D)
Testing Yaesu FTM-7250D settings ... skipped 'Settings not supported'
test_banks (tests.TestCase_YaesuFT65E)
Testing Yaesu FT-65E banks ... ok
test_brute_force (tests.TestCase_YaesuFT65E)
Testing Yaesu FT-65E brute force ... ok
test_clone (tests.TestCase_YaesuFT65E)
Testing Yaesu FT-65E clone ... ok
test_copy_all (tests.TestCase_YaesuFT65E)
Testing Yaesu FT-65E copy all ... ok
test_detect (tests.TestCase_YaesuFT65E)
Testing Yaesu FT-65E detect ... ok
test_edges (tests.TestCase_YaesuFT65E)
Testing Yaesu FT-65E edges ... ok
test_settings (tests.TestCase_YaesuFT65E)
Testing Yaesu FT-65E settings ... ok
======================================================================
ERROR: test_detect (tests.TestCase_BaofengUV5R)
Testing Baofeng UV-5R detect
----------------------------------------------------------------------
Traceback (most recent call last):
File "tests/__init__.py", line 70, in test_detect
self._runtest(run_tests.TestCaseDetect)
File "tests/__init__.py", line 44, in _runtest
failures = testcase.run()
File "tests/run_tests.py", line 880, in run
filename))
TestFailedError: <class 'chirp.drivers.uv5r.BaofengUV5RGeneric'> detected as <class 'chirp.drivers.uv5r.RadioddityGT5RRadio'> for /tmp/Baofeng_UV-5R_Bl1Lun.img
----------------------------------------------------------------------
Ran 1064 tests in 483.772s
FAILED (errors=1, skipped=148)
struct memory {
bbcd rx_freq[4];
bbcd tx_freq[4];
lbcd rx_tone[2];
lbcd tx_tone[2];
u8 unknown10:5,
highpower:1,
unknown11:2;
u8 unknown20:4,
narrow:1,
unknown21:3;
u8 unknown31:1,
scanadd:1,
unknown32:6;
u8 unknown4;
};
struct name {
char name[7];
};
#seekto 0x0010;
struct memory channels[128];
#seekto 0x08C0;
struct name names[128];
#seekto 0x2020;
struct memory vfo1;
struct memory vfo2;
ERROR: InvocationError for command /chirp/.tox/driver/bin/python -munittest -vb tests (exited with code 1)
style create: /chirp/.tox/style
style installdeps: pep8==1.6.2, future
style inst: /chirp/.tox/.tmp/package/1/chirp-0.3.0dev.zip
style installed: DEPRECATION: Python 2.7 will reach the end of its life on January 1st, 2020. Please upgrade your Python as Python 2.7 won't be maintained after that date. A future version of pip will drop support for Python 2.7.,chirp==0.3.0.dev0,configparser==3.7.4,contextlib2==0.5.5,filelock==3.0.12,future==0.15.2,importlib-metadata==0.18,Mako==1.0.3,MarkupSafe==0.23,mercurial==3.7.3,packaging==19.0,pathlib2==2.3.4,pep8==1.6.2,pluggy==0.12.0,py==1.8.0,pygobject==3.20.0,pyparsing==2.4.0,pyserial==3.0.1,scandir==1.10.0,six==1.12.0,toml==0.10.0,tox==3.13.2,virtualenv==16.6.1,zipp==0.5.2
style run-test-pre: PYTHONHASHSEED='2182206856'
style run-test: commands[0] | python ./tools/cpep8.py
___________________________________ summary ____________________________________
ERROR: unit: commands failed
ERROR: driver: commands failed
style: commands succeeded
Build step 'Execute shell' marked build as failure
Email was triggered for: Failure
Sending email for trigger: Failure
1
1
19 May '21
Image attached for testing: Baofeng_BF-T8.img
---------- Forwarded message ---------
From: Jim Unroe <kc9hi(a)comcast.net>
Date: Wed, May 19, 2021 at 9:00 PM
Subject: [PATCH] [BF-T8] add support for the Baofeng BF-T8
To: <Rock.Unroe(a)gmail.com>
# HG changeset patch
# User Jim Unroe <rock.unroe(a)gmail.com>
# Date 1621472333 14400
# Wed May 19 20:58:53 2021 -0400
# Node ID ccf8f96034cd9dbb6f3462bcf10d68526c3e0572
# Parent b04ba05b7b646e144af4f074663941ca122dc4ed
[BF-T8] add support for the Baofeng BF-T8
This patch adds support for the Baofeng BF-T8 (and it variants)
related to #8263
diff -r b04ba05b7b64 -r ccf8f96034cd chirp/drivers/bf-t8.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/chirp/drivers/bf-t8.py Wed May 19 20:58:53 2021 -0400
@@ -0,0 +1,702 @@
+# Copyright 2021 Jim Unroe <rock.unroe(a)gmail.com>
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 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 time
+import os
+import struct
+import logging
+
+from chirp import (
+ bitwise,
+ chirp_common,
+ directory,
+ errors,
+ memmap,
+ util,
+)
+from chirp.settings import (
+ RadioSetting,
+ RadioSettingGroup,
+ RadioSettings,
+ RadioSettingValueBoolean,
+ RadioSettingValueFloat,
+ RadioSettingValueInteger,
+ RadioSettingValueList,
+ RadioSettingValueString,
+)
+
+LOG = logging.getLogger(__name__)
+
+MEM_FORMAT = """
+#seekto 0x0000;
+struct {
+ lbcd rxfreq[4]; // RX Frequency
+ lbcd txfreq[4]; // TX Frequency
+ u8 rx_tmode; // RX Tone Mode
+ u8 rx_tone; // PL/DPL Decode
+ u8 tx_tmode; // TX Tone Mode
+ u8 tx_tone; // PL/DPL Encode
+ u8 unknown1:3, //
+ skip:1, // Scan Add: 1 = Skip, 0 = Scan
+ unknown2:2,
+ isnarrow:1, // W/N: 1 = Narrow, 0 = Wide
+ lowpower:1; // TX Power: 1 = Low, 0 = High
+ u8 unknown3[3]; //
+} memory[99];
+
+#seekto 0x0630;
+struct {
+ u8 squelch; // SQL
+ u8 vox; // Vox Lv
+ u8 tot; // TOT
+ u8 unk1:3, //
+ ste:1, // Tail Clear
+ bcl:1, // BCL
+ save:1, // Save
+ tdr:1, // TDR
+ beep:1; // Beep
+ u8 voice; // Voice
+ u8 abr; // Back Light
+ u8 ring; // Ring
+ u8 unknown; //
+ u8 mra; // MR Channel A
+ u8 mrb; // MR Channel B
+ u8 disp_ab; // Display A/B Selected
+ ul16 fmcur; // Broadcast FM station
+ u8 workmode; // Work Mode
+ u8 wx; // NOAA WX ch#
+ u8 area; // Area Selected
+} settings;
+"""
+
+CMD_ACK = "\x06"
+
+TONES = chirp_common.TONES
+TMODES = ["", "Tone", "DTCS", "DTCS"]
+
+AB_LIST = ["A", "B"]
+ABR_LIST = ["OFF", "ON", "Key"]
+AREA_LIST = ["China", "Japan", "Korea", "Malaysia", "American",
+ "Australia", "Iran", "Taiwan", "Europe", "Russia"]
+MDF_LIST = ["Frequency", "Channel #", "Name"]
+RING_LIST = ["OFF"] + ["%s" % x for x in range(1, 11)]
+TOT_LIST = ["OFF"] + ["%s seconds" % x for x in range(30, 210, 30)]
+VOICE_LIST = ["Off", "Chinese", "English"]
+VOX_LIST = ["OFF"] + ["%s" % x for x in range(1, 6)]
+WORKMODE_LIST = ["General", "PMR"]
+WX_LIST = ["CH01 - 162.550",
+ "CH02 - 162.400",
+ "CH03 - 162.475",
+ "CH04 - 162.425",
+ "CH05 - 162.450",
+ "CH06 - 162.500",
+ "CH07 - 162.525"
+ ]
+
+SETTING_LISTS = {
+ "ab": AB_LIST,
+ "abr": ABR_LIST,
+ "area": AREA_LIST,
+ "mdf": MDF_LIST,
+ "ring": RING_LIST,
+ "tot": TOT_LIST,
+ "voice": VOICE_LIST,
+ "vox": VOX_LIST,
+ "workmode": WORKMODE_LIST,
+ "wx": WX_LIST,
+ }
+
+FRS_FREQS1 = [462.5625, 462.5875, 462.6125, 462.6375, 462.6625,
+ 462.6875, 462.7125]
+FRS_FREQS2 = [467.5625, 467.5875, 467.6125, 467.6375, 467.6625,
+ 467.6875, 467.7125]
+FRS_FREQS3 = [462.5500, 462.5750, 462.6000, 462.6250, 462.6500,
+ 462.6750, 462.7000, 462.7250]
+FRS_FREQS = FRS_FREQS1 + FRS_FREQS2 + FRS_FREQS3
+
+
+def _enter_programming_mode(radio):
+ serial = radio.pipe
+
+ exito = False
+ for i in range(0, 5):
+ serial.write(radio._magic)
+ ack = serial.read(1)
+
+ try:
+ if ack == CMD_ACK:
+ exito = True
+ break
+ except:
+ LOG.debug("Attempt #%s, failed, trying again" % i)
+ pass
+
+ # check if we had EXITO
+ if exito is False:
+ _exit_programming_mode(radio)
+ msg = "The radio did not accept program mode after five tries.\n"
+ msg += "Check you interface cable and power cycle your radio."
+ raise errors.RadioError(msg)
+
+ try:
+ serial.write("\x02")
+ ident = serial.read(len(radio._fingerprint))
+ except:
+ _exit_programming_mode(radio)
+ raise errors.RadioError("Error communicating with radio")
+
+ if not ident == radio._fingerprint:
+ _exit_programming_mode(radio)
+ LOG.debug(util.hexprint(ident))
+ raise errors.RadioError("Radio returned unknown identification string")
+
+ try:
+ serial.write(CMD_ACK)
+ ack = serial.read(1)
+ except:
+ _exit_programming_mode(radio)
+ raise errors.RadioError("Error communicating with radio")
+
+ if ack != CMD_ACK:
+ _exit_programming_mode(radio)
+ raise errors.RadioError("Radio refused to enter programming mode")
+
+
+def _exit_programming_mode(radio):
+ serial = radio.pipe
+ try:
+ serial.write("E")
+ except:
+ raise errors.RadioError("Radio refused to exit programming mode")
+
+
+def _read_block(radio, block_addr, block_size):
+ serial = radio.pipe
+
+ cmd = struct.pack(">cHb", 'R', block_addr, block_size)
+ expectedresponse = "W" + cmd[1:]
+ LOG.debug("Reading block %04x..." % (block_addr))
+
+ try:
+ serial.write(cmd)
+ response = serial.read(4 + block_size)
+ if response[:4] != expectedresponse:
+ raise Exception("Error reading block %04x." % (block_addr))
+
+ block_data = response[4:]
+
+ serial.write(CMD_ACK)
+ ack = serial.read(1)
+ except:
+ _exit_programming_mode(radio)
+ raise errors.RadioError("Failed to read block at %04x" % block_addr)
+
+ if ack != CMD_ACK:
+ _exit_programming_mode(radio)
+ raise Exception("No ACK reading block %04x." % (block_addr))
+
+ return block_data
+
+
+def _write_block(radio, block_addr, block_size):
+ serial = radio.pipe
+
+ cmd = struct.pack(">cHb", 'W', block_addr, block_size)
+ data = radio.get_mmap()[block_addr:block_addr + block_size]
+
+ LOG.debug("Writing Data:")
+ LOG.debug(util.hexprint(cmd + data))
+
+ try:
+ serial.write(cmd + data)
+ if serial.read(1) != CMD_ACK:
+ raise Exception("No ACK")
+ except:
+ _exit_programming_mode(radio)
+ raise errors.RadioError("Failed to send block "
+ "to radio at %04x" % block_addr)
+
+
+def do_download(radio):
+ LOG.debug("download")
+ _enter_programming_mode(radio)
+
+ data = ""
+
+ status = chirp_common.Status()
+ status.msg = "Cloning from radio"
+
+ status.cur = 0
+ status.max = radio._memsize
+
+ for addr in range(0, radio._memsize, radio.BLOCK_SIZE):
+ status.cur = addr + radio.BLOCK_SIZE
+ radio.status_fn(status)
+
+ block = _read_block(radio, addr, radio.BLOCK_SIZE)
+ data += block
+
+ LOG.debug("Address: %04x" % addr)
+ LOG.debug(util.hexprint(block))
+
+ _exit_programming_mode(radio)
+
+ return memmap.MemoryMap(data)
+
+
+def do_upload(radio):
+ status = chirp_common.Status()
+ status.msg = "Uploading to radio"
+
+ _enter_programming_mode(radio)
+
+ status.cur = 0
+ status.max = radio._memsize
+
+ for start_addr, end_addr in radio._ranges:
+ for addr in range(start_addr, end_addr, radio.BLOCK_SIZE_UP):
+ status.cur = addr + radio.BLOCK_SIZE_UP
+ radio.status_fn(status)
+ _write_block(radio, addr, radio.BLOCK_SIZE_UP)
+
+ _exit_programming_mode(radio)
+
+
+class BFT8Radio(chirp_common.CloneModeRadio):
+ """Baofeng BF-T8"""
+ VENDOR = "Baofeng"
+ MODEL = "BF-T8"
+ BAUD_RATE = 9600
+ BLOCK_SIZE = BLOCK_SIZE_UP = 0x10
+ ODD_SPLIT = True
+ HAS_NAMES = False
+ SKIP_VALUES = []
+ DTCS_CODES = sorted(chirp_common.DTCS_CODES)
+
+ POWER_LEVELS = [chirp_common.PowerLevel("High", watts=2.00),
+ chirp_common.PowerLevel("Low", watts=0.50)]
+
+ _magic = "\x02" + "PROGRAM"
+ _fingerprint = "\x2E" + "BF-T6" + "\x2E"
+ _upper = 99
+ _frs = _upper == 22
+
+ _ranges = [
+ (0x0000, 0x0B60),
+ ]
+ _memsize = 0x0B60
+
+ def get_features(self):
+ rf = chirp_common.RadioFeatures()
+ rf.has_settings = True
+ rf.has_bank = False
+ rf.has_ctone = True
+ rf.has_cross = True
+ rf.has_rx_dtcs = True
+ rf.has_tuning_step = False
+ rf.can_odd_split = self.ODD_SPLIT
+ rf.has_name = self.HAS_NAMES
+ rf.valid_skips = self.SKIP_VALUES
+ rf.valid_tmodes = ["", "Tone", "TSQL", "DTCS", "Cross"]
+ rf.valid_cross_modes = ["Tone->Tone", "Tone->DTCS", "DTCS->Tone",
+ "->Tone", "->DTCS", "DTCS->", "DTCS->DTCS"]
+ rf.valid_dtcs_codes = self.DTCS_CODES
+ rf.valid_power_levels = self.POWER_LEVELS
+ rf.valid_duplexes = ["", "-", "+", "split", "off"]
+ rf.valid_modes = ["FM", "NFM"] # 25 kHz, 12.5 KHz.
+ rf.memory_bounds = (1, self._upper)
+ rf.valid_tuning_steps = [2.5, 5., 6.25, 10., 12.5, 25.]
+ rf.valid_bands = [(400000000, 470000000)]
+
+ return rf
+
+ def process_mmap(self):
+ self._memobj = bitwise.parse(MEM_FORMAT, self._mmap)
+
+ def validate_memory(self, mem):
+ msgs = ""
+ msgs = chirp_common.CloneModeRadio.validate_memory(self, mem)
+
+ _msg_freq = 'Memory location cannot change frequency'
+ _msg_simplex = 'Memory location only supports Duplex:(None)'
+ _msg_nfm = 'Memory location only supports Mode: NFM'
+ _msg_txp = 'Memory location only supports Power: Low'
+
+ # FRS only models
+ if self._frs:
+ # range of memories with values set by FCC rules
+ if mem.freq != int(FRS_FREQS[mem.number - 1] * 1000000):
+ # warn user can't change frequency
+ msgs.append(chirp_common.ValidationError(_msg_freq))
+
+ # channels 1 - 22 are simplex only
+ if str(mem.duplex) != "":
+ # warn user can't change duplex
+ msgs.append(chirp_common.ValidationError(_msg_simplex))
+
+ # channels 1 - 22 are NFM only
+ if str(mem.mode) != "NFM":
+ # warn user can't change mode
+ msgs.append(chirp_common.ValidationError(_msg_nfm))
+
+ # channels 8 - 14 are low power NFM only
+ if mem.number >= 8 and mem.number <= 14:
+ if str(mem.power) != "Low":
+ # warn user can't change power
+ msgs.append(chirp_common.ValidationError(_msg_txp))
+
+ return msgs
+
+ def sync_in(self):
+ """Download from radio"""
+ try:
+ data = do_download(self)
+ except errors.RadioError:
+ # Pass through any real errors we raise
+ raise
+ except:
+ # If anything unexpected happens, make sure we raise
+ # a RadioError and log the problem
+ LOG.exception('Unexpected error during download')
+ raise errors.RadioError('Unexpected error communicating '
+ 'with the radio')
+ self._mmap = data
+ self.process_mmap()
+
+ def sync_out(self):
+ """Upload to radio"""
+ try:
+ do_upload(self)
+ except:
+ # If anything unexpected happens, make sure we raise
+ # a RadioError and log the problem
+ LOG.exception('Unexpected error during upload')
+ raise errors.RadioError('Unexpected error communicating '
+ 'with the radio')
+
+ def get_raw_memory(self, number):
+ return repr(self._memobj.memory[number - 1])
+
+ def _get_tone(self, mem, _mem):
+ rx_tone = tx_tone = None
+
+ tx_tmode = TMODES[_mem.tx_tmode]
+ rx_tmode = TMODES[_mem.rx_tmode]
+
+ if tx_tmode == "Tone":
+ tx_tone = TONES[_mem.tx_tone]
+ elif tx_tmode == "DTCS":
+ tx_tone = self.DTCS_CODES[_mem.tx_tone]
+
+ if rx_tmode == "Tone":
+ rx_tone = TONES[_mem.rx_tone]
+ elif rx_tmode == "DTCS":
+ rx_tone = self.DTCS_CODES[_mem.rx_tone]
+
+ tx_pol = _mem.tx_tmode == 0x03 and "R" or "N"
+ rx_pol = _mem.rx_tmode == 0x03 and "R" or "N"
+
+ chirp_common.split_tone_decode(mem, (tx_tmode, tx_tone, tx_pol),
+ (rx_tmode, rx_tone, rx_pol))
+
+ def _get_mem(self, number):
+ return self._memobj.memory[number]
+
+ def get_memory(self, number):
+ _mem = self._get_mem(number - 1)
+
+ mem = chirp_common.Memory()
+
+ mem.number = number
+ mem.freq = int(_mem.rxfreq) * 10
+
+ # We'll consider any blank (i.e. 0MHz frequency) to be empty
+ if mem.freq == 0:
+ mem.empty = True
+ return mem
+
+ if _mem.rxfreq.get_raw() == "\xFF\xFF\xFF\xFF":
+ mem.freq = 0
+ mem.empty = True
+ mem.mode = "NFM"
+ if mem.number <= 22 and not self._frs:
+ LOG.debug("Initializing empty memory")
+ _mem.set_raw("\x00" * 13 + "\xFF" * 3)
+ FRS_FREQ = FRS_FREQS[mem.number - 1] * 1000000
+ mem.freq = FRS_FREQ
+ if mem.number >= 8 and mem.number <= 14:
+ mem.power = "Low"
+ else:
+ mem.power = "High"
+
+ return mem
+
+ if _mem.get_raw() == ("\xFF" * 16):
+ LOG.debug("Initializing empty memory")
+ _mem.set_raw("\x00" * 13 + "\xFF" * 3)
+
+ if int(_mem.rxfreq) == int(_mem.txfreq):
+ mem.duplex = ""
+ mem.offset = 0
+ else:
+ mem.duplex = int(_mem.rxfreq) > int(_mem.txfreq) and "-" or "+"
+ mem.offset = abs(int(_mem.rxfreq) - int(_mem.txfreq)) * 10
+
+ # wide/narrow
+ mem.mode = _mem.isnarrow and "NFM" or "FM"
+
+ # tone data
+ self._get_tone(mem, _mem)
+
+ # tx power
+ levels = self.POWER_LEVELS
+ try:
+ mem.power = levels[_mem.lowpower]
+ except IndexError:
+ LOG.error("Radio reported invalid power level %s (in %s)" %
+ (_mem.power, levels))
+ mem.power = levels[0]
+
+ if mem.number <= 22 and self._frs:
+ FRS_IMMUTABLE = ["freq", "duplex", "offset", "mode"]
+ if mem.number >= 8 and mem.number <= 14:
+ mem.immutable = FRS_IMMUTABLE + ["power"]
+ else:
+ mem.immutable = FRS_IMMUTABLE
+
+ return mem
+
+ def _set_tone(self, mem, _mem):
+ ((txmode, txtone, txpol),
+ (rxmode, rxtone, rxpol)) = chirp_common.split_tone_encode(mem)
+
+ _mem.tx_tmode = TMODES.index(txmode)
+ _mem.rx_tmode = TMODES.index(rxmode)
+ if txmode == "Tone":
+ _mem.tx_tone = TONES.index(txtone)
+ elif txmode == "DTCS":
+ _mem.tx_tmode = txpol == "R" and 0x03 or 0x02
+ _mem.tx_tone = self.DTCS_CODES.index(txtone)
+ if rxmode == "Tone":
+ _mem.rx_tone = TONES.index(rxtone)
+ elif rxmode == "DTCS":
+ _mem.rx_tmode = rxpol == "R" and 0x03 or 0x02
+ _mem.rx_tone = self.DTCS_CODES.index(rxtone)
+
+ def set_memory(self, mem):
+ _mem = self._get_mem(mem.number - 1)
+
+ # if empty memmory
+ if mem.empty:
+ if mem.number <= 22 and self._frs:
+ _mem.set_raw("\xFF" * 8 + "\x00" * 5 + "\xFF" * 3)
+ FRS_FREQ = int(FRS_FREQS[mem.number - 1] * 100000)
+ _mem.rxfreq = _mem.txfreq = FRS_FREQ
+ _mem.isnarrow = True
+ if mem.number >= 8 and mem.number <= 14:
+ _mem.lowpower = True
+ else:
+ _mem.lowpower = False
+ else:
+ _mem.set_raw("\xFF" * 8 + "\x00" * 4 + "\x03" + "\xFF" * 3)
+
+ return mem
+
+ _mem.set_raw("\x00" * 13 + "\xFF" * 3)
+
+ # frequency
+ _mem.rxfreq = mem.freq / 10
+
+ if mem.duplex == "off":
+ for i in range(0, 4):
+ _mem.txfreq[i].set_raw("\xFF")
+ elif mem.duplex == "split":
+ _mem.txfreq = mem.offset / 10
+ elif mem.duplex == "+":
+ _mem.txfreq = (mem.freq + mem.offset) / 10
+ elif mem.duplex == "-":
+ _mem.txfreq = (mem.freq - mem.offset) / 10
+ else:
+ _mem.txfreq = mem.freq / 10
+
+ # wide/narrow
+ _mem.isnarrow = mem.mode == "NFM"
+
+ # tone data
+ self._set_tone(mem, _mem)
+
+ # tx power
+ if mem.power:
+ _mem.lowpower = self.POWER_LEVELS.index(mem.power)
+ else:
+ _mem.lowpower = 0
+
+ return mem
+
+ def get_settings(self):
+ _settings = self._memobj.settings
+ basic = RadioSettingGroup("basic", "Basic Settings")
+ top = RadioSettings(basic)
+
+ # Menu 03
+ rs = RadioSettingValueInteger(0, 9, _settings.squelch)
+ rset = RadioSetting("squelch", "Squelch Level", rs)
+ basic.append(rset)
+
+ # Menu 11
+ rs = RadioSettingValueList(TOT_LIST, TOT_LIST[_settings.tot])
+ rset = RadioSetting("tot", "Time-out timer", rs)
+ basic.append(rset)
+
+ # Menu 06
+ rs = RadioSettingValueList(VOX_LIST, VOX_LIST[_settings.vox])
+ rset = RadioSetting("vox", "VOX Level", rs)
+ basic.append(rset)
+
+ # Menu 15 (BF-T8)
+ rs = RadioSettingValueList(VOICE_LIST, VOICE_LIST[_settings.voice])
+ rset = RadioSetting("voice", "Voice", rs)
+ basic.append(rset)
+
+ # Menu 12
+ rs = RadioSettingValueBoolean(_settings.bcl)
+ rset = RadioSetting("bcl", "Busy Channel Lockout", rs)
+ basic.append(rset)
+
+ # Menu 10
+ rs = RadioSettingValueBoolean(_settings.save)
+ rset = RadioSetting("save", "Battery Saver", rs)
+ basic.append(rset)
+
+ # Menu 08
+ rs = RadioSettingValueBoolean(_settings.tdr)
+ rset = RadioSetting("tdr", "Dual Watch", rs)
+ basic.append(rset)
+
+ # Menu 05
+ rs = RadioSettingValueBoolean(_settings.beep)
+ rset = RadioSetting("beep", "Beep", rs)
+ basic.append(rset)
+
+ # Menu 04
+ rs = RadioSettingValueList(ABR_LIST, ABR_LIST[_settings.abr])
+ rset = RadioSetting("abr", "Back Light", rs)
+ basic.append(rset)
+
+ # Menu 13
+ rs = RadioSettingValueList(RING_LIST, RING_LIST[_settings.ring])
+ rset = RadioSetting("ring", "Ring", rs)
+ basic.append(rset)
+
+ rs = RadioSettingValueBoolean(not _settings.ste)
+ rset = RadioSetting("ste", "Squelch Tail Eliminate", rs)
+ basic.append(rset)
+
+ #
+
+ rs = RadioSettingValueInteger(1, self._upper, _settings.mra)
+ rset = RadioSetting("mra", "MR A Channel #", rs)
+ basic.append(rset)
+
+ rs = RadioSettingValueInteger(1, self._upper, _settings.mrb)
+ rset = RadioSetting("mrb", "MR B Channel #", rs)
+ basic.append(rset)
+
+ rs = RadioSettingValueList(AB_LIST, AB_LIST[_settings.disp_ab])
+ rset = RadioSetting("disp_ab", "Selected Display Line", rs)
+ basic.append(rset)
+
+ rs = RadioSettingValueList(WX_LIST, WX_LIST[_settings.wx])
+ rset = RadioSetting("wx", "NOAA WX Radio", rs)
+ basic.append(rset)
+
+ def myset_freq(setting, obj, atrb, mult):
+ """ Callback to set frequency by applying multiplier"""
+ value = int(float(str(setting.value)) * mult)
+ setattr(obj, atrb, value)
+ return
+
+ # FM Broadcast Settings
+ val = _settings.fmcur
+ val = val / 10.0
+ val_low = 76.0
+ if val < val_low or val > 108.0:
+ val = 90.4
+ rx = RadioSettingValueFloat(val_low, 108.0, val, 0.1, 1)
+ rset = RadioSetting("settings.fmcur", "Broadcast FM Radio (MHz)", rx)
+ rset.set_apply_callback(myset_freq, _settings, "fmcur", 10)
+ basic.append(rset)
+
+ rs = RadioSettingValueList(WORKMODE_LIST,
+ WORKMODE_LIST[_settings.workmode])
+ rset = RadioSetting("workmode", "Work Mode", rs)
+ basic.append(rset)
+
+ rs = RadioSettingValueList(AREA_LIST, AREA_LIST[_settings.area])
+ rs.set_mutable(False)
+ rset = RadioSetting("area", "Area", rs)
+ basic.append(rset)
+
+ return top
+
+ def set_settings(self, settings):
+ for element in settings:
+ if not isinstance(element, RadioSetting):
+ self.set_settings(element)
+ continue
+ else:
+ try:
+ if "." in element.get_name():
+ bits = element.get_name().split(".")
+ obj = self._memobj
+ for bit in bits[:-1]:
+ obj = getattr(obj, bit)
+ setting = bits[-1]
+ else:
+ obj = self._memobj.settings
+ setting = element.get_name()
+
+ if element.has_apply_callback():
+ LOG.debug("Using apply callback")
+ element.run_apply_callback()
+ elif setting == "ste":
+ setattr(obj, setting, not int(element.value))
+ elif element.value.get_mutable():
+ LOG.debug("Setting %s = %s" % (setting, element.value))
+ setattr(obj, setting, element.value)
+ except Exception, e:
+ LOG.debug(element.get_name())
+ raise
+
+ @classmethod
+ def match_model(cls, filedata, filename):
+ # This radio has always been post-metadata, so never do
+ # old-school detection
+ return False
+
+
+class BFU9Alias(chirp_common.Alias):
+ VENDOR = "Baofeng"
+ MODEL = "BF-U9"
+
+
+class AR8Alias(chirp_common.Alias):
+ VENDOR = "Arcshell"
+ MODEL = "AR-8"
+
+
+(a)directory.register
+class BaofengBFT8Generic(BFT8Radio):
+ ALIASES = [BFU9Alias, AR8Alias, ]
diff -r b04ba05b7b64 -r ccf8f96034cd tools/cpep8.manifest
--- a/tools/cpep8.manifest Wed Apr 28 07:50:34 2021 -0700
+++ b/tools/cpep8.manifest Wed May 19 20:58:53 2021 -0400
@@ -19,6 +19,7 @@
./chirp/drivers/baofeng_common.py
./chirp/drivers/baofeng_uv3r.py
./chirp/drivers/baofeng_wp970i.py
+./chirp/drivers/bf-t8.py
./chirp/drivers/bjuv55.py
./chirp/drivers/btech.py
./chirp/drivers/ft1500m.py
1
0
[chirp_devel] Developer setup on Ubuntu 20.04 (python3/2 issue)
by Pavel Milanes Costa (CO7WT) 11 May '21
by Pavel Milanes Costa (CO7WT) 11 May '21
11 May '21
Hi!
I was wondering if any of you have setup a dev environment to develop
Chirp on Ubuntu 20.04?
On the table I have a few options:
* Virtual machine with Ubuntu 18.04 (I'm here now)
* LXD with display export feature (LXC won't work, I was experimenting
this way, all thing point that with LXD it's possible)
* Docker with display export
* Other?
I would like to hear if any of you have found/test another "easy/simple"
solution.
Cheers Pavel.
3
3