kopia lustrzana https://github.com/sq5bpf/uvk5-reverse-engineering
fix eeprom offsets, convert VFO channels to be special channels, change unlock settings names, and general cleanups
rodzic
8427c0618f
commit
11f26a2fe6
146
uvk5.py
146
uvk5.py
|
@ -8,9 +8,7 @@
|
||||||
# https://github.com/sq5bpf/uvk5-reverse-engineering
|
# https://github.com/sq5bpf/uvk5-reverse-engineering
|
||||||
#
|
#
|
||||||
# Warning: this driver is experimental, it may brick your radio,
|
# Warning: this driver is experimental, it may brick your radio,
|
||||||
# eat your lunch and mess up your configuration. Before even attempting
|
# eat your lunch and mess up your configuration.
|
||||||
# to use it save a memory image from the radio using k5prog:
|
|
||||||
# https://github.com/sq5bpf/k5prog
|
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
@ -47,6 +45,7 @@ DEBUG_SHOW_OBFUSCATED_COMMANDS = False
|
||||||
# might be useful for someone debugging some obscure memory issue
|
# might be useful for someone debugging some obscure memory issue
|
||||||
DEBUG_SHOW_MEMORY_ACTIONS = False
|
DEBUG_SHOW_MEMORY_ACTIONS = False
|
||||||
|
|
||||||
|
# TODO: remove the driver version when it's in mainline chirp
|
||||||
DRIVER_VERSION = "Quansheng UV-K5 driver v20230621 (c) Jacek Lipkowski SQ5BPF"
|
DRIVER_VERSION = "Quansheng UV-K5 driver v20230621 (c) Jacek Lipkowski SQ5BPF"
|
||||||
|
|
||||||
MEM_FORMAT = """
|
MEM_FORMAT = """
|
||||||
|
@ -112,8 +111,8 @@ u8 call_channel;
|
||||||
u8 squelch;
|
u8 squelch;
|
||||||
u8 max_talk_time;
|
u8 max_talk_time;
|
||||||
u8 noaa_autoscan;
|
u8 noaa_autoscan;
|
||||||
u8 unknown1;
|
u8 key_lock;
|
||||||
u8 unknown2;
|
u8 vox_switch;
|
||||||
u8 vox_level;
|
u8 vox_level;
|
||||||
u8 mic_gain;
|
u8 mic_gain;
|
||||||
u8 unknown3;
|
u8 unknown3;
|
||||||
|
@ -121,6 +120,7 @@ u8 channel_display_mode;
|
||||||
u8 crossband;
|
u8 crossband;
|
||||||
u8 battery_save;
|
u8 battery_save;
|
||||||
u8 dual_watch;
|
u8 dual_watch;
|
||||||
|
u8 backlight_auto_mode;
|
||||||
u8 tail_note_elimination;
|
u8 tail_note_elimination;
|
||||||
u8 vfo_open;
|
u8 vfo_open;
|
||||||
|
|
||||||
|
@ -193,7 +193,7 @@ u8 int_unknown1;
|
||||||
u8 int_200tx;
|
u8 int_200tx;
|
||||||
u8 int_500tx;
|
u8 int_500tx;
|
||||||
u8 int_350en;
|
u8 int_350en;
|
||||||
u8 int_screen;
|
u8 int_scren;
|
||||||
|
|
||||||
#seekto 0xf50;
|
#seekto 0xf50;
|
||||||
struct {
|
struct {
|
||||||
|
@ -241,6 +241,9 @@ CHANNELDISP_LIST = ["Frequency", "Channel No", "Channel Name"]
|
||||||
# battery save
|
# battery save
|
||||||
BATSAVE_LIST = ["OFF", "1:1", "1:2", "1:3", "1:4"]
|
BATSAVE_LIST = ["OFF", "1:1", "1:2", "1:3", "1:4"]
|
||||||
|
|
||||||
|
# Backlight auto mode
|
||||||
|
BACKLIGHT_LIST = ["Off", "1s", "2s", "3s", "4s", "5s"]
|
||||||
|
|
||||||
# Crossband receiving/transmitting
|
# Crossband receiving/transmitting
|
||||||
CROSSBAND_LIST = ["Off", "Band A", "Band B"]
|
CROSSBAND_LIST = ["Off", "Band A", "Band B"]
|
||||||
DUALWATCH_LIST = CROSSBAND_LIST
|
DUALWATCH_LIST = CROSSBAND_LIST
|
||||||
|
@ -324,6 +327,23 @@ BANDS_NOLIMITS = {
|
||||||
6: [470.0, 1300.0]
|
6: [470.0, 1300.0]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SPECIALS = {
|
||||||
|
"F1(50M-76M)A": 200,
|
||||||
|
"F1(50M-76M)B": 201,
|
||||||
|
"F2(108M-136M)A": 202,
|
||||||
|
"F2(108M-136M)B": 203,
|
||||||
|
"F3(136M-174M)A": 204,
|
||||||
|
"F3(136M-174M)B": 205,
|
||||||
|
"F4(174M-350M)A": 206,
|
||||||
|
"F4(174M-350M)B": 207,
|
||||||
|
"F5(350M-400M)A": 208,
|
||||||
|
"F5(350M-400M)B": 209,
|
||||||
|
"F6(400M-470M)A": 210,
|
||||||
|
"F6(400M-470M)B": 211,
|
||||||
|
"F7(470M-600M)A": 212,
|
||||||
|
"F7(470M-600M)B": 213
|
||||||
|
}
|
||||||
|
|
||||||
VFO_CHANNEL_NAMES = ["F1(50M-76M)A", "F1(50M-76M)B",
|
VFO_CHANNEL_NAMES = ["F1(50M-76M)A", "F1(50M-76M)B",
|
||||||
"F2(108M-136M)A", "F2(108M-136M)B",
|
"F2(108M-136M)A", "F2(108M-136M)B",
|
||||||
"F3(136M-174M)A", "F3(136M-174M)B",
|
"F3(136M-174M)A", "F3(136M-174M)B",
|
||||||
|
@ -403,8 +423,6 @@ def _receive_reply(serport):
|
||||||
(util.hexprint(header), len(header)))
|
(util.hexprint(header), len(header)))
|
||||||
raise errors.RadioError("Bad response header")
|
raise errors.RadioError("Bad response header")
|
||||||
|
|
||||||
return False
|
|
||||||
|
|
||||||
cmd = serport.read(int(header[2]))
|
cmd = serport.read(int(header[2]))
|
||||||
if len(cmd) != int(header[2]):
|
if len(cmd) != int(header[2]):
|
||||||
LOG.warning("Body short read: [%s] len=%i" %
|
LOG.warning("Body short read: [%s] len=%i" %
|
||||||
|
@ -425,7 +443,6 @@ def _receive_reply(serport):
|
||||||
LOG.warning("Bad response footer: %s len=%i" %
|
LOG.warning("Bad response footer: %s len=%i" %
|
||||||
(util.hexprint(footer), len(footer)))
|
(util.hexprint(footer), len(footer)))
|
||||||
raise errors.RadioError("Bad response footer")
|
raise errors.RadioError("Bad response footer")
|
||||||
return False
|
|
||||||
|
|
||||||
if DEBUG_SHOW_OBFUSCATED_COMMANDS:
|
if DEBUG_SHOW_OBFUSCATED_COMMANDS:
|
||||||
LOG.debug("Received reply (obfuscated) len=0x%4.4x:\n%s" %
|
LOG.debug("Received reply (obfuscated) len=0x%4.4x:\n%s" %
|
||||||
|
@ -452,7 +469,7 @@ def _sayhello(serport):
|
||||||
hellopacket = b"\x14\x05\x04\x00\x6a\x39\x57\x64"
|
hellopacket = b"\x14\x05\x04\x00\x6a\x39\x57\x64"
|
||||||
|
|
||||||
tries = 5
|
tries = 5
|
||||||
while (True):
|
while True:
|
||||||
LOG.debug("Sending hello packet")
|
LOG.debug("Sending hello packet")
|
||||||
_send_command(serport, hellopacket)
|
_send_command(serport, hellopacket)
|
||||||
o = _receive_reply(serport)
|
o = _receive_reply(serport)
|
||||||
|
@ -462,7 +479,6 @@ def _sayhello(serport):
|
||||||
if tries == 0:
|
if tries == 0:
|
||||||
LOG.warning("Failed to initialise radio")
|
LOG.warning("Failed to initialise radio")
|
||||||
raise errors.RadioError("Failed to initialize radio")
|
raise errors.RadioError("Failed to initialize radio")
|
||||||
return False
|
|
||||||
firmware = _getstring(o, 4, 16)
|
firmware = _getstring(o, 4, 16)
|
||||||
LOG.info("Found firmware: %s" % firmware)
|
LOG.info("Found firmware: %s" % firmware)
|
||||||
return firmware
|
return firmware
|
||||||
|
@ -509,7 +525,6 @@ def _writemem(serport, data, offset):
|
||||||
else:
|
else:
|
||||||
LOG.warning("Bad data from writemem")
|
LOG.warning("Bad data from writemem")
|
||||||
raise errors.RadioError("Bad response to writemem")
|
raise errors.RadioError("Bad response to writemem")
|
||||||
return False
|
|
||||||
|
|
||||||
|
|
||||||
def _resetradio(serport):
|
def _resetradio(serport):
|
||||||
|
@ -610,10 +625,10 @@ class UVK5Radio(chirp_common.CloneModeRadio):
|
||||||
def get_prompts(x=None):
|
def get_prompts(x=None):
|
||||||
rp = chirp_common.RadioPrompts()
|
rp = chirp_common.RadioPrompts()
|
||||||
rp.experimental = \
|
rp.experimental = \
|
||||||
('This is an experimental driver for the Quanscheng UV-K5. '
|
('This is an experimental driver for the Quansheng UV-K5. '
|
||||||
'It may harm your radio, or worse. Use at your own risk.\n\n'
|
'It may harm your radio, or worse. Use at your own risk.\n\n'
|
||||||
'Before attempting to do any changes please download'
|
'Before attempting to do any changes please download'
|
||||||
'the memory image from the radio with chirp or k5prog '
|
'the memory image from the radio with chirp '
|
||||||
'and keep it. This can be later used to recover the '
|
'and keep it. This can be later used to recover the '
|
||||||
'original settings. \n\n'
|
'original settings. \n\n'
|
||||||
'some details are not yet implemented')
|
'some details are not yet implemented')
|
||||||
|
@ -622,14 +637,14 @@ class UVK5Radio(chirp_common.CloneModeRadio):
|
||||||
"2. Connect cable to mic/spkr connector.\n"
|
"2. Connect cable to mic/spkr connector.\n"
|
||||||
"3. Make sure connector is firmly connected.\n"
|
"3. Make sure connector is firmly connected.\n"
|
||||||
"4. Click OK to download image from device.\n\n"
|
"4. Click OK to download image from device.\n\n"
|
||||||
"It will may not work if you turn o the radio "
|
"It will may not work if you turn on the radio "
|
||||||
"with the cable already attached\n")
|
"with the cable already attached\n")
|
||||||
rp.pre_upload = _(
|
rp.pre_upload = _(
|
||||||
"1. Turn radio on.\n"
|
"1. Turn radio on.\n"
|
||||||
"2. Connect cable to mic/spkr connector.\n"
|
"2. Connect cable to mic/spkr connector.\n"
|
||||||
"3. Make sure connector is firmly connected.\n"
|
"3. Make sure connector is firmly connected.\n"
|
||||||
"4. Click OK to upload the image to device.\n\n"
|
"4. Click OK to upload the image to device.\n\n"
|
||||||
"It will may not work if you turn o the radio "
|
"It will may not work if you turn on the radio "
|
||||||
"with the cable already attached")
|
"with the cable already attached")
|
||||||
return rp
|
return rp
|
||||||
|
|
||||||
|
@ -643,8 +658,9 @@ class UVK5Radio(chirp_common.CloneModeRadio):
|
||||||
rf.has_ctone = True
|
rf.has_ctone = True
|
||||||
rf.has_settings = True
|
rf.has_settings = True
|
||||||
rf.has_comment = False
|
rf.has_comment = False
|
||||||
rf.valid_name_length = 16
|
rf.valid_name_length = 10
|
||||||
rf.valid_power_levels = UVK5_POWER_LEVELS
|
rf.valid_power_levels = UVK5_POWER_LEVELS
|
||||||
|
rf.valid_special_chans = list(SPECIALS.keys())
|
||||||
|
|
||||||
# hack so we can input any frequency,
|
# hack so we can input any frequency,
|
||||||
# the 0.1 and 0.01 steps don't work unfortunately
|
# the 0.1 and 0.01 steps don't work unfortunately
|
||||||
|
@ -661,7 +677,7 @@ class UVK5Radio(chirp_common.CloneModeRadio):
|
||||||
rf.valid_skips = [""]
|
rf.valid_skips = [""]
|
||||||
|
|
||||||
# This radio supports memories 1-200, 201-214 are the VFO memories
|
# This radio supports memories 1-200, 201-214 are the VFO memories
|
||||||
rf.memory_bounds = (1, 214)
|
rf.memory_bounds = (1, 200)
|
||||||
|
|
||||||
# This is what the BK4819 chip supports
|
# This is what the BK4819 chip supports
|
||||||
# Will leave it in a comment, might be useful someday
|
# Will leave it in a comment, might be useful someday
|
||||||
|
@ -770,22 +786,21 @@ class UVK5Radio(chirp_common.CloneModeRadio):
|
||||||
# Extract a high-level memory object from the low-level memory map
|
# Extract a high-level memory object from the low-level memory map
|
||||||
# This is called to populate a memory in the UI
|
# This is called to populate a memory in the UI
|
||||||
def get_memory(self, number2):
|
def get_memory(self, number2):
|
||||||
number = number2-1 # in the radio memories start with 0
|
|
||||||
|
|
||||||
mem = chirp_common.Memory()
|
mem = chirp_common.Memory()
|
||||||
|
|
||||||
# cutting and pasting configs from different radios
|
if isinstance(number2, str):
|
||||||
# might try to set channel 0
|
number = SPECIALS[number2]
|
||||||
if number2 == 0:
|
mem.extd_number = number2
|
||||||
LOG.warning("Attempt to get channel 0")
|
else:
|
||||||
return mem
|
number = number2 - 1
|
||||||
|
|
||||||
|
mem.number = number + 1
|
||||||
|
|
||||||
_mem = self._memobj.channel[number]
|
_mem = self._memobj.channel[number]
|
||||||
|
|
||||||
tmpcomment = ""
|
tmpcomment = ""
|
||||||
|
|
||||||
mem.number = number2
|
|
||||||
|
|
||||||
is_empty = False
|
is_empty = False
|
||||||
# We'll consider any blank (i.e. 0MHz frequency) to be empty
|
# We'll consider any blank (i.e. 0MHz frequency) to be empty
|
||||||
if (_mem.freq == 0xffffffff) or (_mem.freq == 0):
|
if (_mem.freq == 0xffffffff) or (_mem.freq == 0):
|
||||||
|
@ -963,10 +978,15 @@ class UVK5Radio(chirp_common.CloneModeRadio):
|
||||||
# TOT
|
# TOT
|
||||||
if element.get_name() == "tot":
|
if element.get_name() == "tot":
|
||||||
_mem.max_talk_time = int(element.value)
|
_mem.max_talk_time = int(element.value)
|
||||||
|
|
||||||
# NOAA autoscan
|
# NOAA autoscan
|
||||||
if element.get_name() == "noaa_autoscan":
|
if element.get_name() == "noaa_autoscan":
|
||||||
_mem.noaa_autoscan = element.value and 1 or 0
|
_mem.noaa_autoscan = element.value and 1 or 0
|
||||||
|
|
||||||
|
# VOX switch
|
||||||
|
if element.get_name() == "vox_switch":
|
||||||
|
_mem.vox_switch = element.value and 1 or 0
|
||||||
|
|
||||||
# vox level
|
# vox level
|
||||||
if element.get_name() == "vox_level":
|
if element.get_name() == "vox_level":
|
||||||
_mem.vox_level = int(element.value)-1
|
_mem.vox_level = int(element.value)-1
|
||||||
|
@ -991,6 +1011,11 @@ class UVK5Radio(chirp_common.CloneModeRadio):
|
||||||
if element.get_name() == "dualwatch":
|
if element.get_name() == "dualwatch":
|
||||||
_mem.dual_watch = DUALWATCH_LIST.index(str(element.value))
|
_mem.dual_watch = DUALWATCH_LIST.index(str(element.value))
|
||||||
|
|
||||||
|
# Backlight auto mode
|
||||||
|
if element.get_name() == "backlight_auto_mode":
|
||||||
|
_mem.backlight_auto_mode = \
|
||||||
|
BACKLIGHT_LIST.index(str(element.value))
|
||||||
|
|
||||||
# Tail tone elimination
|
# Tail tone elimination
|
||||||
if element.get_name() == "tail_note_elimination":
|
if element.get_name() == "tail_note_elimination":
|
||||||
_mem.tail_note_elimination = element.value and 1 or 0
|
_mem.tail_note_elimination = element.value and 1 or 0
|
||||||
|
@ -1008,6 +1033,10 @@ class UVK5Radio(chirp_common.CloneModeRadio):
|
||||||
_mem.scan_resume_mode = SCANRESUME_LIST.index(
|
_mem.scan_resume_mode = SCANRESUME_LIST.index(
|
||||||
str(element.value))
|
str(element.value))
|
||||||
|
|
||||||
|
# Keypad lock
|
||||||
|
if element.get_name() == "key_lock":
|
||||||
|
_mem.key_lock = element.value and 1 or 0
|
||||||
|
|
||||||
# Auto keypad lock
|
# Auto keypad lock
|
||||||
if element.get_name() == "auto_keypad_lock":
|
if element.get_name() == "auto_keypad_lock":
|
||||||
_mem.auto_keypad_lock = element.value and 1 or 0
|
_mem.auto_keypad_lock = element.value and 1 or 0
|
||||||
|
@ -1058,10 +1087,6 @@ class UVK5Radio(chirp_common.CloneModeRadio):
|
||||||
if element.get_name() == "350tx":
|
if element.get_name() == "350tx":
|
||||||
_mem.int_350tx = element.value and 1 or 0
|
_mem.int_350tx = element.value and 1 or 0
|
||||||
|
|
||||||
# UNKNOWN1
|
|
||||||
if element.get_name() == "unknown1":
|
|
||||||
_mem.int_unknown1 = element.value and 1 or 0
|
|
||||||
|
|
||||||
# 200TX
|
# 200TX
|
||||||
if element.get_name() == "200tx":
|
if element.get_name() == "200tx":
|
||||||
_mem.int_200tx = element.value and 1 or 0
|
_mem.int_200tx = element.value and 1 or 0
|
||||||
|
@ -1074,6 +1099,10 @@ class UVK5Radio(chirp_common.CloneModeRadio):
|
||||||
if element.get_name() == "350en":
|
if element.get_name() == "350en":
|
||||||
_mem.int_350en = element.value and 1 or 0
|
_mem.int_350en = element.value and 1 or 0
|
||||||
|
|
||||||
|
# SCREN
|
||||||
|
if element.get_name() == "scren":
|
||||||
|
_mem.int_scren = element.value and 1 or 0
|
||||||
|
|
||||||
# fm radio
|
# fm radio
|
||||||
for i in range(1, 21):
|
for i in range(1, 21):
|
||||||
freqname = "FM_" + str(i)
|
freqname = "FM_" + str(i)
|
||||||
|
@ -1548,6 +1577,13 @@ class UVK5Radio(chirp_common.CloneModeRadio):
|
||||||
bool(_mem.noaa_autoscan > 0)))
|
bool(_mem.noaa_autoscan > 0)))
|
||||||
basic.append(rs)
|
basic.append(rs)
|
||||||
|
|
||||||
|
# VOX switch
|
||||||
|
rs = RadioSetting(
|
||||||
|
"vox_switch",
|
||||||
|
"VOX enabled", RadioSettingValueBoolean(
|
||||||
|
bool(_mem.vox_switch > 0)))
|
||||||
|
basic.append(rs)
|
||||||
|
|
||||||
# VOX Level
|
# VOX Level
|
||||||
tmpvox = _mem.vox_level+1
|
tmpvox = _mem.vox_level+1
|
||||||
if tmpvox > 10:
|
if tmpvox > 10:
|
||||||
|
@ -1608,6 +1644,17 @@ class UVK5Radio(chirp_common.CloneModeRadio):
|
||||||
DUALWATCH_LIST, DUALWATCH_LIST[tmpdual]))
|
DUALWATCH_LIST, DUALWATCH_LIST[tmpdual]))
|
||||||
basic.append(rs)
|
basic.append(rs)
|
||||||
|
|
||||||
|
# Backlight auto mode
|
||||||
|
tmpback = _mem.backlight_auto_mode
|
||||||
|
if tmpback >= len(BACKLIGHT_LIST):
|
||||||
|
tmpback = 0
|
||||||
|
rs = RadioSetting("backlight_auto_mode",
|
||||||
|
"Backlight auto mode",
|
||||||
|
RadioSettingValueList(
|
||||||
|
BACKLIGHT_LIST,
|
||||||
|
BACKLIGHT_LIST[tmpback]))
|
||||||
|
basic.append(rs)
|
||||||
|
|
||||||
# Tail tone elimination
|
# Tail tone elimination
|
||||||
rs = RadioSetting(
|
rs = RadioSetting(
|
||||||
"tail_note_elimination",
|
"tail_note_elimination",
|
||||||
|
@ -1640,6 +1687,13 @@ class UVK5Radio(chirp_common.CloneModeRadio):
|
||||||
SCANRESUME_LIST[tmpscanres]))
|
SCANRESUME_LIST[tmpscanres]))
|
||||||
basic.append(rs)
|
basic.append(rs)
|
||||||
|
|
||||||
|
# Keypad locked
|
||||||
|
rs = RadioSetting(
|
||||||
|
"key_lock",
|
||||||
|
"Keypad lock",
|
||||||
|
RadioSettingValueBoolean(bool(_mem.key_lock > 0)))
|
||||||
|
basic.append(rs)
|
||||||
|
|
||||||
# Auto keypad lock
|
# Auto keypad lock
|
||||||
rs = RadioSetting(
|
rs = RadioSetting(
|
||||||
"auto_keypad_lock",
|
"auto_keypad_lock",
|
||||||
|
@ -1744,34 +1798,33 @@ class UVK5Radio(chirp_common.CloneModeRadio):
|
||||||
unlock.append(rs)
|
unlock.append(rs)
|
||||||
|
|
||||||
# 350TX
|
# 350TX
|
||||||
rs = RadioSetting("350tx", "350TX", RadioSettingValueBoolean(
|
rs = RadioSetting("350tx", "350TX - unlock 350-400MHz TX",
|
||||||
bool(_mem.int_350tx > 0)))
|
|
||||||
unlock.append(rs)
|
|
||||||
|
|
||||||
# unknown1
|
|
||||||
rs = RadioSetting("unknown11", "UNKNOWN1",
|
|
||||||
RadioSettingValueBoolean(
|
RadioSettingValueBoolean(
|
||||||
bool(_mem.int_unknown1 > 0)))
|
bool(_mem.int_350tx > 0)))
|
||||||
unlock.append(rs)
|
unlock.append(rs)
|
||||||
|
|
||||||
# 200TX
|
# 200TX
|
||||||
rs = RadioSetting("200tx", "200TX", RadioSettingValueBoolean(
|
rs = RadioSetting("200tx", "200TX - unlock 174-350MHz TX",
|
||||||
bool(_mem.int_200tx > 0)))
|
RadioSettingValueBoolean(
|
||||||
|
bool(_mem.int_200tx > 0)))
|
||||||
unlock.append(rs)
|
unlock.append(rs)
|
||||||
|
|
||||||
# 500TX
|
# 500TX
|
||||||
rs = RadioSetting("500tx", "500TX", RadioSettingValueBoolean(
|
rs = RadioSetting("500tx", "500TX - unlock 500-600MHz TX",
|
||||||
bool(_mem.int_500tx > 0)))
|
RadioSettingValueBoolean(
|
||||||
|
bool(_mem.int_500tx > 0)))
|
||||||
unlock.append(rs)
|
unlock.append(rs)
|
||||||
|
|
||||||
# 350EN
|
# 350EN
|
||||||
rs = RadioSetting("350en", "350EN", RadioSettingValueBoolean(
|
rs = RadioSetting("350en", "350EN - unlock 350-400MHz RX",
|
||||||
bool(_mem.int_350en > 0)))
|
RadioSettingValueBoolean(
|
||||||
|
bool(_mem.int_350en > 0)))
|
||||||
unlock.append(rs)
|
unlock.append(rs)
|
||||||
|
|
||||||
# SCREEN
|
# SCREEN
|
||||||
rs = RadioSetting("screen", "SCREEN", RadioSettingValueBoolean(
|
rs = RadioSetting("scren", "SCREN - scrambler enable",
|
||||||
bool(_mem.int_screen > 0)))
|
RadioSettingValueBoolean(
|
||||||
|
bool(_mem.int_scren > 0)))
|
||||||
unlock.append(rs)
|
unlock.append(rs)
|
||||||
|
|
||||||
# readonly info
|
# readonly info
|
||||||
|
@ -1787,6 +1840,7 @@ class UVK5Radio(chirp_common.CloneModeRadio):
|
||||||
rs = RadioSetting("fw_ver", "Firmware Version", val)
|
rs = RadioSetting("fw_ver", "Firmware Version", val)
|
||||||
roinfo.append(rs)
|
roinfo.append(rs)
|
||||||
|
|
||||||
|
# TODO: remove showing the driver version when it's in mainline chirp
|
||||||
# Driver version
|
# Driver version
|
||||||
val = RadioSettingValueString(0, 128, DRIVER_VERSION)
|
val = RadioSettingValueString(0, 128, DRIVER_VERSION)
|
||||||
val.set_mutable(False)
|
val.set_mutable(False)
|
||||||
|
@ -1902,7 +1956,7 @@ class UVK5Radio(chirp_common.CloneModeRadio):
|
||||||
# channels >200 are the 14 VFO chanells and don't have names
|
# channels >200 are the 14 VFO chanells and don't have names
|
||||||
if number < 200:
|
if number < 200:
|
||||||
_mem2 = self._memobj.channelname[number]
|
_mem2 = self._memobj.channelname[number]
|
||||||
tag = mem.name.ljust(16)[:16]
|
tag = mem.name.ljust(10) + "\x00"*6
|
||||||
_mem2.name = tag # Store the alpha tag
|
_mem2.name = tag # Store the alpha tag
|
||||||
|
|
||||||
# tone data
|
# tone data
|
||||||
|
|
Ładowanie…
Reference in New Issue