Developers
Threads by month
- ----- 2025 -----
- May
- April
- March
- February
- January
- ----- 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
- 3 participants
- 2972 discussions

[chirp_devel] Fwd: [PATCH] [RT98] Add support for Retevis RT98 Single Band Mini Mobile Radios
by Jim Unroe 03 Jul '21
by Jim Unroe 03 Jul '21
03 Jul '21
Second try...
---------- Forwarded message ---------
From: Jim Unroe <kc9hi(a)comcast.net>
Date: Sat, Jul 3, 2021 at 2:25 PM
Subject: [PATCH] [RT98] Add support for Retevis RT98 Single Band Mini
Mobile Radios
To: <Rock.Unroe(a)gmail.com>
# HG changeset patch
# User Jim Unroe <rock.unroe(a)gmail.com>
# Date 1625336015 14400
# Sat Jul 03 14:13:35 2021 -0400
# Node ID 0eab8146b294ef686ca4a49c17ea38abde54c7ab
# Parent f586574bc8786fd6bef1e5d54d08d381c81edd47
[RT98] Add support for Retevis RT98 Single Band Mini Mobile Radios
This patch adds support for the various Retevis RT98 mobile radio
models/modes.
VHF FreeNet
VHF COM
VHF COMII
UHF PMR
UHF COM
UHF COMII
#9181
diff -r f586574bc878 -r 0eab8146b294 chirp/drivers/retevis_rt98.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/chirp/drivers/retevis_rt98.py Sat Jul 03 14:13:35 2021 -0400
@@ -0,0 +1,1364 @@
+# 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 os
+import struct
+import time
+import logging
+
+from chirp import bitwise
+from chirp import chirp_common
+from chirp import directory
+from chirp import errors
+from chirp import memmap
+from chirp import util
+from chirp.settings import RadioSettingGroup, RadioSetting, RadioSettings,
\
+ RadioSettingValueList, RadioSettingValueString,
RadioSettingValueBoolean, \
+ RadioSettingValueInteger, RadioSettingValueString, \
+ RadioSettingValueFloat, InvalidValueError
+
+LOG = logging.getLogger(__name__)
+
+#
+# Chirp Driver for Retevis RT98 models: RT98V (136-174 Mhz)
+# RT98U (400-490 Mhz)
+#
+#
+#
+# Global Parameters
+#
+TONES = [62.5] + list(chirp_common.TONES)
+TMODES = ['', 'Tone', 'DTCS']
+DUPLEXES = ['', '+', '-']
+
+TXPOWER_LOW = 0x00
+TXPOWER_MED = 0x01
+TXPOWER_HIGH = 0x02
+
+DUPLEX_NOSPLIT = 0x00
+DUPLEX_POSSPLIT = 0x01
+DUPLEX_NEGSPLIT = 0x02
+
+CHANNEL_WIDTH_12d5kHz = 0x00
+CHANNEL_WIDTH_20kHz = 0x01
+CHANNEL_WIDTH_25kHz = 0x02
+
+TUNING_STEPS = [2.5, 5.0, 6.25, 10.0, 12.5, 20.0, 25.0, 30.0, 50.0]
+
+POWER_LEVELS = [chirp_common.PowerLevel("Low", watts=5),
+ chirp_common.PowerLevel("Mid", watts=10),
+ chirp_common.PowerLevel("High", watts=15)]
+
+PMR_POWER_LEVELS = [chirp_common.PowerLevel("Low", watts=0.5), ]
+
+FREENET_POWER_LEVELS = [chirp_common.PowerLevel("Low", watts=1), ]
+
+PMR_FREQS = [446.00625, 446.01875, 446.03125, 446.04375,
+ 446.05625, 446.06875, 446.08125, 446.09375,
+ 446.10625, 446.11875, 446.13125, 446.14375,
+ 446.15625, 446.16875, 446.18125, 446.19375]
+
+FREENET_FREQS = [149.02500, 149.03750, 149.05000,
+ 149.08750, 149.10000, 149.11250]
+
+CROSS_MODES = ["Tone->Tone", "DTCS->", "->DTCS", "Tone->DTCS",
"DTCS->Tone",
+ "->Tone", "DTCS->DTCS"]
+
+LIST_STEP = [str(x) for x in TUNING_STEPS]
+LIST_TIMEOUT = ["Off"] + ["%s min" % x for x in range(1, 31)]
+LIST_APO = ["Off", "30 min", "1 hr", "2 hrs"]
+LIST_SQUELCH = ["Off"] + ["Level %s" % x for x in range(1, 10)]
+LIST_DISPLAY_MODE = ["Channel", "Frequency", "Name"]
+LIST_AOP = ["Manual", "Auto"]
+LIST_STE_TYPE = ["Off", "Silent", "120 Degree", "180 Degree", "240 Degree"]
+LIST_STE_FREQ = ["Off", "55.2 Hz", "259.2 Hz"]
+
+LIST_PRIORITY_CH = ["Off", "Priority Channel 1", "Priority Channel 2",
+ "Priority Channel 1 + Priority Channel 2"]
+
+LIST_REVERT_CH = ["Selected", "Selected + TalkBack", "Priority Channel 1",
+ "Priority Channel 2", "Last Called", "Last Used",
+ "Priority Channel 1 + TalkBack",
+ "Priority Channel 2 + TalkBack"]
+
+LIST_TIME50 = ["0.1", "0.2", "0.3", "0.4", "0.5",
+ "0.6", "0.7", "0.8", "0.9", "1.0",
+ "1.1", "1.2", "1.3", "1.4", "1.5",
+ "1.6", "1.7", "1.8", "1.9", "2.0",
+ "2.1", "3.2", "2.3", "2.4", "2.5",
+ "2.6", "2.7", "2.8", "2.9", "3.0",
+ "3.1", "3.2", "3.3", "3.4", "3.5",
+ "3.6", "3.7", "3.8", "3.9", "4.0",
+ "4.1", "4.2", "4.3", "4.4", "4.5",
+ "4.6", "4.7", "4.8", "4.9", "5.0"]
+LIST_TIME46 = LIST_TIME50[4:]
+
+LIST_RT98V_MODES = ["FreeNet", "COM", "COMII"]
+LIST_RT98U_MODES = ["PMR", "COM", "COMII"]
+
+LIST_RT98V_FREQS = ["Rx(149 - 149.2 MHz) Tx(149 - 149.2 MHz)",
+ "Rx(136 - 174 MHz) Tx(136 - 174 MHz)",
+ "Rx(147 - 174 MHz) Tx(147 - 174 MHz)"]
+
+LIST_RT98U_FREQS = ["Rx(446 - 446.2 MHz) Tx(446 - 446.2 MHz)",
+ "Rx(400 - 470 MHz) Tx(400 - 470 MHz)",
+ "Rx(450 - 470 MHz) Tx(450 - 470 MHz)"]
+
+SETTING_LISTS = {
+ "tuning_step": LIST_STEP,
+ "timeout_timer": LIST_TIMEOUT,
+ "auto_power_off": LIST_APO,
+ "squelch": LIST_SQUELCH,
+ "display_mode": LIST_DISPLAY_MODE,
+ "auto_power_on": LIST_AOP,
+ "ste_type": LIST_STE_TYPE,
+ "ste_frequency": LIST_STE_FREQ,
+ "priority_ch": LIST_PRIORITY_CH,
+ "revert_ch": LIST_REVERT_CH,
+ "settings2.dropout_delay_time": LIST_TIME50,
+ "settings2.dwell_time": LIST_TIME50,
+ "settings2.look_back_time_a": LIST_TIME46,
+ "settings2.look_back_time_b": LIST_TIME46
+}
+
+# RT98 memory map
+# section: 1 Channel Bank
+# description of channel bank (199 channels , range 1-199)
+# Each 32 Byte (0x20 hex) record:
+# bytes:bit type description
+#
---------------------------------------------------------------------------
+# 4 bbcd freq[4] receive frequency in packed binary coded
+# decimal
+# 4 bbcd offset[4] transceive offset in packed binary coded
+# decimal (note: +/- direction set by
+# 'duplex' field)
+# 1 u8 unknown0
+# 1 u8
+# :1 reverse:1 reverse flag, 0=off, 1=on (reverses
+# transmit and receive freqencies)
+# :1 txoff:1 transmitt off flag, 0=transmit, 1=do not
+# transmit
+# :2 power:2 transmit power setting, value range 0-2,
+# 0=low, 1=middle, 2=high
+# :2 duplex:2 duplex settings, 0=simplex, 1=plus (+)
+# offset, 2=minus(-) offset (see offset
field)
+# :2 channel_width:2 channel spacing, 0=12.5kHz, 1=20kHz,
2=25kHz
+# 1 u8
+# :2 unknown1:2
+# :1 talkaround:1 talkaround flag, 0=off, 1=on
+# (bypasses repeater)
+# :1 squelch_mode:1 squelch mode flag, 0=carrier,
1=ctcss/dcs
+# :1 rxdcsextra:1 use with rxcode for index of rx DCS to
use
+# :1 rxinv:1 inverse DCS rx polarity flag, 0=N, 1=I
+# :1 txdcsextra:1 use with txcode for index of tx DCS to
use
+# :1 txinv:1 inverse DCS tx polarity flag, 0=N, 1=I
+# 1 u8
+# :4 unknown2:4
+# :2 rxtmode:2 rx tone mode, value range 0-2, 0=none,
+# 1=CTCSS, 2=DCS (ctcss tone in field
rxtone)
+# :2 txtmode:2 tx tone mode, value range 0-2, 0=none,
+# 1=CTCSS, 3=DCS (ctcss tone in field
txtone)
+# 1 u8
+# :2 unknown3:2
+# :6 txtone:6 tx ctcss tone, menu index
+# 1 u8
+# :2 unknown4:2
+# :6 rxtone:6 rx ctcss tone, menu index
+# 1 u8 txcode ?, not used for ctcss
+# 1 u8 rxcode ?, not used for ctcss
+# 1 u8
+# :6 unknown5:6
+# :1 busychannellockout:1 busy channel lockout flag, 0=off,
1=enabled
+# :1 unknown6:1
+# 6 char name[6] 6 byte char string for channel name
+# 9 u8 unknown7[9]
+#
+MEM_FORMAT = """
+#seekto 0x0000;
+struct {
+ bbcd freq[4];
+ bbcd offset[4];
+ u8 unknown0;
+ u8 reverse:1,
+ tx_off:1,
+ txpower:2,
+ duplex:2,
+ channel_width:2;
+ u8 unknown1:2,
+ talkaround:1,
+ squelch_mode:1,
+ rxdcsextra:1,
+ rxinv:1,
+ txdcsextra:1,
+ txinv:1;
+ u8 unknown2:4,
+ rxtmode:2,
+ txtmode:2;
+ u8 unknown3:2,
+ txtone:6;
+ u8 unknown4:2,
+ rxtone:6;
+ u8 txcode;
+ u8 rxcode;
+ u8 unknown5:6,
+ busychannellockout:1,
+ unknown6:1;
+ char name[6];
+ u8 unknown7[9];
+} memory[199];
+"""
+
+# RT98 memory map
+# section: 2 and 3 Channel Set/Skip Flags
+#
+# Channel Set (starts 0x3240) : Channel Set bit is value 0 if a memory
+# location in the channel bank is active.
+# Channel Skip (starts 0x3260): Channel Skip bit is value 0 if a memory
+# location in the channel bank is active.
+#
+# Both flag maps are a total 24 bytes in length, aligned on 32 byte
records.
+# bit = 0 channel not set/skip, 1 is channel set/no skip
+#
+# to index a channel:
+# cbyte = channel / 8 ;
+# cbit = channel % 8 ;
+# setflag = csetflag[cbyte].c[cbit] ;
+# skipflag = cskipflag[cbyte].c[cbit] ;
+#
+# channel range is 1-199, range is 32 bytes (last 7 unknown)
+#
+MEM_FORMAT = MEM_FORMAT + """
+#seekto 0x3240;
+struct {
+ bit c[8];
+} csetflag[32];
+
+#seekto 0x3260;
+struct {
+ bit c[8];
+} cskipflag[32];
+
+"""
+
+# RT98 memory map
+# section: 4 Startup Label
+#
+# bytes:bit type description
+#
---------------------------------------------------------------------------
+# 6 char start_label[6] label displayed at startup (usually
+# your call sign)
+#
+MEM_FORMAT = MEM_FORMAT + """
+#seekto 0x3300;
+struct {
+ char startname[6];
+} slabel;
+"""
+
+# RT98 memory map
+# section: 5, 6 and 7 Radio Options
+# used to set a number of radio options
+#
+# description of function setup options, starting at 0x3310 (settings3)
+#
+# bytes:bit type description
+#
---------------------------------------------------------------------------
+# 1 u8
+# :6 unknown:6
+# :2 bandlimit_3310:2 frequency ranges, range 0-2,
+# 0=freenet(vhf) or pmr(uhf), 1=com,
2=comii
+# rt98v - 00 FreeNet Rx(149 - 149.2 MHz) Tx(149 - 149.2
MHz)
+# 01 COM Rx(136 - 174 MHz) Tx(136 - 174 MHz)
+# 02 COMII Rx(147 - 174 MHz) Tx(147 - 174 MHz)
+# rt98u - 00 PMR Rx(446 - 446.2 MHz) Tx(446 - 446.2
MHz)
+# 01 COM Rx(400 - 470 MHz) Tx(400 - 470 MHz)
+# 02 COMII Rx(450 - 470 MHz) Tx(450 - 470 MHz)
+# 1 u8 ch_number; channel number, range 1-199
+#
+# description of function setup options, starting at 0x3340 (settings)
+#
+# bytes:bit type description
+#
---------------------------------------------------------------------------
+# 1 u8
+# :4 unknown_3340:4
+# :4 tuning_step:4 tuning step, menu index value from 0-8
+# 2.5, 5, 6.25, 10, 12.5, 20, 25, 30, 50
+# 1 u8
+# :7 unknown_3341:7
+# :1 beep:1 beep mode, range 0-1, 0=off, 1=on
+# 1 u8
+# :3 unknown_3342:3
+# :5 timeout_timer:5 timeout timer, range off (no timeout),
+# 1-30 minutes
+# 1 u8
+# :6 unknown_3343:6
+# :2 auto_power_off:2 auto power off, range 0-3, off, 30min,
+# 1hr, 2hr
+# 1 u8
+# :4 unknown_3344:4
+# :4 squelch:4 squelch level, range off, 1-9
+# 1 u8
+# :3 unknown_3345:3
+# :5 volume:5 volume level, range 1-30 (no zero)
+# 1 u8 unknown_3346
+# 1 u8 unknown_3347
+# 1 u8 0x3348 [12]
+# :6 unknown_3348:6
+# :2 display_mode display mode, range 0-2, 0=channel,
+# 1=frequency, 2=name
+# 1 u8
+# :7 unknown_3349:7
+# :1 auto_power_on:1 auto power on, range 0-1, 0=manual,
+# 1=auto
+# 1 u8
+# :3 unknown_334A:3
+# :5 mic_gain:5 mic gain, range 1-30 (no zero)
+# 1 u8
+# :5 unknown_334C:5
+# :3 ste_type:3 ste type, range 0-4, 0=off, 1=silent,
+# 2=120degree, 3=180degree, 4=240degree
+# 1 u8
+# :7 unknown_334D:7
+# :1 ste_frequency:1 ste frequency, range 0-2, 0=off,
+# 1=55.2Hz, 2=259.2Hz
+# 1 u8
+# :2 unknown_0x334E:2
+# :1 forbid_setting:1 forbid setting(optional function),
+# range 0-1, 0=disabled, 1=enabled
+# :1 forbid_initialize:1 forbid initialize operate, range 0-1,
+# 0=enabled, 1=disabled (inverted)
+# :1 save_chan_param:1 save channel parameters, range 0-1,
+# 0=disabled, 1=enabled
+# :1 forbid_chan_menu:1 forbid channel menu, range 0-1,
+# 0=disabled, 1=enabled
+# :1 sql_key_function:1 sql key function, range 0-1,
+# 0=squelch off momentary, 1=squelch off
+# :1 unknown:1
+#
+# description of function setup options, starting at 0x3380 (settings2)
+#
+# bytes:bit type description
+#
---------------------------------------------------------------------------
+# 1 u8
+# :7 unknown_3380:7
+# :1 scan_mode:1 scan mode, range 0-1, 0=off, 1=on
+# 1 u8
+# :6 unknown_3381:6
+# :2 priority_ch:2 priority channel, range 0-3, 0=off,
+# 1=priority channel 1,
+# 2=priority channel 2,
+# 3=priority channel 1 + priority
channel 2
+# 1 u8 priority_ch1 priority channel 1 number, range 1-199
+# 1 u8 priority_ch2 priority channel 2 number, range 1-199
+# 1 u8
+# :4 unknown_3384:4
+# :4 revert_ch:4 revert channel, range 0-3, 0=selected,
+# 1=selected + talkback, 2=last called,
+# 3=last used
+# 1 u8 look_back_time_a look back time a, range 0-45
+# 1 u8 look_back_time_b look back time b, range 0-45
+# 1 u8 dropout_delay_time dropout delay time, range 0-49
+# 1 u8 dwell_time dwell time, range 0-49
+#
+MEM_FORMAT = MEM_FORMAT + """
+#seekto 0x3310;
+struct {
+ u8 bandlimit;
+ u8 ch_number;
+} settings3;
+"""
+
+MEM_FORMAT = MEM_FORMAT + """
+#seekto 0x3340;
+struct {
+ u8 unknown_3340:4,
+ tuning_step:4;
+ u8 unknown_3341:7,
+ beep:1;
+ u8 unknown_3342:3,
+ timeout_timer:5;
+ u8 unknown_3343:6,
+ auto_power_off:2;
+ u8 unknown_3344:4,
+ squelch:4;
+ u8 unknown_3345:3,
+ volume:5;
+ u8 unknown_3346;
+ u8 unknown_3347;
+ u8 unknown_3348:6,
+ display_mode:2;
+ u8 unknown_3349:7,
+ auto_power_on:1;
+ u8 unknown_334A:3,
+ mic_gain:5;
+ u8 unknown_334B;
+ u8 unknown_334C:5,
+ ste_type:3;
+ u8 unknown_334D:6,
+ ste_frequency:2;
+ u8 unknown_334E:1,
+ forbid_setting:1,
+ unknown1:1,
+ forbid_initialize:1,
+ save_chan_param:1,
+ forbid_chan_menu:1,
+ sql_key_function:1,
+ unknown2:1;
+} settings;
+"""
+
+MEM_FORMAT = MEM_FORMAT + """
+#seekto 0x3380;
+struct {
+ u8 unknown_3380:7,
+ scan_mode:1;
+ u8 unknown_3381:6,
+ priority_ch:2;
+ u8 priority_ch1;
+ u8 priority_ch2;
+ u8 unknown_3384:4,
+ revert_ch:4;
+ u8 look_back_time_a;
+ u8 look_back_time_b;
+ u8 dropout_delay_time;
+ u8 dwell_time;
+} settings2;
+"""
+
+# RT98 memory map
+# section: 8 Embedded Messages
+#
+# bytes:bit type description
+#
---------------------------------------------------------------------------
+# 6 char radio_type[5] radio type, vhf=rt98v, uhf=rt98u
+# 2 u8 unknown1[2]
+# 4 char mcu_version[4] mcu version, [x.xx]
+# 2 u8 unknown2[2]
+# 1 u8 mode rt98u mode: 0=pmr, 1=com, 2=comii
+# rt98v mode: 0=freenet, 1=com, 2=comii
+# 1 u8 unknown3
+# 10 u8 unused1[10]
+# 4 u8 unknown4[4]
+# 3 u8 unused2[3]
+# 16 u8 unknown5[16]
+# 10 char date_mfg[16] date manufactured, [yyyy-mm-dd]
+#
+MEM_FORMAT = MEM_FORMAT + """
+#seekto 0x3D00;
+struct {
+char radio_type[5];
+u8 unknown1[2];
+char mcu_version[4];
+u8 unknown2[2];
+u8 mode;
+u8 unknown3;
+u8 unused1[10];
+u8 unknown4[4];
+u8 unused2[3];
+u8 unknown5[16];
+char date_mfg[10];
+} embedded_msg;
+"""
+
+
+# Format for the version messages returned by the radio
+VER_FORMAT = '''
+u8 hdr;
+char model[5];
+u8 unknown[2];
+u8 bandlimit;
+char version[6];
+u8 ack;
+'''
+
+
+# Radio supports upper case and symbols
+CHARSET_ASCII_PLUS = chirp_common.CHARSET_UPPER_NUMERIC + '- '
+
+# Band limits as defined by the band byte in ver_response, defined in Hz,
for
+# VHF and UHF, used for RX and TX.
+RT98V_BAND_LIMITS = {0x00: [(149000000, 149200000)],
+ 0x01: [(136000000, 174000000)],
+ 0x02: [(147000000, 174000000)]}
+
+RT98U_BAND_LIMITS = {0x00: [(446000000, 446200000)],
+ 0x01: [(400000000, 470000000)],
+ 0x02: [(450000000, 470000000)]}
+
+
+# Get band limits from a band limit value
+def get_band_limits_Hz(radio_type, limit_value):
+ if radio_type == "RT98U":
+ if limit_value not in RT98U_BAND_LIMITS:
+ limit_value = 0x01
+ LOG.warning('Unknown band limit value 0x%02x, default to 0x01')
+ bandlimitfrequencies = RT98U_BAND_LIMITS[limit_value]
+ elif radio_type == "RT98V":
+ if limit_value not in RT98V_BAND_LIMITS:
+ limit_value = 0x01
+ LOG.warning('Unknown band limit value 0x%02x, default to 0x01')
+ bandlimitfrequencies = RT98V_BAND_LIMITS[limit_value]
+ return bandlimitfrequencies
+
+
+def _echo_write(radio, data):
+ try:
+ radio.pipe.write(data)
+ radio.pipe.read(len(data))
+ except Exception, e:
+ LOG.error("Error writing to radio: %s" % e)
+ raise errors.RadioError("Unable to write to radio")
+
+
+def _checksum(data):
+ cs = 0
+ for byte in data:
+ cs += ord(byte)
+ return cs % 256
+
+
+def _read(radio, length):
+ try:
+ data = radio.pipe.read(length)
+ except Exception, e:
+ _finish(radio)
+ LOG.error("Error reading from radio: %s" % e)
+ raise errors.RadioError("Unable to read from radio")
+
+ if len(data) != length:
+ _finish(radio)
+ LOG.error("Short read from radio (%i, expected %i)" %
+ (len(data), length))
+ LOG.debug(util.hexprint(data))
+ raise errors.RadioError("Short read from radio")
+ return data
+
+
+# strip trailing 0x00 to convert a string returned by bitwise.parse into a
+# python string
+def cstring_to_py_string(cstring):
+ return "".join(c for c in cstring if c != '\x00')
+
+
+# Check the radio version reported to see if it's one we support,
+# returns bool version supported, and the band index
+def check_ver(ver_response, allowed_types):
+ ''' Check the returned radio version is one we approve of '''
+
+ LOG.debug('ver_response = ')
+ LOG.debug(util.hexprint(ver_response))
+
+ resp = bitwise.parse(VER_FORMAT, ver_response)
+ verok = False
+
+ if resp.hdr == 0x49 and resp.ack == 0x06:
+ model, version =
[cstring_to_py_string(bitwise.get_string(s)).strip()
+ for s in (resp.model, resp.version)]
+ LOG.debug('radio model: \'%s\' version: \'%s\'' %
+ (model, version))
+ LOG.debug('allowed_types = %s' % allowed_types)
+
+ if model in allowed_types:
+ LOG.debug('model in allowed_types')
+
+ if version in allowed_types[model]:
+ LOG.debug('version in allowed_types[model]')
+ verok = True
+ else:
+ _finish(radio)
+ raise errors.RadioError('Failed to parse version response')
+
+ return verok, str(resp.model), int(resp.bandlimit)
+
+
+def _ident(radio):
+ radio.pipe.timeout = 1
+ _echo_write(radio, "PROGRAM")
+ response = radio.pipe.read(3)
+ if response != "QX\06":
+ _finish(radio)
+ LOG.debug("Response was :\n%s" % util.hexprint(response))
+ raise errors.RadioError("Radio did not respond. Check connection.")
+ _echo_write(radio, "\x02")
+ ver_response = radio.pipe.read(16)
+ LOG.debug(util.hexprint(ver_response))
+
+ verok, model, bandlimit = check_ver(ver_response,
+ radio.ALLOWED_RADIO_TYPES)
+ if not verok:
+ _finish(radio)
+ raise errors.RadioError(
+ 'Radio version not in allowed list for %s-%s: %s' %
+ (radio.VENDOR, radio.MODEL, util.hexprint(ver_response)))
+
+ return model, bandlimit
+
+
+def _send(radio, cmd, addr, length, data=None):
+ frame = struct.pack(">cHb", cmd, addr, length)
+ if data:
+ frame += data
+ frame += chr(_checksum(frame[1:]))
+ frame += "\x06"
+ _echo_write(radio, frame)
+ LOG.debug("Sent:\n%s" % util.hexprint(frame))
+ if data:
+ result = radio.pipe.read(1)
+ if result != "\x06":
+ _finish(radio)
+ LOG.debug("Ack was: %s" % repr(result))
+ raise errors.RadioError("Radio did not accept block at %04x"
+ % addr)
+ return
+ result = _read(radio, length + 6)
+ LOG.debug("Got:\n%s" % util.hexprint(result))
+ header = result[0:4]
+ data = result[4:-2]
+ ack = result[-1]
+ if ack != "\x06":
+ _finish(radio)
+ LOG.debug("Ack was: %s" % repr(ack))
+ raise errors.RadioError("Radio NAK'd block at %04x" % addr)
+ _cmd, _addr, _length = struct.unpack(">cHb", header)
+ if _addr != addr or _length != _length:
+ _finish(radio)
+ LOG.debug("Expected/Received:")
+ LOG.debug(" Length: %02x/%02x" % (length, _length))
+ LOG.debug(" Addr: %04x/%04x" % (addr, _addr))
+ raise errors.RadioError("Radio send unexpected block")
+ cs = _checksum(result[1:-2])
+ if cs != ord(result[-2]):
+ _finish(radio)
+ LOG.debug("Calculated: %02x" % cs)
+ LOG.debug("Actual: %02x" % ord(result[-2]))
+ raise errors.RadioError("Block at 0x%04x failed checksum" % addr)
+ return data
+
+
+def _finish(radio):
+ endframe = "\x45\x4E\x44"
+ _echo_write(radio, endframe)
+ result = radio.pipe.read(1)
+ if result != "\x06":
+ LOG.error("Got:\n%s" % util.hexprint(result))
+ raise errors.RadioError("Radio did not finish cleanly")
+
+
+def do_download(radio):
+
+ _ident(radio)
+
+ _memobj = None
+ data = ""
+
+ for addr in range(0, radio._memsize, 0x10):
+ block = _send(radio, 'R', addr, 0x10)
+ data += block
+ status = chirp_common.Status()
+ status.cur = len(data)
+ status.max = radio._memsize
+ status.msg = "Downloading from radio"
+ radio.status_fn(status)
+
+ _finish(radio)
+
+ return memmap.MemoryMap(data)
+
+
+def do_upload(radio):
+ model, bandlimit = _ident(radio)
+ _embedded = radio._memobj.embedded_msg
+
+ if model != str(_embedded.radio_type):
+ LOG.warning('radio and image model types differ')
+ LOG.warning('model type (radio): %s' % str(model))
+ LOG.warning('model type (image): %s' % str(_embedded.radio_type))
+
+ _finish(radio)
+
+ msg = ("The upload was stopped because the radio type "
+ "of the image (%s) does not match that "
+ "of the radio (%s).")
+ raise errors.RadioError(msg % (str(_embedded.radio_type),
str(model)))
+
+ if bandlimit != int(_embedded.mode):
+ if str(_embedded.radio_type) == "RT98U":
+ image_band_limits = LIST_RT98U_FREQS[int(_embedded.mode)]
+ if str(_embedded.radio_type) == "RT98V":
+ image_band_limits = LIST_RT98V_FREQS[int(_embedded.mode)]
+ if model == "RT98U":
+ radio_band_limits = LIST_RT98U_FREQS[int(bandlimit)]
+ if model == "RT98V":
+ radio_band_limits = LIST_RT98V_FREQS[int(bandlimit)]
+
+ LOG.warning('radio and image band limits differ')
+ LOG.warning('image band limits: %s' % image_band_limits)
+ LOG.warning('radio band limits: %s' % radio_band_limits)
+
+ _finish(radio)
+
+ msg = ("The upload was stopped because the band limits "
+ "of the image (%s) does not match that "
+ "of the radio (%s).")
+ raise errors.RadioError(msg % (image_band_limits,
radio_band_limits))
+
+ try:
+ for start, end in radio._ranges:
+ for addr in range(start, end, 0x10):
+ block = radio._mmap[addr:addr+0x10]
+ _send(radio, 'W', addr, len(block), block)
+ status = chirp_common.Status()
+ status.cur = addr
+ status.max = end
+ status.msg = "Uploading to Radio"
+ radio.status_fn(status)
+ _finish(radio)
+ except errors.RadioError:
+ raise
+ except Exception as e:
+ _finish(radio)
+ raise errors.RadioError('Failed to upload to radio: %s' % e)
+
+
+#
+# The base class, extended for use with other models
+#
+class Rt98BaseRadio(chirp_common.CloneModeRadio,
+ chirp_common.ExperimentalRadio):
+ """Retevis RT98 Base"""
+ VENDOR = "Retevis"
+ MODEL = "RT98 Base"
+ BAUD_RATE = 9600
+
+ _memsize = 0x3E00
+ _ranges = [(0x0000, 0x3310),
+ (0x3320, 0x3390)]
+
+ @classmethod
+ def get_prompts(cls):
+ rp = chirp_common.RadioPrompts()
+ rp.experimental = ("The Retevis RT98 driver is an beta version."
+ "Proceed with Caution and backup your data")
+ return rp
+
+ def get_features(self):
+ _embedded = self._memobj.embedded_msg
+ rf = chirp_common.RadioFeatures()
+ rf.has_settings = True
+ rf.has_bank = False
+ rf.can_odd_split = True
+ rf.has_name = True
+ if _embedded.mode == 0: # PMR or FreeNet
+ rf.has_offset = False
+ else:
+ rf.has_offset = True
+ rf.has_ctone = True
+ rf.has_cross = True
+ rf.has_tuning_step = False
+ rf.has_dtcs = True
+ rf.has_rx_dtcs = True
+ rf.has_dtcs_polarity = True
+ rf.valid_skips = ["", "S"]
+ rf.memory_bounds = (1, 199)
+ rf.valid_name_length = 6
+ if _embedded.mode == 0: # PMR or FreeNet
+ rf.valid_duplexes = ['']
+ else:
+ rf.valid_duplexes = DUPLEXES + ['split', 'off']
+ rf.valid_characters = chirp_common.CHARSET_UPPER_NUMERIC + "- "
+ if _embedded.mode == 0: # PMR or FreeNet
+ rf.valid_modes = ['NFM']
+ else:
+ rf.valid_modes = ['FM', 'NFM']
+ rf.valid_tmodes = ['', 'Tone', 'TSQL', 'DTCS', 'Cross']
+ rf.valid_cross_modes = CROSS_MODES
+ if _embedded.mode == 0: # PMR or FreeNet
+ if str(_embedded.radio_type) == "RT98U":
+ rf.valid_power_levels = PMR_POWER_LEVELS
+ if str(_embedded.radio_type) == "RT98V":
+ rf.valid_power_levels = FREENET_POWER_LEVELS
+ else:
+ rf.valid_power_levels = POWER_LEVELS
+ rf.valid_dtcs_codes = chirp_common.ALL_DTCS_CODES
+
+ try:
+ rf.valid_bands = get_band_limits_Hz(
+ str(_embedded.radio_type),
+ int(_embedded.mode))
+ except TypeError as e:
+ # If we're asked without memory loaded, assume the most
permissive
+ rf.valid_bands = get_band_limits_Hz(str(_embedded.radio_type),
1)
+ except Exception as e:
+ LOG.error('Failed to get band limits for RT98: %s' % e)
+ rf.valid_bands = get_band_limits_Hz(str(_embedded.radio_type),
1)
+
+ rf.valid_tuning_steps = TUNING_STEPS
+ return rf
+
+ def validate_memory(self, mem):
+ _embedded = self._memobj.embedded_msg
+ msgs = ""
+ msgs = chirp_common.CloneModeRadio.validate_memory(self, mem)
+
+ # FreeNet and PMR radio types
+ if _embedded.mode == 0: # PMR or FreeNet
+ freq = float(mem.freq) / 1000000
+
+ # FreeNet
+ if str(_embedded.radio_type) == "RT98V":
+ if freq not in FREENET_FREQS:
+ _msg_freq = 'Memory location not a valid FreeNet
frequency'
+ # warn user invalid frequency
+ msgs.append(chirp_common.ValidationError(_msg_freq))
+
+ # PMR
+ if str(_embedded.radio_type) == "RT98U":
+ if freq not in PMR_FREQS:
+ _msg_freq = 'Memory location not a valid PMR frequency'
+ # warn user invalid frequency
+ msgs.append(chirp_common.ValidationError(_msg_freq))
+
+ return msgs
+
+ # Do a download of the radio from the serial port
+ def sync_in(self):
+ self._mmap = do_download(self)
+ self.process_mmap()
+
+ # Do an upload of the radio to the serial port
+ def sync_out(self):
+ do_upload(self)
+
+ def process_mmap(self):
+ self._memobj = bitwise.parse(MEM_FORMAT, self._mmap)
+
+ # Return a raw representation of the memory object, which
+ # is very helpful for development
+ def get_raw_memory(self, number):
+ return repr(self._memobj.memory[number - 1])
+
+ def _get_dcs_index(self, _mem, which):
+ base = getattr(_mem, '%scode' % which)
+ extra = getattr(_mem, '%sdcsextra' % which)
+ return (int(extra) << 8) | int(base)
+
+ def _set_dcs_index(self, _mem, which, index):
+ base = getattr(_mem, '%scode' % which)
+ extra = getattr(_mem, '%sdcsextra' % which)
+ base.set_value(index & 0xFF)
+ extra.set_value(index >> 8)
+
+ # Extract a high-level memory object from the low-level memory map
+ # This is called to populate a memory in the UI
+ def get_memory(self, number):
+ _embedded = self._memobj.embedded_msg
+ # Get a low-level memory object mapped to the image
+ _mem = self._memobj.memory[number - 1]
+
+ # get flag info
+ cbyte = (number - 1) / 8
+ cbit = 7 - ((number - 1) % 8)
+ setflag = self._memobj.csetflag[cbyte].c[cbit]
+ skipflag = self._memobj.cskipflag[cbyte].c[cbit]
+
+ mem = chirp_common.Memory()
+
+ mem.number = number # Set the memory number
+
+ # We'll consider any blank (i.e. 0MHz frequency) to be empty
+ if _mem.freq == 0:
+ mem.empty = True
+ return mem
+
+ if setflag == 0:
+ mem.empty = True
+ return mem
+
+ if _mem.get_raw()[0] == "\xFF":
+ mem.empty = True
+ return mem
+
+ # set the name
+ mem.name = str(_mem.name).rstrip() # Set the alpha tag
+
+ # Convert your low-level frequency and offset to Hertz
+ mem.freq = int(_mem.freq) * 10
+ mem.offset = int(_mem.offset) * 10
+
+ # Set the duplex flags
+ if _mem.duplex == DUPLEX_POSSPLIT:
+ mem.duplex = '+'
+ elif _mem.duplex == DUPLEX_NEGSPLIT:
+ mem.duplex = '-'
+ elif _mem.duplex == DUPLEX_NOSPLIT:
+ mem.duplex = ''
+ elif _mem.duplex == DUPLEX_ODDSPLIT:
+ mem.duplex = 'split'
+ else:
+ LOG.error('%s: get_mem: unhandled duplex: %02x' %
+ (mem.name, _mem.duplex))
+
+ # handle tx off
+ if _mem.tx_off:
+ mem.duplex = 'off'
+
+ # Set the channel width
+ if _mem.channel_width == CHANNEL_WIDTH_12d5kHz:
+ mem.mode = 'NFM'
+ elif _embedded.mode == 0: # PMR or FreeNet
+ LOG.info('PMR and FreeNet channels must be Channel Width
12.5kHz')
+ mem.mode = 'NFM'
+ elif _mem.channel_width == CHANNEL_WIDTH_25kHz:
+ mem.mode = 'FM'
+ elif _mem.channel_width == CHANNEL_WIDTH_20kHz:
+ LOG.info(
+ '%s: get_mem: promoting 20kHz channel width to 25kHz' %
+ mem.name)
+ mem.mode = 'FM'
+ else:
+ LOG.error('%s: get_mem: unhandled channel width: 0x%02x' %
+ (mem.name, _mem.channel_width))
+
+ # set the power level
+ if _embedded.mode == 0: # PMR or FreeNet
+ if str(_embedded.radio_type) == "RT98U":
+ LOG.info('using PMR power levels')
+ _levels = PMR_POWER_LEVELS
+ if str(_embedded.radio_type) == "RT98V":
+ LOG.info('using FreeNet power levels')
+ _levels = FREENET_POWER_LEVELS
+ else: # COM or COMII
+ LOG.info('using general power levels')
+ _levels = POWER_LEVELS
+
+ if _mem.txpower == TXPOWER_LOW:
+ mem.power = _levels[0]
+ elif _embedded.mode == 0: # PMR or FreeNet
+ LOG.info('FreeNet or PMR channel is not set to TX Power Low')
+ LOG.info('Setting channel to TX Power Low')
+ mem.power = _levels[0]
+ elif _mem.txpower == TXPOWER_MED:
+ mem.power = _levels[1]
+ elif _mem.txpower == TXPOWER_HIGH:
+ mem.power = _levels[2]
+ else:
+ LOG.error('%s: get_mem: unhandled power level: 0x%02x' %
+ (mem.name, _mem.txpower))
+
+ # CTCSS Tones and DTCS Codes
+ rxtone = txtone = None
+
+ rxmode = TMODES[_mem.rxtmode]
+ txmode = TMODES[_mem.txtmode]
+
+ if rxmode == "Tone":
+ rxtone = TONES[_mem.rxtone]
+ elif rxmode == "DTCS":
+ rxtone = chirp_common.ALL_DTCS_CODES[self._get_dcs_index(
+ _mem, 'rx')]
+
+ if txmode == "Tone":
+ txtone = TONES[_mem.txtone]
+ elif txmode == "DTCS":
+ txtone = chirp_common.ALL_DTCS_CODES[self._get_dcs_index(
+ _mem, 'tx')]
+
+ rxpol = _mem.rxinv and "R" or "N"
+ txpol = _mem.txinv and "R" or "N"
+
+ chirp_common.split_tone_decode(mem,
+ (txmode, txtone, txpol),
+ (rxmode, rxtone, rxpol))
+
+ # Check if this memory is in the scan enabled list
+ mem.skip = "S" if skipflag == 0 else ""
+
+ # Extra
+ mem.extra = RadioSettingGroup("extra", "Extra")
+
+ rs = RadioSettingValueBoolean(bool(_mem.busychannellockout))
+ rset = RadioSetting("busychannellockout", "Busy channel lockout",
rs)
+ mem.extra.append(rset)
+
+ rs = RadioSettingValueBoolean(bool(_mem.reverse))
+ rset = RadioSetting("reverse", "Reverse", rs)
+ mem.extra.append(rset)
+
+ rs = RadioSettingValueBoolean(bool(_mem.talkaround))
+ rset = RadioSetting("talkaround", "Talk around", rs)
+ mem.extra.append(rset)
+
+ rs = RadioSettingValueBoolean(bool(_mem.squelch_mode))
+ rset = RadioSetting("squelch_mode", "Squelch mode", rs)
+ mem.extra.append(rset)
+
+ return mem
+
+ # Store details about a high-level memory to the memory map
+ # This is called when a user edits a memory in the UI
+ def set_memory(self, mem):
+ _embedded = self._memobj.embedded_msg
+ # Get a low-level memory object mapped to the image
+
+ _mem = self._memobj.memory[mem.number - 1]
+
+ cbyte = (mem.number - 1) / 8
+ cbit = 7 - ((mem.number - 1) % 8)
+
+ if mem.empty:
+ self._memobj.csetflag[cbyte].c[cbit] = 0
+ self._memobj.cskipflag[cbyte].c[cbit] = 0
+ _mem.set_raw('\xff' * (_mem.size() / 8))
+ return
+
+ _mem.set_raw('\x00' * (_mem.size() / 8))
+
+ # set the occupied bitfield
+ self._memobj.csetflag[cbyte].c[cbit] = 1
+ # set the scan add bitfield
+ self._memobj.cskipflag[cbyte].c[cbit] = 0 if (mem.skip == "S")
else 1
+
+ _mem.freq = mem.freq / 10 # Convert to low-level
frequency
+ _mem.offset = mem.offset / 10 # Convert to low-level
frequency
+
+ # Store the alpha tag
+ _mem.name = mem.name.ljust(6)[:6] # Store the alpha tag
+
+ # Set duplex bitfields
+ if mem.duplex == '+':
+ _mem.duplex = DUPLEX_POSSPLIT
+ elif mem.duplex == '-':
+ _mem.duplex = DUPLEX_NEGSPLIT
+ elif mem.duplex == '':
+ _mem.duplex = DUPLEX_NOSPLIT
+ elif mem.duplex == 'split':
+ diff = mem.offset - mem.freq
+ _mem.duplex = DUPLEXES.index("-") \
+ if diff < 0 else DUPLEXES.index("+")
+ _mem.offset = abs(diff) / 10
+ else:
+ LOG.error('%s: set_mem: unhandled duplex: %s' %
+ (mem.name, mem.duplex))
+
+ # handle tx off
+ _mem.tx_off = 0
+ if mem.duplex == 'off':
+ _mem.tx_off = 1
+
+ # Set the channel width - remember we promote 20kHz channels to FM
+ # on import, so don't handle them here
+ if mem.mode == 'FM':
+ _mem.channel_width = CHANNEL_WIDTH_25kHz
+ elif mem.mode == 'NFM':
+ _mem.channel_width = CHANNEL_WIDTH_12d5kHz
+ else:
+ LOG.error('%s: set_mem: unhandled mode: %s' % (
+ mem.name, mem.mode))
+
+ # CTCSS Tones and DTCS Codes
+ ((txmode, txtone, txpol),
+ (rxmode, rxtone, rxpol)) = chirp_common.split_tone_encode(mem)
+
+ _mem.txtmode = TMODES.index(txmode)
+
+ _mem.rxtmode = TMODES.index(rxmode)
+
+ if txmode == "Tone":
+ _mem.txtone = TONES.index(txtone)
+ elif txmode == "DTCS":
+ self._set_dcs_index(_mem, 'tx',
+ chirp_common.ALL_DTCS_CODES.index(txtone))
+
+ _mem.squelch_mode = False
+ if rxmode == "Tone":
+ _mem.rxtone = TONES.index(rxtone)
+ _mem.squelch_mode = True
+ elif rxmode == "DTCS":
+ self._set_dcs_index(_mem, 'rx',
+ chirp_common.ALL_DTCS_CODES.index(rxtone))
+ _mem.squelch_mode = True
+
+ _mem.txinv = txpol == "R"
+ _mem.rxinv = rxpol == "R"
+
+ # set the power level
+ if mem.power == POWER_LEVELS[0]:
+ _mem.txpower = TXPOWER_LOW
+ elif mem.power == POWER_LEVELS[1]:
+ _mem.txpower = TXPOWER_MED
+ elif mem.power == POWER_LEVELS[2]:
+ _mem.txpower = TXPOWER_HIGH
+ else:
+ LOG.error('%s: set_mem: unhandled power level: %s' %
+ (mem.name, mem.power))
+
+ # extra settings
+ for setting in mem.extra:
+ setattr(_mem, setting.get_name(), setting.value)
+
+ def _get_settings(self):
+ _embedded = self._memobj.embedded_msg
+ _settings = self._memobj.settings
+ _settings2 = self._memobj.settings2
+ _settings3 = self._memobj.settings3
+ _slabel = self._memobj.slabel
+
+ function = RadioSettingGroup("function", "Function Setup")
+ group = RadioSettings(function)
+
+ # Function Setup
+ # MODE SET
+ rs = RadioSettingValueList(LIST_DISPLAY_MODE,
+
LIST_DISPLAY_MODE[_settings.display_mode])
+ rset = RadioSetting("display_mode", "Display Mode", rs)
+ function.append(rset)
+
+ rs = RadioSettingValueInteger(1, 199, _settings3.ch_number + 1)
+ rset = RadioSetting("settings3.ch_number", "Channel Number", rs)
+ function.append(rset)
+
+ # DISPLAY SET
+ def _filter(name):
+ filtered = ""
+ for char in str(name):
+ if char in chirp_common.CHARSET_ASCII:
+ filtered += char
+ else:
+ filtered += " "
+ return filtered
+
+ val = RadioSettingValueString(0, 6, _filter(_slabel.startname))
+ rs = RadioSetting("slabel.startname", "Startup Label", val)
+ function.append(rs)
+
+ # VOL SET
+ rs = RadioSettingValueBoolean(bool(_settings.beep))
+ rset = RadioSetting("beep", "Beep Prompt", rs)
+ function.append(rset)
+
+ rs = RadioSettingValueInteger(1, 30, _settings.volume)
+ rset = RadioSetting("volume", "Volume Level", rs)
+ function.append(rset)
+
+ rs = RadioSettingValueInteger(1, 16, _settings.mic_gain)
+ rset = RadioSetting("mic_gain", "Mic Gain", rs)
+ function.append(rset)
+
+ # ON/OFF SET
+ rs = RadioSettingValueList(LIST_APO,
+ LIST_APO[_settings.auto_power_off])
+ rset = RadioSetting("auto_power_off", "Auto Power Off", rs)
+ function.append(rset)
+
+ rs = RadioSettingValueList(LIST_AOP,
LIST_AOP[_settings.auto_power_on])
+ rset = RadioSetting("auto_power_on", "Power On Method", rs)
+ function.append(rset)
+
+ # STE SET
+ rs = RadioSettingValueList(LIST_STE_FREQ,
+ LIST_STE_FREQ[_settings.ste_frequency])
+ rset = RadioSetting("ste_frequency", "STE Frequency", rs)
+ function.append(rset)
+
+ rs = RadioSettingValueList(LIST_STE_TYPE,
+ LIST_STE_TYPE[_settings.ste_type])
+ rset = RadioSetting("ste_type", "STE Type", rs)
+ function.append(rset)
+
+ # FUNCTION SET
+ rs = RadioSettingValueList(LIST_STEP,
LIST_STEP[_settings.tuning_step])
+ rset = RadioSetting("tuning_step", "Tuning Step", rs)
+ function.append(rset)
+
+ rs = RadioSettingValueList(LIST_SQUELCH,
+ LIST_SQUELCH[_settings.squelch])
+ rset = RadioSetting("squelch", "Squelch Level", rs)
+ function.append(rset)
+
+ rs = RadioSettingValueBoolean(bool(_settings.sql_key_function))
+ rset = RadioSetting("sql_key_function", "SQL Key Function", rs)
+ function.append(rset)
+
+ rs = RadioSettingValueList(LIST_TIMEOUT,
+ LIST_TIMEOUT[_settings.timeout_timer])
+ rset = RadioSetting("timeout_timer", "Timeout Timer", rs)
+ function.append(rset)
+
+ # uncategorized
+ rs = RadioSettingValueBoolean(bool(_settings.save_chan_param))
+ rset = RadioSetting("save_chan_param", "Save Channel Parameters",
rs)
+ function.append(rset)
+
+ rs = RadioSettingValueBoolean(bool(_settings.forbid_chan_menu))
+ rset = RadioSetting("forbid_chan_menu", "Forbid Channel Menu", rs)
+ function.append(rset)
+
+ rs = RadioSettingValueBoolean(bool(not
_settings.forbid_initialize))
+ rset = RadioSetting("forbid_initialize", "Forbid Initialize", rs)
+ function.append(rset)
+
+ rs = RadioSettingValueBoolean(bool(_settings.forbid_setting))
+ rset = RadioSetting("forbid_setting", "Forbid Setting", rs)
+ function.append(rset)
+
+ # Information Of Scanning Channel
+ scanning = RadioSettingGroup("scanning", "Scanning Setup")
+ group.append(scanning)
+
+ rs = RadioSettingValueBoolean(bool(_settings2.scan_mode))
+ rset = RadioSetting("settings2.scan_mode", "Scan Mode", rs)
+ scanning.append(rset)
+
+ rs = RadioSettingValueList(LIST_PRIORITY_CH,
+
LIST_PRIORITY_CH[_settings2.priority_ch])
+ rset = RadioSetting("settings2.priority_ch", "Priority Channel",
rs)
+ scanning.append(rset)
+
+ rs = RadioSettingValueInteger(1, 199, _settings2.priority_ch1 + 1)
+ rset = RadioSetting("settings2.priority_ch1", "Priority Channel
1", rs)
+ scanning.append(rset)
+
+ rs = RadioSettingValueInteger(1, 199, _settings2.priority_ch2 + 1)
+ rset = RadioSetting("settings2.priority_ch2", "Priority Channel
2", rs)
+ scanning.append(rset)
+
+ rs = RadioSettingValueList(LIST_REVERT_CH,
+ LIST_REVERT_CH[_settings2.revert_ch])
+ rset = RadioSetting("settings2.revert_ch", "Revert Channel", rs)
+ scanning.append(rset)
+
+ rs = RadioSettingValueList(LIST_TIME46,
+
LIST_TIME46[_settings2.look_back_time_a])
+ rset = RadioSetting("settings2.look_back_time_a",
+ "Look Back Time A", rs)
+ scanning.append(rset)
+
+ rs = RadioSettingValueList(LIST_TIME46,
+
LIST_TIME46[_settings2.look_back_time_b])
+ rset = RadioSetting("settings2.look_back_time_b",
+ "Look Back Time B", rs)
+ scanning.append(rset)
+
+ rs = RadioSettingValueList(LIST_TIME50,
+
LIST_TIME50[_settings2.dropout_delay_time])
+ rset = RadioSetting("settings2.dropout_delay_time",
+ "Dropout Delay Time", rs)
+ scanning.append(rset)
+
+ rs = RadioSettingValueList(LIST_TIME50,
+ LIST_TIME50[_settings2.dwell_time])
+ rset = RadioSetting("settings2.dwell_time", "Dwell Time", rs)
+ scanning.append(rset)
+
+ # Embedded Message
+ embedded = RadioSettingGroup("embedded", "Embedded Message")
+ group.append(embedded)
+
+ rs = RadioSettingValueString(0, 5, _filter(_embedded.radio_type))
+ rs.set_mutable(False)
+ rset = RadioSetting("embedded_msg.radio_type", "Radio Type", rs)
+ embedded.append(rset)
+
+ if str(_embedded.radio_type) == "RT98V":
+ options = LIST_RT98V_MODES
+ else:
+ options = LIST_RT98U_MODES
+ rs = RadioSettingValueList(options, options[_embedded.mode])
+ rs.set_mutable(False)
+ rset = RadioSetting("embedded_msg.mode", "Mode", rs)
+ embedded.append(rset)
+
+ # frequency
+ if str(_embedded.radio_type) == "RT98V":
+ options = LIST_RT98V_FREQS
+ else:
+ options = LIST_RT98U_FREQS
+ rs = RadioSettingValueList(options, options[_settings3.bandlimit])
+ rs.set_mutable(False)
+ rset = RadioSetting("settings3.bandlimit", "Frequency", rs)
+ embedded.append(rset)
+
+ rs = RadioSettingValueString(0, 10, _filter(_embedded.date_mfg))
+ rs.set_mutable(False)
+ rset = RadioSetting("embedded_msg.date_mfg", "Production Date", rs)
+ embedded.append(rset)
+
+ rs = RadioSettingValueString(0, 4, _filter(_embedded.mcu_version))
+ rs.set_mutable(False)
+ rset = RadioSetting("embedded_msg.mcu_version", "MCU Version", rs)
+ embedded.append(rset)
+
+ return group
+
+ def get_settings(self):
+ try:
+ return self._get_settings()
+ except:
+ import traceback
+ LOG.error("failed to parse settings")
+ traceback.print_exc()
+ return None
+
+ 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 == "ch_number":
+ setattr(obj, setting, int(element.value) - 1)
+ elif setting == "forbid_initialize":
+ setattr(obj, setting, not int(element.value))
+ elif setting == "priority_ch1":
+ setattr(obj, setting, int(element.value) - 1)
+ elif setting == "priority_ch2":
+ 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
+
+
+(a)directory.register
+class Rt98Radio(Rt98BaseRadio):
+ """Retevis RT98"""
+ VENDOR = "Retevis"
+ MODEL = "RT98"
+ # Allowed radio types is a dict keyed by model of a list of version
+ # strings
+ ALLOWED_RADIO_TYPES = {'RT98V': ['V100'],
+ 'RT98U': ['V100']}
diff -r f586574bc878 -r 0eab8146b294 tools/cpep8.manifest
--- a/tools/cpep8.manifest Thu Jun 17 21:57:05 2021 -0400
+++ b/tools/cpep8.manifest Sat Jul 03 14:13:35 2021 -0400
@@ -83,6 +83,7 @@
./chirp/drivers/retevis_rt23.py
./chirp/drivers/retevis_rt26.py
./chirp/drivers/retevis_rt76p.py
+./chirp/drivers/retevis_rt98.py
./chirp/drivers/rfinder.py
./chirp/drivers/tdxone_tdq8a.py
./chirp/drivers/template.py
1
0

[chirp_devel] Fwd: [PATCH] [RT98] Add support for Retevis RT98 Single Band Mini Mobile Radios
by Jim Unroe 03 Jul '21
by Jim Unroe 03 Jul '21
03 Jul '21
CHIRP Radio Images (*.img) file for testing attached.
Jim KC9HI
---------- Forwarded message ---------
From: Jim Unroe <kc9hi(a)comcast.net>
Date: Sat, Jul 3, 2021 at 2:25 PM
Subject: [PATCH] [RT98] Add support for Retevis RT98 Single Band Mini
Mobile Radios
To: <Rock.Unroe(a)gmail.com>
# HG changeset patch
# User Jim Unroe <rock.unroe(a)gmail.com>
# Date 1625336015 14400
# Sat Jul 03 14:13:35 2021 -0400
# Node ID 0eab8146b294ef686ca4a49c17ea38abde54c7ab
# Parent f586574bc8786fd6bef1e5d54d08d381c81edd47
[RT98] Add support for Retevis RT98 Single Band Mini Mobile Radios
This patch adds support for the various Retevis RT98 mobile radio
models/modes.
VHF FreeNet
VHF COM
VHF COMII
UHF PMR
UHF COM
UHF COMII
#9181
diff -r f586574bc878 -r 0eab8146b294 chirp/drivers/retevis_rt98.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/chirp/drivers/retevis_rt98.py Sat Jul 03 14:13:35 2021 -0400
@@ -0,0 +1,1364 @@
+# 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 os
+import struct
+import time
+import logging
+
+from chirp import bitwise
+from chirp import chirp_common
+from chirp import directory
+from chirp import errors
+from chirp import memmap
+from chirp import util
+from chirp.settings import RadioSettingGroup, RadioSetting, RadioSettings,
\
+ RadioSettingValueList, RadioSettingValueString,
RadioSettingValueBoolean, \
+ RadioSettingValueInteger, RadioSettingValueString, \
+ RadioSettingValueFloat, InvalidValueError
+
+LOG = logging.getLogger(__name__)
+
+#
+# Chirp Driver for Retevis RT98 models: RT98V (136-174 Mhz)
+# RT98U (400-490 Mhz)
+#
+#
+#
+# Global Parameters
+#
+TONES = [62.5] + list(chirp_common.TONES)
+TMODES = ['', 'Tone', 'DTCS']
+DUPLEXES = ['', '+', '-']
+
+TXPOWER_LOW = 0x00
+TXPOWER_MED = 0x01
+TXPOWER_HIGH = 0x02
+
+DUPLEX_NOSPLIT = 0x00
+DUPLEX_POSSPLIT = 0x01
+DUPLEX_NEGSPLIT = 0x02
+
+CHANNEL_WIDTH_12d5kHz = 0x00
+CHANNEL_WIDTH_20kHz = 0x01
+CHANNEL_WIDTH_25kHz = 0x02
+
+TUNING_STEPS = [2.5, 5.0, 6.25, 10.0, 12.5, 20.0, 25.0, 30.0, 50.0]
+
+POWER_LEVELS = [chirp_common.PowerLevel("Low", watts=5),
+ chirp_common.PowerLevel("Mid", watts=10),
+ chirp_common.PowerLevel("High", watts=15)]
+
+PMR_POWER_LEVELS = [chirp_common.PowerLevel("Low", watts=0.5), ]
+
+FREENET_POWER_LEVELS = [chirp_common.PowerLevel("Low", watts=1), ]
+
+PMR_FREQS = [446.00625, 446.01875, 446.03125, 446.04375,
+ 446.05625, 446.06875, 446.08125, 446.09375,
+ 446.10625, 446.11875, 446.13125, 446.14375,
+ 446.15625, 446.16875, 446.18125, 446.19375]
+
+FREENET_FREQS = [149.02500, 149.03750, 149.05000,
+ 149.08750, 149.10000, 149.11250]
+
+CROSS_MODES = ["Tone->Tone", "DTCS->", "->DTCS", "Tone->DTCS",
"DTCS->Tone",
+ "->Tone", "DTCS->DTCS"]
+
+LIST_STEP = [str(x) for x in TUNING_STEPS]
+LIST_TIMEOUT = ["Off"] + ["%s min" % x for x in range(1, 31)]
+LIST_APO = ["Off", "30 min", "1 hr", "2 hrs"]
+LIST_SQUELCH = ["Off"] + ["Level %s" % x for x in range(1, 10)]
+LIST_DISPLAY_MODE = ["Channel", "Frequency", "Name"]
+LIST_AOP = ["Manual", "Auto"]
+LIST_STE_TYPE = ["Off", "Silent", "120 Degree", "180 Degree", "240 Degree"]
+LIST_STE_FREQ = ["Off", "55.2 Hz", "259.2 Hz"]
+
+LIST_PRIORITY_CH = ["Off", "Priority Channel 1", "Priority Channel 2",
+ "Priority Channel 1 + Priority Channel 2"]
+
+LIST_REVERT_CH = ["Selected", "Selected + TalkBack", "Priority Channel 1",
+ "Priority Channel 2", "Last Called", "Last Used",
+ "Priority Channel 1 + TalkBack",
+ "Priority Channel 2 + TalkBack"]
+
+LIST_TIME50 = ["0.1", "0.2", "0.3", "0.4", "0.5",
+ "0.6", "0.7", "0.8", "0.9", "1.0",
+ "1.1", "1.2", "1.3", "1.4", "1.5",
+ "1.6", "1.7", "1.8", "1.9", "2.0",
+ "2.1", "3.2", "2.3", "2.4", "2.5",
+ "2.6", "2.7", "2.8", "2.9", "3.0",
+ "3.1", "3.2", "3.3", "3.4", "3.5",
+ "3.6", "3.7", "3.8", "3.9", "4.0",
+ "4.1", "4.2", "4.3", "4.4", "4.5",
+ "4.6", "4.7", "4.8", "4.9", "5.0"]
+LIST_TIME46 = LIST_TIME50[4:]
+
+LIST_RT98V_MODES = ["FreeNet", "COM", "COMII"]
+LIST_RT98U_MODES = ["PMR", "COM", "COMII"]
+
+LIST_RT98V_FREQS = ["Rx(149 - 149.2 MHz) Tx(149 - 149.2 MHz)",
+ "Rx(136 - 174 MHz) Tx(136 - 174 MHz)",
+ "Rx(147 - 174 MHz) Tx(147 - 174 MHz)"]
+
+LIST_RT98U_FREQS = ["Rx(446 - 446.2 MHz) Tx(446 - 446.2 MHz)",
+ "Rx(400 - 470 MHz) Tx(400 - 470 MHz)",
+ "Rx(450 - 470 MHz) Tx(450 - 470 MHz)"]
+
+SETTING_LISTS = {
+ "tuning_step": LIST_STEP,
+ "timeout_timer": LIST_TIMEOUT,
+ "auto_power_off": LIST_APO,
+ "squelch": LIST_SQUELCH,
+ "display_mode": LIST_DISPLAY_MODE,
+ "auto_power_on": LIST_AOP,
+ "ste_type": LIST_STE_TYPE,
+ "ste_frequency": LIST_STE_FREQ,
+ "priority_ch": LIST_PRIORITY_CH,
+ "revert_ch": LIST_REVERT_CH,
+ "settings2.dropout_delay_time": LIST_TIME50,
+ "settings2.dwell_time": LIST_TIME50,
+ "settings2.look_back_time_a": LIST_TIME46,
+ "settings2.look_back_time_b": LIST_TIME46
+}
+
+# RT98 memory map
+# section: 1 Channel Bank
+# description of channel bank (199 channels , range 1-199)
+# Each 32 Byte (0x20 hex) record:
+# bytes:bit type description
+#
---------------------------------------------------------------------------
+# 4 bbcd freq[4] receive frequency in packed binary coded
+# decimal
+# 4 bbcd offset[4] transceive offset in packed binary coded
+# decimal (note: +/- direction set by
+# 'duplex' field)
+# 1 u8 unknown0
+# 1 u8
+# :1 reverse:1 reverse flag, 0=off, 1=on (reverses
+# transmit and receive freqencies)
+# :1 txoff:1 transmitt off flag, 0=transmit, 1=do not
+# transmit
+# :2 power:2 transmit power setting, value range 0-2,
+# 0=low, 1=middle, 2=high
+# :2 duplex:2 duplex settings, 0=simplex, 1=plus (+)
+# offset, 2=minus(-) offset (see offset
field)
+# :2 channel_width:2 channel spacing, 0=12.5kHz, 1=20kHz,
2=25kHz
+# 1 u8
+# :2 unknown1:2
+# :1 talkaround:1 talkaround flag, 0=off, 1=on
+# (bypasses repeater)
+# :1 squelch_mode:1 squelch mode flag, 0=carrier,
1=ctcss/dcs
+# :1 rxdcsextra:1 use with rxcode for index of rx DCS to
use
+# :1 rxinv:1 inverse DCS rx polarity flag, 0=N, 1=I
+# :1 txdcsextra:1 use with txcode for index of tx DCS to
use
+# :1 txinv:1 inverse DCS tx polarity flag, 0=N, 1=I
+# 1 u8
+# :4 unknown2:4
+# :2 rxtmode:2 rx tone mode, value range 0-2, 0=none,
+# 1=CTCSS, 2=DCS (ctcss tone in field
rxtone)
+# :2 txtmode:2 tx tone mode, value range 0-2, 0=none,
+# 1=CTCSS, 3=DCS (ctcss tone in field
txtone)
+# 1 u8
+# :2 unknown3:2
+# :6 txtone:6 tx ctcss tone, menu index
+# 1 u8
+# :2 unknown4:2
+# :6 rxtone:6 rx ctcss tone, menu index
+# 1 u8 txcode ?, not used for ctcss
+# 1 u8 rxcode ?, not used for ctcss
+# 1 u8
+# :6 unknown5:6
+# :1 busychannellockout:1 busy channel lockout flag, 0=off,
1=enabled
+# :1 unknown6:1
+# 6 char name[6] 6 byte char string for channel name
+# 9 u8 unknown7[9]
+#
+MEM_FORMAT = """
+#seekto 0x0000;
+struct {
+ bbcd freq[4];
+ bbcd offset[4];
+ u8 unknown0;
+ u8 reverse:1,
+ tx_off:1,
+ txpower:2,
+ duplex:2,
+ channel_width:2;
+ u8 unknown1:2,
+ talkaround:1,
+ squelch_mode:1,
+ rxdcsextra:1,
+ rxinv:1,
+ txdcsextra:1,
+ txinv:1;
+ u8 unknown2:4,
+ rxtmode:2,
+ txtmode:2;
+ u8 unknown3:2,
+ txtone:6;
+ u8 unknown4:2,
+ rxtone:6;
+ u8 txcode;
+ u8 rxcode;
+ u8 unknown5:6,
+ busychannellockout:1,
+ unknown6:1;
+ char name[6];
+ u8 unknown7[9];
+} memory[199];
+"""
+
+# RT98 memory map
+# section: 2 and 3 Channel Set/Skip Flags
+#
+# Channel Set (starts 0x3240) : Channel Set bit is value 0 if a memory
+# location in the channel bank is active.
+# Channel Skip (starts 0x3260): Channel Skip bit is value 0 if a memory
+# location in the channel bank is active.
+#
+# Both flag maps are a total 24 bytes in length, aligned on 32 byte
records.
+# bit = 0 channel not set/skip, 1 is channel set/no skip
+#
+# to index a channel:
+# cbyte = channel / 8 ;
+# cbit = channel % 8 ;
+# setflag = csetflag[cbyte].c[cbit] ;
+# skipflag = cskipflag[cbyte].c[cbit] ;
+#
+# channel range is 1-199, range is 32 bytes (last 7 unknown)
+#
+MEM_FORMAT = MEM_FORMAT + """
+#seekto 0x3240;
+struct {
+ bit c[8];
+} csetflag[32];
+
+#seekto 0x3260;
+struct {
+ bit c[8];
+} cskipflag[32];
+
+"""
+
+# RT98 memory map
+# section: 4 Startup Label
+#
+# bytes:bit type description
+#
---------------------------------------------------------------------------
+# 6 char start_label[6] label displayed at startup (usually
+# your call sign)
+#
+MEM_FORMAT = MEM_FORMAT + """
+#seekto 0x3300;
+struct {
+ char startname[6];
+} slabel;
+"""
+
+# RT98 memory map
+# section: 5, 6 and 7 Radio Options
+# used to set a number of radio options
+#
+# description of function setup options, starting at 0x3310 (settings3)
+#
+# bytes:bit type description
+#
---------------------------------------------------------------------------
+# 1 u8
+# :6 unknown:6
+# :2 bandlimit_3310:2 frequency ranges, range 0-2,
+# 0=freenet(vhf) or pmr(uhf), 1=com,
2=comii
+# rt98v - 00 FreeNet Rx(149 - 149.2 MHz) Tx(149 - 149.2
MHz)
+# 01 COM Rx(136 - 174 MHz) Tx(136 - 174 MHz)
+# 02 COMII Rx(147 - 174 MHz) Tx(147 - 174 MHz)
+# rt98u - 00 PMR Rx(446 - 446.2 MHz) Tx(446 - 446.2
MHz)
+# 01 COM Rx(400 - 470 MHz) Tx(400 - 470 MHz)
+# 02 COMII Rx(450 - 470 MHz) Tx(450 - 470 MHz)
+# 1 u8 ch_number; channel number, range 1-199
+#
+# description of function setup options, starting at 0x3340 (settings)
+#
+# bytes:bit type description
+#
---------------------------------------------------------------------------
+# 1 u8
+# :4 unknown_3340:4
+# :4 tuning_step:4 tuning step, menu index value from 0-8
+# 2.5, 5, 6.25, 10, 12.5, 20, 25, 30, 50
+# 1 u8
+# :7 unknown_3341:7
+# :1 beep:1 beep mode, range 0-1, 0=off, 1=on
+# 1 u8
+# :3 unknown_3342:3
+# :5 timeout_timer:5 timeout timer, range off (no timeout),
+# 1-30 minutes
+# 1 u8
+# :6 unknown_3343:6
+# :2 auto_power_off:2 auto power off, range 0-3, off, 30min,
+# 1hr, 2hr
+# 1 u8
+# :4 unknown_3344:4
+# :4 squelch:4 squelch level, range off, 1-9
+# 1 u8
+# :3 unknown_3345:3
+# :5 volume:5 volume level, range 1-30 (no zero)
+# 1 u8 unknown_3346
+# 1 u8 unknown_3347
+# 1 u8 0x3348 [12]
+# :6 unknown_3348:6
+# :2 display_mode display mode, range 0-2, 0=channel,
+# 1=frequency, 2=name
+# 1 u8
+# :7 unknown_3349:7
+# :1 auto_power_on:1 auto power on, range 0-1, 0=manual,
+# 1=auto
+# 1 u8
+# :3 unknown_334A:3
+# :5 mic_gain:5 mic gain, range 1-30 (no zero)
+# 1 u8
+# :5 unknown_334C:5
+# :3 ste_type:3 ste type, range 0-4, 0=off, 1=silent,
+# 2=120degree, 3=180degree, 4=240degree
+# 1 u8
+# :7 unknown_334D:7
+# :1 ste_frequency:1 ste frequency, range 0-2, 0=off,
+# 1=55.2Hz, 2=259.2Hz
+# 1 u8
+# :2 unknown_0x334E:2
+# :1 forbid_setting:1 forbid setting(optional function),
+# range 0-1, 0=disabled, 1=enabled
+# :1 forbid_initialize:1 forbid initialize operate, range 0-1,
+# 0=enabled, 1=disabled (inverted)
+# :1 save_chan_param:1 save channel parameters, range 0-1,
+# 0=disabled, 1=enabled
+# :1 forbid_chan_menu:1 forbid channel menu, range 0-1,
+# 0=disabled, 1=enabled
+# :1 sql_key_function:1 sql key function, range 0-1,
+# 0=squelch off momentary, 1=squelch off
+# :1 unknown:1
+#
+# description of function setup options, starting at 0x3380 (settings2)
+#
+# bytes:bit type description
+#
---------------------------------------------------------------------------
+# 1 u8
+# :7 unknown_3380:7
+# :1 scan_mode:1 scan mode, range 0-1, 0=off, 1=on
+# 1 u8
+# :6 unknown_3381:6
+# :2 priority_ch:2 priority channel, range 0-3, 0=off,
+# 1=priority channel 1,
+# 2=priority channel 2,
+# 3=priority channel 1 + priority
channel 2
+# 1 u8 priority_ch1 priority channel 1 number, range 1-199
+# 1 u8 priority_ch2 priority channel 2 number, range 1-199
+# 1 u8
+# :4 unknown_3384:4
+# :4 revert_ch:4 revert channel, range 0-3, 0=selected,
+# 1=selected + talkback, 2=last called,
+# 3=last used
+# 1 u8 look_back_time_a look back time a, range 0-45
+# 1 u8 look_back_time_b look back time b, range 0-45
+# 1 u8 dropout_delay_time dropout delay time, range 0-49
+# 1 u8 dwell_time dwell time, range 0-49
+#
+MEM_FORMAT = MEM_FORMAT + """
+#seekto 0x3310;
+struct {
+ u8 bandlimit;
+ u8 ch_number;
+} settings3;
+"""
+
+MEM_FORMAT = MEM_FORMAT + """
+#seekto 0x3340;
+struct {
+ u8 unknown_3340:4,
+ tuning_step:4;
+ u8 unknown_3341:7,
+ beep:1;
+ u8 unknown_3342:3,
+ timeout_timer:5;
+ u8 unknown_3343:6,
+ auto_power_off:2;
+ u8 unknown_3344:4,
+ squelch:4;
+ u8 unknown_3345:3,
+ volume:5;
+ u8 unknown_3346;
+ u8 unknown_3347;
+ u8 unknown_3348:6,
+ display_mode:2;
+ u8 unknown_3349:7,
+ auto_power_on:1;
+ u8 unknown_334A:3,
+ mic_gain:5;
+ u8 unknown_334B;
+ u8 unknown_334C:5,
+ ste_type:3;
+ u8 unknown_334D:6,
+ ste_frequency:2;
+ u8 unknown_334E:1,
+ forbid_setting:1,
+ unknown1:1,
+ forbid_initialize:1,
+ save_chan_param:1,
+ forbid_chan_menu:1,
+ sql_key_function:1,
+ unknown2:1;
+} settings;
+"""
+
+MEM_FORMAT = MEM_FORMAT + """
+#seekto 0x3380;
+struct {
+ u8 unknown_3380:7,
+ scan_mode:1;
+ u8 unknown_3381:6,
+ priority_ch:2;
+ u8 priority_ch1;
+ u8 priority_ch2;
+ u8 unknown_3384:4,
+ revert_ch:4;
+ u8 look_back_time_a;
+ u8 look_back_time_b;
+ u8 dropout_delay_time;
+ u8 dwell_time;
+} settings2;
+"""
+
+# RT98 memory map
+# section: 8 Embedded Messages
+#
+# bytes:bit type description
+#
---------------------------------------------------------------------------
+# 6 char radio_type[5] radio type, vhf=rt98v, uhf=rt98u
+# 2 u8 unknown1[2]
+# 4 char mcu_version[4] mcu version, [x.xx]
+# 2 u8 unknown2[2]
+# 1 u8 mode rt98u mode: 0=pmr, 1=com, 2=comii
+# rt98v mode: 0=freenet, 1=com, 2=comii
+# 1 u8 unknown3
+# 10 u8 unused1[10]
+# 4 u8 unknown4[4]
+# 3 u8 unused2[3]
+# 16 u8 unknown5[16]
+# 10 char date_mfg[16] date manufactured, [yyyy-mm-dd]
+#
+MEM_FORMAT = MEM_FORMAT + """
+#seekto 0x3D00;
+struct {
+char radio_type[5];
+u8 unknown1[2];
+char mcu_version[4];
+u8 unknown2[2];
+u8 mode;
+u8 unknown3;
+u8 unused1[10];
+u8 unknown4[4];
+u8 unused2[3];
+u8 unknown5[16];
+char date_mfg[10];
+} embedded_msg;
+"""
+
+
+# Format for the version messages returned by the radio
+VER_FORMAT = '''
+u8 hdr;
+char model[5];
+u8 unknown[2];
+u8 bandlimit;
+char version[6];
+u8 ack;
+'''
+
+
+# Radio supports upper case and symbols
+CHARSET_ASCII_PLUS = chirp_common.CHARSET_UPPER_NUMERIC + '- '
+
+# Band limits as defined by the band byte in ver_response, defined in Hz,
for
+# VHF and UHF, used for RX and TX.
+RT98V_BAND_LIMITS = {0x00: [(149000000, 149200000)],
+ 0x01: [(136000000, 174000000)],
+ 0x02: [(147000000, 174000000)]}
+
+RT98U_BAND_LIMITS = {0x00: [(446000000, 446200000)],
+ 0x01: [(400000000, 470000000)],
+ 0x02: [(450000000, 470000000)]}
+
+
+# Get band limits from a band limit value
+def get_band_limits_Hz(radio_type, limit_value):
+ if radio_type == "RT98U":
+ if limit_value not in RT98U_BAND_LIMITS:
+ limit_value = 0x01
+ LOG.warning('Unknown band limit value 0x%02x, default to 0x01')
+ bandlimitfrequencies = RT98U_BAND_LIMITS[limit_value]
+ elif radio_type == "RT98V":
+ if limit_value not in RT98V_BAND_LIMITS:
+ limit_value = 0x01
+ LOG.warning('Unknown band limit value 0x%02x, default to 0x01')
+ bandlimitfrequencies = RT98V_BAND_LIMITS[limit_value]
+ return bandlimitfrequencies
+
+
+def _echo_write(radio, data):
+ try:
+ radio.pipe.write(data)
+ radio.pipe.read(len(data))
+ except Exception, e:
+ LOG.error("Error writing to radio: %s" % e)
+ raise errors.RadioError("Unable to write to radio")
+
+
+def _checksum(data):
+ cs = 0
+ for byte in data:
+ cs += ord(byte)
+ return cs % 256
+
+
+def _read(radio, length):
+ try:
+ data = radio.pipe.read(length)
+ except Exception, e:
+ _finish(radio)
+ LOG.error("Error reading from radio: %s" % e)
+ raise errors.RadioError("Unable to read from radio")
+
+ if len(data) != length:
+ _finish(radio)
+ LOG.error("Short read from radio (%i, expected %i)" %
+ (len(data), length))
+ LOG.debug(util.hexprint(data))
+ raise errors.RadioError("Short read from radio")
+ return data
+
+
+# strip trailing 0x00 to convert a string returned by bitwise.parse into a
+# python string
+def cstring_to_py_string(cstring):
+ return "".join(c for c in cstring if c != '\x00')
+
+
+# Check the radio version reported to see if it's one we support,
+# returns bool version supported, and the band index
+def check_ver(ver_response, allowed_types):
+ ''' Check the returned radio version is one we approve of '''
+
+ LOG.debug('ver_response = ')
+ LOG.debug(util.hexprint(ver_response))
+
+ resp = bitwise.parse(VER_FORMAT, ver_response)
+ verok = False
+
+ if resp.hdr == 0x49 and resp.ack == 0x06:
+ model, version =
[cstring_to_py_string(bitwise.get_string(s)).strip()
+ for s in (resp.model, resp.version)]
+ LOG.debug('radio model: \'%s\' version: \'%s\'' %
+ (model, version))
+ LOG.debug('allowed_types = %s' % allowed_types)
+
+ if model in allowed_types:
+ LOG.debug('model in allowed_types')
+
+ if version in allowed_types[model]:
+ LOG.debug('version in allowed_types[model]')
+ verok = True
+ else:
+ _finish(radio)
+ raise errors.RadioError('Failed to parse version response')
+
+ return verok, str(resp.model), int(resp.bandlimit)
+
+
+def _ident(radio):
+ radio.pipe.timeout = 1
+ _echo_write(radio, "PROGRAM")
+ response = radio.pipe.read(3)
+ if response != "QX\06":
+ _finish(radio)
+ LOG.debug("Response was :\n%s" % util.hexprint(response))
+ raise errors.RadioError("Radio did not respond. Check connection.")
+ _echo_write(radio, "\x02")
+ ver_response = radio.pipe.read(16)
+ LOG.debug(util.hexprint(ver_response))
+
+ verok, model, bandlimit = check_ver(ver_response,
+ radio.ALLOWED_RADIO_TYPES)
+ if not verok:
+ _finish(radio)
+ raise errors.RadioError(
+ 'Radio version not in allowed list for %s-%s: %s' %
+ (radio.VENDOR, radio.MODEL, util.hexprint(ver_response)))
+
+ return model, bandlimit
+
+
+def _send(radio, cmd, addr, length, data=None):
+ frame = struct.pack(">cHb", cmd, addr, length)
+ if data:
+ frame += data
+ frame += chr(_checksum(frame[1:]))
+ frame += "\x06"
+ _echo_write(radio, frame)
+ LOG.debug("Sent:\n%s" % util.hexprint(frame))
+ if data:
+ result = radio.pipe.read(1)
+ if result != "\x06":
+ _finish(radio)
+ LOG.debug("Ack was: %s" % repr(result))
+ raise errors.RadioError("Radio did not accept block at %04x"
+ % addr)
+ return
+ result = _read(radio, length + 6)
+ LOG.debug("Got:\n%s" % util.hexprint(result))
+ header = result[0:4]
+ data = result[4:-2]
+ ack = result[-1]
+ if ack != "\x06":
+ _finish(radio)
+ LOG.debug("Ack was: %s" % repr(ack))
+ raise errors.RadioError("Radio NAK'd block at %04x" % addr)
+ _cmd, _addr, _length = struct.unpack(">cHb", header)
+ if _addr != addr or _length != _length:
+ _finish(radio)
+ LOG.debug("Expected/Received:")
+ LOG.debug(" Length: %02x/%02x" % (length, _length))
+ LOG.debug(" Addr: %04x/%04x" % (addr, _addr))
+ raise errors.RadioError("Radio send unexpected block")
+ cs = _checksum(result[1:-2])
+ if cs != ord(result[-2]):
+ _finish(radio)
+ LOG.debug("Calculated: %02x" % cs)
+ LOG.debug("Actual: %02x" % ord(result[-2]))
+ raise errors.RadioError("Block at 0x%04x failed checksum" % addr)
+ return data
+
+
+def _finish(radio):
+ endframe = "\x45\x4E\x44"
+ _echo_write(radio, endframe)
+ result = radio.pipe.read(1)
+ if result != "\x06":
+ LOG.error("Got:\n%s" % util.hexprint(result))
+ raise errors.RadioError("Radio did not finish cleanly")
+
+
+def do_download(radio):
+
+ _ident(radio)
+
+ _memobj = None
+ data = ""
+
+ for addr in range(0, radio._memsize, 0x10):
+ block = _send(radio, 'R', addr, 0x10)
+ data += block
+ status = chirp_common.Status()
+ status.cur = len(data)
+ status.max = radio._memsize
+ status.msg = "Downloading from radio"
+ radio.status_fn(status)
+
+ _finish(radio)
+
+ return memmap.MemoryMap(data)
+
+
+def do_upload(radio):
+ model, bandlimit = _ident(radio)
+ _embedded = radio._memobj.embedded_msg
+
+ if model != str(_embedded.radio_type):
+ LOG.warning('radio and image model types differ')
+ LOG.warning('model type (radio): %s' % str(model))
+ LOG.warning('model type (image): %s' % str(_embedded.radio_type))
+
+ _finish(radio)
+
+ msg = ("The upload was stopped because the radio type "
+ "of the image (%s) does not match that "
+ "of the radio (%s).")
+ raise errors.RadioError(msg % (str(_embedded.radio_type),
str(model)))
+
+ if bandlimit != int(_embedded.mode):
+ if str(_embedded.radio_type) == "RT98U":
+ image_band_limits = LIST_RT98U_FREQS[int(_embedded.mode)]
+ if str(_embedded.radio_type) == "RT98V":
+ image_band_limits = LIST_RT98V_FREQS[int(_embedded.mode)]
+ if model == "RT98U":
+ radio_band_limits = LIST_RT98U_FREQS[int(bandlimit)]
+ if model == "RT98V":
+ radio_band_limits = LIST_RT98V_FREQS[int(bandlimit)]
+
+ LOG.warning('radio and image band limits differ')
+ LOG.warning('image band limits: %s' % image_band_limits)
+ LOG.warning('radio band limits: %s' % radio_band_limits)
+
+ _finish(radio)
+
+ msg = ("The upload was stopped because the band limits "
+ "of the image (%s) does not match that "
+ "of the radio (%s).")
+ raise errors.RadioError(msg % (image_band_limits,
radio_band_limits))
+
+ try:
+ for start, end in radio._ranges:
+ for addr in range(start, end, 0x10):
+ block = radio._mmap[addr:addr+0x10]
+ _send(radio, 'W', addr, len(block), block)
+ status = chirp_common.Status()
+ status.cur = addr
+ status.max = end
+ status.msg = "Uploading to Radio"
+ radio.status_fn(status)
+ _finish(radio)
+ except errors.RadioError:
+ raise
+ except Exception as e:
+ _finish(radio)
+ raise errors.RadioError('Failed to upload to radio: %s' % e)
+
+
+#
+# The base class, extended for use with other models
+#
+class Rt98BaseRadio(chirp_common.CloneModeRadio,
+ chirp_common.ExperimentalRadio):
+ """Retevis RT98 Base"""
+ VENDOR = "Retevis"
+ MODEL = "RT98 Base"
+ BAUD_RATE = 9600
+
+ _memsize = 0x3E00
+ _ranges = [(0x0000, 0x3310),
+ (0x3320, 0x3390)]
+
+ @classmethod
+ def get_prompts(cls):
+ rp = chirp_common.RadioPrompts()
+ rp.experimental = ("The Retevis RT98 driver is an beta version."
+ "Proceed with Caution and backup your data")
+ return rp
+
+ def get_features(self):
+ _embedded = self._memobj.embedded_msg
+ rf = chirp_common.RadioFeatures()
+ rf.has_settings = True
+ rf.has_bank = False
+ rf.can_odd_split = True
+ rf.has_name = True
+ if _embedded.mode == 0: # PMR or FreeNet
+ rf.has_offset = False
+ else:
+ rf.has_offset = True
+ rf.has_ctone = True
+ rf.has_cross = True
+ rf.has_tuning_step = False
+ rf.has_dtcs = True
+ rf.has_rx_dtcs = True
+ rf.has_dtcs_polarity = True
+ rf.valid_skips = ["", "S"]
+ rf.memory_bounds = (1, 199)
+ rf.valid_name_length = 6
+ if _embedded.mode == 0: # PMR or FreeNet
+ rf.valid_duplexes = ['']
+ else:
+ rf.valid_duplexes = DUPLEXES + ['split', 'off']
+ rf.valid_characters = chirp_common.CHARSET_UPPER_NUMERIC + "- "
+ if _embedded.mode == 0: # PMR or FreeNet
+ rf.valid_modes = ['NFM']
+ else:
+ rf.valid_modes = ['FM', 'NFM']
+ rf.valid_tmodes = ['', 'Tone', 'TSQL', 'DTCS', 'Cross']
+ rf.valid_cross_modes = CROSS_MODES
+ if _embedded.mode == 0: # PMR or FreeNet
+ if str(_embedded.radio_type) == "RT98U":
+ rf.valid_power_levels = PMR_POWER_LEVELS
+ if str(_embedded.radio_type) == "RT98V":
+ rf.valid_power_levels = FREENET_POWER_LEVELS
+ else:
+ rf.valid_power_levels = POWER_LEVELS
+ rf.valid_dtcs_codes = chirp_common.ALL_DTCS_CODES
+
+ try:
+ rf.valid_bands = get_band_limits_Hz(
+ str(_embedded.radio_type),
+ int(_embedded.mode))
+ except TypeError as e:
+ # If we're asked without memory loaded, assume the most
permissive
+ rf.valid_bands = get_band_limits_Hz(str(_embedded.radio_type),
1)
+ except Exception as e:
+ LOG.error('Failed to get band limits for RT98: %s' % e)
+ rf.valid_bands = get_band_limits_Hz(str(_embedded.radio_type),
1)
+
+ rf.valid_tuning_steps = TUNING_STEPS
+ return rf
+
+ def validate_memory(self, mem):
+ _embedded = self._memobj.embedded_msg
+ msgs = ""
+ msgs = chirp_common.CloneModeRadio.validate_memory(self, mem)
+
+ # FreeNet and PMR radio types
+ if _embedded.mode == 0: # PMR or FreeNet
+ freq = float(mem.freq) / 1000000
+
+ # FreeNet
+ if str(_embedded.radio_type) == "RT98V":
+ if freq not in FREENET_FREQS:
+ _msg_freq = 'Memory location not a valid FreeNet
frequency'
+ # warn user invalid frequency
+ msgs.append(chirp_common.ValidationError(_msg_freq))
+
+ # PMR
+ if str(_embedded.radio_type) == "RT98U":
+ if freq not in PMR_FREQS:
+ _msg_freq = 'Memory location not a valid PMR frequency'
+ # warn user invalid frequency
+ msgs.append(chirp_common.ValidationError(_msg_freq))
+
+ return msgs
+
+ # Do a download of the radio from the serial port
+ def sync_in(self):
+ self._mmap = do_download(self)
+ self.process_mmap()
+
+ # Do an upload of the radio to the serial port
+ def sync_out(self):
+ do_upload(self)
+
+ def process_mmap(self):
+ self._memobj = bitwise.parse(MEM_FORMAT, self._mmap)
+
+ # Return a raw representation of the memory object, which
+ # is very helpful for development
+ def get_raw_memory(self, number):
+ return repr(self._memobj.memory[number - 1])
+
+ def _get_dcs_index(self, _mem, which):
+ base = getattr(_mem, '%scode' % which)
+ extra = getattr(_mem, '%sdcsextra' % which)
+ return (int(extra) << 8) | int(base)
+
+ def _set_dcs_index(self, _mem, which, index):
+ base = getattr(_mem, '%scode' % which)
+ extra = getattr(_mem, '%sdcsextra' % which)
+ base.set_value(index & 0xFF)
+ extra.set_value(index >> 8)
+
+ # Extract a high-level memory object from the low-level memory map
+ # This is called to populate a memory in the UI
+ def get_memory(self, number):
+ _embedded = self._memobj.embedded_msg
+ # Get a low-level memory object mapped to the image
+ _mem = self._memobj.memory[number - 1]
+
+ # get flag info
+ cbyte = (number - 1) / 8
+ cbit = 7 - ((number - 1) % 8)
+ setflag = self._memobj.csetflag[cbyte].c[cbit]
+ skipflag = self._memobj.cskipflag[cbyte].c[cbit]
+
+ mem = chirp_common.Memory()
+
+ mem.number = number # Set the memory number
+
+ # We'll consider any blank (i.e. 0MHz frequency) to be empty
+ if _mem.freq == 0:
+ mem.empty = True
+ return mem
+
+ if setflag == 0:
+ mem.empty = True
+ return mem
+
+ if _mem.get_raw()[0] == "\xFF":
+ mem.empty = True
+ return mem
+
+ # set the name
+ mem.name = str(_mem.name).rstrip() # Set the alpha tag
+
+ # Convert your low-level frequency and offset to Hertz
+ mem.freq = int(_mem.freq) * 10
+ mem.offset = int(_mem.offset) * 10
+
+ # Set the duplex flags
+ if _mem.duplex == DUPLEX_POSSPLIT:
+ mem.duplex = '+'
+ elif _mem.duplex == DUPLEX_NEGSPLIT:
+ mem.duplex = '-'
+ elif _mem.duplex == DUPLEX_NOSPLIT:
+ mem.duplex = ''
+ elif _mem.duplex == DUPLEX_ODDSPLIT:
+ mem.duplex = 'split'
+ else:
+ LOG.error('%s: get_mem: unhandled duplex: %02x' %
+ (mem.name, _mem.duplex))
+
+ # handle tx off
+ if _mem.tx_off:
+ mem.duplex = 'off'
+
+ # Set the channel width
+ if _mem.channel_width == CHANNEL_WIDTH_12d5kHz:
+ mem.mode = 'NFM'
+ elif _embedded.mode == 0: # PMR or FreeNet
+ LOG.info('PMR and FreeNet channels must be Channel Width
12.5kHz')
+ mem.mode = 'NFM'
+ elif _mem.channel_width == CHANNEL_WIDTH_25kHz:
+ mem.mode = 'FM'
+ elif _mem.channel_width == CHANNEL_WIDTH_20kHz:
+ LOG.info(
+ '%s: get_mem: promoting 20kHz channel width to 25kHz' %
+ mem.name)
+ mem.mode = 'FM'
+ else:
+ LOG.error('%s: get_mem: unhandled channel width: 0x%02x' %
+ (mem.name, _mem.channel_width))
+
+ # set the power level
+ if _embedded.mode == 0: # PMR or FreeNet
+ if str(_embedded.radio_type) == "RT98U":
+ LOG.info('using PMR power levels')
+ _levels = PMR_POWER_LEVELS
+ if str(_embedded.radio_type) == "RT98V":
+ LOG.info('using FreeNet power levels')
+ _levels = FREENET_POWER_LEVELS
+ else: # COM or COMII
+ LOG.info('using general power levels')
+ _levels = POWER_LEVELS
+
+ if _mem.txpower == TXPOWER_LOW:
+ mem.power = _levels[0]
+ elif _embedded.mode == 0: # PMR or FreeNet
+ LOG.info('FreeNet or PMR channel is not set to TX Power Low')
+ LOG.info('Setting channel to TX Power Low')
+ mem.power = _levels[0]
+ elif _mem.txpower == TXPOWER_MED:
+ mem.power = _levels[1]
+ elif _mem.txpower == TXPOWER_HIGH:
+ mem.power = _levels[2]
+ else:
+ LOG.error('%s: get_mem: unhandled power level: 0x%02x' %
+ (mem.name, _mem.txpower))
+
+ # CTCSS Tones and DTCS Codes
+ rxtone = txtone = None
+
+ rxmode = TMODES[_mem.rxtmode]
+ txmode = TMODES[_mem.txtmode]
+
+ if rxmode == "Tone":
+ rxtone = TONES[_mem.rxtone]
+ elif rxmode == "DTCS":
+ rxtone = chirp_common.ALL_DTCS_CODES[self._get_dcs_index(
+ _mem, 'rx')]
+
+ if txmode == "Tone":
+ txtone = TONES[_mem.txtone]
+ elif txmode == "DTCS":
+ txtone = chirp_common.ALL_DTCS_CODES[self._get_dcs_index(
+ _mem, 'tx')]
+
+ rxpol = _mem.rxinv and "R" or "N"
+ txpol = _mem.txinv and "R" or "N"
+
+ chirp_common.split_tone_decode(mem,
+ (txmode, txtone, txpol),
+ (rxmode, rxtone, rxpol))
+
+ # Check if this memory is in the scan enabled list
+ mem.skip = "S" if skipflag == 0 else ""
+
+ # Extra
+ mem.extra = RadioSettingGroup("extra", "Extra")
+
+ rs = RadioSettingValueBoolean(bool(_mem.busychannellockout))
+ rset = RadioSetting("busychannellockout", "Busy channel lockout",
rs)
+ mem.extra.append(rset)
+
+ rs = RadioSettingValueBoolean(bool(_mem.reverse))
+ rset = RadioSetting("reverse", "Reverse", rs)
+ mem.extra.append(rset)
+
+ rs = RadioSettingValueBoolean(bool(_mem.talkaround))
+ rset = RadioSetting("talkaround", "Talk around", rs)
+ mem.extra.append(rset)
+
+ rs = RadioSettingValueBoolean(bool(_mem.squelch_mode))
+ rset = RadioSetting("squelch_mode", "Squelch mode", rs)
+ mem.extra.append(rset)
+
+ return mem
+
+ # Store details about a high-level memory to the memory map
+ # This is called when a user edits a memory in the UI
+ def set_memory(self, mem):
+ _embedded = self._memobj.embedded_msg
+ # Get a low-level memory object mapped to the image
+
+ _mem = self._memobj.memory[mem.number - 1]
+
+ cbyte = (mem.number - 1) / 8
+ cbit = 7 - ((mem.number - 1) % 8)
+
+ if mem.empty:
+ self._memobj.csetflag[cbyte].c[cbit] = 0
+ self._memobj.cskipflag[cbyte].c[cbit] = 0
+ _mem.set_raw('\xff' * (_mem.size() / 8))
+ return
+
+ _mem.set_raw('\x00' * (_mem.size() / 8))
+
+ # set the occupied bitfield
+ self._memobj.csetflag[cbyte].c[cbit] = 1
+ # set the scan add bitfield
+ self._memobj.cskipflag[cbyte].c[cbit] = 0 if (mem.skip == "S")
else 1
+
+ _mem.freq = mem.freq / 10 # Convert to low-level
frequency
+ _mem.offset = mem.offset / 10 # Convert to low-level
frequency
+
+ # Store the alpha tag
+ _mem.name = mem.name.ljust(6)[:6] # Store the alpha tag
+
+ # Set duplex bitfields
+ if mem.duplex == '+':
+ _mem.duplex = DUPLEX_POSSPLIT
+ elif mem.duplex == '-':
+ _mem.duplex = DUPLEX_NEGSPLIT
+ elif mem.duplex == '':
+ _mem.duplex = DUPLEX_NOSPLIT
+ elif mem.duplex == 'split':
+ diff = mem.offset - mem.freq
+ _mem.duplex = DUPLEXES.index("-") \
+ if diff < 0 else DUPLEXES.index("+")
+ _mem.offset = abs(diff) / 10
+ else:
+ LOG.error('%s: set_mem: unhandled duplex: %s' %
+ (mem.name, mem.duplex))
+
+ # handle tx off
+ _mem.tx_off = 0
+ if mem.duplex == 'off':
+ _mem.tx_off = 1
+
+ # Set the channel width - remember we promote 20kHz channels to FM
+ # on import, so don't handle them here
+ if mem.mode == 'FM':
+ _mem.channel_width = CHANNEL_WIDTH_25kHz
+ elif mem.mode == 'NFM':
+ _mem.channel_width = CHANNEL_WIDTH_12d5kHz
+ else:
+ LOG.error('%s: set_mem: unhandled mode: %s' % (
+ mem.name, mem.mode))
+
+ # CTCSS Tones and DTCS Codes
+ ((txmode, txtone, txpol),
+ (rxmode, rxtone, rxpol)) = chirp_common.split_tone_encode(mem)
+
+ _mem.txtmode = TMODES.index(txmode)
+
+ _mem.rxtmode = TMODES.index(rxmode)
+
+ if txmode == "Tone":
+ _mem.txtone = TONES.index(txtone)
+ elif txmode == "DTCS":
+ self._set_dcs_index(_mem, 'tx',
+ chirp_common.ALL_DTCS_CODES.index(txtone))
+
+ _mem.squelch_mode = False
+ if rxmode == "Tone":
+ _mem.rxtone = TONES.index(rxtone)
+ _mem.squelch_mode = True
+ elif rxmode == "DTCS":
+ self._set_dcs_index(_mem, 'rx',
+ chirp_common.ALL_DTCS_CODES.index(rxtone))
+ _mem.squelch_mode = True
+
+ _mem.txinv = txpol == "R"
+ _mem.rxinv = rxpol == "R"
+
+ # set the power level
+ if mem.power == POWER_LEVELS[0]:
+ _mem.txpower = TXPOWER_LOW
+ elif mem.power == POWER_LEVELS[1]:
+ _mem.txpower = TXPOWER_MED
+ elif mem.power == POWER_LEVELS[2]:
+ _mem.txpower = TXPOWER_HIGH
+ else:
+ LOG.error('%s: set_mem: unhandled power level: %s' %
+ (mem.name, mem.power))
+
+ # extra settings
+ for setting in mem.extra:
+ setattr(_mem, setting.get_name(), setting.value)
+
+ def _get_settings(self):
+ _embedded = self._memobj.embedded_msg
+ _settings = self._memobj.settings
+ _settings2 = self._memobj.settings2
+ _settings3 = self._memobj.settings3
+ _slabel = self._memobj.slabel
+
+ function = RadioSettingGroup("function", "Function Setup")
+ group = RadioSettings(function)
+
+ # Function Setup
+ # MODE SET
+ rs = RadioSettingValueList(LIST_DISPLAY_MODE,
+
LIST_DISPLAY_MODE[_settings.display_mode])
+ rset = RadioSetting("display_mode", "Display Mode", rs)
+ function.append(rset)
+
+ rs = RadioSettingValueInteger(1, 199, _settings3.ch_number + 1)
+ rset = RadioSetting("settings3.ch_number", "Channel Number", rs)
+ function.append(rset)
+
+ # DISPLAY SET
+ def _filter(name):
+ filtered = ""
+ for char in str(name):
+ if char in chirp_common.CHARSET_ASCII:
+ filtered += char
+ else:
+ filtered += " "
+ return filtered
+
+ val = RadioSettingValueString(0, 6, _filter(_slabel.startname))
+ rs = RadioSetting("slabel.startname", "Startup Label", val)
+ function.append(rs)
+
+ # VOL SET
+ rs = RadioSettingValueBoolean(bool(_settings.beep))
+ rset = RadioSetting("beep", "Beep Prompt", rs)
+ function.append(rset)
+
+ rs = RadioSettingValueInteger(1, 30, _settings.volume)
+ rset = RadioSetting("volume", "Volume Level", rs)
+ function.append(rset)
+
+ rs = RadioSettingValueInteger(1, 16, _settings.mic_gain)
+ rset = RadioSetting("mic_gain", "Mic Gain", rs)
+ function.append(rset)
+
+ # ON/OFF SET
+ rs = RadioSettingValueList(LIST_APO,
+ LIST_APO[_settings.auto_power_off])
+ rset = RadioSetting("auto_power_off", "Auto Power Off", rs)
+ function.append(rset)
+
+ rs = RadioSettingValueList(LIST_AOP,
LIST_AOP[_settings.auto_power_on])
+ rset = RadioSetting("auto_power_on", "Power On Method", rs)
+ function.append(rset)
+
+ # STE SET
+ rs = RadioSettingValueList(LIST_STE_FREQ,
+ LIST_STE_FREQ[_settings.ste_frequency])
+ rset = RadioSetting("ste_frequency", "STE Frequency", rs)
+ function.append(rset)
+
+ rs = RadioSettingValueList(LIST_STE_TYPE,
+ LIST_STE_TYPE[_settings.ste_type])
+ rset = RadioSetting("ste_type", "STE Type", rs)
+ function.append(rset)
+
+ # FUNCTION SET
+ rs = RadioSettingValueList(LIST_STEP,
LIST_STEP[_settings.tuning_step])
+ rset = RadioSetting("tuning_step", "Tuning Step", rs)
+ function.append(rset)
+
+ rs = RadioSettingValueList(LIST_SQUELCH,
+ LIST_SQUELCH[_settings.squelch])
+ rset = RadioSetting("squelch", "Squelch Level", rs)
+ function.append(rset)
+
+ rs = RadioSettingValueBoolean(bool(_settings.sql_key_function))
+ rset = RadioSetting("sql_key_function", "SQL Key Function", rs)
+ function.append(rset)
+
+ rs = RadioSettingValueList(LIST_TIMEOUT,
+ LIST_TIMEOUT[_settings.timeout_timer])
+ rset = RadioSetting("timeout_timer", "Timeout Timer", rs)
+ function.append(rset)
+
+ # uncategorized
+ rs = RadioSettingValueBoolean(bool(_settings.save_chan_param))
+ rset = RadioSetting("save_chan_param", "Save Channel Parameters",
rs)
+ function.append(rset)
+
+ rs = RadioSettingValueBoolean(bool(_settings.forbid_chan_menu))
+ rset = RadioSetting("forbid_chan_menu", "Forbid Channel Menu", rs)
+ function.append(rset)
+
+ rs = RadioSettingValueBoolean(bool(not
_settings.forbid_initialize))
+ rset = RadioSetting("forbid_initialize", "Forbid Initialize", rs)
+ function.append(rset)
+
+ rs = RadioSettingValueBoolean(bool(_settings.forbid_setting))
+ rset = RadioSetting("forbid_setting", "Forbid Setting", rs)
+ function.append(rset)
+
+ # Information Of Scanning Channel
+ scanning = RadioSettingGroup("scanning", "Scanning Setup")
+ group.append(scanning)
+
+ rs = RadioSettingValueBoolean(bool(_settings2.scan_mode))
+ rset = RadioSetting("settings2.scan_mode", "Scan Mode", rs)
+ scanning.append(rset)
+
+ rs = RadioSettingValueList(LIST_PRIORITY_CH,
+
LIST_PRIORITY_CH[_settings2.priority_ch])
+ rset = RadioSetting("settings2.priority_ch", "Priority Channel",
rs)
+ scanning.append(rset)
+
+ rs = RadioSettingValueInteger(1, 199, _settings2.priority_ch1 + 1)
+ rset = RadioSetting("settings2.priority_ch1", "Priority Channel
1", rs)
+ scanning.append(rset)
+
+ rs = RadioSettingValueInteger(1, 199, _settings2.priority_ch2 + 1)
+ rset = RadioSetting("settings2.priority_ch2", "Priority Channel
2", rs)
+ scanning.append(rset)
+
+ rs = RadioSettingValueList(LIST_REVERT_CH,
+ LIST_REVERT_CH[_settings2.revert_ch])
+ rset = RadioSetting("settings2.revert_ch", "Revert Channel", rs)
+ scanning.append(rset)
+
+ rs = RadioSettingValueList(LIST_TIME46,
+
LIST_TIME46[_settings2.look_back_time_a])
+ rset = RadioSetting("settings2.look_back_time_a",
+ "Look Back Time A", rs)
+ scanning.append(rset)
+
+ rs = RadioSettingValueList(LIST_TIME46,
+
LIST_TIME46[_settings2.look_back_time_b])
+ rset = RadioSetting("settings2.look_back_time_b",
+ "Look Back Time B", rs)
+ scanning.append(rset)
+
+ rs = RadioSettingValueList(LIST_TIME50,
+
LIST_TIME50[_settings2.dropout_delay_time])
+ rset = RadioSetting("settings2.dropout_delay_time",
+ "Dropout Delay Time", rs)
+ scanning.append(rset)
+
+ rs = RadioSettingValueList(LIST_TIME50,
+ LIST_TIME50[_settings2.dwell_time])
+ rset = RadioSetting("settings2.dwell_time", "Dwell Time", rs)
+ scanning.append(rset)
+
+ # Embedded Message
+ embedded = RadioSettingGroup("embedded", "Embedded Message")
+ group.append(embedded)
+
+ rs = RadioSettingValueString(0, 5, _filter(_embedded.radio_type))
+ rs.set_mutable(False)
+ rset = RadioSetting("embedded_msg.radio_type", "Radio Type", rs)
+ embedded.append(rset)
+
+ if str(_embedded.radio_type) == "RT98V":
+ options = LIST_RT98V_MODES
+ else:
+ options = LIST_RT98U_MODES
+ rs = RadioSettingValueList(options, options[_embedded.mode])
+ rs.set_mutable(False)
+ rset = RadioSetting("embedded_msg.mode", "Mode", rs)
+ embedded.append(rset)
+
+ # frequency
+ if str(_embedded.radio_type) == "RT98V":
+ options = LIST_RT98V_FREQS
+ else:
+ options = LIST_RT98U_FREQS
+ rs = RadioSettingValueList(options, options[_settings3.bandlimit])
+ rs.set_mutable(False)
+ rset = RadioSetting("settings3.bandlimit", "Frequency", rs)
+ embedded.append(rset)
+
+ rs = RadioSettingValueString(0, 10, _filter(_embedded.date_mfg))
+ rs.set_mutable(False)
+ rset = RadioSetting("embedded_msg.date_mfg", "Production Date", rs)
+ embedded.append(rset)
+
+ rs = RadioSettingValueString(0, 4, _filter(_embedded.mcu_version))
+ rs.set_mutable(False)
+ rset = RadioSetting("embedded_msg.mcu_version", "MCU Version", rs)
+ embedded.append(rset)
+
+ return group
+
+ def get_settings(self):
+ try:
+ return self._get_settings()
+ except:
+ import traceback
+ LOG.error("failed to parse settings")
+ traceback.print_exc()
+ return None
+
+ 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 == "ch_number":
+ setattr(obj, setting, int(element.value) - 1)
+ elif setting == "forbid_initialize":
+ setattr(obj, setting, not int(element.value))
+ elif setting == "priority_ch1":
+ setattr(obj, setting, int(element.value) - 1)
+ elif setting == "priority_ch2":
+ 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
+
+
+(a)directory.register
+class Rt98Radio(Rt98BaseRadio):
+ """Retevis RT98"""
+ VENDOR = "Retevis"
+ MODEL = "RT98"
+ # Allowed radio types is a dict keyed by model of a list of version
+ # strings
+ ALLOWED_RADIO_TYPES = {'RT98V': ['V100'],
+ 'RT98U': ['V100']}
diff -r f586574bc878 -r 0eab8146b294 tools/cpep8.manifest
--- a/tools/cpep8.manifest Thu Jun 17 21:57:05 2021 -0400
+++ b/tools/cpep8.manifest Sat Jul 03 14:13:35 2021 -0400
@@ -83,6 +83,7 @@
./chirp/drivers/retevis_rt23.py
./chirp/drivers/retevis_rt26.py
./chirp/drivers/retevis_rt76p.py
+./chirp/drivers/retevis_rt98.py
./chirp/drivers/rfinder.py
./chirp/drivers/tdxone_tdq8a.py
./chirp/drivers/template.py
1
0

24 Jun '21
# HG changeset patch
# User Kosta A. <ve7kcy(a)gmail.com>
# Date 1624595990 25200
# Thu Jun 24 21:39:50 2021 -0700
# Branch open-recent
# Node ID bea11de983007eac96d69b3a0aeccfdcaab1c2a7
# Parent f586574bc8786fd6bef1e5d54d08d381c81edd47
Add support for clearing recently opened files. #9127
o Add Clear Recently Open files menu item
o Order recently opened files list by most recent
o Normalize camel case accross all menu items
diff --git a/chirp/ui/mainapp.py b/chirp/ui/mainapp.py
--- a/chirp/ui/mainapp.py
+++ b/chirp/ui/mainapp.py
@@ -339,6 +339,10 @@
if not fname:
return
+ if not os.path.exists(fname):
+ LOG.error("Unable to find file %s" % fname)
+ return
+
self.record_recent_file(fname)
if icf.is_icf_file(fname):
@@ -531,54 +535,61 @@
return recent
def _set_recent_list(self, recent):
- for fn in recent:
- CONF.set("recent%i" % recent.index(fn), fn, "state")
+ for index in range(0, KEEP_RECENT):
+ key = "recent%i" % index
+ if (index < len(recent)):
+ fn = recent[index]
+ CONF.set(key, fn, "state")
+ else:
+ CONF.remove_option(key, "state")
def update_recent_files(self):
- i = 0
- for fname in self._get_recent_list():
- action_name = "recent%i" % i
+ recent_files = self._get_recent_list()
+ for index in range(0, KEEP_RECENT):
+ action_name = "recent%i" % index
path = "/MenuBar/file/recent"
old_action = self.menu_ag.get_action(action_name)
if old_action:
+ old_action.set_visible(False)
self.menu_ag.remove_action(old_action)
- file_basename = os.path.basename(fname).replace("_", "__")
- widget_name = action_name
- widget_label = "_%i. %s" % (i + 1, file_basename)
- widget_tip = _("Open recent file") + (" {name}").format(name=fname)
- widget_icon = ""
- action = gtk.Action(widget_name, widget_label,
- widget_tip, widget_icon)
+ if (index < len(recent_files)):
+ fname = recent_files[index]
+ widget_label = os.path.basename(fname).replace("_", "__")
+ widget_tip = _("Open recent file") + (" {name}").format(name=fname)
+ widget_path = path + "/" + action_name
- action.connect("activate", lambda a, f: self.do_open(f), fname)
- mid = self.menu_uim.new_merge_id()
- self.menu_uim.add_ui(mid, path,
- action_name, action_name,
- gtk.UI_MANAGER_MENUITEM, False)
- self.menu_ag.add_action(action)
+ action = gtk.Action(action_name, widget_label, widget_tip, "")
+ action.connect("activate", lambda a, f: self.do_open(f), fname)
+
+ mid = self.menu_uim.new_merge_id()
+ self.menu_uim.add_ui(mid, path,
+ action_name, action_name,
+ gtk.UI_MANAGER_MENUITEM, True)
+ self.menu_ag.add_action(action)
- widget_uim_path = path + "/" + widget_name
- try:
- widget_item = self.menu_uim.get_widget(widget_uim_path)
- widget_item.set_tooltip_text(widget_tip)
- except:
- pass
-
- i += 1
+ try:
+ widget = self.menu_uim.get_widget(widget_path)
+ widget.set_tooltip_text(tip)
+ except:
+ pass
- def record_recent_file(self, filename):
-
+ def record_recent_file(self, fname):
recent_files = self._get_recent_list()
- if filename not in recent_files:
- if len(recent_files) == KEEP_RECENT:
- del recent_files[-1]
- recent_files.insert(0, filename)
- self._set_recent_list(recent_files)
+ if fname in recent_files:
+ recent_files.remove(fname)
+ if len(recent_files) == KEEP_RECENT:
+ recent_files.pop(0)
+ recent_files.append(fname)
+ self._set_recent_list(recent_files)
self.update_recent_files()
+ def clear_recent_files(self):
+ self._set_recent_list([])
+ self.update_recent_files();
+
def import_stock_config(self, action, config):
eset = self.get_current_editorset()
count = eset.do_import(config)
@@ -621,9 +632,9 @@
"")
action.connect("activate", self.import_stock_config, config)
mid = self.menu_uim.new_merge_id()
- mid = self.menu_uim.add_ui(mid, path,
- action_name, action_name,
- gtk.UI_MANAGER_MENUITEM, False)
+ self.menu_uim.add_ui(mid, path,
+ action_name, action_name,
+ gtk.UI_MANAGER_MENUITEM, False)
self.menu_ag.add_action(action)
def _do_open_action(config):
@@ -637,9 +648,9 @@
"")
action.connect("activate", lambda a, c: self.do_open(c), config)
mid = self.menu_uim.new_merge_id()
- mid = self.menu_uim.add_ui(mid, path,
- action_name, action_name,
- gtk.UI_MANAGER_MENUITEM, False)
+ self.menu_uim.add_ui(mid, path,
+ action_name, action_name,
+ gtk.UI_MANAGER_MENUITEM, False)
self.menu_ag.add_action(action)
configs = glob(os.path.join(stock_dir, "*.csv"))
@@ -881,6 +892,9 @@
count = eset.do_import(filen)
reporting.report_model_usage(eset.rthread.radio, "import", count > 0)
+ def do_clear_recently_opened(self):
+ self.clear_recent_files()
+
def do_dmrmarc_prompt(self):
fields = {"1City": (gtk.Entry(), lambda x: x),
"2State": (gtk.Entry(), lambda x: x),
@@ -1805,6 +1819,8 @@
self.do_close()
elif action == "import":
self.do_import()
+ elif action == "clearrecent":
+ self.do_clear_recently_opened()
elif action in ["qdmrmarc", "idmrmarc"]:
self.do_dmrmarc(action[0] == "i")
elif action in ["qrfinder", "irfinder"]:
@@ -1868,7 +1884,10 @@
<menuitem action="new"/>
<menuitem action="open"/>
<menu action="openstock" name="openstock"/>
- <menu action="recent" name="recent"/>
+ <menu action="recent" name="recent">
+ <separator/>
+ <menuitem action="clearrecent"/>
+ </menu>
<menuitem action="save"/>
<menuitem action="saveas"/>
<menuitem action="loadmod"/>
@@ -1961,8 +1980,9 @@
('file', None, _("_File"), None, None, self.mh),
('new', gtk.STOCK_NEW, None, None, None, self.mh),
('open', gtk.STOCK_OPEN, None, None, None, self.mh),
- ('openstock', None, _("Open stock config"), None, None, self.mh),
- ('recent', None, _("_Recent"), None, None, self.mh),
+ ('openstock', None, _("Open Stock Config"), None, None, self.mh),
+ ('recent', None, _("Open _Recent"), None, None, self.mh),
+ ('clearrecent', None, _("Clear Recently Opened"), None, None, self.mh),
('save', gtk.STOCK_SAVE, None, None, None, self.mh),
('saveas', gtk.STOCK_SAVE_AS, None, None, None, self.mh),
('loadmod', None, _("Load Module"), None, None, self.mh),
@@ -1985,13 +2005,13 @@
('view', None, _("_View"), None, None, self.mh),
('columns', None, _("Columns"), None, None, self.mh),
('viewdeveloper', None, _("Developer"), None, None, self.mh),
- ('devshowraw', None, _('Show raw memory'),
+ ('devshowraw', None, _('Show Raw Memory'),
"%s<Shift>r" % CTRL_KEY, None, self.mh),
- ('devdiffraw', None, _("Diff raw memories"),
+ ('devdiffraw', None, _("Diff Raw Memories"),
"%s<Shift>d" % CTRL_KEY, None, self.mh),
- ('devdifftab', None, _("Diff tabs"),
+ ('devdifftab', None, _("Diff Tabs"),
"%s<Shift>t" % CTRL_KEY, None, self.mh),
- ('language', None, _("Change language"), None, None, self.mh),
+ ('language', None, _("Change Language"), None, None, self.mh),
('radio', None, _("_Radio"), None, None, self.mh),
('download', None, _("Download From Radio"),
"%sd" % ALT_KEY, None, self.mh),
@@ -1999,7 +2019,7 @@
"%su" % ALT_KEY, None, self.mh),
('import', None, _("Import"), "%si" % ALT_KEY, None, self.mh),
('export', None, _("Export"), "%se" % ALT_KEY, None, self.mh),
- ('importsrc', None, _("Import from data source"),
+ ('importsrc', None, _("Import From Data Source"),
None, None, self.mh),
('idmrmarc', None, _("DMR-MARC Repeaters"), None, None, self.mh),
('iradioref', None, _("RadioReference"), None, None, self.mh),
@@ -2009,12 +2029,12 @@
None, None, self.mh),
('irfinder', None, _("RFinder"), None, None, self.mh),
('irbook', None, _("RepeaterBook"), None, None, self.mh),
- ('irbookpolitical', None, _("RepeaterBook political query"), None,
+ ('irbookpolitical', None, _("RepeaterBook Political Query"), None,
None, self.mh),
- ('irbookproximity', None, _("RepeaterBook proximity query"), None,
+ ('irbookproximity', None, _("RepeaterBook Proximity Query"), None,
None, self.mh),
('ipr', None, _("przemienniki.net"), None, None, self.mh),
- ('querysrc', None, _("Query data source"), None, None, self.mh),
+ ('querysrc', None, _("Query Data Source"), None, None, self.mh),
('qdmrmarc', None, _("DMR-MARC Repeaters"), None, None, self.mh),
('qradioref', None, _("RadioReference"), None, None, self.mh),
('qradioreference', None, _("RadioReference.com US"),
@@ -2024,16 +2044,16 @@
('qrfinder', None, _("RFinder"), None, None, self.mh),
('qpr', None, _("przemienniki.net"), None, None, self.mh),
('qrbook', None, _("RepeaterBook"), None, None, self.mh),
- ('qrbookpolitical', None, _("RepeaterBook political query"), None,
+ ('qrbookpolitical', None, _("RepeaterBook Political Query"), None,
None, self.mh),
- ('qrbookproximity', None, _("RepeaterBook proximity query"), None,
+ ('qrbookproximity', None, _("RepeaterBook Proximity Query"), None,
None, self.mh),
('export_chirp', None, _("CHIRP Native File"),
None, None, self.mh),
('export_csv', None, _("CSV File"), None, None, self.mh),
- ('stock', None, _("Import from stock config"),
+ ('stock', None, _("Import From Stock Config"),
None, None, self.mh),
- ('channel_defaults', None, _("Channel defaults"),
+ ('channel_defaults', None, _("Channel Defaults"),
None, None, self.mh),
('cancelq', gtk.STOCK_STOP, None, "Escape", None, self.mh),
('help', None, _('Help'), None, None, self.mh),
@@ -2254,8 +2274,6 @@
vbox = gtk.VBox(False, 2)
- self._recent = []
-
self.menu_ag = None
mbar = self.make_menubar()
1
0

[chirp_devel] [PATCH] Optimizing generic csv files load times by removing duplicate load for an empty list. Fixes #8991
by Kosta A. 23 Jun '21
by Kosta A. 23 Jun '21
23 Jun '21
# HG changeset patch
# User Kosta A. <ve7kcy(a)gmail.com>
# Date 1624429267 25200
# Tue Jun 22 23:21:07 2021 -0700
# Branch generic-csv
# Node ID 6b816f380d29518e9d45fe6a6a8fa32d3e96b805
# Parent f586574bc8786fd6bef1e5d54d08d381c81edd47
Optimizing generic csv files load times by removing duplicate load for an empty list. 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
@@ -73,14 +73,12 @@
"Comment": (str, "comment"),
}
- def _blank(self):
+ def _blank(self, setDefault=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 (setDefault):
+ self.memories[0].empty = False
+ self.memories[0].freq = 146010000
def __init__(self, pipe):
chirp_common.FileBackedRadio.__init__(self, None)
@@ -92,7 +90,7 @@
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()
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):
1
0
# HG changeset patch
# User Jim Unroe <rock.unroe(a)gmail.com>
# Date 1623981425 14400
# Thu Jun 17 21:57:05 2021 -0400
# Node ID f586574bc8786fd6bef1e5d54d08d381c81edd47
# Parent 7a13867d60472789687f5320c62b00d034846cbc
[KT8900D] Add MCU version for QYT KT8900D
This patch adds an additional MCU version to support the QYT KT8900D
dual-band mobile radio.
fixes #9139
diff --git a/chirp/drivers/btech.py b/chirp/drivers/btech.py
--- a/chirp/drivers/btech.py
+++ b/chirp/drivers/btech.py
@@ -1,4 +1,4 @@
-# Copyright 2016-2020:
+# Copyright 2016-2021:
# * Pavel Milanes CO7WT, <pavelmc(a)gmail.com>
# * Jim Unroe KC9HI, <rock.unroe(a)gmail.com>
#
@@ -245,6 +245,7 @@
# KT8900D (dual band)
KT8900D_fp = "VC2002"
KT8900D_fp1 = "VC8632"
+KT8900D_fp2 = "VC3402"
# LUITON LT-588UV
LT588UV_fp = "V2G1F4"
@@ -3939,7 +3940,7 @@
_vhf_range = (136000000, 175000000)
_uhf_range = (400000000, 481000000)
_magic = MSTRING_KT8900D
- _fileid = [KT8900D_fp, KT8900D_fp1]
+ _fileid = [KT8900D_fp2, KT8900D_fp1, KT8900D_fp]
# Clones
ALIASES = [OTGRadioV1]
2
1

22 Jun '21
# HG changeset patch
# User Kosta A. <ve7kcy(a)gmail.com>
# Date 1624429345 25200
# Tue Jun 22 23:22:25 2021 -0700
# Branch misc
# Node ID d156d3a46b7e6cbce985dc14186f0e07b5d3016b
# Parent f586574bc8786fd6bef1e5d54d08d381c81edd47
Reduce additional spew by forcing bandplan log to info.
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()
1
0

[chirp_devel] [PATCH] Removing default support for Icom Dstar from generic csv radios. #8991
by Kosta A. 22 Jun '21
by Kosta A. 22 Jun '21
22 Jun '21
# HG changeset patch
# User Kosta A. <ve7kcy(a)gmail.com>
# Date 1624428411 25200
# Tue Jun 22 23:06:51 2021 -0700
# Branch no-dstar
# Node ID b5f407175d8797bd41020e59c2024777a9e490e8
# Parent f586574bc8786fd6bef1e5d54d08d381c81edd47
Removing default support for Icom Dstar from generic csv radios. #8991
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,9 +67,6 @@
"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"),
}
1
0
# HG changeset patch
# User Kosta A. <ve7kcy(a)gmail.com>
# Date 1624378359 25200
# Tue Jun 22 09:12:39 2021 -0700
# Branch generic
# Node ID e1e3497b8f7be6f6641a53843479be161c51d0f4
# Parent f586574bc8786fd6bef1e5d54d08d381c81edd47
Memory bounds are inclusive. #8991
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
@@ -99,7 +99,7 @@
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
1
0
Tested changes:
Changes for Build #921
[Jim Unroe <rock.unroe(a)gmail.com>] [KT8900D] Add MCU version for QYT KT8900D
This patch adds an additional MCU version to support the QYT KT8900D
dual-band mobile radio.
fixes #9139
[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 841 lines...]
test_copy_all (tests.TestCase_WouxunKGUV8E)
Testing Wouxun KG-UV8E copy all ... ok
test_detect (tests.TestCase_WouxunKGUV8E)
Testing Wouxun KG-UV8E detect ... ok
test_edges (tests.TestCase_WouxunKGUV8E)
Testing Wouxun KG-UV8E edges ... ok
test_settings (tests.TestCase_WouxunKGUV8E)
Testing Wouxun KG-UV8E settings ... ok
test_banks (tests.TestCase_KenwoodTHD72clonemode)
Testing Kenwood TH-D72 (clone mode) banks ... skipped 'Banks not supported'
test_brute_force (tests.TestCase_KenwoodTHD72clonemode)
Testing Kenwood TH-D72 (clone mode) brute force ... ok
test_clone (tests.TestCase_KenwoodTHD72clonemode)
Testing Kenwood TH-D72 (clone mode) clone ... ok
test_copy_all (tests.TestCase_KenwoodTHD72clonemode)
Testing Kenwood TH-D72 (clone mode) copy all ... ok
test_detect (tests.TestCase_KenwoodTHD72clonemode)
Testing Kenwood TH-D72 (clone mode) detect ... ok
test_edges (tests.TestCase_KenwoodTHD72clonemode)
Testing Kenwood TH-D72 (clone mode) edges ... ok
test_settings (tests.TestCase_KenwoodTHD72clonemode)
Testing Kenwood TH-D72 (clone mode) settings ... ok
test_banks (tests.TestCase_IcomICT8A)
Testing Icom IC-T8A banks ... skipped 'Banks not supported'
test_brute_force (tests.TestCase_IcomICT8A)
Testing Icom IC-T8A brute force ... ok
test_clone (tests.TestCase_IcomICT8A)
Testing Icom IC-T8A clone ... ok
test_copy_all (tests.TestCase_IcomICT8A)
Testing Icom IC-T8A copy all ... ok
test_detect (tests.TestCase_IcomICT8A)
Testing Icom IC-T8A detect ... ok
test_edges (tests.TestCase_IcomICT8A)
Testing Icom IC-T8A edges ... ok
test_settings (tests.TestCase_IcomICT8A)
Testing Icom IC-T8A settings ... skipped 'Settings not supported'
test_banks (tests.TestCase_BTECHGMRSV1)
Testing BTECH GMRS-V1 banks ... skipped 'Banks not supported'
test_brute_force (tests.TestCase_BTECHGMRSV1)
Testing BTECH GMRS-V1 brute force ... ok
test_clone (tests.TestCase_BTECHGMRSV1)
Testing BTECH GMRS-V1 clone ... ok
test_copy_all (tests.TestCase_BTECHGMRSV1)
Testing BTECH GMRS-V1 copy all ... ok
test_detect (tests.TestCase_BTECHGMRSV1)
Testing BTECH GMRS-V1 detect ... ok
test_edges (tests.TestCase_BTECHGMRSV1)
Testing BTECH GMRS-V1 edges ... ok
test_settings (tests.TestCase_BTECHGMRSV1)
Testing BTECH GMRS-V1 settings ... ok
test_banks (tests.TestCase_BaofengUV6R)
Testing Baofeng UV-6R banks ... skipped 'Banks not supported'
test_brute_force (tests.TestCase_BaofengUV6R)
Testing Baofeng UV-6R brute force ... ok
test_clone (tests.TestCase_BaofengUV6R)
Testing Baofeng UV-6R clone ... ok
test_copy_all (tests.TestCase_BaofengUV6R)
Testing Baofeng UV-6R copy all ... ok
test_detect (tests.TestCase_BaofengUV6R)
Testing Baofeng UV-6R detect ... ok
test_edges (tests.TestCase_BaofengUV6R)
Testing Baofeng UV-6R edges ... ok
test_settings (tests.TestCase_BaofengUV6R)
Testing Baofeng UV-6R settings ... ok
test_banks (tests.TestCase_RuggedRH5RV2)
Testing Rugged RH5R-V2 banks ... skipped 'Banks not supported'
test_brute_force (tests.TestCase_RuggedRH5RV2)
Testing Rugged RH5R-V2 brute force ... ok
test_clone (tests.TestCase_RuggedRH5RV2)
Testing Rugged RH5R-V2 clone ... ok
test_copy_all (tests.TestCase_RuggedRH5RV2)
Testing Rugged RH5R-V2 copy all ... ok
test_detect (tests.TestCase_RuggedRH5RV2)
Testing Rugged RH5R-V2 detect ... ok
test_edges (tests.TestCase_RuggedRH5RV2)
Testing Rugged RH5R-V2 edges ... ok
test_settings (tests.TestCase_RuggedRH5RV2)
Testing Rugged RH5R-V2 settings ... skipped 'Settings not supported'
test_banks (tests.TestCase_YaesuVX2)
Testing Yaesu VX-2 banks ... ok
test_brute_force (tests.TestCase_YaesuVX2)
Testing Yaesu VX-2 brute force ... ok
test_clone (tests.TestCase_YaesuVX2)
Testing Yaesu VX-2 clone ... ok
test_copy_all (tests.TestCase_YaesuVX2)
Testing Yaesu VX-2 copy all ... ok
test_detect (tests.TestCase_YaesuVX2)
Testing Yaesu VX-2 detect ... ok
test_edges (tests.TestCase_YaesuVX2)
Testing Yaesu VX-2 edges ... ok
test_settings (tests.TestCase_YaesuVX2)
Testing Yaesu VX-2 settings ... ok
test_banks (tests.TestCase_QYTKT8R)
Testing QYT KT-8R banks ... skipped 'Banks not supported'
test_brute_force (tests.TestCase_QYTKT8R)
Testing QYT KT-8R brute force ... ok
test_clone (tests.TestCase_QYTKT8R)
Testing QYT KT-8R clone ... ok
test_copy_all (tests.TestCase_QYTKT8R)
Testing QYT KT-8R copy all ... ok
test_detect (tests.TestCase_QYTKT8R)
Testing QYT KT-8R detect ... ok
test_edges (tests.TestCase_QYTKT8R)
Testing QYT KT-8R edges ... ok
test_settings (tests.TestCase_QYTKT8R)
Testing QYT KT-8R 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_YaesuFT70D)
Testing Yaesu FT-70D banks ... ok
test_brute_force (tests.TestCase_YaesuFT70D)
Testing Yaesu FT-70D brute force ... ok
test_clone (tests.TestCase_YaesuFT70D)
Testing Yaesu FT-70D clone ... ok
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_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_KenwoodTK272G)
Testing Kenwood TK-272G banks ... ok
test_brute_force (tests.TestCase_KenwoodTK272G)
Testing Kenwood TK-272G brute force ... ok
test_clone (tests.TestCase_KenwoodTK272G)
Testing Kenwood TK-272G clone ... ok
test_copy_all (tests.TestCase_KenwoodTK272G)
Testing Kenwood TK-272G copy all ... ok
test_detect (tests.TestCase_KenwoodTK272G)
Testing Kenwood TK-272G detect ... ok
test_edges (tests.TestCase_KenwoodTK272G)
Testing Kenwood TK-272G edges ... ok
test_settings (tests.TestCase_KenwoodTK272G)
Testing Kenwood TK-272G settings ... ok
test_banks (tests.TestCase_BTECHMURSV1)
Testing BTECH MURS-V1 banks ... skipped 'Banks not supported'
test_brute_force (tests.TestCase_BTECHMURSV1)
Testing BTECH MURS-V1 brute force ... ok
test_clone (tests.TestCase_BTECHMURSV1)
Testing BTECH MURS-V1 clone ... ok
test_copy_all (tests.TestCase_BTECHMURSV1)
Testing BTECH MURS-V1 copy all ... ok
test_detect (tests.TestCase_BTECHMURSV1)
Testing BTECH MURS-V1 detect ... ok
test_edges (tests.TestCase_BTECHMURSV1)
Testing BTECH MURS-V1 edges ... skipped 'No mutable memory locations found'
test_settings (tests.TestCase_BTECHMURSV1)
Testing BTECH MURS-V1 settings ... ok
test_banks (tests.TestCase_BaofengUVB5)
Testing Baofeng UV-B5 banks ... skipped 'Banks not supported'
test_brute_force (tests.TestCase_BaofengUVB5)
Testing Baofeng UV-B5 brute force ... ok
test_clone (tests.TestCase_BaofengUVB5)
Testing Baofeng UV-B5 clone ... ok
test_copy_all (tests.TestCase_BaofengUVB5)
Testing Baofeng UV-B5 copy all ... ok
test_detect (tests.TestCase_BaofengUVB5)
Testing Baofeng UV-B5 detect ... ok
test_edges (tests.TestCase_BaofengUVB5)
Testing Baofeng UV-B5 edges ... ok
test_settings (tests.TestCase_BaofengUVB5)
Testing Baofeng UV-B5 settings ... ok
test_banks (tests.TestCase_TDXoneTDQ8A)
Testing TDXone TD-Q8A banks ... skipped 'Banks not supported'
test_brute_force (tests.TestCase_TDXoneTDQ8A)
Testing TDXone TD-Q8A brute force ... ok
test_clone (tests.TestCase_TDXoneTDQ8A)
Testing TDXone TD-Q8A clone ... ok
test_copy_all (tests.TestCase_TDXoneTDQ8A)
Testing TDXone TD-Q8A copy all ... ok
test_detect (tests.TestCase_TDXoneTDQ8A)
Testing TDXone TD-Q8A detect ... ok
test_edges (tests.TestCase_TDXoneTDQ8A)
Testing TDXone TD-Q8A edges ... ok
test_settings (tests.TestCase_TDXoneTDQ8A)
Testing TDXone TD-Q8A settings ... ok
test_banks (tests.TestCase_QYTKT7900D)
Testing QYT KT7900D banks ... skipped 'Banks not supported'
test_brute_force (tests.TestCase_QYTKT7900D)
Testing QYT KT7900D brute force ... ok
test_clone (tests.TestCase_QYTKT7900D)
Testing QYT KT7900D clone ... ok
test_copy_all (tests.TestCase_QYTKT7900D)
Testing QYT KT7900D copy all ... ok
test_detect (tests.TestCase_QYTKT7900D)
Testing QYT KT7900D detect ... ok
test_edges (tests.TestCase_QYTKT7900D)
Testing QYT KT7900D edges ... ok
test_settings (tests.TestCase_QYTKT7900D)
Testing QYT KT7900D 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_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_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_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_BTECHUV2501220)
Testing BTECH UV-2501+220 banks ... skipped 'Banks not supported'
test_brute_force (tests.TestCase_BTECHUV2501220)
Testing BTECH UV-2501+220 brute force ... ok
test_clone (tests.TestCase_BTECHUV2501220)
Testing BTECH UV-2501+220 clone ... ok
test_copy_all (tests.TestCase_BTECHUV2501220)
Testing BTECH UV-2501+220 copy all ... ok
test_detect (tests.TestCase_BTECHUV2501220)
Testing BTECH UV-2501+220 detect ... ok
test_edges (tests.TestCase_BTECHUV2501220)
Testing BTECH UV-2501+220 edges ... ok
test_settings (tests.TestCase_BTECHUV2501220)
Testing BTECH UV-2501+220 settings ... ok
test_banks (tests.TestCase_BaojieBJ9900)
Testing Baojie BJ-9900 banks ... skipped 'Banks not supported'
test_brute_force (tests.TestCase_BaojieBJ9900)
Testing Baojie BJ-9900 brute force ... ok
test_clone (tests.TestCase_BaojieBJ9900)
Testing Baojie BJ-9900 clone ... ok
test_copy_all (tests.TestCase_BaojieBJ9900)
Testing Baojie BJ-9900 copy all ... ok
test_detect (tests.TestCase_BaojieBJ9900)
Testing Baojie BJ-9900 detect ... ok
test_edges (tests.TestCase_BaojieBJ9900)
Testing Baojie BJ-9900 edges ... ok
test_settings (tests.TestCase_BaojieBJ9900)
Testing Baojie BJ-9900 settings ... skipped 'Settings not supported'
test_banks (tests.TestCase_TYTTH350)
Testing TYT TH-350 banks ... skipped 'Banks not supported'
test_brute_force (tests.TestCase_TYTTH350)
Testing TYT TH-350 brute force ... ok
test_clone (tests.TestCase_TYTTH350)
Testing TYT TH-350 clone ... ok
test_copy_all (tests.TestCase_TYTTH350)
Testing TYT TH-350 copy all ... ok
test_detect (tests.TestCase_TYTTH350)
Testing TYT TH-350 detect ... ok
test_edges (tests.TestCase_TYTTH350)
Testing TYT TH-350 edges ... ok
test_settings (tests.TestCase_TYTTH350)
Testing TYT TH-350 settings ... ok
test_banks (tests.TestCase_KenwoodTK3180K2)
Testing Kenwood TK-3180K2 banks ... skipped 'Banks not supported'
test_brute_force (tests.TestCase_KenwoodTK3180K2)
Testing Kenwood TK-3180K2 brute force ... ok
test_clone (tests.TestCase_KenwoodTK3180K2)
Testing Kenwood TK-3180K2 clone ... ok
test_copy_all (tests.TestCase_KenwoodTK3180K2)
Testing Kenwood TK-3180K2 copy all ... ok
test_detect (tests.TestCase_KenwoodTK3180K2)
Testing Kenwood TK-3180K2 detect ... ok
test_edges (tests.TestCase_KenwoodTK3180K2)
Testing Kenwood TK-3180K2 edges ... ok
test_settings (tests.TestCase_KenwoodTK3180K2)
Testing Kenwood TK-3180K2 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_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_QYTKT8900D)
Testing QYT KT8900D banks ... skipped 'Banks not supported'
test_brute_force (tests.TestCase_QYTKT8900D)
Testing QYT KT8900D brute force ... ok
test_clone (tests.TestCase_QYTKT8900D)
Testing QYT KT8900D clone ... ok
test_copy_all (tests.TestCase_QYTKT8900D)
Testing QYT KT8900D copy all ... ok
test_detect (tests.TestCase_QYTKT8900D)
Testing QYT KT8900D detect ... ok
test_edges (tests.TestCase_QYTKT8900D)
Testing QYT KT8900D edges ... ok
test_settings (tests.TestCase_QYTKT8900D)
Testing QYT KT8900D settings ... ok
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_BoblovX3Plus)
Testing Boblov X3Plus banks ... skipped 'Banks not supported'
test_brute_force (tests.TestCase_BoblovX3Plus)
Testing Boblov X3Plus brute force ... ok
test_clone (tests.TestCase_BoblovX3Plus)
Testing Boblov X3Plus clone ... ok
test_copy_all (tests.TestCase_BoblovX3Plus)
Testing Boblov X3Plus copy all ... ok
test_detect (tests.TestCase_BoblovX3Plus)
Testing Boblov X3Plus detect ... ok
test_edges (tests.TestCase_BoblovX3Plus)
Testing Boblov X3Plus edges ... ok
test_settings (tests.TestCase_BoblovX3Plus)
Testing Boblov X3Plus 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_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_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_KenwoodTK760G)
Testing Kenwood TK-760G banks ... ok
test_brute_force (tests.TestCase_KenwoodTK760G)
Testing Kenwood TK-760G brute force ... ok
test_clone (tests.TestCase_KenwoodTK760G)
Testing Kenwood TK-760G clone ... ok
test_copy_all (tests.TestCase_KenwoodTK760G)
Testing Kenwood TK-760G copy all ... ok
test_detect (tests.TestCase_KenwoodTK760G)
Testing Kenwood TK-760G detect ... ok
test_edges (tests.TestCase_KenwoodTK760G)
Testing Kenwood TK-760G edges ... ok
test_settings (tests.TestCase_KenwoodTK760G)
Testing Kenwood TK-760G 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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_RetevisRT16)
Testing Retevis RT16 banks ... skipped 'Banks not supported'
test_brute_force (tests.TestCase_RetevisRT16)
Testing Retevis RT16 brute force ... ok
test_clone (tests.TestCase_RetevisRT16)
Testing Retevis RT16 clone ... ok
test_copy_all (tests.TestCase_RetevisRT16)
Testing Retevis RT16 copy all ... ok
test_detect (tests.TestCase_RetevisRT16)
Testing Retevis RT16 detect ... ok
test_edges (tests.TestCase_RetevisRT16)
Testing Retevis RT16 edges ... skipped 'No mutable memory locations found'
test_settings (tests.TestCase_RetevisRT16)
Testing Retevis RT16 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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_RetevisRT22S)
Testing Retevis RT22S banks ... skipped 'Banks not supported'
test_brute_force (tests.TestCase_RetevisRT22S)
Testing Retevis RT22S brute force ... ok
test_clone (tests.TestCase_RetevisRT22S)
Testing Retevis RT22S clone ... ok
test_copy_all (tests.TestCase_RetevisRT22S)
Testing Retevis RT22S copy all ... ok
test_detect (tests.TestCase_RetevisRT22S)
Testing Retevis RT22S detect ... ok
test_edges (tests.TestCase_RetevisRT22S)
Testing Retevis RT22S edges ... skipped 'No mutable memory locations found'
test_settings (tests.TestCase_RetevisRT22S)
Testing Retevis RT22S 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_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_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'
----------------------------------------------------------------------
Ran 1085 tests in 480.847s
OK (skipped=153)
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;
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='691812099'
style run-test: commands[0] | python ./tools/cpep8.py
___________________________________ summary ____________________________________
unit: commands succeeded
driver: commands succeeded
style: commands succeeded
congratulations :)
Email was triggered for: Success
Sending email for trigger: Success
1
0

