[chirp_devel] [PATCH][New Model] Yaesu FT-1500M, fixes #3

Josh
Thu Dec 5 14:07:53 PST 2019


Here's a patch to add support for the Yaesu FT-1500M, see issue #3.
Tests appear to pass, and an image file has been attached to the issue.

- Josh

-------------- next part --------------
# HG changeset patch
# User Josh Small VK2HFF <chirp at vk2hff.ampr.org>
# Date 1575540875 -39600
#      Thu Dec 05 21:14:35 2019 +1100
# Node ID 93e6ed0dc09d5ac2a7e76ebdd795003d528b2556
# Parent  c9c97668945488ab558494b0ed8b05403a1b4f2e
Issue #3 - New(!) Model, Yaesu FT-1500M

diff -r c9c976689454 -r 93e6ed0dc09d chirp/drivers/ft1500m.py
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/chirp/drivers/ft1500m.py	Thu Dec 05 21:14:35 2019 +1100
@@ -0,0 +1,235 @@
+# Copyright 2019 Josh Small VK2HFF <chirp at vk2hff.ampr.org>
+# - Derived from ./ft1802.py Copyright 2012 Tom Hayward <tom at tomh.us>
+#
+# 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/>.
+
+# FT-1500M Clone Proceedure
+# 1. Turn radio off.
+# 2. Connect cable to mic jack.
+# 3. Press and hold in the [MHz],[LOW] and [D/MR] keys
+#    while turning the radio on.
+# 4. In Chirp, choose Download from Radio.
+# 5. Press the [MHz(SET)] key to send image.
+# or
+# 4. Press the [D/MR(MW)] key ("--WAIT--" will appear on the LCD).
+# 5. In Chirp, choose Upload to Radio.
+
+from chirp.drivers import yaesu_clone
+from chirp import chirp_common, bitwise, directory
+from chirp.settings import RadioSetting, RadioSettingGroup, \
+    RadioSettingValueBoolean, RadioSettings
+from textwrap import dedent
+
+MEM_FORMAT = """
+#seekto 0x002a;
+struct {
+  u8 unknown_f:4,
+     pskip:1,
+     skip:1,
+     visible:1,
+     valid:1;
+} flags[130];
+
+#seekto 0x00ca;
+struct {
+  u8 unknown1a:2,
+     narrow:1,
+     clk_shift:1,
+     unknown1b:4;
+  u8 unknown2a:3,
+     unknown2b:2,
+     tune_step:3;
+  bbcd freq[3];
+  u8 tone;
+  u8 name[6];
+  u8 unknown3;
+  u8 offset;
+  u8 unknown4a:1,
+     unknown4b:1,
+     unknown4c:2,
+     unknown4d:4;
+  u8 unknown5a:2,
+     tmode:2,
+     power:2,
+     duplex:2;
+} memory[130];
+"""
+
+
+MODES = ["FM", "NFM"]
+TMODES = ["", "Tone", "TSQL"]
+DUPLEX = ["", "-", "+"]
+STEPS = [5.0, 10.0, 12.5, 15.0, 20.0, 25.0, 50.0, 100.0]
+POWER_LEVELS = [chirp_common.PowerLevel("LOW1", watts=5),
+                chirp_common.PowerLevel("LOW2", watts=10),
+                chirp_common.PowerLevel("LOW3", watts=25),
+                chirp_common.PowerLevel("HIGH", watts=50),
+                ]
+CHARSET = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ +-/?()?_"
+
+
+ at directory.register
+class FT1500Radio(yaesu_clone.YaesuCloneModeRadio):
+    """Yaesu FT-1500M"""
+    VENDOR = "Yaesu"
+    MODEL = "FT-1500M"
+    BAUD_RATE = 9600
+
+    _model = "AH4N0"
+    _block_lengths = [10, 16, 3953]
+    _memsize = 3979
+
+    @classmethod
+    def get_prompts(cls):
+        rp = chirp_common.RadioPrompts()
+        rp.pre_download = _(dedent("""\
+1. Turn radio off.
+2. Connect cable to mic jack.
+3. Press and hold in the [MHz], [LOW], and [D/MR] keys
+   while turning the radio on.
+4. <b>After clicking OK</b>, press the [MHz(SET)] key to send image."""))
+        rp.pre_upload = _(dedent("""\
+1. Turn radio off.
+2. Connect cable to mic jack.
+3. Press and hold in the [MHz], [LOW], and [D/MR] keys
+   while turning the radio on.
+4. Press the [D/MR(MW)] key ("--WAIT--" will appear on the LCD)."""))
+        return rp
+
+    def get_features(self):
+        rf = chirp_common.RadioFeatures()
+
+        rf.memory_bounds = (0, 129)
+
+        rf.can_odd_split = False
+        rf.has_ctone = False
+        rf.has_tuning_step = True
+        rf.has_dtcs_polarity = False
+        rf.has_bank = False
+
+        rf.valid_tuning_steps = STEPS
+        rf.valid_modes = MODES
+        rf.valid_tmodes = TMODES
+        rf.valid_bands = [(137000000, 174000000)]
+        rf.valid_power_levels = POWER_LEVELS
+        rf.valid_duplexes = DUPLEX
+        rf.valid_skips = ["", "S", "P"]
+        rf.valid_name_length = 6
+        rf.valid_characters = CHARSET
+        rf.has_cross = False
+
+        return rf
+
+    def _checksums(self):
+        return [yaesu_clone.YaesuChecksum(0, self._memsize-2)]
+
+    def process_mmap(self):
+        self._memobj = bitwise.parse(MEM_FORMAT, self._mmap)
+
+    def get_raw_memory(self, number):
+        return repr(self._memobj.memory[number]) + \
+               repr(self._memobj.flags[number])
+
+    def get_memory(self, number):
+        _mem = self._memobj.memory[number]
+        _flag = self._memobj.flags[number]
+        visible = _flag["visible"]
+        valid = _flag["valid"]
+        skip = _flag["skip"]
+        pskip = _flag["pskip"]
+        mem = chirp_common.Memory()
+        mem.number = number
+
+        if not visible:
+            mem.empty = True
+        if not valid:
+            mem.empty = True
+            return mem
+
+        mem.freq = chirp_common.fix_rounded_step(int(_mem.freq) * 1000)
+        mem.offset = chirp_common.fix_rounded_step(int(_mem.offset) * 100000)
+        mem.duplex = DUPLEX[_mem.duplex]
+        mem.tuning_step = STEPS[_mem.tune_step] or STEPS[0]
+        mem.tmode = TMODES[_mem.tmode]
+        mem.rtone = chirp_common.TONES[_mem.tone]
+        for i in _mem.name:
+            if i == 0xFF:
+                break
+            if i & 0x80 == 0x80:
+                mem.name += CHARSET[0x80 ^ int(i)]
+            else:
+                mem.name += CHARSET[i]
+        mem.name = mem.name.rstrip()
+        mem.mode = _mem.narrow and "NFM" or "FM"
+        mem.skip = pskip and "P" or skip and "S" or ""
+        mem.power = POWER_LEVELS[_mem.power]
+
+        mem.extra = RadioSettingGroup("extra", "Extra Settings")
+        rs = RadioSetting("clk_shift", "Clock Shift",
+                          RadioSettingValueBoolean(_mem.clk_shift))
+        mem.extra.append(rs)
+        return mem
+
+    def set_memory(self, mem):
+        _mem = self._memobj.memory[mem.number]
+        _flag = self._memobj.flags[mem.number]
+        valid = _flag["valid"]
+        visible = _flag["visible"]
+
+        if not mem.empty and not valid:
+            _flag["valid"] = True
+            _mem.unknown1a = 0x00
+            _mem.clk_shift = 0x00
+            _mem.unknown1b = 0x00
+            _mem.unknown2a = 0x00
+            _mem.unknown2b = 0x00
+            _mem.unknown3 = 0x00
+            _mem.unknown4a = 0x00
+            _mem.unknown4b = 0x00
+            _mem.unknown4c = 0x00
+            _mem.unknown4d = 0x00
+            _mem.unknown5a = 0x00
+
+        if mem.empty and valid and not visible:
+            _flag["valid"] = False
+            return
+        _flag["visible"] = not mem.empty
+
+        if mem.empty:
+            return
+
+        _flag["valid"] = True
+
+        _mem.freq = mem.freq / 1000
+        _mem.offset = mem.offset / 100000
+        _mem.duplex = DUPLEX.index(mem.duplex)
+        _mem.tune_step = STEPS.index(mem.tuning_step)
+        _mem.tmode = TMODES.index(mem.tmode)
+        _mem.tone = chirp_common.TONES.index(mem.rtone)
+
+        _mem.name = [0xFF] * 6
+        for i in range(0, len(mem.name)):
+            try:
+                _mem.name[i] = CHARSET.index(mem.name[i])
+            except IndexError:
+                raise Exception("Character `%s' not supported")
+
+        _mem.narrow = MODES.index(mem.mode)
+        _mem.power = 3 if mem.power is None else POWER_LEVELS.index(mem.power)
+
+        _flag["pskip"] = mem.skip == "P"
+        _flag["skip"] = mem.skip == "S"
+
+        for element in mem.extra:
+            setattr(_mem, element.get_name(), element.value)
diff -r c9c976689454 -r 93e6ed0dc09d tests/images/Yaesu_FT-1500M.img
Binary file tests/images/Yaesu_FT-1500M.img has changed
diff -r c9c976689454 -r 93e6ed0dc09d tools/cpep8.manifest
--- a/tools/cpep8.manifest	Fri Nov 22 06:58:54 2019 -0800
+++ b/tools/cpep8.manifest	Thu Dec 05 21:14:35 2019 +1100
@@ -18,6 +18,7 @@
 ./chirp/drivers/baofeng_wp970i.py
 ./chirp/drivers/bjuv55.py
 ./chirp/drivers/btech.py
+./chirp/drivers/ft1500m.py
 ./chirp/drivers/ft1802.py
 ./chirp/drivers/ft1d.py
 ./chirp/drivers/ft2800.py


More information about the chirp_devel mailing list