|
# Copyright 2010 Dan Smith <dsmith@danplanet.com>
|
|
#
|
|
# This program is free software: you can redistribute it and/or modify
|
|
# it under the terms of the GNU General Public License as published by
|
|
# the Free Software Foundation, either version 3 of the License, or
|
|
# (at your option) any later version.
|
|
#
|
|
# This program is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU General Public License
|
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
import logging
|
|
import math
|
|
import os
|
|
import threading
|
|
|
|
from chirp import chirp_common, directory, errors, util
|
|
from chirp.settings import RadioSetting, RadioSettingGroup, \
|
|
RadioSettingValueInteger, RadioSettingValueBoolean, \
|
|
RadioSettingValueString, RadioSettingValueList, RadioSettingValueMap, \
|
|
RadioSettings, RadioSettingValueFloat
|
|
|
|
LOG = logging.getLogger(__name__)
|
|
|
|
|
|
class KenwoodD7Position(RadioSettingGroup):
|
|
def __init__(self, name, shortname, radio, *args, **kwargs):
|
|
super().__init__(name, shortname, *args, **kwargs)
|
|
self._radio = radio
|
|
if ' ' in name:
|
|
index = name.split(" ", 1)[1]
|
|
else:
|
|
index = ''
|
|
rs = RadioSetting("latd%s" % index, "Latitude degrees",
|
|
RadioSettingValueInteger(0, 90, 0))
|
|
self.append(rs)
|
|
rs = RadioSetting("latm%s" % index, "Latitude minutes",
|
|
RadioSettingValueFloat(0, 59.99, 0,
|
|
resolution=0.01,
|
|
precision=2))
|
|
self.append(rs)
|
|
rs = RadioSetting("south%s" % index, "South",
|
|
RadioSettingValueBoolean(False))
|
|
self.append(rs)
|
|
rs = RadioSetting("longd%s" % index, "Longitude degrees",
|
|
RadioSettingValueInteger(0, 180, 0))
|
|
self.append(rs)
|
|
rs = RadioSetting("longm%s" % index, "Longitude minutes",
|
|
RadioSettingValueFloat(0, 59.99, 0,
|
|
resolution=0.01, precision=2))
|
|
self.append(rs)
|
|
rs = RadioSetting("west%s" % index, "West",
|
|
RadioSettingValueBoolean(False))
|
|
self.append(rs)
|
|
|
|
def kenwood_d7_read_value(self):
|
|
index = self._get_index()
|
|
name = self.get_name()
|
|
rawval = self._radio._kenwood_get(name)[1]
|
|
curr_value = int(rawval[0:2])
|
|
self["latd%s" % index].value.set_value(curr_value)
|
|
curr_value = int(rawval[2:6]) / 100
|
|
self["latm%s" % index].value.set_value(curr_value)
|
|
curr_value = int(rawval[6:8])
|
|
self["south%s" % index].value.set_value(curr_value)
|
|
curr_value = int(rawval[8:11])
|
|
self["longd%s" % index].value.set_value(curr_value)
|
|
curr_value = int(rawval[11:15]) / 100
|
|
self["longm%s" % index].value.set_value(curr_value)
|
|
curr_value = int(rawval[15:17])
|
|
self["west%s" % index].value.set_value(curr_value)
|
|
self['latd%s' % index].value._has_changed = False
|
|
self['latm%s' % index].value._has_changed = False
|
|
self['south%s' % index].value._has_changed = False
|
|
self['longd%s' % index].value._has_changed = False
|
|
self['longm%s' % index].value._has_changed = False
|
|
self['west%s' % index].value._has_changed = False
|
|
|
|
def _get_index(self):
|
|
name = self.get_name()
|
|
if ' ' in name:
|
|
return name.split(" ", 1)[1]
|
|
return ''
|
|
|
|
def changed(self):
|
|
index = self._get_index()
|
|
if self['latd%s' % index].changed():
|
|
return True
|
|
if self['latm%s' % index].changed():
|
|
return True
|
|
if self['south%s' % index].changed():
|
|
return True
|
|
if self['longd%s' % index].changed():
|
|
return True
|
|
if self['longm%s' % index].changed():
|
|
return True
|
|
if self['west%s' % index].changed():
|
|
return True
|
|
return False
|
|
|
|
def kenwood_d7_set_value(self):
|
|
index = self._get_index()
|
|
latd = self['latd%s' % index].value.get_value()
|
|
latm = self['latm%s' % index].value.get_value()
|
|
latmd = int(round(math.modf(latm)[0] * 100))
|
|
latm = int(round(latm))
|
|
south = int(self['south%s' % index].value.get_value())
|
|
longd = self['longd%s' % index].value.get_value()
|
|
longm = self['longm%s' % index].value.get_value()
|
|
longmd = int(round(math.modf(longm)[0] * 100))
|
|
longm = int(round(longm))
|
|
west = int(self['west%s' % index].value.get_value())
|
|
args = '%s%02d%02d%02d%02d%03d%02d%02d%02d' % (index,
|
|
latd, latm, latmd,
|
|
south,
|
|
longd, longm, longmd,
|
|
west)
|
|
if index != '':
|
|
index = ' ' + index
|
|
self._radio._kenwood_set('MP%s' % index, args)
|
|
# TODO: Hacking up _has_changed is bad... but we don't want
|
|
# to re-send all the set commands each time either.
|
|
self['latd%s' % index].value._has_changed = False
|
|
self['latm%s' % index].value._has_changed = False
|
|
self['south%s' % index].value._has_changed = False
|
|
self['longd%s' % index].value._has_changed = False
|
|
self['longm%s' % index].value._has_changed = False
|
|
self['west%s' % index].value._has_changed = False
|
|
|
|
|
|
class KenwoodD7DTMFMemory(RadioSettingGroup):
|
|
DTMF_CHARSET = "ABCD#*0123456789 "
|
|
|
|
def __init__(self, name, shortname, radio, *args, **kwargs):
|
|
super().__init__(name, shortname, *args, **kwargs)
|
|
self._radio = radio
|
|
self._name = name
|
|
index = self._get_index()
|
|
rs = RadioSetting("DMN %s" % index, "Memory Name",
|
|
RadioSettingValueString(0, 8, '', False))
|
|
self.append(rs)
|
|
rs = RadioSetting("DM %s" % index, "Memory Value",
|
|
RadioSettingValueString(0, 16, '', False,
|
|
self.DTMF_CHARSET))
|
|
self.append(rs)
|
|
|
|
def _get_index(self):
|
|
return "%02d" % int(self._name.split(" ", 1)[1])
|
|
|
|
def kenwood_d7_read_value(self):
|
|
index = self._get_index()
|
|
value = self._radio._kenwood_get("DM %s" % index)[1]
|
|
value = value.replace("E", "*").replace("F", "#")
|
|
vname = self._radio._kenwood_get("DMN %s" % index)[1]
|
|
self["DMN %s" % index].value.set_value(vname)
|
|
self["DMN %s" % index].value._has_changed = False
|
|
self["DM %s" % index].value.set_value(value)
|
|
self["DM %s" % index].value._has_changed = False
|
|
|
|
def changed(self):
|
|
for element in self:
|
|
if element.changed():
|
|
return True
|
|
return False
|
|
|
|
def kenwood_d7_set_value(self):
|
|
for element in self:
|
|
if not element.changed():
|
|
continue
|
|
newval = element.value.get_value()
|
|
newval = newval.replace("*", "E").replace("#", "F")
|
|
self._radio._kenwood_set(element.get_name(),
|
|
newval)
|
|
element.value._has_changed = False
|
|
|
|
|
|
class KenwoodD7ProgrammableVFOs(RadioSettingGroup):
|
|
def __init__(self, name, shortname, radio, *args, **kwargs):
|
|
self._radio = radio
|
|
super().__init__(name, shortname, *args, **kwargs)
|
|
for optname, index, minimum, maximum in self._radio._PROGRAMMABLE_VFOS:
|
|
group = RadioSettingGroup("PV %d" % index, optname)
|
|
self.append(group)
|
|
rs = RadioSetting("PV %dL" % index, "Lower Limit",
|
|
RadioSettingValueInteger(minimum, maximum,
|
|
minimum))
|
|
group.append(rs)
|
|
rs = RadioSetting("PV %dU" % index, "Upper Limit",
|
|
RadioSettingValueInteger(minimum, maximum,
|
|
maximum))
|
|
group.append(rs)
|
|
|
|
def _get_index(self, element):
|
|
name = element.get_name()
|
|
return int(name.split(" ", 1)[1])
|
|
|
|
def kenwood_d7_read_value(self):
|
|
for element in self:
|
|
index = self._get_index(element)
|
|
rv = self._radio._kenwood_get("PV %d" % index)[1]
|
|
lower, upper = rv.split(',', 1)
|
|
lower = int(lower)
|
|
upper = int(upper)
|
|
pvdl = "PV %dL" % index
|
|
pvdu = "PV %dU" % index
|
|
element[pvdl].value.set_value(lower)
|
|
element[pvdl].value._has_changed = False
|
|
element[pvdu].value.set_value(upper)
|
|
element[pvdu].value._has_changed = False
|
|
|
|
def changed(self):
|
|
for element in self:
|
|
for bound in element:
|
|
if bound.changed():
|
|
return True
|
|
return False
|
|
|
|
# TODO: Custom validator things...
|
|
|
|
def kenwood_d7_set_value(self):
|
|
for element in self:
|
|
index = self._get_index(element)
|
|
pvdl = "PV %dL" % index
|
|
pvdu = "PV %dU" % index
|
|
if element[pvdl].changed() or element[pvdu].changed():
|
|
lower = element[pvdl].value.get_value()
|
|
upper = element[pvdu].value.get_value()
|
|
args = "%05d,%05d" % (lower, upper)
|
|
self._radio._kenwood_set(element.get_name(), args)
|
|
element[pvdl].value._has_changed = False
|
|
element[pvdu].value._has_changed = False
|
|
|
|
|
|
class KenwoodD7Family(chirp_common.LiveRadio):
|
|
VENDOR = "Kenwood"
|
|
MODEL = ""
|
|
HARDWARE_FLOW = False
|
|
|
|
_ARG_DELIMITER = " "
|
|
_BAUDS = [9600]
|
|
_CMD_DELIMITER = "\r"
|
|
_DISABLE_AI_CMD = ('AI', '0')
|
|
_DUPLEX = {0: "", 1: "+", 2: "-"}
|
|
_HAS_NAME = True
|
|
_LOCK = threading.Lock()
|
|
_MODES = {0: "FM", 1: "AM"}
|
|
_NOCACHE = "CHIRP_NOCACHE" in os.environ
|
|
_SPLIT = True
|
|
_STEPS = (5.0, 6.25, 10.0, 12.5, 15.0, 20.0, 25.0, 30.0, 50.0, 100.0)
|
|
_TONES = chirp_common.OLD_TONES
|
|
_LOWER = 0
|
|
_UPPER = 199
|
|
_BANDS = []
|
|
|
|
_CALL_CHANS = ("VHF Call", "UHF Call")
|
|
_SPECIAL_CHANS = ("L0", "U0",
|
|
"L1", "U1",
|
|
"L2", "U2",
|
|
"L3", "U3",
|
|
"L4", "U4",
|
|
"L5", "U5",
|
|
"L6", "U6",
|
|
"L7", "U7",
|
|
"L8", "U8",
|
|
"L9", "U9",
|
|
*_CALL_CHANS)
|
|
|
|
# These are used more than once in _COMMON_SETTINGS
|
|
_BOOL = {'type': 'bool'}
|
|
_DATA_BAND = {'type': 'list',
|
|
'values': ("A", "B", "A:TX/B:RX", "A:RX/B:TX")}
|
|
_DTMF_MEMORY = {'type': KenwoodD7DTMFMemory}
|
|
_ON_OFF_DUAL_MAP = {'type': 'map',
|
|
'map': (("Off", "0"), ("On", "1,0")),
|
|
'set_requires': (('DL', True),),
|
|
'get_requires': (('DL', True),)}
|
|
_POSITION = {'type': KenwoodD7Position}
|
|
_SSTV_CHARSET = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 !?-/"
|
|
_SSTV_COLOURS = {'type': 'list',
|
|
'values': ("Black", "Blue", "Red", "Magenta", "Green",
|
|
"Cyan", "Yellow", "White")}
|
|
_STATUS_TEXT = {'type': 'string', 'max_len': 32}
|
|
_SQUELCH = {'type': 'list', 'digits': 2,
|
|
'values': ("Open", "1", "2", "3", "4", "5")}
|
|
# Settings that are shared by at least two radios.
|
|
# If a third radio does not have the setting at all, the presence
|
|
# here won't matter. If it has it but with different parameters,
|
|
# it can be overridden in the subclass _SETTINGS dict.
|
|
_COMMON_SETTINGS = {
|
|
"AIP": _BOOL,
|
|
"ARL": {'type': 'map',
|
|
'map': (('Off', '0000'),) + tuple(
|
|
[('%i' % x, '%04i' % x)
|
|
for x in range(10, 2510, 10)])},
|
|
"ARLM": {'type': 'string', 'max_len': 45},
|
|
"AMGG": {'type': 'string', 'max_len': 45,
|
|
'charset': "ABCDEFGHIJKLMNOPQRSTUVWXYZ*,-0123456789"},
|
|
"AMR": _BOOL,
|
|
"APO": {'type': 'list',
|
|
'values': ("Off", "30min", "60min")},
|
|
"ARO": _BOOL,
|
|
# ASC x requires that the specified VFO is enabled on TH-D7G
|
|
# (ie: dual is on or VFO is current) for both fetch and set
|
|
# Easiest to just enable DL before set/read
|
|
"ASC 0": _ON_OFF_DUAL_MAP,
|
|
"ASC 1": _ON_OFF_DUAL_MAP,
|
|
"BAL": {'type': 'list',
|
|
'values': ("4:0", "3:1", "2:2", "1:3", "0:4")},
|
|
"BC": {'type': 'list',
|
|
'values': ("A", "B")},
|
|
"BCN": _BOOL,
|
|
# BEL x requires that the specified VFO is enabled on TH-D7G
|
|
# (ie: dual is on or VFO is current) for both fetch and set
|
|
# Easiest to just enable DL before set/read
|
|
"BEL 0": _ON_OFF_DUAL_MAP,
|
|
"BEL 1": _ON_OFF_DUAL_MAP,
|
|
"BEP": {'type': 'list',
|
|
'values': ("Off", "Key", "Key+Data", "All")},
|
|
"BEPT": {'type': 'list',
|
|
'values': ("Off", "Mine", "All New", "All")},
|
|
"CH": _BOOL,
|
|
"CKEY": {'type': 'list',
|
|
'values': ("Call", "1750 Hz")},
|
|
"CNT": {'type': 'integer', 'min': 1, 'max': 16},
|
|
"DL": _BOOL,
|
|
"DS": {'type': 'list',
|
|
'values': ("Data Band", "Both Bands")},
|
|
"DTB": _DATA_BAND,
|
|
"DTBA": _DATA_BAND,
|
|
"dtmfmem 00": _DTMF_MEMORY,
|
|
"dtmfmem 01": _DTMF_MEMORY,
|
|
"dtmfmem 02": _DTMF_MEMORY,
|
|
"dtmfmem 03": _DTMF_MEMORY,
|
|
"dtmfmem 04": _DTMF_MEMORY,
|
|
"dtmfmem 05": _DTMF_MEMORY,
|
|
"dtmfmem 06": _DTMF_MEMORY,
|
|
"dtmfmem 07": _DTMF_MEMORY,
|
|
"dtmfmem 08": _DTMF_MEMORY,
|
|
"dtmfmem 09": _DTMF_MEMORY,
|
|
"DTX": {'type': 'list',
|
|
'values': ("Manual", "PTT", "Auto")},
|
|
"ELK": {'type': 'bool'},
|
|
"GU": {'type': 'list',
|
|
'values': ("Not Used", "NMEA", "NMEA96")},
|
|
# This isn't exactly shared, but each radio adds to this list
|
|
"ICO": {'type': 'map',
|
|
'map': (('Kenwood', '0,0'),
|
|
('Runner', '0,1'),
|
|
('House ', '0,2'),
|
|
('Tent', '0,3'),
|
|
('Boat', '0,4'),
|
|
('SSTV', '0,5'),
|
|
('Plane', '0,6'),
|
|
('Speedboat', '0,7'),
|
|
('Car', '0,8'),
|
|
('Bicycle', '0,9'),
|
|
('TRIANGLE(DF station)', '0,A'),
|
|
('Jeep', '0,B'),
|
|
('Recreational Vehicle', '0,C'),
|
|
('Truck ', '0,D'),
|
|
('Van', '0,E'))},
|
|
"KILO": {'type': 'list',
|
|
'values': ("Miles", "Kilometers")},
|
|
"LK": _BOOL,
|
|
"LMP": _BOOL,
|
|
"MAC": _SSTV_COLOURS,
|
|
"MES": {'type': 'string', 'max_len': 8},
|
|
# NOTE: Requires memory mode to be active
|
|
"MNF": {'type': 'list',
|
|
'values': ("Name", "Frequency")},
|
|
"MP 1": _POSITION,
|
|
"MP 2": _POSITION,
|
|
"MP 3": _POSITION,
|
|
"MYC": {'type': 'string', 'max_len': 9},
|
|
"PAMB": {'type': 'list',
|
|
'values': ("Off", "1 Digit", "2 Digits", "3 Digits",
|
|
"4 Digits")},
|
|
"PKSA": {'type': 'list',
|
|
'values': ("1200", "9600")},
|
|
"POSC": {'type': 'list',
|
|
'values': ("Off Duty", "Enroute", "In Service", "Returning",
|
|
"Committed", "Special", "Priority", "CUSTOM 0",
|
|
"CUSTOM 1", "CUSTOM 2", "CUSTOM 4", "CUSTOM 5",
|
|
"CUSTOM 6", "Emergency")},
|
|
"PP": {'type': 'string', 'max_len': 32},
|
|
"PT": {'type': 'list',
|
|
'values': ("100ms", "200ms", "500ms", "750ms",
|
|
"1000ms", "1500ms", "2000ms")},
|
|
"PV": {'type': KenwoodD7ProgrammableVFOs},
|
|
"RSC": _SSTV_COLOURS,
|
|
"RSV": {'type': 'string', 'max_len': 10, 'charset': _SSTV_CHARSET},
|
|
"SCC": {'type': 'string', 'max_len': 8},
|
|
"SCR": {'type': 'list',
|
|
'values': ("Time", "Carrier", "Seek")},
|
|
"SCT": {'type': 'string', 'max_len': 8},
|
|
"SKTN": {'type': 'map',
|
|
'map': tuple([(str(x), "%02d" % (ind + 1))
|
|
for ind, x in enumerate(_TONES) if x != 69.3])},
|
|
"SMC": _SSTV_COLOURS,
|
|
"SMSG": {'type': 'string', 'max_len': 9, 'charset': _SSTV_CHARSET},
|
|
"SMY": {'type': 'string', 'max_len': 8, 'charset': _SSTV_CHARSET},
|
|
"SQ 0": _SQUELCH,
|
|
"SQ 1": _SQUELCH,
|
|
"STAT 1": _STATUS_TEXT,
|
|
"STAT 2": _STATUS_TEXT,
|
|
"STAT 3": _STATUS_TEXT,
|
|
"STXR": {'type': 'list',
|
|
'values': ("Off", "1/1", "1/2", "1/3", "1/4", "1/5", "1/6",
|
|
"1/7", "1/8")},
|
|
"SV": {'type': 'list',
|
|
'values': ("Off", "0.2s", "0.4s", "0.6s", "0.8s", "1.0s",
|
|
"2s", "3s", "4s", "5s")},
|
|
"TEMP": {'type': 'list',
|
|
'values': ("ยฐF", "ยฐC")},
|
|
"TH": _BOOL,
|
|
"TNC": _BOOL,
|
|
"TSP": _BOOL,
|
|
"TXD": {'type': 'map',
|
|
'map': (("100ms", "1"), ("200ms", "2"), ("300ms", "3"),
|
|
("400ms", "4"), ("500ms", "5"), ("750ms", "6"),
|
|
("1000ms", "7"))},
|
|
"TXH": _BOOL,
|
|
"TXI": {'type': 'list',
|
|
'values': ("30sec", "1min", "2min", "3min", "4min", "5min",
|
|
"10min", "20min", "30min")},
|
|
"TXS": _BOOL,
|
|
"TZ": {'type': 'list',
|
|
'values': ("UTC - 12:00", "UTC - 11:30", "UTC - 11:00",
|
|
"UTC - 10:30", "UTC - 10:00", "UTC - 9:30",
|
|
"UTC - 9:00", "UTC - 8:30", "UTC - 8:00",
|
|
"UTC - 7:30", "UTC - 7:00", "UTC - 6:30",
|
|
"UTC - 6:00", "UTC - 5:30", "UTC - 5:00",
|
|
"UTC - 4:30", "UTC - 4:00", "UTC - 3:30",
|
|
"UTC - 3:00", "UTC - 2:30", "UTC - 2:00",
|
|
"UTC - 1:30", "UTC - 1:00", "UTC - 0:30",
|
|
"UTC", "UTC + 0:30", "UTC + 1:00", "UTC + 1:30",
|
|
"UTC + 2:00", "UTC + 2:30", "UTC + 3:00",
|
|
"UTC + 3:30", "UTC + 4:00", "UTC + 4:30",
|
|
"UTC + 5:00", "UTC + 5:30", "UTC + 6:00",
|
|
"UTC + 6:30", "UTC + 7:00", "UTC + 7:30",
|
|
"UTC + 8:00", "UTC + 8:30", "UTC + 9:00",
|
|
"UTC + 9:30", "UTC + 10:00", "UTC + 10:30",
|
|
"UTC + 11:00", "UTC + 11:30", "UTC + 12:00")},
|
|
"UPR": {'type': 'string', 'max_len': 9,
|
|
'charset': "ABCDEFGHIJKLMNOPQRSTUVWXYZ-0123456789"},
|
|
"VCS": _BOOL,
|
|
"WAY": {'type': 'list',
|
|
'values': ("Off", "6 digit NMEA", "7 digit NMEA",
|
|
"8 digit NMEA", "9 digit NMEA", "6 digit Magellan",
|
|
"DGPS")}}
|
|
|
|
_PROGRAMMABLE_VFOS = (
|
|
("Band A, 118 MHz Sub-Band", 1, 118, 135),
|
|
("Band A, VHF Sub-Band", 2, 136, 173),
|
|
("Band B, VHF Sub-Band", 3, 144, 147),
|
|
("Band B, UHF Sub-Band", 6, 400, 479))
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
chirp_common.LiveRadio.__init__(self, *args, **kwargs)
|
|
|
|
# Clear the caches
|
|
self._memcache = {}
|
|
self._setcache = {}
|
|
self._baud = 9600
|
|
self._cur_setting = 0
|
|
self._setting_count = 0
|
|
self._vfo = 0
|
|
if self.pipe:
|
|
self.pipe.timeout = 0.5
|
|
radio_id = self._get_id()
|
|
if hasattr(self, '_ID_STRING'):
|
|
id_str = self._ID_STRING
|
|
else:
|
|
id_str = self.MODEL.split(" ")[0]
|
|
if radio_id != id_str:
|
|
raise Exception("Radio reports %s (not %s)" % (radio_id,
|
|
id_str))
|
|
|
|
self._command(*self._DISABLE_AI_CMD)
|
|
|
|
# This returns the index value for CR/CW commands, not the index
|
|
# in the memory list grid
|
|
def _call_index(self, memid_or_index):
|
|
if isinstance(memid_or_index, int):
|
|
memid = self._index_to_memid(memid_or_index)
|
|
else:
|
|
memid = memid_or_index
|
|
return self._CALL_CHANS.index(memid)
|
|
|
|
# This returns the memid from the index value in CR/CW commands, not
|
|
# the index in the memory list grid
|
|
def _call_index_to_memid(self, index):
|
|
return self._CALL_CHANS[index]
|
|
|
|
def _cmd_get_memory_name(self, memid):
|
|
return "MNA", "%i,%s" % (self._vfo, memid)
|
|
|
|
def _cmd_get_memory_or_split(self, memid, split):
|
|
sd = split and 1 or 0
|
|
if self._is_call(memid):
|
|
return "CR", "%d,%d" % (self._call_index(memid), split)
|
|
return "MR", "%i,%d,%s" % (self._vfo, sd, memid)
|
|
|
|
def _cmd_set_memory_name(self, memid, name):
|
|
if self._is_call(memid):
|
|
return None
|
|
return "MNA", "%i,%s,%s" % (self._vfo, memid, name)
|
|
|
|
def _cmd_set_memory_or_split(self, memid, memory, split):
|
|
if not memory.empty:
|
|
spec = "," + ",".join(self._make_mem_spec(memid, memory))
|
|
else:
|
|
spec = ''
|
|
sd = split and 1 or 0
|
|
if (self._is_call(memid)):
|
|
return "CW", "%d,%d%s" % (self._call_index(memid), sd, spec)
|
|
return "MW", "%i,%d,%s%s" % (self._vfo, sd, memid, spec)
|
|
|
|
def _count_settings(self, entries):
|
|
for entry in entries:
|
|
if (type(entry[1]) is tuple):
|
|
self._count_settings(entry[1])
|
|
else:
|
|
self._setting_count += 1
|
|
|
|
def _create_group(self, entries, grp=None):
|
|
if grp is None:
|
|
grp = RadioSettings()
|
|
for entry in entries:
|
|
if (type(entry[1]) is tuple):
|
|
subgrp = RadioSettingGroup(entry[0].lower(), entry[0])
|
|
grp.append(self._create_group(entry[1], subgrp))
|
|
else:
|
|
setting = self._get_setting_data(entry[0])
|
|
if setting['type'] == 'undefined':
|
|
continue
|
|
if setting['type'] == 'list':
|
|
rsvl = RadioSettingValueList(setting['values'])
|
|
rs = RadioSetting(entry[0], entry[1], rsvl)
|
|
elif setting['type'] == 'bool':
|
|
rs = RadioSetting(entry[0], entry[1],
|
|
RadioSettingValueBoolean(False))
|
|
elif setting['type'] == 'string':
|
|
params = {}
|
|
if 'charset' in setting:
|
|
params['charset'] = setting['charset']
|
|
else:
|
|
params['charset'] = chirp_common.CHARSET_ASCII
|
|
minlen = 'min_len' in setting and setting['min_len'] or 0
|
|
dummy = params['charset'][0] * minlen
|
|
rsvs = RadioSettingValueString(minlen,
|
|
setting['max_len'],
|
|
dummy,
|
|
False, **params)
|
|
rs = RadioSetting(entry[0], entry[1], rsvs)
|
|
elif setting['type'] == 'integer':
|
|
rs = RadioSetting(entry[0], entry[1],
|
|
RadioSettingValueInteger(setting['min'],
|
|
setting['max'],
|
|
setting['min']))
|
|
elif setting['type'] == 'map':
|
|
rsvs = RadioSettingValueMap(setting['map'],
|
|
setting['map'][0][1])
|
|
rs = RadioSetting(entry[0], entry[1], rsvs)
|
|
else:
|
|
rs = setting['type'](entry[0], entry[1], self)
|
|
rs.kenwood_d7_loaded = False
|
|
grp.append(rs)
|
|
self._setcache[entry[0]] = rs
|
|
return grp
|
|
|
|
def _do_prerequisite(self, cmd, get, do):
|
|
if get:
|
|
arg = 'get_requires'
|
|
else:
|
|
arg = 'set_requires'
|
|
setting = self._get_setting_data(cmd)
|
|
if arg not in setting:
|
|
return
|
|
# Undo prerequisites in the reverse order they were applied
|
|
if not do:
|
|
it = reversed(setting[arg])
|
|
else:
|
|
it = iter(setting[arg])
|
|
for prereq, value in it:
|
|
entry = self._setcache[prereq]
|
|
if not entry.kenwood_d7_loaded:
|
|
self._refresh_setting(entry)
|
|
if do:
|
|
entry.kenwood_d7_old_value = entry.value.get_value()
|
|
entry.value.set_value(value)
|
|
else:
|
|
entry.value.set_value(entry.kenwood_d7_old_value)
|
|
sdata = self._get_setting_data(prereq)
|
|
self._set_setting(prereq, sdata, entry)
|
|
|
|
def _drain_input(self):
|
|
oldto = self.pipe.timeout
|
|
self.pipe.timeout = 0
|
|
# Read until a timeout
|
|
while len(self.pipe.read(1)):
|
|
pass
|
|
self.pipe.timeout = oldto
|
|
|
|
def _empty_memory(self, memid):
|
|
mem = chirp_common.Memory()
|
|
if self._is_special(memid):
|
|
mem.extd_number = memid
|
|
mem.number = self._memid_to_index(memid)
|
|
mem.empty = True
|
|
mem.immutable = self._get_immutable(memid)
|
|
return mem
|
|
|
|
def _get_id(self):
|
|
"""Get the ID of the radio attached to @ser"""
|
|
|
|
for i in self._BAUDS:
|
|
LOG.info("Trying ID at baud %i" % i)
|
|
self.pipe.baudrate = i
|
|
# Try to force an error
|
|
self.pipe.write(self._CMD_DELIMITER.encode('cp1252'))
|
|
# Wait for it to be sent
|
|
self.pipe.flush()
|
|
self._drain_input()
|
|
try:
|
|
resp = self._command("ID")
|
|
except UnicodeDecodeError:
|
|
# If we got binary here, we are using the wrong rate
|
|
# or not talking to a kenwood live radio.
|
|
continue
|
|
|
|
ret = self._parse_id_response(resp)
|
|
if ret is not None:
|
|
self._baud = i
|
|
return ret
|
|
|
|
# Radio responded in the right baud rate,
|
|
# but threw an error because of all the crap
|
|
# we have been hurling at it. Retry the ID at this
|
|
# baud rate, which will almost definitely work.
|
|
if "?" in resp:
|
|
resp = self._command("ID")
|
|
ret = self._parse_id_response(resp)
|
|
if ret is not None:
|
|
self._baud = i
|
|
return ret
|
|
raise errors.RadioError("No response from radio")
|
|
|
|
def _get_immutable(self, memid_or_index):
|
|
if self._is_call(memid_or_index):
|
|
return ['name', 'skip']
|
|
if self._is_pscan(memid_or_index):
|
|
return ['skip']
|
|
return []
|
|
|
|
def _get_setting_data(self, setting):
|
|
if setting in self._SETTINGS:
|
|
return self._SETTINGS[setting]
|
|
if setting in self._COMMON_SETTINGS:
|
|
return self._COMMON_SETTINGS[setting]
|
|
if (setting.upper() == setting):
|
|
LOG.debug("Undefined setting: %s" % setting)
|
|
return {'type': 'undefined'}
|
|
|
|
def _get_setting_digits(self, setting_data):
|
|
if 'digits' in setting_data:
|
|
return setting_data['digits']
|
|
if setting_data['type'] == 'integer':
|
|
return len(str(setting_data['max']))
|
|
if setting_data['type'] == 'list':
|
|
return len(str(len(setting_data['values'])))
|
|
raise TypeError('Setting data should not have digits')
|
|
|
|
def _get_tmode(self, tone, ctcss, dcs):
|
|
"""Get the tone mode based on the values of the tone, ctcss, dcs"""
|
|
if dcs and int(dcs) == 1:
|
|
return "DTCS"
|
|
elif int(ctcss):
|
|
return "TSQL"
|
|
elif int(tone):
|
|
return "Tone"
|
|
else:
|
|
return ""
|
|
|
|
def _index_to_memid(self, index):
|
|
if not isinstance(index, int):
|
|
raise errors.RadioError("%s passed as memory index"
|
|
% str(type(index)))
|
|
if index <= self._UPPER:
|
|
return "%03d" % index
|
|
index -= self._UPPER
|
|
index -= 1
|
|
return self._SPECIAL_CHANS[index]
|
|
|
|
def _is_call(self, memid_or_index):
|
|
if isinstance(memid_or_index, int):
|
|
memid = self._index_to_memid(memid_or_index)
|
|
else:
|
|
memid = memid_or_index
|
|
return memid in self._CALL_CHANS
|
|
|
|
def _is_pscan(self, memid_or_index):
|
|
if isinstance(memid_or_index, int):
|
|
memid = self._index_to_memid(memid_or_index)
|
|
else:
|
|
memid = memid_or_index
|
|
if memid[0] == 'L' or memid[0] == 'U':
|
|
if memid[1:].isdigit():
|
|
return True
|
|
return False
|
|
|
|
def _is_special(self, memid_or_index):
|
|
if isinstance(memid_or_index, str):
|
|
index = self._memid_to_index(memid_or_index)
|
|
else:
|
|
index = memid_or_index
|
|
return index > self._UPPER
|
|
|
|
def _iserr(self, result):
|
|
"""Returns True if the @result from a radio is an error"""
|
|
return result in ["N", "?"]
|
|
|
|
def _keep_reading(self, result):
|
|
return False
|
|
|
|
def _kenwood_get(self, cmd):
|
|
self._do_prerequisite(cmd, True, True)
|
|
ret = None
|
|
if " " in cmd:
|
|
suffix = cmd.split(" ", 1)[1]
|
|
resp = self._kenwood_simple_get(cmd)
|
|
if resp[1][0:len(suffix)+1] == suffix + ',':
|
|
resp = (cmd, resp[1][len(suffix)+1:])
|
|
ret = resp
|
|
else:
|
|
raise errors.RadioError("Command %s response value '%s' "
|
|
"unusable" % (cmd, resp[1]))
|
|
else:
|
|
ret = self._kenwood_simple_get(cmd)
|
|
self._do_prerequisite(cmd, True, False)
|
|
return ret
|
|
|
|
def _kenwood_get_bool(self, cmd):
|
|
_cmd, result = self._kenwood_get(cmd)
|
|
return result == "1"
|
|
|
|
def _kenwood_get_int(self, cmd):
|
|
_cmd, result = self._kenwood_get(cmd)
|
|
return int(result)
|
|
|
|
def _kenwood_set_success(self, cmd, modcmd, value, response):
|
|
if response[:len(modcmd)] == modcmd:
|
|
return True
|
|
return False
|
|
|
|
def _kenwood_set(self, cmd, value):
|
|
self._do_prerequisite(cmd, False, True)
|
|
if " " in cmd:
|
|
resp = self._command(cmd + "," + value)
|
|
modcmd = cmd.split(" ", 1)[0]
|
|
else:
|
|
resp = self._command(cmd, value)
|
|
modcmd = cmd
|
|
self._do_prerequisite(cmd, False, False)
|
|
if self._kenwood_set_success(cmd, modcmd, value, resp):
|
|
return
|
|
raise errors.RadioError("Radio refused to set %s" % cmd)
|
|
|
|
def _kenwood_set_bool(self, cmd, value):
|
|
return self._kenwood_set(cmd, str(int(value)))
|
|
|
|
def _kenwood_set_int(self, cmd, value, digits=1):
|
|
return self._kenwood_set(cmd, ("%%0%ii" % digits) % value)
|
|
|
|
def _kenwood_simple_get(self, cmd):
|
|
resp = self._command(cmd)
|
|
if " " in resp:
|
|
return resp.split(" ", 1)
|
|
else:
|
|
if resp == cmd:
|
|
return [resp, ""]
|
|
else:
|
|
raise errors.RadioError("Radio refused to return %s" % cmd)
|
|
|
|
def _mem_spec_fixup(self, spec, memid, mem):
|
|
pass
|
|
|
|
def _make_mem_spec(self, memid, mem):
|
|
if mem.duplex in " -+":
|
|
duplex = util.get_dict_rev(self._DUPLEX, mem.duplex)
|
|
offset = mem.offset
|
|
else:
|
|
duplex = 0
|
|
offset = 0
|
|
|
|
spec = [
|
|
"%011i" % mem.freq,
|
|
"%X" % self._STEPS.index(mem.tuning_step),
|
|
"%i" % duplex,
|
|
"0",
|
|
"%i" % (mem.tmode == "Tone"),
|
|
"%i" % (mem.tmode == "TSQL"),
|
|
"", # DCS Flag
|
|
"%02i" % (self._TONES.index(mem.rtone) + 1),
|
|
"", # DCS Code
|
|
"%02i" % (self._TONES.index(mem.ctone) + 1),
|
|
"%09i" % offset,
|
|
"%i" % util.get_dict_rev(self._MODES, mem.mode)]
|
|
if not self._is_call(memid):
|
|
spec.append("%i" % ((mem.skip == "S") and 1 or 0))
|
|
self._mem_spec_fixup(spec, memid, mem)
|
|
|
|
return tuple(spec)
|
|
|
|
def _make_split_spec(self, mem):
|
|
return ("%011i" % mem.offset, "0")
|
|
|
|
def _memid_to_index(self, memid):
|
|
if not isinstance(memid, str):
|
|
raise errors.RadioError("%s passed as memory id"
|
|
% str(type(memid)))
|
|
if memid in self._SPECIAL_CHANS:
|
|
return self._SPECIAL_CHANS.index(memid) + self._UPPER + 1
|
|
return int(memid)
|
|
|
|
def _parse_id_response(self, resp):
|
|
# most kenwood VHF+ radios
|
|
if " " in resp:
|
|
return resp.split(" ")[1]
|
|
return None
|
|
|
|
def _parse_mem_fixup(self, mem, spec):
|
|
pass
|
|
|
|
def _parse_mem(self, result):
|
|
mem = chirp_common.Memory()
|
|
|
|
value = result.split(" ")[1]
|
|
spec = value.split(",")
|
|
if len(spec) == 14: # This is a Call memory
|
|
spec.insert(1, 0) # Add "bank"
|
|
spec.insert(15, 0) # Add "skip"
|
|
memid = self._call_index_to_memid(int(spec[0]))
|
|
mem.extd_number = memid
|
|
mem.number = self._memid_to_index(mem.extd_number)
|
|
elif spec[2].isdigit(): # Normal memory
|
|
mem.number = int(spec[2])
|
|
memid = self._index_to_memid(mem.number)
|
|
else: # Program Scan memory
|
|
memid = spec[2]
|
|
mem.extd_number = memid
|
|
mem.number = self._memid_to_index(mem.extd_number)
|
|
mem.immutable = self._get_immutable(memid)
|
|
mem.freq = int(spec[3], 10)
|
|
mem.tuning_step = self._STEPS[int(spec[4], 16)]
|
|
mem.duplex = self._DUPLEX[int(spec[5])]
|
|
mem.tmode = self._get_tmode(spec[7], spec[8], spec[9])
|
|
mem.rtone = self._TONES[int(spec[10]) - 1]
|
|
mem.ctone = self._TONES[int(spec[12]) - 1]
|
|
if spec[13]:
|
|
mem.offset = int(spec[13])
|
|
else:
|
|
mem.offset = 0
|
|
mem.mode = self._MODES[int(spec[14])]
|
|
if 'skip' not in mem.immutable:
|
|
mem.skip = int(spec[15]) and "S" or ""
|
|
self._parse_mem_fixup(mem, spec)
|
|
return mem
|
|
|
|
def _parse_split(self, mem, result):
|
|
value = result.split(" ")[1]
|
|
spec = value.split(",")
|
|
mem.duplex = "split"
|
|
# TODO: There's another parameter here... not sure what it is
|
|
if len(spec) == 14: # Call memory
|
|
mem.offset = int(spec[2])
|
|
else:
|
|
mem.offset = int(spec[3])
|
|
|
|
def _refresh_setting(self, entry):
|
|
name = entry.get_name()
|
|
setting = self._get_setting_data(name)
|
|
# TODO: It would be nice to bump_wait_dialog here...
|
|
# Also, this is really only useful for the cli. :(
|
|
if self.status_fn:
|
|
status = chirp_common.Status()
|
|
status.cur = self._cur_setting
|
|
status.max = self._setting_count
|
|
status.msg = "Fetching %-30s" % entry.get_shortname()
|
|
# self.bump_wait_dialog(int(status.cur * 100 / status.max),
|
|
# "Fetching %s" % entry[1])
|
|
self.status_fn(status)
|
|
self._cur_setting += 1
|
|
if setting['type'] == 'list':
|
|
value = self._kenwood_get_int(name)
|
|
entry.value.set_index(value)
|
|
elif setting['type'] == 'bool':
|
|
value = self._kenwood_get_bool(name)
|
|
entry.value.set_value(value)
|
|
elif setting['type'] == 'string':
|
|
value = self._kenwood_get(name)[1]
|
|
entry.value.set_value(value)
|
|
elif setting['type'] == 'integer':
|
|
value = self._kenwood_get_int(name)
|
|
entry.value.set_value(value)
|
|
elif setting['type'] == 'map':
|
|
value = self._kenwood_get(name)[1]
|
|
entry.value.set_mem_val(value)
|
|
else:
|
|
entry.kenwood_d7_read_value()
|
|
if hasattr(entry, 'value'):
|
|
if hasattr(entry.value, '_has_changed'):
|
|
entry.value._has_changed = False
|
|
entry.kenwood_d7_loaded = True
|
|
|
|
def _refresh_settings(self):
|
|
for entry in self._setcache.values():
|
|
if not entry.kenwood_d7_loaded:
|
|
self._refresh_setting(entry)
|
|
|
|
def _validate_memid(self, memid_or_index):
|
|
if isinstance(memid_or_index, int):
|
|
index = memid_or_index
|
|
memid = self._index_to_memid(memid_or_index)
|
|
else:
|
|
memid = memid_or_index
|
|
index = self._memid_to_index(memid_or_index)
|
|
if memid in self._SPECIAL_CHANS:
|
|
pass
|
|
elif index < self._LOWER or index > self._UPPER:
|
|
raise errors.InvalidMemoryLocation(
|
|
"Number must be between %i and %i" % (self._LOWER,
|
|
self._UPPER))
|
|
return index, memid
|
|
|
|
def _validate_memory(self, memory):
|
|
if memory.number is None:
|
|
return self._validate_memid(memory.extd_number)
|
|
return self._validate_memid(memory.number)
|
|
|
|
def _set_setting(self, name, sdata, element):
|
|
if sdata['type'] == 'bool':
|
|
value = element.value.get_value()
|
|
self._kenwood_set_bool(name, value)
|
|
element.value._has_changed = False
|
|
elif sdata['type'] == 'integer':
|
|
value = element.value.get_value()
|
|
digits = self._get_setting_digits(sdata)
|
|
self._kenwood_set_int(name, value, digits)
|
|
element.value._has_changed = False
|
|
elif sdata['type'] == 'string':
|
|
value = element.value.get_value()
|
|
self._kenwood_set(name, value)
|
|
element.value._has_changed = False
|
|
elif sdata['type'] == 'list':
|
|
value = element.value.get_value()
|
|
digits = self._get_setting_digits(sdata)
|
|
self._kenwood_set_int(name, sdata['values'].index(value),
|
|
digits)
|
|
element.value._has_changed = False
|
|
elif sdata['type'] == 'map':
|
|
self._kenwood_set(name, element.value.get_mem_val())
|
|
element.value._has_changed = False
|
|
# TODO: I would like to have tried this first then fetched
|
|
# value, but we can't use hasattr() on settings due to the
|
|
# Magic foo.value attribute in chirp/settings.py. Instead,
|
|
# I need to get_value() each time. :(
|
|
elif hasattr(element, 'kenwood_d7_set_value'):
|
|
element.kenwood_d7_set_value()
|
|
else:
|
|
raise TypeError('No way to set %s value' % name)
|
|
|
|
def _command(self, cmd, *args):
|
|
"""Send @cmd to radio via @ser"""
|
|
|
|
# This lock is needed to allow clicking the settings tab while
|
|
# the memories are still loading. Most important with the TH-D7A
|
|
# and TH-D7A(G) with the 9600bps maximum.
|
|
with self._LOCK:
|
|
if args:
|
|
cmd += self._ARG_DELIMITER + self._ARG_DELIMITER.join(args)
|
|
cmd += self._CMD_DELIMITER
|
|
self._drain_input()
|
|
|
|
LOG.debug("PC->RADIO: %s" % cmd.strip())
|
|
self.pipe.write(cmd.encode('cp1252'))
|
|
cd = self._CMD_DELIMITER.encode('cp1252')
|
|
keep_reading = True
|
|
while keep_reading:
|
|
result = self.pipe.read_until(cd).decode('cp1252')
|
|
if result.endswith(self._CMD_DELIMITER):
|
|
keep_reading = self._keep_reading(result)
|
|
LOG.debug("RADIO->PC: %r" % result.strip())
|
|
result = result[:-1]
|
|
else:
|
|
keep_reading = False
|
|
LOG.error("Timeout waiting for data")
|
|
|
|
return result.strip()
|
|
|
|
def erase_memory(self, memid_or_index):
|
|
index, memid = self._validate_memid(memid_or_index)
|
|
if memid not in self._memcache:
|
|
return
|
|
# TODO: Can't disable the menu item?
|
|
if self._is_call(memid):
|
|
# Raising an error just makes the memory errored
|
|
return
|
|
cmd = self._cmd_set_memory_or_split(memid, self._empty_memory(memid),
|
|
False)
|
|
resp = self._command(*cmd)
|
|
if self._iserr(resp):
|
|
raise errors.RadioError("Radio refused delete of %s" % memid)
|
|
del self._memcache[memid]
|
|
|
|
def get_features(self, *args, **kwargs):
|
|
rf = chirp_common.RadioFeatures(*args, **kwargs)
|
|
rf.valid_tones = tuple([x for x in self._TONES if x != 69.3])
|
|
rf.has_settings = True
|
|
rf.has_dtcs = False
|
|
rf.has_dtcs_polarity = False
|
|
rf.has_bank = False
|
|
rf.has_mode = True
|
|
rf.has_tuning_step = True
|
|
rf.can_odd_split = True
|
|
rf.valid_name_length = 8
|
|
rf.valid_duplexes = ["", "-", "+", "split"]
|
|
rf.valid_modes = list(self._MODES.values())
|
|
rf.valid_tmodes = ["", "Tone", "TSQL"]
|
|
rf.valid_characters = \
|
|
chirp_common.CHARSET_ALPHANUMERIC + "/.-+*)('&%$#! ~}|{"
|
|
rf.valid_tuning_steps = self._STEPS
|
|
rf.memory_bounds = (self._LOWER, self._UPPER)
|
|
rf.valid_special_chans = self._SPECIAL_CHANS
|
|
rf.valid_bands = self._BANDS
|
|
return rf
|
|
|
|
def get_memory(self, memid_or_index):
|
|
index, memid = self._validate_memid(memid_or_index)
|
|
if memid in self._memcache and not self._NOCACHE:
|
|
return self._memcache[memid]
|
|
|
|
result = self._command(*self._cmd_get_memory_or_split(memid,
|
|
False))
|
|
if result == "N":
|
|
mem = self._empty_memory(memid)
|
|
self._memcache[memid] = mem
|
|
return mem
|
|
elif self._ARG_DELIMITER not in result:
|
|
LOG.error("Not sure what to do with this: `%s'" % result)
|
|
raise errors.RadioError("Unexpected result returned from radio")
|
|
|
|
mem = self._parse_mem(result)
|
|
self._memcache[memid] = mem
|
|
|
|
if self._HAS_NAME:
|
|
cmd = self._cmd_get_memory_name(memid)
|
|
if cmd is not None:
|
|
result = self._command(*cmd)
|
|
if " " in result:
|
|
value = result.split(" ", 1)[1]
|
|
mem.name = value.split(",", 2)[2]
|
|
if mem.duplex == "" and self._SPLIT:
|
|
cmd = self._cmd_get_memory_or_split(memid, True)
|
|
if cmd is not None:
|
|
result = self._command(*cmd)
|
|
if " " in result:
|
|
self._parse_split(mem, result)
|
|
|
|
return mem
|
|
|
|
def get_settings(self):
|
|
if self._setting_count == 0:
|
|
self._count_settings(self._SETTINGS_MENUS)
|
|
ret = self._create_group(self._SETTINGS_MENUS)
|
|
self._cur_setting = 0
|
|
self._refresh_settings()
|
|
status = chirp_common.Status()
|
|
status.cur = self._setting_count
|
|
status.max = self._setting_count
|
|
status.msg = "%-40s" % "Done"
|
|
self.status_fn(status)
|
|
return ret
|
|
|
|
def set_memory(self, memory):
|
|
index, memid = self._validate_memory(memory)
|
|
if memory.empty:
|
|
self.erase_memory(memid)
|
|
LOG.debug("set_memory passed an empty memory, perhaps "
|
|
"you wanted erase_memory()?")
|
|
return
|
|
r1 = self._command(*self._cmd_set_memory_or_split(memid, memory,
|
|
False))
|
|
if self._iserr(r1):
|
|
raise errors.InvalidDataError("Radio refused %s" % memid)
|
|
self._memcache[memid] = memory.dupe()
|
|
if self._HAS_NAME:
|
|
r2cmd = self._cmd_set_memory_name(memid, memory.name)
|
|
if r2cmd is not None:
|
|
r2 = self._command(*r2cmd)
|
|
if self._iserr(r2):
|
|
raise errors.InvalidDataError("Radio refused name %s: %s" %
|
|
(memid, repr(memory.name)))
|
|
if memory.duplex == "split" and self._SPLIT:
|
|
result = self._command(*self._cmd_set_memory_or_split(memid,
|
|
memory,
|
|
True))
|
|
if self._iserr(result):
|
|
raise errors.InvalidDataError("Radio refused %s" %
|
|
memid)
|
|
|
|
def set_settings(self, settings):
|
|
for element in settings:
|
|
name = element.get_name()
|
|
sdata = self._get_setting_data(name)
|
|
if sdata['type'] == 'undefined':
|
|
if isinstance(element, RadioSettingGroup):
|
|
self.set_settings(element)
|
|
continue
|
|
if not element.changed():
|
|
continue
|
|
self._set_setting(name, sdata, element)
|
|
|
|
|
|
@directory.register
|
|
class THD7Radio(KenwoodD7Family):
|
|
"""Kenwood TH-D7"""
|
|
MODEL = "TH-D7"
|
|
|
|
_BANDS = [(118000000, 174000000), (400000000, 470000000)]
|
|
_SETTINGS = {
|
|
"BEPT": {'type': 'list',
|
|
'values': ("Off", "Mine", "All New")},
|
|
"DTB": {'type': 'list',
|
|
'values': ("A", "B")},
|
|
"DTBA": {'type': 'list',
|
|
'values': ("A", "B", "A:TX/B:RX", "A:RX/B:TX")},
|
|
"GU": {'type': 'list',
|
|
'values': ("Not Used", "NMEA")},
|
|
"MP": {'type': 'position'},
|
|
"STAT": {'type': 'string', 'max_len': 20},
|
|
"TEMP": {'type': 'list',
|
|
'values': ("Miles / ยฐF", "Kilometers / ยฐC")}}
|
|
|
|
_SETTINGS_MENUS = (
|
|
('Main',
|
|
(("ASC 0", "Automatic Simplex Check Band A"),
|
|
("ASC 1", "Automatic Simplex Check Band B"),
|
|
("BAL", "Balance"),
|
|
("BC", "Band"),
|
|
("BEL 0", "Tone Alert Band A"),
|
|
("BEL 1", "Tone Alert Band B"),
|
|
("CH", "Channel Mode Display"),
|
|
("DL", "Dual"),
|
|
("LMP", "Lamp"),
|
|
("LK", "Lock"),
|
|
# MNF requires that the *current* VFO be in MR mode
|
|
# Also, it has a direct key
|
|
# ("MNF", "Memory Display Mode"),
|
|
("SQ 0", "Band A Squelch"),
|
|
("SQ 1", "Band B Squelch"),
|
|
# We likely don't want to enable this from Chirp...
|
|
# ("TNC", "Packet Mode"))),
|
|
)),
|
|
('Radio',
|
|
(('Display',
|
|
(("MES", "Power-ON Message"),
|
|
("CNT", "Contrast"))),
|
|
('Save',
|
|
(("SV", "Battery Saver Interval"),
|
|
("APO", "Automatic Power Off (APO)"))),
|
|
('DTMF',
|
|
(("dtmfmem 00", "Number Store #0"),
|
|
("dtmfmem 01", "Number Store #1"),
|
|
("dtmfmem 02", "Number Store #2"),
|
|
("dtmfmem 03", "Number Store #3"),
|
|
("dtmfmem 04", "Number Store #4"),
|
|
("dtmfmem 05", "Number Store #5"),
|
|
("dtmfmem 06", "Number Store #6"),
|
|
("dtmfmem 07", "Number Store #7"),
|
|
("dtmfmem 08", "Number Store #8"),
|
|
("dtmfmem 09", "Number Store #9"),
|
|
("TSP", "TX Speed"),
|
|
("TXH", "TX Hold"),
|
|
("PT", "Pause"))),
|
|
('TNC',
|
|
(("DTB", "Data band select"),
|
|
("DS", "DCD sense"))),
|
|
('AUX',
|
|
(("ARO", "Automatic Repeater Offset"),
|
|
("SCR", "Scan Resume"),
|
|
("BEP", "Key Beep"),
|
|
("ELK", "Tuning Enable"),
|
|
("TXS", "TX Inhibit"),
|
|
("AIP", "Advanced Intercept Point"),
|
|
("TH", "TX Hold, 1750 Hz"),
|
|
("XXX", "VHF band narrow TX deviation"))))),
|
|
('APRS',
|
|
(("MYC", "My call sign"),
|
|
("GU", "GPS receiver"),
|
|
# Untested... D7G and D700 take an index, but since D7A only has
|
|
# one position and is older, it may not.
|
|
# ("MP", "Latitude / longitude data"),
|
|
("POSC", "Position comment"),
|
|
("ICO", "Station icon"),
|
|
("STAT", "Status text"),
|
|
("TXI", "Beacon transmit interval"),
|
|
("PP", "Packet path"),
|
|
("DTX", "Beacon transmit method"),
|
|
("UPR", "Group code"),
|
|
("ARL", "Reception restriction distance"),
|
|
("TEMP", "Unit for temperature"))),
|
|
('SSTV',
|
|
(("SMY", "My call sign"),
|
|
("MAC", "Color for call sign"),
|
|
("SMSG", "Message"),
|
|
("SMC", "Color for message"),
|
|
("RSV", "RSV report"),
|
|
("RSC", "Color for RSV report"),
|
|
("VCS", "VC-H1 Control"))),
|
|
('SkyCommand',
|
|
(("SCC", "Commander call sign"),
|
|
("SCT", "Transporter call sign"),
|
|
("SKTN", "Tone frequency select"))))
|
|
|
|
|
|
@directory.register
|
|
class THD7GRadio(KenwoodD7Family):
|
|
"""Kenwood TH-D7G"""
|
|
MODEL = "TH-D7G"
|
|
|
|
_BANDS = [(118000000, 174000000), (400000000, 470000000)]
|
|
_APRS_EXTRA = (('WEATHER Station (blue)', '1,/#'),
|
|
('House QTH (VHF)', '1,/-'),
|
|
('Boy Scouts', '1,/,'),
|
|
('Campground (Portable ops)', '1,/;'),
|
|
('FIRE', '1,/:'),
|
|
('Police, Sheriff', '1,/!'),
|
|
('SERVER for Files', '1,/?'),
|
|
('X', '1,/.'),
|
|
('Small AIRCRAFT (SSID-11)', "1,/'"),
|
|
('reserved (was rain)', '1,/"'),
|
|
('Mobile Satellite Station', '1,/('),
|
|
('Wheelchair (handicapped)', '1,/)'),
|
|
('Human/Person (SSID-7)', '1,/['),
|
|
('MAIL/PostOffice(was PBBS)', '1,/]'),
|
|
('/{ (J1)', '1,/{'),
|
|
('/} (J3)', '1,/}'),
|
|
('HC FUTURE predict (dot)', '1,/@'),
|
|
('SnowMobile', '1,/*'),
|
|
('Red Dot', '1,//'),
|
|
('TRIANGLE(DF station)', '1,/\\'),
|
|
('HF GATEway', '1,/&'),
|
|
('DIGI (white center)', '1,/#'),
|
|
('DX CLUSTER', '1,/%'),
|
|
('Dish Antenna', '1,/`'),
|
|
('LARGE AIRCRAFT', '1,/^'),
|
|
('Red Cross', '1,/+'),
|
|
('Motorcycle (SSID-10)', '1,/<'),
|
|
('RAILROAD ENGINE', '1,/='),
|
|
('CAR (SSID-9)', '1,/>'),
|
|
('TNC Stream Switch', '1,/|'),
|
|
('TNC Stream Switch', '1,/~'),
|
|
('PHONE', '1,/$'),
|
|
('# circle (obsolete)', '1,/0'),
|
|
('TBD (these were numbered)', '1,/1'),
|
|
('TBD (circles like pool)', '1,/2'),
|
|
('TBD (balls. But with)', '1,/3'),
|
|
('TBD (overlays, we can)', '1,/4'),
|
|
("TBD (put all #'s on one)", '1,/5'),
|
|
('TBD (So 1-9 are available)', '1,/6'),
|
|
('TBD (for new uses?)', '1,/7'),
|
|
('TBD (They are often used)', '1,/8'),
|
|
('TBD (as mobiles at events)', '1,/9'),
|
|
('Aid Station', '1,/A'),
|
|
('AMBULANCE (SSID-1)', '1,/a'),
|
|
('BBS or PBBS', '1,/B'),
|
|
('BIKE (SSID-4)', '1,/b'),
|
|
('Canoe', '1,/C'),
|
|
('Incident Command Post', '1,/c'),
|
|
('/D (PD)', '1,/D'),
|
|
('Fire dept', '1,/d'),
|
|
('EYEBALL (Events, etc!)', '1,/E'),
|
|
('HORSE (equestrian)', '1,/e'),
|
|
('Farm Vehicle (tractor)', '1,/F'),
|
|
('FIRE TRUCK (SSID-3)', '1,/f'),
|
|
('Grid Square (6 digit)', '1,/G'),
|
|
('Glider', '1,/g'),
|
|
('HOTEL (blue bed symbol)', '1,/H'),
|
|
('HOSPITAL', '1,/h'),
|
|
('TcpIp on air network stn', '1,/I'),
|
|
('IOTA (islands on the air)', '1,/i'),
|
|
('/J (PJ)', '1,/J'),
|
|
('JEEP (SSID-12)', '1,/j'),
|
|
('School', '1,/K'),
|
|
('TRUCK (SSID-14)', '1,/k'),
|
|
('PC user (Jan 03)', '1,/L'),
|
|
('Laptop (Jan 03) (Feb 07)', '1,/l'),
|
|
('MacAPRS', '1,/M'),
|
|
('Mic-E Repeater', '1,/m'),
|
|
('NTS Station', '1,/N'),
|
|
('Node (black bulls-eye)', '1,/n'),
|
|
('BALLOON (SSID-11)', '1,/O'),
|
|
('EOC', '1,/o'),
|
|
('Police', '1,/P'),
|
|
('ROVER (puppy, or dog)', '1,/p'),
|
|
('TBD', '1,/Q'),
|
|
('GRID SQ shown above 128 m', '1,/q'),
|
|
('REC. VEHICLE (SSID-13)', '1,/R'),
|
|
('Repeater (Feb 07)', '1,/r'),
|
|
('SHUTTLE', '1,/S'),
|
|
('SHIP (pwr boat) (SSID-8)', '1,/s'),
|
|
('SSTV', '1,/T'),
|
|
('TRUCK STOP', '1,/t'),
|
|
('BUS (SSID-2)', '1,/U'),
|
|
('TRUCK (18 wheeler)', '1,/u'),
|
|
('ATV', '1,/V'),
|
|
('VAN (SSID-15)', '1,/v'),
|
|
('National WX Service Site', '1,/W'),
|
|
('WATER station', '1,/w'),
|
|
('HELO (SSID-6)', '1,/X'),
|
|
('xAPRS (Unix)', '1,/x'),
|
|
('YACHT (sail) (SSID-5)', '1,/Y'),
|
|
('YAGI @ QTH', '1,/y'),
|
|
('WinAPRS', '1,/Z'),
|
|
('TBD', '1,/z'),
|
|
('# WX site (green digi)', '1,\\_'),
|
|
('# WX site (green digi) with Zero overlaid', '1,0_'),
|
|
('# WX site (green digi) with One overlaid', '1,1_'),
|
|
('# WX site (green digi) with Two overlaid', '1,2_'),
|
|
('# WX site (green digi) with Three overlaid', '1,3_'),
|
|
('# WX site (green digi) with Four overlaid', '1,4_'),
|
|
('# WX site (green digi) with Five overlaid', '1,5_'),
|
|
('# WX site (green digi) with Six overlaid', '1,6_'),
|
|
('# WX site (green digi) with Seven overlaid', '1,7_'),
|
|
('# WX site (green digi) with Eight overlaid', '1,8_'),
|
|
('# WX site (green digi) with Nine overlaid', '1,9_'),
|
|
('# WX site (green digi) with Letter A overlaid', '1,A_'),
|
|
('# WX site (green digi) with Letter B overlaid', '1,B_'),
|
|
('# WX site (green digi) with Letter C overlaid', '1,C_'),
|
|
('# WX site (green digi) with Letter D overlaid', '1,D_'),
|
|
('# WX site (green digi) with Letter E overlaid', '1,E_'),
|
|
('# WX site (green digi) with Letter F overlaid', '1,F_'),
|
|
('# WX site (green digi) with Letter G overlaid', '1,G_'),
|
|
('# WX site (green digi) with Letter H overlaid', '1,H_'),
|
|
('# WX site (green digi) with Letter I overlaid', '1,I_'),
|
|
('# WX site (green digi) with Letter J overlaid', '1,J_'),
|
|
('# WX site (green digi) with Letter K overlaid', '1,K_'),
|
|
('# WX site (green digi) with Letter L overlaid', '1,L_'),
|
|
('# WX site (green digi) with Letter M overlaid', '1,M_'),
|
|
('# WX site (green digi) with Letter N overlaid', '1,N_'),
|
|
('# WX site (green digi) with Letter O overlaid', '1,O_'),
|
|
('# WX site (green digi) with Letter P overlaid', '1,P_'),
|
|
('# WX site (green digi) with Letter Q overlaid', '1,Q_'),
|
|
('# WX site (green digi) with Letter R overlaid', '1,R_'),
|
|
('# WX site (green digi) with Letter S overlaid', '1,S_'),
|
|
('# WX site (green digi) with Letter T overlaid', '1,T_'),
|
|
('# WX site (green digi) with Letter U overlaid', '1,U_'),
|
|
('# WX site (green digi) with Letter V overlaid', '1,V_'),
|
|
('# WX site (green digi) with Letter W overlaid', '1,W_'),
|
|
('# WX site (green digi) with Letter X overlaid', '1,X_'),
|
|
('# WX site (green digi) with Letter Y overlaid', '1,Y_'),
|
|
('# WX site (green digi) with Letter Z overlaid', '1,Z_'),
|
|
('House (H=HF) (O = Op Present)', '1,\\-'),
|
|
('Girl Scouts', '1,\\,'),
|
|
('Park/Picnic + overlay events', '1,\\;'),
|
|
('AVAIL (Hail ==> ` ovly H)', '1,\\:'),
|
|
('EMERGENCY (and overlays)', '1,\\!'),
|
|
('INFO Kiosk (Blue box with ?)', '1,\\?'),
|
|
('Ambiguous (Big Question mark)', '1,\\.'),
|
|
('Crash (& now Incident sites)', "1,\\'"),
|
|
('reserved', '1,\\"'),
|
|
('CLOUDY (other clouds w ovrly)', '1,\\('),
|
|
('Firenet MEO, MODIS Earth Obs.', '1,\\)'),
|
|
('W.Cloud (& humans w Ovrly)', '1,\\['),
|
|
('AVAIL', '1,\\]'),
|
|
('AVAIL? (Fog ==> E ovly F)', '1,\\{'),
|
|
('AVAIL? (maybe)', '1,\\}'),
|
|
('HURICANE/Trop-Storm', '1,\\@'),
|
|
('AVAIL (SNOW moved to ` ovly S)', '1,\\*'),
|
|
('Waypoint Destination See APRSdos MOBILE.txt', '1,\\/'),
|
|
('New overlayable GPS symbol', '1,\\\\'),
|
|
('I=Igte R=RX T=1hopTX 2=2hopTX', '1,\\&'),
|
|
('I=Igte R=RX T=1hopTX 2=2hopTX with Zero overlaid',
|
|
'1,0&'),
|
|
('I=Igte R=RX T=1hopTX 2=2hopTX with One overlaid', '1,1&'),
|
|
('TX igate with path set to 2 hops', '1,2&'),
|
|
('I=Igte R=RX T=1hopTX 2=2hopTX with Three overlaid',
|
|
'1,3&'),
|
|
('I=Igte R=RX T=1hopTX 2=2hopTX with Four overlaid',
|
|
'1,4&'),
|
|
('I=Igte R=RX T=1hopTX 2=2hopTX with Five overlaid',
|
|
'1,5&'),
|
|
('I=Igte R=RX T=1hopTX 2=2hopTX with Six overlaid', '1,6&'),
|
|
('I=Igte R=RX T=1hopTX 2=2hopTX with Seven overlaid',
|
|
'1,7&'),
|
|
('I=Igte R=RX T=1hopTX 2=2hopTX with Eight overlaid',
|
|
'1,8&'),
|
|
('I=Igte R=RX T=1hopTX 2=2hopTX with Nine overlaid',
|
|
'1,9&'),
|
|
('I=Igte R=RX T=1hopTX 2=2hopTX with Letter A overlaid',
|
|
'1,A&'),
|
|
('I=Igte R=RX T=1hopTX 2=2hopTX with Letter B overlaid',
|
|
'1,B&'),
|
|
('I=Igte R=RX T=1hopTX 2=2hopTX with Letter C overlaid',
|
|
'1,C&'),
|
|
('I=Igte R=RX T=1hopTX 2=2hopTX with Letter D overlaid',
|
|
'1,D&'),
|
|
('I=Igte R=RX T=1hopTX 2=2hopTX with Letter E overlaid',
|
|
'1,E&'),
|
|
('I=Igte R=RX T=1hopTX 2=2hopTX with Letter F overlaid',
|
|
'1,F&'),
|
|
('I=Igte R=RX T=1hopTX 2=2hopTX with Letter G overlaid',
|
|
'1,G&'),
|
|
('I=Igte R=RX T=1hopTX 2=2hopTX with Letter H overlaid',
|
|
'1,H&'),
|
|
('Igate Generic', '1,I&'),
|
|
('I=Igte R=RX T=1hopTX 2=2hopTX with Letter J overlaid',
|
|
'1,J&'),
|
|
('I=Igte R=RX T=1hopTX 2=2hopTX with Letter K overlaid',
|
|
'1,K&'),
|
|
('Lora Igate', '1,L&'),
|
|
('I=Igte R=RX T=1hopTX 2=2hopTX with Letter M overlaid',
|
|
'1,M&'),
|
|
('I=Igte R=RX T=1hopTX 2=2hopTX with Letter N overlaid',
|
|
'1,N&'),
|
|
('I=Igte R=RX T=1hopTX 2=2hopTX with Letter O overlaid',
|
|
'1,O&'),
|
|
('PSKmail node', '1,P&'),
|
|
('I=Igte R=RX T=1hopTX 2=2hopTX with Letter Q overlaid',
|
|
'1,Q&'),
|
|
('Receive only Igate', '1,R&'),
|
|
('I=Igte R=RX T=1hopTX 2=2hopTX with Letter S overlaid',
|
|
'1,S&'),
|
|
('TX igate with path set to 1 hop only', '1,T&'),
|
|
('I=Igte R=RX T=1hopTX 2=2hopTX with Letter U overlaid',
|
|
'1,U&'),
|
|
('I=Igte R=RX T=1hopTX 2=2hopTX with Letter V overlaid',
|
|
'1,V&'),
|
|
('WIRES-X', '1,W&'),
|
|
('I=Igte R=RX T=1hopTX 2=2hopTX with Letter X overlaid',
|
|
'1,X&'),
|
|
('I=Igte R=RX T=1hopTX 2=2hopTX with Letter Y overlaid',
|
|
'1,Y&'),
|
|
('I=Igte R=RX T=1hopTX 2=2hopTX with Letter Z overlaid',
|
|
'1,Z&'),
|
|
('OVERLAY DIGI (green star)', '1,\\#'),
|
|
('OVERLAY DIGI (green star) with Zero overlaid', '1,0#'),
|
|
('OVERLAY DIGI (green star) with One overlaid', '1,1#'),
|
|
('OVERLAY DIGI (green star) with Two overlaid', '1,2#'),
|
|
('OVERLAY DIGI (green star) with Three overlaid', '1,3#'),
|
|
('OVERLAY DIGI (green star) with Four overlaid', '1,4#'),
|
|
('OVERLAY DIGI (green star) with Five overlaid', '1,5#'),
|
|
('OVERLAY DIGI (green star) with Six overlaid', '1,6#'),
|
|
('OVERLAY DIGI (green star) with Seven overlaid', '1,7#'),
|
|
('OVERLAY DIGI (green star) with Eight overlaid', '1,8#'),
|
|
('OVERLAY DIGI (green star) with Nine overlaid', '1,9#'),
|
|
('OVERLAY DIGI (green star) with Letter A overlaid',
|
|
'1,A#'),
|
|
('OVERLAY DIGI (green star) with Letter B overlaid',
|
|
'1,B#'),
|
|
('OVERLAY DIGI (green star) with Letter C overlaid',
|
|
'1,C#'),
|
|
('OVERLAY DIGI (green star) with Letter D overlaid',
|
|
'1,D#'),
|
|
('OVERLAY DIGI (green star) with Letter E overlaid',
|
|
'1,E#'),
|
|
('OVERLAY DIGI (green star) with Letter F overlaid',
|
|
'1,F#'),
|
|
('OVERLAY DIGI (green star) with Letter G overlaid',
|
|
'1,G#'),
|
|
('OVERLAY DIGI (green star) with Letter H overlaid',
|
|
'1,H#'),
|
|
('OVERLAY DIGI (green star) with Letter I overlaid',
|
|
'1,I#'),
|
|
('OVERLAY DIGI (green star) with Letter J overlaid',
|
|
'1,J#'),
|
|
('OVERLAY DIGI (green star) with Letter K overlaid',
|
|
'1,K#'),
|
|
('OVERLAY DIGI (green star) with Letter L overlaid',
|
|
'1,L#'),
|
|
('OVERLAY DIGI (green star) with Letter M overlaid',
|
|
'1,M#'),
|
|
('OVERLAY DIGI (green star) with Letter N overlaid',
|
|
'1,N#'),
|
|
('OVERLAY DIGI (green star) with Letter O overlaid',
|
|
'1,O#'),
|
|
('OVERLAY DIGI (green star) with Letter P overlaid',
|
|
'1,P#'),
|
|
('OVERLAY DIGI (green star) with Letter Q overlaid',
|
|
'1,Q#'),
|
|
('OVERLAY DIGI (green star) with Letter R overlaid',
|
|
'1,R#'),
|
|
('OVERLAY DIGI (green star) with Letter S overlaid',
|
|
'1,S#'),
|
|
('OVERLAY DIGI (green star) with Letter T overlaid',
|
|
'1,T#'),
|
|
('OVERLAY DIGI (green star) with Letter U overlaid',
|
|
'1,U#'),
|
|
('OVERLAY DIGI (green star) with Letter V overlaid',
|
|
'1,V#'),
|
|
('OVERLAY DIGI (green star) with Letter W overlaid',
|
|
'1,W#'),
|
|
('OVERLAY DIGI (green star) with Letter X overlaid',
|
|
'1,X#'),
|
|
('OVERLAY DIGI (green star) with Letter Y overlaid',
|
|
'1,Y#'),
|
|
('OVERLAY DIGI (green star) with Letter Z overlaid',
|
|
'1,Z#'),
|
|
('Power Plant with overlay', '1,\\%'),
|
|
('Rain (all types w ovrly)', '1,\\`'),
|
|
('other Aircraft ovrlys (2014)', '1,\\^'),
|
|
('other Aircraft ovrlys (2014) with Zero overlaid', '1,0^'),
|
|
('other Aircraft ovrlys (2014) with One overlaid', '1,1^'),
|
|
('other Aircraft ovrlys (2014) with Two overlaid', '1,2^'),
|
|
('other Aircraft ovrlys (2014) with Three overlaid',
|
|
'1,3^'),
|
|
('other Aircraft ovrlys (2014) with Four overlaid', '1,4^'),
|
|
('other Aircraft ovrlys (2014) with Five overlaid', '1,5^'),
|
|
('other Aircraft ovrlys (2014) with Six overlaid', '1,6^'),
|
|
('other Aircraft ovrlys (2014) with Seven overlaid',
|
|
'1,7^'),
|
|
('other Aircraft ovrlys (2014) with Eight overlaid',
|
|
'1,8^'),
|
|
('other Aircraft ovrlys (2014) with Nine overlaid', '1,9^'),
|
|
('Autonomous', '1,A^'),
|
|
('other Aircraft ovrlys (2014) with Letter B overlaid',
|
|
'1,B^'),
|
|
('other Aircraft ovrlys (2014) with Letter C overlaid',
|
|
'1,C^'),
|
|
('Drone', '1,D^'),
|
|
('Electric aircraft', '1,E^'),
|
|
('other Aircraft ovrlys (2014) with Letter F overlaid',
|
|
'1,F^'),
|
|
('other Aircraft ovrlys (2014) with Letter G overlaid',
|
|
'1,G^'),
|
|
('Hovercraft', '1,H^'),
|
|
('other Aircraft ovrlys (2014) with Letter I overlaid',
|
|
'1,I^'),
|
|
('JET', '1,J^'),
|
|
('other Aircraft ovrlys (2014) with Letter K overlaid',
|
|
'1,K^'),
|
|
('other Aircraft ovrlys (2014) with Letter L overlaid',
|
|
'1,L^'),
|
|
('Missle', '1,M^'),
|
|
('other Aircraft ovrlys (2014) with Letter N overlaid',
|
|
'1,N^'),
|
|
('other Aircraft ovrlys (2014) with Letter O overlaid',
|
|
'1,O^'),
|
|
('Prop', '1,P^'),
|
|
('other Aircraft ovrlys (2014) with Letter Q overlaid',
|
|
'1,Q^'),
|
|
('Remotely Piloted', '1,R^'),
|
|
('Solar Powered', '1,S^'),
|
|
('other Aircraft ovrlys (2014) with Letter T overlaid',
|
|
'1,T^'),
|
|
('other Aircraft ovrlys (2014) with Letter U overlaid',
|
|
'1,U^'),
|
|
('Vertical takeoff', '1,V^'),
|
|
('other Aircraft ovrlys (2014) with Letter W overlaid',
|
|
'1,W^'),
|
|
('Experimental', '1,X^'),
|
|
('other Aircraft ovrlys (2014) with Letter Y overlaid',
|
|
'1,Y^'),
|
|
('other Aircraft ovrlys (2014) with Letter Z overlaid',
|
|
'1,Z^'),
|
|
('Church', '1,\\+'),
|
|
('ADVISORY (one WX flag)', '1,\\<'),
|
|
('avail. symbol overlay group', '1,\\='),
|
|
('OVERLAYED CARs & Vehicles', '1,\\>'),
|
|
('OVERLAYED CARs & Vehicles with Zero overlaid', '1,0>'),
|
|
('OVERLAYED CARs & Vehicles with One overlaid', '1,1>'),
|
|
('OVERLAYED CARs & Vehicles with Two overlaid', '1,2>'),
|
|
('Model 3 (Tesla)', '1,3>'),
|
|
('OVERLAYED CARs & Vehicles with Four overlaid', '1,4>'),
|
|
('OVERLAYED CARs & Vehicles with Five overlaid', '1,5>'),
|
|
('OVERLAYED CARs & Vehicles with Six overlaid', '1,6>'),
|
|
('OVERLAYED CARs & Vehicles with Seven overlaid', '1,7>'),
|
|
('OVERLAYED CARs & Vehicles with Eight overlaid', '1,8>'),
|
|
('OVERLAYED CARs & Vehicles with Nine overlaid', '1,9>'),
|
|
('OVERLAYED CARs & Vehicles with Letter A overlaid',
|
|
'1,A>'),
|
|
('BEV - Battery EV', '1,B>'),
|
|
('OVERLAYED CARs & Vehicles with Letter C overlaid',
|
|
'1,C>'),
|
|
('DIY - Do it yourself ', '1,D>'),
|
|
('Ethanol (was electric)', '1,E>'),
|
|
('Fuelcell or hydrogen', '1,F>'),
|
|
('OVERLAYED CARs & Vehicles with Letter G overlaid',
|
|
'1,G>'),
|
|
('Hybrid', '1,H>'),
|
|
('OVERLAYED CARs & Vehicles with Letter I overlaid',
|
|
'1,I>'),
|
|
('OVERLAYED CARs & Vehicles with Letter J overlaid',
|
|
'1,J>'),
|
|
('OVERLAYED CARs & Vehicles with Letter K overlaid',
|
|
'1,K>'),
|
|
('Leaf', '1,L>'),
|
|
('OVERLAYED CARs & Vehicles with Letter M overlaid',
|
|
'1,M>'),
|
|
('OVERLAYED CARs & Vehicles with Letter N overlaid',
|
|
'1,N>'),
|
|
('OVERLAYED CARs & Vehicles with Letter O overlaid',
|
|
'1,O>'),
|
|
('PHEV - Plugin-hybrid', '1,P>'),
|
|
('OVERLAYED CARs & Vehicles with Letter Q overlaid',
|
|
'1,Q>'),
|
|
('OVERLAYED CARs & Vehicles with Letter R overlaid',
|
|
'1,R>'),
|
|
('Solar powered', '1,S>'),
|
|
('Tesla (temporary)', '1,T>'),
|
|
('OVERLAYED CARs & Vehicles with Letter U overlaid',
|
|
'1,U>'),
|
|
('Volt (temporary)', '1,V>'),
|
|
('OVERLAYED CARs & Vehicles with Letter W overlaid',
|
|
'1,W>'),
|
|
('Model X', '1,X>'),
|
|
('OVERLAYED CARs & Vehicles with Letter Y overlaid',
|
|
'1,Y>'),
|
|
('OVERLAYED CARs & Vehicles with Letter Z overlaid',
|
|
'1,Z>'),
|
|
('TNC Stream Switch', '1,\\|'),
|
|
('TNC Stream Switch', '1,\\~'),
|
|
('Bank or ATM (green box)', '1,\\$'),
|
|
('CIRCLE (IRLP/Echolink/WIRES)', '1,\\0'),
|
|
('CIRCLE (IRLP/Echolink/WIRES) with Zero overlaid', '1,00'),
|
|
('CIRCLE (IRLP/Echolink/WIRES) with One overlaid', '1,10'),
|
|
('CIRCLE (IRLP/Echolink/WIRES) with Two overlaid', '1,20'),
|
|
('CIRCLE (IRLP/Echolink/WIRES) with Three overlaid',
|
|
'1,30'),
|
|
('CIRCLE (IRLP/Echolink/WIRES) with Four overlaid', '1,40'),
|
|
('CIRCLE (IRLP/Echolink/WIRES) with Five overlaid', '1,50'),
|
|
('CIRCLE (IRLP/Echolink/WIRES) with Six overlaid', '1,60'),
|
|
('CIRCLE (IRLP/Echolink/WIRES) with Seven overlaid',
|
|
'1,70'),
|
|
('CIRCLE (IRLP/Echolink/WIRES) with Eight overlaid',
|
|
'1,80'),
|
|
('CIRCLE (IRLP/Echolink/WIRES) with Nine overlaid', '1,90'),
|
|
('Allstar Node', '1,A0'),
|
|
('CIRCLE (IRLP/Echolink/WIRES) with Letter B overlaid',
|
|
'1,B0'),
|
|
('CIRCLE (IRLP/Echolink/WIRES) with Letter C overlaid',
|
|
'1,C0'),
|
|
('CIRCLE (IRLP/Echolink/WIRES) with Letter D overlaid',
|
|
'1,D0'),
|
|
('Echolink Node', '1,E0'),
|
|
('CIRCLE (IRLP/Echolink/WIRES) with Letter F overlaid',
|
|
'1,F0'),
|
|
('CIRCLE (IRLP/Echolink/WIRES) with Letter G overlaid',
|
|
'1,G0'),
|
|
('CIRCLE (IRLP/Echolink/WIRES) with Letter H overlaid',
|
|
'1,H0'),
|
|
('IRLP repeater', '1,I0'),
|
|
('CIRCLE (IRLP/Echolink/WIRES) with Letter J overlaid',
|
|
'1,J0'),
|
|
('CIRCLE (IRLP/Echolink/WIRES) with Letter K overlaid',
|
|
'1,K0'),
|
|
('CIRCLE (IRLP/Echolink/WIRES) with Letter L overlaid',
|
|
'1,L0'),
|
|
('CIRCLE (IRLP/Echolink/WIRES) with Letter M overlaid',
|
|
'1,M0'),
|
|
('CIRCLE (IRLP/Echolink/WIRES) with Letter N overlaid',
|
|
'1,N0'),
|
|
('CIRCLE (IRLP/Echolink/WIRES) with Letter O overlaid',
|
|
'1,O0'),
|
|
('CIRCLE (IRLP/Echolink/WIRES) with Letter P overlaid',
|
|
'1,P0'),
|
|
('CIRCLE (IRLP/Echolink/WIRES) with Letter Q overlaid',
|
|
'1,Q0'),
|
|
('CIRCLE (IRLP/Echolink/WIRES) with Letter R overlaid',
|
|
'1,R0'),
|
|
('Staging Area', '1,S0'),
|
|
('CIRCLE (IRLP/Echolink/WIRES) with Letter T overlaid',
|
|
'1,T0'),
|
|
('CIRCLE (IRLP/Echolink/WIRES) with Letter U overlaid',
|
|
'1,U0'),
|
|
('Echolink and IRLP', '1,V0'),
|
|
('WIRES (Yaesu VOIP)', '1,W0'),
|
|
('CIRCLE (IRLP/Echolink/WIRES) with Letter X overlaid',
|
|
'1,X0'),
|
|
('CIRCLE (IRLP/Echolink/WIRES) with Letter Y overlaid',
|
|
'1,Y0'),
|
|
('CIRCLE (IRLP/Echolink/WIRES) with Letter Z overlaid',
|
|
'1,Z0'),
|
|
('AVAIL', '1,\\1'),
|
|
('AVAIL', '1,\\2'),
|
|
('AVAIL', '1,\\3'),
|
|
('AVAIL', '1,\\4'),
|
|
('AVAIL', '1,\\5'),
|
|
('AVAIL', '1,\\6'),
|
|
('AVAIL', '1,\\7'),
|
|
('802.11 or other network node', '1,\\8'),
|
|
('Gas Station (blue pump)', '1,\\9'),
|
|
('overlayBOX DTMF & RFID & XO', '1,\\A'),
|
|
('overlayBOX DTMF & RFID & XO with Zero overlaid', '1,0A'),
|
|
('overlayBOX DTMF & RFID & XO with One overlaid', '1,1A'),
|
|
('overlayBOX DTMF & RFID & XO with Two overlaid', '1,2A'),
|
|
('overlayBOX DTMF & RFID & XO with Three overlaid', '1,3A'),
|
|
('overlayBOX DTMF & RFID & XO with Four overlaid', '1,4A'),
|
|
('overlayBOX DTMF & RFID & XO with Five overlaid', '1,5A'),
|
|
('overlayBOX DTMF & RFID & XO with Six overlaid', '1,6A'),
|
|
('HT DTMF user', '1,7A'),
|
|
('overlayBOX DTMF & RFID & XO with Eight overlaid', '1,8A'),
|
|
('Mobile DTMF user', '1,9A'),
|
|
('AllStar DTMF report', '1,AA'),
|
|
('overlayBOX DTMF & RFID & XO with Letter B overlaid',
|
|
'1,BA'),
|
|
('overlayBOX DTMF & RFID & XO with Letter C overlaid',
|
|
'1,CA'),
|
|
('D-Star report', '1,DA'),
|
|
('Echolink DTMF report', '1,EA'),
|
|
('overlayBOX DTMF & RFID & XO with Letter F overlaid',
|
|
'1,FA'),
|
|
('overlayBOX DTMF & RFID & XO with Letter G overlaid',
|
|
'1,GA'),
|
|
('House DTMF user', '1,HA'),
|
|
('IRLP DTMF report', '1,IA'),
|
|
('overlayBOX DTMF & RFID & XO with Letter J overlaid',
|
|
'1,JA'),
|
|
('overlayBOX DTMF & RFID & XO with Letter K overlaid',
|
|
'1,KA'),
|
|
('overlayBOX DTMF & RFID & XO with Letter L overlaid',
|
|
'1,LA'),
|
|
('overlayBOX DTMF & RFID & XO with Letter M overlaid',
|
|
'1,MA'),
|
|
('overlayBOX DTMF & RFID & XO with Letter N overlaid',
|
|
'1,NA'),
|
|
('overlayBOX DTMF & RFID & XO with Letter O overlaid',
|
|
'1,OA'),
|
|
('overlayBOX DTMF & RFID & XO with Letter P overlaid',
|
|
'1,PA'),
|
|
('overlayBOX DTMF & RFID & XO with Letter Q overlaid',
|
|
'1,QA'),
|
|
('RFID report', '1,RA'),
|
|
('overlayBOX DTMF & RFID & XO with Letter S overlaid',
|
|
'1,SA'),
|
|
('overlayBOX DTMF & RFID & XO with Letter T overlaid',
|
|
'1,TA'),
|
|
('overlayBOX DTMF & RFID & XO with Letter U overlaid',
|
|
'1,UA'),
|
|
('overlayBOX DTMF & RFID & XO with Letter V overlaid',
|
|
'1,VA'),
|
|
('overlayBOX DTMF & RFID & XO with Letter W overlaid',
|
|
'1,WA'),
|
|
('OLPC Laptop XO', '1,XA'),
|
|
('overlayBOX DTMF & RFID & XO with Letter Y overlaid',
|
|
'1,YA'),
|
|
('overlayBOX DTMF & RFID & XO with Letter Z overlaid',
|
|
'1,ZA'),
|
|
('ARRL,ARES,WinLINK,Dstar, etc', '1,\\a'),
|
|
('AVAIL (BlwngSnow ==> E ovly B', '1,\\B'),
|
|
('AVAIL (Blwng Dst/Snd => E ovly)', '1,\\b'),
|
|
('Coast Guard', '1,\\C'),
|
|
('CD triangle RACES/SATERN/etc', '1,\\c'),
|
|
('DX spot by callsign', '1,\\d'),
|
|
("DEPOTS (Drizzle ==> ' ovly D)", '1,\\D A'),
|
|
('Smoke (& other vis codes)', '1,\\E'),
|
|
('Sleet (& future ovrly codes)', '1,\\e'),
|
|
('AVAIL (FrzngRain ==> `F)', '1,\\F'),
|
|
('Funnel Cloud', '1,\\f'),
|
|
('AVAIL (Snow Shwr ==> I ovly S)', '1,\\G'),
|
|
('Gale Flags', '1,\\g'),
|
|
('\\Haze (& Overlay Hazards)', '1,\\H'),
|
|
('Store. or HAMFST Hh=HAM store', '1,\\h'),
|
|
('Rain Shower', '1,\\I'),
|
|
('BOX or points of Interest', '1,\\i'),
|
|
('AVAIL (Lightning ==> I ovly L)', '1,\\J'),
|
|
('WorkZone (Steam Shovel)', '1,\\j'),
|
|
('Kenwood HT (W)', '1,\\K'),
|
|
('Special Vehicle SUV,ATV,4x4', '1,\\k'),
|
|
('Lighthouse', '1,\\L'),
|
|
('Areas (box,circles,etc)', '1,\\l'),
|
|
('MARS (A=Army,N=Navy,F=AF)', '1,\\M'),
|
|
('Value Sign (3 digit display)', '1,\\m'),
|
|
('Navigation Buoy', '1,\\N'),
|
|
('OVERLAY TRIANGLE', '1,\\n'),
|
|
('OVERLAY TRIANGLE with Zero overlaid', '1,0n'),
|
|
('OVERLAY TRIANGLE with One overlaid', '1,1n'),
|
|
('OVERLAY TRIANGLE with Two overlaid', '1,2n'),
|
|
('OVERLAY TRIANGLE with Three overlaid', '1,3n'),
|
|
('OVERLAY TRIANGLE with Four overlaid', '1,4n'),
|
|
('OVERLAY TRIANGLE with Five overlaid', '1,5n'),
|
|
('OVERLAY TRIANGLE with Six overlaid', '1,6n'),
|
|
('OVERLAY TRIANGLE with Seven overlaid', '1,7n'),
|
|
('OVERLAY TRIANGLE with Eight overlaid', '1,8n'),
|
|
('OVERLAY TRIANGLE with Nine overlaid', '1,9n'),
|
|
('OVERLAY TRIANGLE with Letter A overlaid', '1,An'),
|
|
('OVERLAY TRIANGLE with Letter B overlaid', '1,Bn'),
|
|
('OVERLAY TRIANGLE with Letter C overlaid', '1,Cn'),
|
|
('OVERLAY TRIANGLE with Letter D overlaid', '1,Dn'),
|
|
('OVERLAY TRIANGLE with Letter E overlaid', '1,En'),
|
|
('OVERLAY TRIANGLE with Letter F overlaid', '1,Fn'),
|
|
('OVERLAY TRIANGLE with Letter G overlaid', '1,Gn'),
|
|
('OVERLAY TRIANGLE with Letter H overlaid', '1,Hn'),
|
|
('OVERLAY TRIANGLE with Letter I overlaid', '1,In'),
|
|
('OVERLAY TRIANGLE with Letter J overlaid', '1,Jn'),
|
|
('OVERLAY TRIANGLE with Letter K overlaid', '1,Kn'),
|
|
('OVERLAY TRIANGLE with Letter L overlaid', '1,Ln'),
|
|
('OVERLAY TRIANGLE with Letter M overlaid', '1,Mn'),
|
|
('OVERLAY TRIANGLE with Letter N overlaid', '1,Nn'),
|
|
('OVERLAY TRIANGLE with Letter O overlaid', '1,On'),
|
|
('OVERLAY TRIANGLE with Letter P overlaid', '1,Pn'),
|
|
('OVERLAY TRIANGLE with Letter Q overlaid', '1,Qn'),
|
|
('OVERLAY TRIANGLE with Letter R overlaid', '1,Rn'),
|
|
('OVERLAY TRIANGLE with Letter S overlaid', '1,Sn'),
|
|
('OVERLAY TRIANGLE with Letter T overlaid', '1,Tn'),
|
|
('OVERLAY TRIANGLE with Letter U overlaid', '1,Un'),
|
|
('OVERLAY TRIANGLE with Letter V overlaid', '1,Vn'),
|
|
('OVERLAY TRIANGLE with Letter W overlaid', '1,Wn'),
|
|
('OVERLAY TRIANGLE with Letter X overlaid', '1,Xn'),
|
|
('OVERLAY TRIANGLE with Letter Y overlaid', '1,Yn'),
|
|
('OVERLAY TRIANGLE with Letter Z overlaid', '1,Zn'),
|
|
('Overlay Balloon (Rocket = \\O)', '1,\\O'),
|
|
('small circle', '1,\\o'),
|
|
('Parking', '1,\\P'),
|
|
('AVAIL (PrtlyCldy => ( ovly P', '1,\\p'),
|
|
('QUAKE', '1,\\Q'),
|
|
('AVAIL', '1,\\q'),
|
|
('Restaurant', '1,\\R'),
|
|
('Restrooms', '1,\\r'),
|
|
('Satellite/Pacsat', '1,\\S'),
|
|
('OVERLAY SHIP/boats', '1,\\s'),
|
|
('OVERLAY SHIP/boats with Zero overlaid', '1,0s'),
|
|
('OVERLAY SHIP/boats with One overlaid', '1,1s'),
|
|
('OVERLAY SHIP/boats with Two overlaid', '1,2s'),
|
|
('OVERLAY SHIP/boats with Three overlaid', '1,3s'),
|
|
('OVERLAY SHIP/boats with Four overlaid', '1,4s'),
|
|
('OVERLAY SHIP/boats with Five overlaid', '1,5s'),
|
|
('Shipwreck ("deep6")', '1,6s'),
|
|
('OVERLAY SHIP/boats with Seven overlaid', '1,7s'),
|
|
('OVERLAY SHIP/boats with Eight overlaid', '1,8s'),
|
|
('OVERLAY SHIP/boats with Nine overlaid', '1,9s'),
|
|
('OVERLAY SHIP/boats with Letter A overlaid', '1,As'),
|
|
('Pleasure Boat', '1,Bs'),
|
|
('Cargo', '1,Cs'),
|
|
('Diving', '1,Ds'),
|
|
('Emergency or Medical transport', '1,Es'),
|
|
('Fishing', '1,Fs'),
|
|
('OVERLAY SHIP/boats with Letter G overlaid', '1,Gs'),
|
|
('High-speed Craft', '1,Hs'),
|
|
('OVERLAY SHIP/boats with Letter I overlaid', '1,Is'),
|
|
('Jet Ski', '1,Js'),
|
|
('OVERLAY SHIP/boats with Letter K overlaid', '1,Ks'),
|
|
('Law enforcement', '1,Ls'),
|
|
('Miltary', '1,Ms'),
|
|
('OVERLAY SHIP/boats with Letter N overlaid', '1,Ns'),
|
|
('Oil Rig', '1,Os'),
|
|
('Pilot Boat', '1,Ps'),
|
|
('Torpedo', '1,Qs'),
|
|
('OVERLAY SHIP/boats with Letter R overlaid', '1,Rs'),
|
|
('Search and Rescue', '1,Ss'),
|
|
('Tug', '1,Ts'),
|
|
('Underwater ops or submarine', '1,Us'),
|
|
('OVERLAY SHIP/boats with Letter V overlaid', '1,Vs'),
|
|
('Wing-in-Ground effect (or Hovercraft)', '1,Ws'),
|
|
('Passenger (paX)(ferry)', '1,Xs'),
|
|
('Sailing (large ship)', '1,Ys'),
|
|
('OVERLAY SHIP/boats with Letter Z overlaid', '1,Zs'),
|
|
('Thunderstorm', '1,\\T'),
|
|
('Tornado', '1,\\t'),
|
|
('SUNNY', '1,\\U'),
|
|
('OVERLAYED TRUCK', '1,\\u'),
|
|
('OVERLAYED TRUCK with Zero overlaid', '1,0u'),
|
|
('OVERLAYED TRUCK with One overlaid', '1,1u'),
|
|
('OVERLAYED TRUCK with Two overlaid', '1,2u'),
|
|
('OVERLAYED TRUCK with Three overlaid', '1,3u'),
|
|
('OVERLAYED TRUCK with Four overlaid', '1,4u'),
|
|
('OVERLAYED TRUCK with Five overlaid', '1,5u'),
|
|
('OVERLAYED TRUCK with Six overlaid', '1,6u'),
|
|
('OVERLAYED TRUCK with Seven overlaid', '1,7u'),
|
|
('OVERLAYED TRUCK with Eight overlaid', '1,8u'),
|
|
('OVERLAYED TRUCK with Nine overlaid', '1,9u'),
|
|
('OVERLAYED TRUCK with Letter A overlaid', '1,Au'),
|
|
('Buldozer/construction/Backhoe', '1,Bu'),
|
|
('Chlorine Tanker', '1,Cu'),
|
|
('OVERLAYED TRUCK with Letter D overlaid', '1,Du'),
|
|
('OVERLAYED TRUCK with Letter E overlaid', '1,Eu'),
|
|
('OVERLAYED TRUCK with Letter F overlaid', '1,Fu'),
|
|
('Gas', '1,Gu'),
|
|
('Hazardous', '1,Hu'),
|
|
('OVERLAYED TRUCK with Letter I overlaid', '1,Iu'),
|
|
('OVERLAYED TRUCK with Letter J overlaid', '1,Ju'),
|
|
('OVERLAYED TRUCK with Letter K overlaid', '1,Ku'),
|
|
('OVERLAYED TRUCK with Letter L overlaid', '1,Lu'),
|
|
('OVERLAYED TRUCK with Letter M overlaid', '1,Mu'),
|
|
('OVERLAYED TRUCK with Letter N overlaid', '1,Nu'),
|
|
('OVERLAYED TRUCK with Letter O overlaid', '1,Ou'),
|
|
('Plow or SnowPlow', '1,Pu'),
|
|
('OVERLAYED TRUCK with Letter Q overlaid', '1,Qu'),
|
|
('OVERLAYED TRUCK with Letter R overlaid', '1,Ru'),
|
|
('OVERLAYED TRUCK with Letter S overlaid', '1,Su'),
|
|
('Tanker', '1,Tu'),
|
|
('OVERLAYED TRUCK with Letter U overlaid', '1,Uu'),
|
|
('OVERLAYED TRUCK with Letter V overlaid', '1,Vu'),
|
|
('OVERLAYED TRUCK with Letter W overlaid', '1,Wu'),
|
|
('OVERLAYED TRUCK with Letter X overlaid', '1,Xu'),
|
|
('OVERLAYED TRUCK with Letter Y overlaid', '1,Yu'),
|
|
('OVERLAYED TRUCK with Letter Z overlaid', '1,Zu'),
|
|
('VORTAC Nav Aid', '1,\\V'),
|
|
('OVERLAYED Van', '1,\\v'),
|
|
('OVERLAYED Van with Zero overlaid', '1,0v'),
|
|
('OVERLAYED Van with One overlaid', '1,1v'),
|
|
('OVERLAYED Van with Two overlaid', '1,2v'),
|
|
('OVERLAYED Van with Three overlaid', '1,3v'),
|
|
('OVERLAYED Van with Four overlaid', '1,4v'),
|
|
('OVERLAYED Van with Five overlaid', '1,5v'),
|
|
('OVERLAYED Van with Six overlaid', '1,6v'),
|
|
('OVERLAYED Van with Seven overlaid', '1,7v'),
|
|
('OVERLAYED Van with Eight overlaid', '1,8v'),
|
|
('OVERLAYED Van with Nine overlaid', '1,9v'),
|
|
('OVERLAYED Van with Letter A overlaid', '1,Av'),
|
|
('OVERLAYED Van with Letter B overlaid', '1,Bv'),
|
|
('OVERLAYED Van with Letter C overlaid', '1,Cv'),
|
|
('OVERLAYED Van with Letter D overlaid', '1,Dv'),
|
|
('OVERLAYED Van with Letter E overlaid', '1,Ev'),
|
|
('OVERLAYED Van with Letter F overlaid', '1,Fv'),
|
|
('OVERLAYED Van with Letter G overlaid', '1,Gv'),
|
|
('OVERLAYED Van with Letter H overlaid', '1,Hv'),
|
|
('OVERLAYED Van with Letter I overlaid', '1,Iv'),
|
|
('OVERLAYED Van with Letter J overlaid', '1,Jv'),
|
|
('OVERLAYED Van with Letter K overlaid', '1,Kv'),
|
|
('OVERLAYED Van with Letter L overlaid', '1,Lv'),
|
|
('OVERLAYED Van with Letter M overlaid', '1,Mv'),
|
|
('OVERLAYED Van with Letter N overlaid', '1,Nv'),
|
|
('OVERLAYED Van with Letter O overlaid', '1,Ov'),
|
|
('OVERLAYED Van with Letter P overlaid', '1,Pv'),
|
|
('OVERLAYED Van with Letter Q overlaid', '1,Qv'),
|
|
('OVERLAYED Van with Letter R overlaid', '1,Rv'),
|
|
('OVERLAYED Van with Letter S overlaid', '1,Sv'),
|
|
('OVERLAYED Van with Letter T overlaid', '1,Tv'),
|
|
('OVERLAYED Van with Letter U overlaid', '1,Uv'),
|
|
('OVERLAYED Van with Letter V overlaid', '1,Vv'),
|
|
('OVERLAYED Van with Letter W overlaid', '1,Wv'),
|
|
('OVERLAYED Van with Letter X overlaid', '1,Xv'),
|
|
('OVERLAYED Van with Letter Y overlaid', '1,Yv'),
|
|
('OVERLAYED Van with Letter Z overlaid', '1,Zv'),
|
|
('# NWS site (NWS options)', '1,\\W'),
|
|
('# NWS site (NWS options) with Zero overlaid', '1,0W'),
|
|
('# NWS site (NWS options) with One overlaid', '1,1W'),
|
|
('# NWS site (NWS options) with Two overlaid', '1,2W'),
|
|
('# NWS site (NWS options) with Three overlaid', '1,3W'),
|
|
('# NWS site (NWS options) with Four overlaid', '1,4W'),
|
|
('# NWS site (NWS options) with Five overlaid', '1,5W'),
|
|
('# NWS site (NWS options) with Six overlaid', '1,6W'),
|
|
('# NWS site (NWS options) with Seven overlaid', '1,7W'),
|
|
('# NWS site (NWS options) with Eight overlaid', '1,8W'),
|
|
('# NWS site (NWS options) with Nine overlaid', '1,9W'),
|
|
('# NWS site (NWS options) with Letter A overlaid', '1,AW'),
|
|
('# NWS site (NWS options) with Letter B overlaid', '1,BW'),
|
|
('# NWS site (NWS options) with Letter C overlaid', '1,CW'),
|
|
('# NWS site (NWS options) with Letter D overlaid', '1,DW'),
|
|
('# NWS site (NWS options) with Letter E overlaid', '1,EW'),
|
|
('# NWS site (NWS options) with Letter F overlaid', '1,FW'),
|
|
('# NWS site (NWS options) with Letter G overlaid', '1,GW'),
|
|
('# NWS site (NWS options) with Letter H overlaid', '1,HW'),
|
|
('# NWS site (NWS options) with Letter I overlaid', '1,IW'),
|
|
('# NWS site (NWS options) with Letter J overlaid', '1,JW'),
|
|
('# NWS site (NWS options) with Letter K overlaid', '1,KW'),
|
|
('# NWS site (NWS options) with Letter L overlaid', '1,LW'),
|
|
('# NWS site (NWS options) with Letter M overlaid', '1,MW'),
|
|
('# NWS site (NWS options) with Letter N overlaid', '1,NW'),
|
|
('# NWS site (NWS options) with Letter O overlaid', '1,OW'),
|
|
('# NWS site (NWS options) with Letter P overlaid', '1,PW'),
|
|
('# NWS site (NWS options) with Letter Q overlaid', '1,QW'),
|
|
('# NWS site (NWS options) with Letter R overlaid', '1,RW'),
|
|
('# NWS site (NWS options) with Letter S overlaid', '1,SW'),
|
|
('# NWS site (NWS options) with Letter T overlaid', '1,TW'),
|
|
('# NWS site (NWS options) with Letter U overlaid', '1,UW'),
|
|
('# NWS site (NWS options) with Letter V overlaid', '1,VW'),
|
|
('# NWS site (NWS options) with Letter W overlaid', '1,WW'),
|
|
('# NWS site (NWS options) with Letter X overlaid', '1,XW'),
|
|
('# NWS site (NWS options) with Letter Y overlaid', '1,YW'),
|
|
('# NWS site (NWS options) with Letter Z overlaid', '1,ZW'),
|
|
('Flooding (Avalanches/Slides)', '1,\\w'),
|
|
('Pharmacy Rx (Apothecary)', '1,\\X'),
|
|
('Wreck or Obstruction ->X<-', '1,\\x'),
|
|
('Radios and devices', '1,\\Y'),
|
|
('Skywarn', '1,\\y'),
|
|
('AVAIL', '1,\\Z'),
|
|
('OVERLAYED Shelter', '1,\\z'))
|
|
_SETTINGS = {
|
|
"DS": {'type': 'list',
|
|
'values': ("Data Band", "Both Bands", "Ignore DCD")},
|
|
"DSPA": {'type': 'list',
|
|
'values': ("Entire Display", "One Line")},
|
|
"ICO": {'type': 'map',
|
|
'map': (
|
|
KenwoodD7Family.
|
|
_COMMON_SETTINGS["ICO"]["map"] + # type: ignore
|
|
_APRS_EXTRA)}}
|
|
|
|
_SETTINGS_MENUS = (
|
|
('Main',
|
|
(("ASC 0", "Automatic Simplex Check Band A"),
|
|
("ASC 1", "Automatic Simplex Check Band B"),
|
|
("BAL", "Balance"),
|
|
("BC", "Band"),
|
|
("BEL 0", "Tone Alert Band A"),
|
|
("BEL 1", "Tone Alert Band B"),
|
|
("CH", "Channel Mode Display"),
|
|
("DL", "Dual"),
|
|
("LK", "Lock"),
|
|
("LMP", "Lamp"),
|
|
# MNF requires that the *current* VFO be in MR mode
|
|
# Also, it has a direct key
|
|
# ("MNF", "Memory Display Mode"),
|
|
("PV", "Programmable VFOs"),
|
|
("SQ 0", "Band A Squelch"),
|
|
("SQ 1", "Band B Squelch"),
|
|
# We likely don't want to enable this from Chirp...
|
|
# ("TNC", "Packet Mode"))),
|
|
)),
|
|
('Radio',
|
|
(('Display',
|
|
(("MES", "Power-ON Message"),
|
|
("CNT", "Contrast"))),
|
|
('Save',
|
|
(("SV", "Battery Saver Interval"),
|
|
("APO", "Automatic Power Off (APO)"))),
|
|
('DTMF',
|
|
(("dtmfmem 00", "Number Store #0"),
|
|
("dtmfmem 01", "Number Store #1"),
|
|
("dtmfmem 02", "Number Store #2"),
|
|
("dtmfmem 03", "Number Store #3"),
|
|
("dtmfmem 04", "Number Store #4"),
|
|
("dtmfmem 05", "Number Store #5"),
|
|
("dtmfmem 06", "Number Store #6"),
|
|
("dtmfmem 07", "Number Store #7"),
|
|
("dtmfmem 08", "Number Store #8"),
|
|
("dtmfmem 09", "Number Store #9"),
|
|
("TSP", "TX Speed"),
|
|
("TXH", "TX Hold"),
|
|
("PT", "Pause"))),
|
|
('TNC',
|
|
(("DTB", "Data band select"),
|
|
("DS", "DCD sense"))),
|
|
('AUX',
|
|
(("ARO", "Automatic Repeater Offset"),
|
|
("SCR", "Scan Resume"),
|
|
("BEP", "Key Beep"),
|
|
("ELK", "Tuning Enable"),
|
|
("TXS", "TX Inhibit"),
|
|
("AIP", "Advanced Intercept Point"),
|
|
("CKEY", "Call Key function"),
|
|
("TH", "TX Hold, 1750 Hz"))))),
|
|
('APRS',
|
|
(("MYC", "My call sign"),
|
|
("GU", "GPS receiver"),
|
|
("WAY", "Waypoint"),
|
|
("MP 1", "My position #1"),
|
|
("MP 2", "My position #2"),
|
|
("MP 3", "My position #3"),
|
|
("PAMB", "Position Ambiguity"),
|
|
("POSC", "Position comment"),
|
|
("ARL", "Reception restriction distance"),
|
|
("ICO", "Station icon"),
|
|
("STAT 1", "Status text #1"),
|
|
("STAT 2", "Status text #2"),
|
|
("STAT 3", "Status text #3"),
|
|
("STXR", "Status text transmit rate"),
|
|
("PP", "Packet path"),
|
|
("DTX", "Packet transmit method"),
|
|
("TXI", "Packet transmit interval"),
|
|
("UPR", "Group code"),
|
|
("BEPT", "Beep"),
|
|
("DSPA", "Display area"),
|
|
("KILO", "Unit for distance"),
|
|
("TEMP", "Unit for temperature"),
|
|
("AMR", "Auto Answer Reply"),
|
|
("ARLM", "Reply message"),
|
|
("AMGG", "Message group"),
|
|
("DTBA", "Data band"),
|
|
("PKSA", "Packet transfer rate"),
|
|
("TZ", "Time Zone"),
|
|
("TXD", "Packet transmit delay"))),
|
|
('SSTV',
|
|
(("SMY", "My call sign"),
|
|
("MAC", "Color for call sign"),
|
|
("SMSG", "Message"),
|
|
("SMC", "Color for message"),
|
|
("RSV", "RSV report"),
|
|
("RSC", "Color for RSV report"),
|
|
("VCS", "VC-H1 Control"))),
|
|
('SkyCommand',
|
|
(("SCC", "Commander call sign"),
|
|
("SCT", "Transporter call sign"),
|
|
("SKTN", "Tone frequency select"))))
|
|
|
|
|
|
@directory.register
|
|
class TMD700Radio(KenwoodD7Family):
|
|
"""Kenwood TH-D700"""
|
|
MODEL = "TM-D700"
|
|
HARDWARE_FLOW = True
|
|
|
|
# Details taken from https://www.qsl.net/k7jar/pages/D700Cmds.html
|
|
# And https://www.qsl.net/k/kb9rku/aprs/ (continued on next line)
|
|
# PC%20Command%20Specifications%20for%20TM-D700_Rev1.pdf
|
|
_BAUDS = [57600, 38400, 19200, 9600]
|
|
_LOWER = 1
|
|
_UPPER = 200
|
|
_BANDS = [(118000000, 524000000), (800000000, 1300000000)]
|
|
|
|
_BOOL = {'type': 'bool'}
|
|
_PKEY_FUNCTION = {'type': 'list',
|
|
'values': ('Power', 'A/B', 'Monitor', 'Enter', 'Voice',
|
|
'1750', 'PM', 'Menu', 'VFO', 'MR', 'CALL',
|
|
'MHz', 'Tone', 'Rev', 'Low', 'Mute', 'Ctrl',
|
|
'PM.In', 'A.B.C', 'M>V', 'M.In', 'C.In',
|
|
'Lock', 'T.Sel', 'Shift', 'Step', 'Visual',
|
|
'Dim', 'Sub-Band Select', 'DX', 'TNC', 'List',
|
|
'P.Mon', 'BCon', 'Msg', 'Pos')}
|
|
_VOLUME = {'type': 'list',
|
|
'values': ('Off', '1', '2', '3', '4', '5', '6', 'Maximum')}
|
|
_SETTINGS = {
|
|
"ABLG": {'type': 'string', 'max_len': 29},
|
|
"AD": _BOOL,
|
|
"BEP": {'type': 'list',
|
|
'values': ("Off", "Key")},
|
|
"BVOL": _VOLUME,
|
|
"CP": {'type': 'list',
|
|
'values': ('9600bps', '19200bps', '38400bps', '57600bps')},
|
|
"DATP": {'type': 'list',
|
|
'values': ('1200bps', '9600bps')},
|
|
"DIG": _BOOL,
|
|
"DTM": _BOOL,
|
|
"FUNC": {'type': 'map',
|
|
'map': (("Mode 1", "1"), ("Mode 2", "2"), ("Mode 3", "3"))},
|
|
"ICO": {'type': 'map',
|
|
'map': (KenwoodD7Family.
|
|
_COMMON_SETTINGS["ICO"]["map"] + # type: ignore
|
|
(('Digipeater', '0,F'),) +
|
|
THD7GRadio._APRS_EXTRA)},
|
|
"MCL 0": _BOOL,
|
|
"MCL 1": _BOOL,
|
|
"MCNT": _BOOL,
|
|
"MD": {'type': 'list', 'values': ('FM', 'AM')},
|
|
"NP": _BOOL,
|
|
"OS": {'type': 'integer', 'min': -99999999, 'max': 999999999,
|
|
'digits': 9},
|
|
"PF 1": _PKEY_FUNCTION,
|
|
"PF 2": _PKEY_FUNCTION,
|
|
"PF 3": _PKEY_FUNCTION,
|
|
"PF 4": _PKEY_FUNCTION,
|
|
"PMM": _BOOL,
|
|
"RCA": _BOOL,
|
|
"RC": _BOOL,
|
|
"RCC": {'type': 'integer', 'min': 0, 'max': 999},
|
|
"REP": {'type': 'list',
|
|
'values': ('Off', 'Locked-Band', 'Cross-Band')},
|
|
"REPL": _BOOL,
|
|
"SHT": {'type': 'list',
|
|
'values': ('Off', '125ms', '250ms', '500ms')},
|
|
"SSEL": {'type': 'map',
|
|
'map': (("MODE1", "1"), ("MODE2", "2"))},
|
|
"SSQ 0": _BOOL,
|
|
"SSQ 1": _BOOL,
|
|
"TOT": {'type': 'list',
|
|
'values': ('3 minutes', '5 minutes', '10 minutes')},
|
|
"UDIG": {'type': 'string', 'max_len': 39, 'charset': '0123456789'
|
|
'ABCDEFGHIJKLMNOPQRSTUVWXYZ,-'},
|
|
"VOM": {'type': 'list',
|
|
'values': ('Off', 'English', 'APRS only', 'Japanese')},
|
|
"VS3": _VOLUME,
|
|
"VSM": {'type': 'map',
|
|
'map': (('31 Channels', '1'), ('61 Channels', '2'),
|
|
('91 Channels', '3'), ('181 Channels', '4'))}}
|
|
|
|
_PROGRAMMABLE_VFOS = (
|
|
("Band A 118 MHz Sub-Band", 1, 118, 135),
|
|
("Band A VHF Sub-Band", 2, 136, 199),
|
|
("Band B VHF Sub-Band", 3, 136, 174),
|
|
("Band A 220 MHz Sub-Band", 4, 200, 299),
|
|
("Band B 300 MHz Sub-Band", 5, 300, 399),
|
|
("Band A 300 MHz Sub-Band", 6, 300, 399),
|
|
("Band B UHF Sub-Band", 7, 400, 523),
|
|
("Band A UHF Sub-Band", 8, 400, 469),
|
|
("Band B 1.2 GHz Sub-Band", 9, 800, 1299))
|
|
|
|
_SETTINGS_MENUS = (
|
|
('Main',
|
|
(("ASC 0", "Automatic Simplex Check Band A"),
|
|
("ASC 1", "Automatic Simplex Check Band B"),
|
|
("DL", "Dual"),
|
|
("LK", "Lock"),
|
|
# MNF requires that the *current* VFO be in MR mode
|
|
# ("MNF", "Memory Display Mode"),
|
|
# We likely don't want to enable this from Chirp...
|
|
# ("TNC", "Packet Mode"))),
|
|
)),
|
|
('Radio',
|
|
(('Display',
|
|
(("MES", "Power-ON Message"),
|
|
("CNT", "Contrast"),
|
|
("NP", "Reverse mode"),
|
|
("AD", "Auto Dimmer Change"),
|
|
("FUNC", "Multi-function button"))),
|
|
('Audio',
|
|
(("BVOL", "Beep volume"),
|
|
("BEP", "Key Beep"),
|
|
("SSEL", "Speaker configuration"),
|
|
("VOM", "Voice Synthesizer"),
|
|
("VS3", "Voice volume"))),
|
|
('TX/RX',
|
|
(("PV", "Programmable VFO"),
|
|
("SSQ 0", "Band A S-meter Squelch"),
|
|
("SSQ 1", "Band B S-meter Squelch"),
|
|
("SHT", "Squelch hang time"),
|
|
("MD", "FM / AM mode"),
|
|
("AIP", "Advanced Intercept Point"),
|
|
("XXX", "TX/ RX deviation"))),
|
|
('Memory',
|
|
(("PMM", "Auto PM Channel Store"),
|
|
("CH", "Channel Display"),
|
|
("MCL 0", "Band A Memory Channel Lockout"),
|
|
("MCL 1", "Band B Memory Channel Lockout"),
|
|
("XXX", "Memory channel name"))),
|
|
('DTMF',
|
|
(("dtmfmem 00", "Number Store #0"),
|
|
("dtmfmem 01", "Number Store #1"),
|
|
("dtmfmem 02", "Number Store #2"),
|
|
("dtmfmem 03", "Number Store #3"),
|
|
("dtmfmem 04", "Number Store #4"),
|
|
("dtmfmem 05", "Number Store #5"),
|
|
("dtmfmem 06", "Number Store #6"),
|
|
("dtmfmem 07", "Number Store #7"),
|
|
("dtmfmem 08", "Number Store #8"),
|
|
("dtmfmem 09", "Number Store #9"),
|
|
("TSP", "TX Speed"),
|
|
("PT", "Pause"))),
|
|
('TNC',
|
|
(("DTB", "Data band"),
|
|
("DS", "DCD sense"),
|
|
("XXX", "Time"),
|
|
("XXX", "Date"),
|
|
("TZ", "Time zone"))),
|
|
('Repeater',
|
|
(("OS", "Offset frequency"),
|
|
("ARO", "Automatic Repeater Offset"),
|
|
("CKEY", "Call Button Function"),
|
|
("TH", "TX Hold"),
|
|
("REPH", "Repeater Hold"),
|
|
("REP", "Repeater function"))),
|
|
('Mic',
|
|
(("PF 1", "Mic PF Key"),
|
|
("PF 2", "Mic MR Key"),
|
|
("PF 3", "Mic VFO Key"),
|
|
("PF 4", "Mic CALL Key"),
|
|
("MCNT", "Microphone Control"),
|
|
("DTM", "DTMF Monitor"))),
|
|
('Aux',
|
|
(("SCR", "Scan Resume"),
|
|
("VSM", "Number of Channels for Visual Scan"),
|
|
("APO", "Automatic Power Off (APO)"),
|
|
("TOT", "Time-Out Timer (TOT)"),
|
|
("CP", "COM port"),
|
|
("DATP", "Data port"))),
|
|
('Remote Control',
|
|
(("RCC", "Secret code"),
|
|
("RCA", "Acknowledgement"),
|
|
("RC", "Remote Control"))))),
|
|
('SSTV',
|
|
(("SMY", "My call sign"),
|
|
("MAC", "Color for call sign"),
|
|
("SMSG", "Message"),
|
|
("SMC", "Color for message"),
|
|
("RSV", "RSV report"),
|
|
("RSC", "Color for RSV report"),
|
|
("VCS", "VC-H1 Control"))),
|
|
('APRS',
|
|
(("MYC", "My call sign"),
|
|
("GU", "GPS receiver"),
|
|
("WAY", "Waypoint"),
|
|
("MP 1", "My position #1"),
|
|
("MP 2", "My position #2"),
|
|
("MP 3", "My position #3"),
|
|
("PAMB", "Position Ambiguity"),
|
|
("POSC", "Position comment"),
|
|
("ARL", "Reception restriction distance"),
|
|
("ICO", "Station icon"),
|
|
("STAT 1", "Status text #1"),
|
|
("STAT 2", "Status text #2"),
|
|
("STAT 3", "Status text #3"),
|
|
("STXR", "Status text transmit rate"),
|
|
("PP", "Packet path"),
|
|
("DTX", "Packet transmit method"),
|
|
("TXI", "Packet transmit interval"),
|
|
("UPR", "Group code"),
|
|
("BEPT", "Beep"),
|
|
("KILO", "Unit for distance"),
|
|
("TEMP", "Unit for temperature"),
|
|
("DTBA", "Data band"),
|
|
("PKSA", "Packet transfer rate"),
|
|
("DIG", "Digipeater"),
|
|
("UDIG", "Digipeating path"),
|
|
("AMR", "Auto Answer Reply"),
|
|
("ARLM", "Reply message"),
|
|
("ABLG", "Bulletin group"))),
|
|
('SkyCommand',
|
|
(("SCC", "Commander call sign"),
|
|
("SCT", "Transporter call sign"),
|
|
("SKTN", "Tone frequency select"))))
|
|
|
|
# Apparently, when sent "CH 1", the radio will return "SM 0,00"
|
|
# which is the current value of the Band A S-Meter. We'll ignore that
|
|
# and read the next line (which is hopefully "CH 1")
|
|
def _keep_reading(self, result):
|
|
if result[0:3] == 'SM ':
|
|
return True
|
|
return False
|
|
|
|
# It also seems that "CH 1" can return "N" when the current memory
|
|
# is invalid (but still enters CH mode)
|
|
def _kenwood_set_success(self, cmd, modcmd, value, response):
|
|
if cmd == 'CH' and value == "1":
|
|
if response == 'N':
|
|
return True
|
|
return super()._kenwood_set_success(cmd, modcmd, value, response)
|
|
|
|
def _mem_spec_fixup(self, spec, memid, mem):
|
|
spec[6] = "%i" % (mem.tmode == "DTCS")
|
|
spec[8] = "%03i0" % (chirp_common.DTCS_CODES.index(mem.dtcs) + 1)
|
|
|
|
def _parse_mem_fixup(self, mem, spec):
|
|
if spec[11] and spec[11].isdigit():
|
|
mem.dtcs = chirp_common.DTCS_CODES[int(spec[11][:-1]) - 1]
|
|
else:
|
|
LOG.warn("Unknown or invalid DCS: %s" % spec[11])
|
|
|
|
def get_features(self, *args, **kwargs):
|
|
rf = super().get_features(*args, **kwargs)
|
|
rf.has_dtcs = True
|
|
rf.valid_tmodes = ["", "Tone", "TSQL", "DTCS"]
|
|
return rf
|