[chirp_devel] New Kenwood_Live.py
Rick DeWitt AA0RD
Thu Nov 7 14:05:11 PST 2019
The first of three patches. This one adds Kenwood TS-480 and TS-590
models to the existing Kenwood_live driver.
--
Rick DeWitt
AA0RD
Sequim, Washington, USA 98382
(360) 681-3494
-------------- next part --------------
# HG changeset patch
# User Rick DeWitt <aa0rd at yahoo.com>
# Date 1573163817 28800
# Thu Nov 07 13:56:57 2019 -0800
# Node ID b5f040349251c09265f07f2747ae073e838798f9
# Parent 60b0754e45de1557ca2597c41a2966129653eeef
[kenwood_live] Added TS-480 and TS-590 live mode, per issues #7077, #7079
Added Kenwood HF rigs to Kenwood_Live per #7077 and #7079
diff -r 60b0754e45de -r b5f040349251 chirp/drivers/kenwood_live.py
--- a/chirp/drivers/kenwood_live.py Thu Oct 24 15:46:01 2019 +0200
+++ b/chirp/drivers/kenwood_live.py Thu Nov 07 13:56:57 2019 -0800
@@ -45,9 +45,13 @@
THF6_MODES = ["FM", "WFM", "AM", "LSB", "USB", "CW"]
+
RADIO_IDS = {
"ID019": "TS-2000",
"ID009": "TS-850",
+ "ID020": "TS-480_LiveMode",
+ "ID021": "TS-590S/SG_LiveMode", # S-model uses same class
+ "ID023": "TS-590S/SG_LiveMode" # as SG
}
LOCK = threading.Lock()
@@ -55,8 +59,9 @@
LAST_BAUD = 4800
LAST_DELIMITER = ("\r", " ")
-# The Kenwood TS-2000 & TS-850 uses ";" as a CAT command message delimiter,
-# and all others use "\n". Also, TS-2000 doesn't space delimite the command
+# The Kenwood TS-2000, TS-480, TS-590 & TS-850 use ";"
+# as a CAT command message delimiter, and all others use "\n".
+# Also, TS-2000 and TS-590 don't space delimite the command
# fields, but others do.
@@ -96,7 +101,7 @@
def get_id(ser):
"""Get the ID of the radio attached to @ser"""
global LAST_BAUD
- bauds = [4800, 9600, 19200, 38400, 57600]
+ bauds = [4800, 9600, 19200, 38400, 57600, 115200]
bauds.remove(LAST_BAUD)
bauds.insert(0, LAST_BAUD)
@@ -994,6 +999,7 @@
"""Kenwood TH-F7"""
MODEL = "TH-F7"
+
D710_DUPLEX = ["", "+", "-", "split"]
D710_MODES = ["FM", "NFM", "AM"]
D710_SKIP = ["", "S"]
@@ -1335,3 +1341,360 @@
def _cmd_set_memory_name(self, number, name):
return "MN", "%03i,%s" % (number, name)
+
+
+ at directory.register
+class TS590Radio(KenwoodLiveRadio):
+ """Kenwood TS-590S/SG"""
+ MODEL = "TS-590S/SG_LiveMode"
+
+ _kenwood_valid_tones = list(KENWOOD_TONES)
+ _kenwood_valid_tones.append(1750)
+
+ _upper = 99
+ _duplex = ["", "-", "+"]
+ _skip = ["", "S"]
+ _modes = ["LSB", "USB", "CW", "FM", "AM", "FSK", "CW-R",
+ "FSK-R", "Data+LSB", "Data+USB", "Data+FM"]
+ _bands = [(1800000, 2000000), # 160M Band
+ (3500000, 4000000), # 80M Band
+ (5167500, 5450000), # 60M Band
+ (7000000, 7300000), # 40M Band
+ (10100000, 10150000), # 30M Band
+ (14000000, 14350000), # 20M Band
+ (18068000, 18168000), # 17M Band
+ (21000000, 21450000), # 15M Band
+ (24890000, 24990000), # 12M Band
+ (28000000, 29700000), # 10M Band
+ (50000000, 54000000)] # 6M Band
+
+ def get_features(self):
+ rf = chirp_common.RadioFeatures()
+
+ rf.can_odd_split = False
+ rf.has_bank = False
+ rf.has_ctone = True
+ rf.has_dtcs = False
+ rf.has_dtcs_polarity = False
+ rf.has_name = True
+ rf.has_settings = False
+ rf.has_offset = True
+ rf.has_mode = True
+ rf.has_tuning_step = False
+ rf.has_nostep_tuning = True
+ rf.has_cross = True
+ rf.has_comment = False
+
+ rf.memory_bounds = (0, self._upper)
+
+ rf.valid_bands = self._bands
+ rf.valid_characters = chirp_common.CHARSET_UPPER_NUMERIC + "*+-/"
+ rf.valid_duplexes = ["", "-", "+"]
+ rf.valid_modes = self._modes
+ rf.valid_skips = ["", "S"]
+ rf.valid_tmodes = ["", "Tone", "TSQL", "Cross"]
+ rf.valid_cross_modes = ["Tone->Tone", "->Tone"]
+ rf.valid_name_length = 8 # 8 character channel names
+
+ return rf
+
+ def _my_val_list(setting, opts, obj, atrb):
+ """Callback:from ValueList. Set the integer index."""
+ value = opts.index(str(setting.value))
+ setattr(obj, atrb, value)
+ return
+
+ def get_memory(self, number):
+ """Convert ascii channel data spec into UI columns (mem)"""
+ mem = chirp_common.Memory()
+ mem.extra = RadioSettingGroup("extra", "Extra")
+ # Read the base and split MR strings
+ mem.number = number
+ spec0 = command(self.pipe, "MR0 %02i" % mem.number)
+ spec1 = command(self.pipe, "MR1 %02i" % mem.number)
+ mem.name = spec0[41:49] # Max 8-Char Name if assigned
+ mem.name = mem.name.strip()
+ mem.name = mem.name.upper()
+ _p4 = int(spec0[6:17]) # Rx Frequency
+ _p4s = int(spec1[6:17]) # Offset freq (Tx)
+ _p5 = int(spec0[17]) # Mode
+ _p6 = int(spec0[18]) # Data Mode
+ _p7 = int(spec0[19]) # Tone Mode
+ _p8 = int(spec0[20:22]) # Tone Frequency Index
+ _p9 = int(spec0[22:24]) # CTCSS Frequency Index
+ _p11 = int(spec0[27]) # Filter A/B
+ _p14 = int(spec0[38:40]) # FM Mode
+ _p15 = int(spec0[40]) # Chan Lockout (Skip)
+ if _p4 == 0:
+ mem.empty = True
+ return mem
+ mem.empty = False
+ mem.freq = _p4
+ mem.duplex = self._duplex[0] # None by default
+ mem.offset = 0
+ if _p4 < _p4s: # + shift
+ mem.duplex = self._duplex[2]
+ mem.offset = _p4s - _p4
+ if _p4 > _p4s: # - shift
+ mem.duplex = self._duplex[1]
+ mem.offset = _p4 - _p4s
+ mx = _p5 - 1 # CAT modes start at 1
+ if _p5 == 9: # except CAT FSK-R is 9, there is no 8
+ mx = 7
+ if _p6: # LSB+Data= 8, USB+Data= 9, FM+Data= 10
+ if _p5 == 1: # CAT LSB
+ mx = 8
+ elif _p5 == 2: # CAT USB
+ mx = 9
+ elif _p5 == 4: # CAT FM
+ mx = 10
+ mem.mode = self._modes[mx]
+ mem.tmode = ""
+ mem.cross_mode = "Tone->Tone"
+ mem.ctone = self._kenwood_valid_tones[_p9]
+ mem.rtone = self._kenwood_valid_tones[_p8]
+ if _p7 == 1:
+ mem.tmode = "Tone"
+ elif _p7 == 2:
+ mem.tmode = "TSQL"
+ elif _p7 == 3:
+ mem.tmode = "Cross"
+ mem.skip = self._skip[_p15]
+
+ rx = RadioSettingValueBoolean(bool(_p14))
+ rset = RadioSetting("fmnrw", "FM Narrow mode (off = Wide)", rx)
+ mem.extra.append(rset)
+ return mem
+
+ def erase_memory(self, number):
+ """ Send the blank string to MW0 """
+ mem = chirp_common.Memory()
+ mem.empty = True
+ mem.freq = 0
+ mem.offset = 0
+ spx = "MW0%03i00000000000000000000000000000000000" % number
+ rx = command(self.pipe, spx) # Send MW0
+ return mem
+
+ def set_memory(self, mem):
+ """Send UI column data (mem) to radio"""
+ pfx = "MW0%03i" % mem.number
+ xmode = 0
+ xtmode = 0
+ xrtone = 8
+ xctone = 8
+ xdata = 0
+ xfltr = 0
+ xfm = 0
+ xskip = 0
+ xfreq = mem.freq
+ if xfreq > 0: # if empty; use those defaults
+ ix = self._modes.index(mem.mode)
+ xmode = ix + 1 # stored as CAT values, LSB= 1
+ if ix == 7: # FSK-R
+ xmode = 9 # There is no CAT 8
+ if ix > 7: # a Data mode
+ xdata = 1
+ if ix == 8:
+ xmode = 1 # LSB
+ elif ix == 9:
+ xmode = 2 # USB
+ elif ix == 10:
+ xmode = 4 # FM
+ if mem.tmode == "Tone":
+ xtmode = 1
+ xrtone = self._kenwood_valid_tones.index(mem.rtone)
+ if mem.tmode == "TSQL" or mem.tmode == "Cross":
+ xtmode = 2
+ if mem.tmode == "Cross":
+ xtmode = 3
+ xctone = self._kenwood_valid_tones.index(mem.ctone)
+ for setting in mem.extra:
+ if setting.get_name() == "fmnrw":
+ xfm = setting.value
+ if mem.skip == "S":
+ xskip = 1
+ spx = "%011i%1i%1i%1i%02i%02i000%1i0000000000%02i%1i%s" \
+ % (xfreq, xmode, xdata, xtmode, xrtone,
+ xctone, xfltr, xfm, xskip, mem.name)
+ rx = command(self.pipe, pfx, spx) # Send MW0
+ if mem.offset != 0:
+ pfx = "MW1%03i" % mem.number
+ xfreq = mem.freq - mem.offset
+ if mem.duplex == "+":
+ xfreq = mem.freq + mem.offset
+ spx = "%011i%1i%1i%1i%02i%02i000%1i0000000000%02i%1i%s" \
+ % (xfreq, xmode, xdata, xtmode, xrtone,
+ xctone, xfltr, xfm, xskip, mem.name)
+ rx = command(self.pipe, pfx, spx) # Send MW1
+
+
+ at directory.register
+class TS480Radio(KenwoodLiveRadio):
+ """Kenwood TS-480"""
+ MODEL = "TS-480_LiveMode"
+
+ _kenwood_valid_tones = list(KENWOOD_TONES)
+ _kenwood_valid_tones.append(1750)
+
+ _upper = 99
+ _duplex = ["", "-", "+"]
+ _skip = ["", "S"]
+ _modes = ["LSB", "USB", "CW", "FM", "AM", "FSK", "CW-R", "N/A",
+ "FSK-R"]
+ _bands = [(1800000, 2000000), # 160M Band
+ (3500000, 4000000), # 80M Band
+ (5167500, 5450000), # 60M Band
+ (7000000, 7300000), # 40M Band
+ (10100000, 10150000), # 30M Band
+ (14000000, 14350000), # 20M Band
+ (18068000, 18168000), # 17M Band
+ (21000000, 21450000), # 15M Band
+ (24890000, 24990000), # 12M Band
+ (28000000, 29700000), # 10M Band
+ (50000000, 54000000)] # 6M Band
+
+ _tsteps = [0.5, 1.0, 2.5, 5.0, 6.25, 10.0, 12.5,
+ 15.0, 20.0, 25.0, 30.0, 50.0, 100.0]
+
+ def get_features(self):
+ rf = chirp_common.RadioFeatures()
+
+ rf.can_odd_split = False
+ rf.has_bank = False
+ rf.has_ctone = True
+ rf.has_dtcs = False
+ rf.has_dtcs_polarity = False
+ rf.has_name = True
+ rf.has_settings = False
+ rf.has_offset = True
+ rf.has_mode = True
+ rf.has_tuning_step = True
+ rf.has_nostep_tuning = True
+ rf.has_cross = True
+ rf.has_comment = False
+
+ rf.memory_bounds = (0, self._upper)
+
+ rf.valid_bands = self._bands
+ rf.valid_characters = chirp_common.CHARSET_UPPER_NUMERIC + "*+-/"
+ rf.valid_duplexes = ["", "-", "+"]
+ rf.valid_modes = self._modes
+ rf.valid_skips = ["", "S"]
+ rf.valid_tmodes = ["", "Tone", "TSQL", "Cross"]
+ rf.valid_cross_modes = ["Tone->Tone", "->Tone"]
+ rf.valid_name_length = 8 # 8 character channel names
+ rf.valid_tuning_steps = self._tsteps
+
+ return rf
+
+ def _my_val_list(setting, opts, obj, atrb):
+ """Callback:from ValueList. Set the integer index."""
+ value = opts.index(str(setting.value))
+ setattr(obj, atrb, value)
+ return
+
+ def get_memory(self, number):
+ """Convert ascii channel data spec into UI columns (mem)"""
+ mem = chirp_common.Memory()
+ # Read the base and split MR strings
+ mem.number = number
+ spec0 = command(self.pipe, "MR0%03i" % mem.number)
+ spec1 = command(self.pipe, "MR1%03i" % mem.number)
+ # Add 1 to string idecis if refering to CAT manual
+ mem.name = spec0[41:49] # Max 8-Char Name if assigned
+ mem.name = mem.name.strip()
+ mem.name = mem.name.upper()
+ _p4 = int(spec0[6:17]) # Rx Frequency
+ _p4s = int(spec1[6:17]) # Offset freq (Tx)
+ _p5 = int(spec0[17]) # Mode
+ _p6 = int(spec0[18]) # Chan Lockout (Skip)
+ _p7 = int(spec0[19]) # Tone Mode
+ _p8 = int(spec0[20:22]) # Tone Frequency Index
+ _p9 = int(spec0[22:24]) # CTCSS Frequency Index
+ _p14 = int(spec0[38:40]) # Tune Step
+ if _p4 == 0:
+ mem.empty = True
+ return mem
+ mem.empty = False
+ mem.freq = _p4
+ mem.duplex = self._duplex[0] # None by default
+ mem.offset = 0
+ if _p4 < _p4s: # + shift
+ mem.duplex = self._duplex[2]
+ mem.offset = _p4s - _p4
+ if _p4 > _p4s: # - shift
+ mem.duplex = self._duplex[1]
+ mem.offset = _p4 - _p4s
+ mx = _p5 - 1 # CAT modes start at 1
+ mem.mode = self._modes[mx]
+ mem.tmode = ""
+ mem.cross_mode = "Tone->Tone"
+ mem.ctone = self._kenwood_valid_tones[_p9]
+ mem.rtone = self._kenwood_valid_tones[_p8]
+ if _p7 == 1:
+ mem.tmode = "Tone"
+ elif _p7 == 2:
+ mem.tmode = "TSQL"
+ elif _p7 == 3:
+ mem.tmode = "Cross"
+ mem.skip = self._skip[_p6]
+ # Tuning step depends on mode
+ options = [0.5, 1.0, 2.5, 5.0, 10.0] # SSB/CS/FSK
+ if _p14 == 4 or _p14 == 5: # AM/FM
+ options = self._tsteps[3:]
+ mem.tuning_step = options[_p14]
+
+ return mem
+
+ def erase_memory(self, number):
+ mem = chirp_common.Memory()
+ mem.empty = True
+ mem.freq = 0
+ mem.offset = 0
+ spx = "MW0%03i00000000000000000000000000000000000" % number
+ rx = command(self.pipe, spx) # Send MW0
+ return mem
+
+ def set_memory(self, mem):
+ """Send UI column data (mem) to radio"""
+ pfx = "MW0%03i" % mem.number
+ xtmode = 0
+ xdata = 0
+ xrtone = 8
+ xctone = 8
+ xskip = 0
+ xstep = 0
+ xfreq = mem.freq
+ if xfreq > 0: # if empty, use those defaults
+ ix = self._modes.index(mem.mode)
+ xmode = ix + 1 # stored as CAT values, LSB= 1
+ if ix == 7: # FSK-R
+ xmode = 9 # There is no CAT 8
+ if mem.tmode == "Tone":
+ xtmode = 1
+ xrtone = self._kenwood_valid_tones.index(mem.rtone)
+ if mem.tmode == "TSQL" or mem.tmode == "Cross":
+ xtmode = 2
+ if mem.tmode == "Cross":
+ xtmode = 3
+ xctone = self._kenwood_valid_tones.index(mem.ctone)
+ if mem.skip == "S":
+ xskip = 1
+ options = [0.5, 1.0, 2.5, 5.0, 10.0] # SSB/CS/FSK
+ if xmode == 4 or xmode == 5:
+ options = self._tsteps[3:]
+ xstep = options.index(mem.tuning_step)
+ spx = "%011i%1i%1i%1i%02i%02i00000000000000%02i%s" \
+ % (xfreq, xmode, xskip, xtmode, xrtone,
+ xctone, xstep, mem.name)
+ rx = command(self.pipe, pfx, spx) # Send MW0
+ if mem.offset != 0: # Don't send MW1 if empty
+ pfx = "MW1%03i" % mem.number
+ xfreq = mem.freq - mem.offset
+ if mem.duplex == "+":
+ xfreq = mem.freq + mem.offset
+ spx = "%011i%1i%1i%1i%02i%02i00000000000000%02i%s" \
+ % (xfreq, xmode, xskip, xtmode, xrtone,
+ xctone, xstep, mem.name)
+ rx = command(self.pipe, pfx, spx) # Send MW1
More information about the chirp_devel
mailing list