[chirp_devel] [PATCH] While implementing two more radios of the Yaesu FT-4 family (the FT-25, see #7543, and the FT-4V, see #7387), I found that with some moderate reorganization, implementation of new radios will become easier. The proposed reorganization implements one more interstitial layer of inheritance to support the sub families of FT-4 (containing the FT-4X and FT-4V) and FT-65 (containing FT-65 and FT-25). Also, some variable assignments have been moved from the individual radio classes to the SCU-35 base class and to the interstitial classes named above

Bernhard Hailer
Mon Feb 3 19:54:39 PST 2020


# HG changeset patch
# User Bernhard Hailer <ham73tux at gmail.com>
# Date 1580597959 28800
#      Sat Feb 01 14:59:19 2020 -0800
# Node ID 04404b4e386b95acfe95b590af75d9f26619d0ba
# Parent  53cd045bbf8253d32b43a528b245caff243e4c02
While implementing two more radios of the Yaesu FT-4 family (the FT-25, see #7543, and the FT-4V, see #7387), I found that with some moderate reorganization, implementation of new radios will become easier. The proposed reorganization implements one more interstitial layer of inheritance to support the sub families of FT-4 (containing the FT-4X and FT-4V) and FT-65 (containing FT-65 and FT-25). Also, some variable assignments have been moved from the individual radio classes to the SCU-35 base class and to the interstitial classes named above.

This change also adds the infrastructure for adding European or Asian models, and as such prepare for addressing a number of currently open issues (6.25kHz tune step issues on EU models, frequency limitations; see #6619, #6651, #6677, #6761, #6869). It will also make it easier for a few additional fixes for issues which were found during my work on this driver (#7601, #7603, #7605). I will submit these fixes in additional patches.

Fixes: #7615

diff --git a/chirp/drivers/ft4.py b/chirp/drivers/ft4.py
--- a/chirp/drivers/ft4.py
+++ b/chirp/drivers/ft4.py
@@ -2,6 +2,7 @@
 #    Derives loosely from two sources released under GPLv2:
 #      ./template.py, Copyright 2012 Dan Smith <dsmith at danplanet.com>
 #      ./ft60.py, Copyright 2011 Dan Smith <dsmith at danplanet.com>
+#    Edited 2020 Bernhard Hailer AE6YN <ham73tux at gmail.com>
 #
 # This program is free software: you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
@@ -18,8 +19,8 @@
 
 """
 CHIRP driver for Yaesu radios that use the SCU-35 cable. This includes at
-least the FT-4, FT-25, FT-35, and FT-65. This driver will not work with
-older Yaesu models.
+least the FT-4X, FT-4V, FT-65, and FT-25. This driver will not work with older
+Yaesu models.
 """
 import logging
 import struct
@@ -261,7 +262,8 @@
         msg = "Bad echo. Sent:" + util.hexprint(cmd) + ", "
         msg += "Received:" + util.hexprint(echo)
         LOG.debug(msg)
-        raise errors.RadioError("Incorrect echo on serial port. Bad cable?")
+        raise errors.RadioError(
+            "Incorrect echo on serial port. Radio off? Bad cable?")
     if response_len is None:
         return variable_len_resp(pipe)
     if response_len > 0:
@@ -474,8 +476,6 @@
 
 SKIPS = ["", "S"]
 
-BASETYPE_FT4 = ["FT-4XR", "FT-4XE"]
-BASETYPE_FT65 = ["FT-65R"]
 POWER_LEVELS = [chirp_common.PowerLevel("Low", watts=0.5),
                 chirp_common.PowerLevel("Mid", watts=2.5),
                 chirp_common.PowerLevel("High", watts=5.0)]
@@ -560,16 +560,53 @@
 # Each special has unique constrants: band, name yes/no, and pms L/U
 # The FT-65 class replaces the "prog" entry in this list.
 # The name field must be the name of a slot array in MEM_FORMAT
-SPECIALS = [
+SPECIALS_FT4 = [
     ("pms", PMSNAMES),
     ("vfo", ["VFO A UHF", "VFO A VHF", "VFO B FM", "VFO B VHF", "VFO B UHF"]),
     ("home", ["HOME FM", "HOME VHF", "HOME UHF"]),
     ("prog", ["P1", "P2"])
     ]
-BAND_ASSIGNMENTS = [2, 1, 0, 1, 2, 0, 1, 2]  # bands for the vfos and homes
+SPECIALS_FT65 = SPECIALS_FT4
 FT65_PROGS = ("prog", ["P1", "P2", "P3", "P4"])
-FT65_SPECIALS = list(SPECIALS)    # a shallow copy works here
-FT65_SPECIALS[-1] = FT65_PROGS    # replace the last entry (P key names)
+SPECIALS_FT65[-1] = FT65_PROGS    # replace the last entry (P key names)
+
+# I wonder whether we should simply open the bands to what the radios allow
+# for RX? The radios do take care of allowing or prohibiting TX on their own.
+# In that case, the ASIA settings can be used for any region model.
+# To be discussed with Dan Clemmensen. [AE6YN]
+
+VALID_BANDS_US_DUAL = [
+    (65000000, 108000000),     # broadcast FM, receive only
+    (144000000, 148000000),    # VHF, US version, TX and RX
+    (430000000, 450000000)     # UHF, US version, TX and RX
+    ]
+VALID_BANDS_EU_DUAL = [
+    (65000000, 108000000),     # broadcast FM, receive only
+    (144000000, 146000000),    # VHF, EU version, TX and RX
+    (430000000, 440000000)     # UHF, EU version, TX and RX
+    ]
+VALID_BANDS_ASIA_DUAL = [
+    (65000000, 108000000),     # broadcast FM, receive only
+    (136000000, 174000000),    # VHF, Asia version, TX and RX
+    (400000000, 480000000)     # UHF, Asia version, TX and RX
+    ]
+
+VALID_BANDS_US_VHF = [
+    (65000000, 108000000),     # broadcast FM, receive only
+    (144000000, 148000000),    # VHF, US version, TX and RX
+    ]
+VALID_BANDS_EU_VHF = [
+    (65000000, 108000000),     # broadcast FM, receive only
+    (144000000, 146000000),    # VHF, EU version, TX and RX
+    ]
+VALID_BANDS_ASIA_VHF = [
+    (65000000, 108000000),     # broadcast FM, receive only
+    (136000000, 174000000),    # VHF, Asia version, TX and RX
+    ]
+
+# bands for the five VFO and three home channel memories
+BAND_ASSIGNMENTS_DUALBAND = [2, 1, 0, 1, 2, 0, 1, 2]  # all locations used
+BAND_ASSIGNMENTS_MONO_VHF = [1, 1, 0, 1, 1, 0, 1, 1]  # UHF locations unused
 
 
 # None, and 50 Tones. Use this explicit array because the
@@ -620,8 +657,8 @@
                             chirp_common.ExperimentalRadio):
     """
     Base class for all Yaesu radios using the SCU-35 programming cable
-    and its protocol. Classes for specific radios extend this class and
-    are found at the end of this file.
+    and its protocol. Classes for sub families extend this class and
+    are found towards the end of this file.
     """
     VENDOR = "Yaesu"
     MODEL = "SCU-35Generic"  # No radio directly uses the base class
@@ -629,6 +666,12 @@
     MAX_MEM_SLOT = 200
     NEEDS_COMPAT_SERIAL = False
 
+    # These settings are common to all radios in this family.
+    _valid_chars = chirp_common.CHARSET_ASCII
+    numblocks = 0x215           # number of 16-byte blocks in the radio
+    _memsize = 16 * numblocks   # used by CHIRP file loader to guess radio type
+    MAX_MEM_SLOT = 200
+
     @classmethod
     def get_prompts(cls):
         rp = chirp_common.RadioPrompts()
@@ -669,7 +712,6 @@
         rf.has_dtcs_polarity = False    # REV TN reverses the tone, not the dcs
         rf.has_cross = True
         rf.has_settings = True
-        rf.valid_tuning_steps = self.legal_steps
 
         return rf
 
@@ -1027,14 +1069,11 @@
         mem = chirp_common.Memory()
         _mem, ndx, num, regtype, sname = self.slotloc(memref)
         mem.number = num
-        mem.freq = int(_mem.freq) * 10
-        mem.offset = int(_mem.offset) * self.freq_offset_scale
-        mem.duplex = DUPLEX[_mem.duplex]
 
-        self.decode_sql(mem, _mem)
-        mem.power = POWER_LEVELS[_mem.tx_pwr]
-        mem.mode = ["FM", "NFM"][_mem.tx_width]
-        mem.tuning_step = STEP_CODE[_mem.step]
+        # First, we need to know whether a channel is enabled,
+        # then we can process any channel parameters.
+        # It was found (at least on an FT-25) that channels might be
+        # uninitialized and memory is just completely filled with 0xFF.
 
         if regtype == "pms":
             mem.extd_number = sname
@@ -1043,15 +1082,34 @@
             mem.name = clean_name(self._memobj.names[ndx].chrs)
             mem.empty = not retrieve_bit(self._memobj.enable, ndx)
             mem.skip = SKIPS[retrieve_bit(self._memobj.scan, ndx)]
-            txfreq = int(self._memobj.txfreqs[ndx].freq) * 10
-            if (txfreq != 0) and (txfreq != mem.freq):
-                    mem.duplex = "split"
-                    mem.offset = txfreq
         else:
             mem.empty = False
             mem.extd_number = sname
             mem.immutable = ["number", "extd_number", "name", "skip"]
 
+        # So, now if channel is not empty, we can do the evaluation of
+        # all parameters. Otherwise we set them to defaults.
+
+        if mem.empty:
+            mem.freq = 0
+            mem.offset = 0
+            mem.duplex = "off"
+            mem.power = POWER_LEVELS[0]  # "High"
+            mem.mode = "FM"
+            mem.tuning_step = 0
+        else:
+            mem.freq = int(_mem.freq) * 10
+            txfreq = int(self._memobj.txfreqs[ndx].freq) * 10
+            if (txfreq != 0) and (txfreq != mem.freq):
+                mem.duplex = "split"
+                mem.offset = txfreq
+            else:
+                mem.offset = int(_mem.offset) * self.freq_offset_scale
+                mem.duplex = DUPLEX[_mem.duplex]
+            self.decode_sql(mem, _mem)
+            mem.power = POWER_LEVELS[2 - _mem.tx_pwr]
+            mem.mode = ["FM", "NFM"][_mem.tx_width]
+            mem.tuning_step = STEP_CODE[_mem.step]
         return mem
 
     def enforce_band(self, memloc, freq, mem_num, sname):
@@ -1105,28 +1163,16 @@
         return
 
 
- at directory.register
-class YaesuFT4Radio(YaesuSC35GenericRadio):
-    MODEL = "FT-4XR"
-    _basetype = BASETYPE_FT4
-    valid_bands = [
-        (65000000, 108000000),     # broadcast FM, receive only
-        (144000000, 148000000),    # VHF, US version, TX and RX
-        (430000000, 450000000)     # UHF, US version, TX and RX
-                                   # VHF, RX (136000000, 174000000)
-                                   # UHF, RX (400000000, 480000000)
-        ]
-    _valid_chars = chirp_common.CHARSET_ASCII
-    numblocks = 0x215      # number of 16-byte blocks in the radio
-    _memsize = 16 * numblocks   # used by CHIRP file loader to guess radio type
-    MAX_MEM_SLOT = 200
-    Pkeys = 2     # number of programmable keys on the FT-4
-    namelen = 6   # length of the mem name display on the FT-4 front-panel
-    id_str = b'IFT-35R\x00\x00V100\x00\x00'
+class YaesuFT4GenericRadio(YaesuSC35GenericRadio):
+    """
+    FT-4 sub family class. Classes for individual radios extend
+    these classes and are found at the end of this file.
+    """
+    class_specials = SPECIALS_FT4
+    Pkeys = 2     # number of programmable keys
+    namelen = 6   # length of the mem name display on the front-panel
     freq_offset_scale = 25000
-    legal_steps = US_LEGAL_STEPS
     class_group_descs = YaesuSC35GenericRadio.group_descriptions
-    class_specials = SPECIALS
     # names for the setmode function for the programmable keys. Mode zero means
     # that the key is programmed for a memory not a setmode.
     SETMODES = [
@@ -1143,31 +1189,19 @@
         ]
 
 
- at directory.register
-class YaesuFT65Radio(YaesuSC35GenericRadio):
-    MODEL = "FT-65R"
-    _basetype = BASETYPE_FT65
-    valid_bands = [
-        (65000000, 108000000),     # broadcast FM, receive only
-        (144000000, 148000000),    # VHF, US version, TX and RX
-        (430000000, 450000000)     # UHF, US version, TX and RX
-                                   # VHF, RX (136000000, 174000000)
-                                   # UHF, RX (400000000, 480000000)
-        ]
-    _valid_chars = chirp_common.CHARSET_ASCII
-    numblocks = 0x215      # number of 16-byte blocks in the radio
-    _memsize = 16 * numblocks   # used by CHIRP file loader to guess radio type
-    MAX_MEM_SLOT = 200
-    Pkeys = 4     # number of programmable keys on the FT-65
-    namelen = 8   # length of the mem name display on the FT-65 front panel
-    id_str = b'IH-420\x00\x00\x00V100\x00\x00'
+class YaesuFT65GenericRadio(YaesuSC35GenericRadio):
+    """
+    FT-65 sub family class. Classes for individual radios extend
+    these classes and are found at the end of this file.
+    """
+    class_specials = SPECIALS_FT65
+    Pkeys = 4     # number of programmable keys
+    namelen = 8   # length of the mem name display on the front-panel
     freq_offset_scale = 50000
-    legal_steps = US_LEGAL_STEPS
     # we need a deep copy here because we are adding deeper than the top level.
     class_group_descs = copy.deepcopy(YaesuSC35GenericRadio.group_descriptions)
     add_paramdesc(
         class_group_descs, "misc", ("compander", "Compander", ["OFF", "ON"]))
-    class_specials = FT65_SPECIALS
     # names for the setmode function for the programmable keys. Mode zero means
     # that the key is programmed for a memory not a setmode.
     SETMODES = [
@@ -1180,3 +1214,31 @@
         "step", "tot", "tx pwr", "tx save", "vfo.spl",             # 30-34
         "vox", "wfm.rcv", "wide/nar", "wx alert", "scramble"       # 35-39
         ]
+
+
+# Classes for each individual radio.
+
+
+ at directory.register
+class YaesuFT4XRRadio(YaesuFT4GenericRadio):
+    """
+    FT-4X dual band, US version
+    """
+    MODEL = "FT-4XR"
+    id_str = b'IFT-35R\x00\x00V100\x00\x00'
+    valid_bands = VALID_BANDS_US_DUAL
+    legal_steps = US_LEGAL_STEPS
+    BAND_ASSIGNMENTS = BAND_ASSIGNMENTS_DUALBAND
+
+
+ at directory.register
+class YaesuFT65RRadio(YaesuFT65GenericRadio):
+    """
+    FT-65 dual band, US version
+    """
+    MODEL = "FT-65R"
+    id_str = b'IH-420\x00\x00\x00V100\x00\x00'
+    valid_bands = VALID_BANDS_US_DUAL
+    legal_steps = US_LEGAL_STEPS
+    BAND_ASSIGNMENTS = BAND_ASSIGNMENTS_DUALBAND
+



More information about the chirp_devel mailing list