17 Jun '21
---------- Forwarded message ---------
From: Jim Unroe <kc9hi(a)comcast.net>
Date: Thu, Jun 17, 2021 at 9:58 PM
Subject: [PATCH] [KT8900D] Add MCU version for QYT KT8900D
To: <Rock.Unroe(a)gmail.com>
# HG changeset patch
# User Jim Unroe <rock.unroe(a)gmail.com>
# Date 1623981425 14400
# Thu Jun 17 21:57:05 2021 -0400
# Node ID 748d2199525bb0d0f046a0b851cf297cf303ff90
# Parent 6be165140f5f41141a12cd73dd9a8eebc27f4934
[KT8900D] Add MCU version for QYT KT8900D
This patch adds an additional MCU version to support the QYT KT8900D
dual-band mobile radio.
fixes #9139
diff -r 6be165140f5f -r 748d2199525b chirp/drivers/btech.py
--- a/chirp/drivers/btech.py Fri Jun 11 15:42:23 2021 -0400
+++ b/chirp/drivers/btech.py Thu Jun 17 21:57:05 2021 -0400
@@ -1,4 +1,4 @@
-# Copyright 2016-2020:
+# Copyright 2016-2021:
# * Pavel Milanes CO7WT, <pavelmc(a)gmail.com>
# * Jim Unroe KC9HI, <rock.unroe(a)gmail.com>
#
@@ -245,6 +245,7 @@
# KT8900D (dual band)
KT8900D_fp = "VC2002"
KT8900D_fp1 = "VC8632"
+KT8900D_fp2 = "VC3402"
# LUITON LT-588UV
LT588UV_fp = "V2G1F4"
@@ -3939,7 +3940,7 @@
_vhf_range = (136000000, 175000000)
_uhf_range = (400000000, 481000000)
_magic = MSTRING_KT8900D
- _fileid = [KT8900D_fp, KT8900D_fp1]
+ _fileid = [KT8900D_fp2, KT8900D_fp1, KT8900D_fp]
# Clones
ALIASES = [OTGRadioV1]
1
0