[chirp_devel] [PATCH] [ft1802] Add support for Yaesu FT-1802. #273
Tom Hayward
Tue Sep 4 17:06:31 PDT 2012
# HG changeset patch
# User Tom Hayward <tom at tomh.us>
# Date 1346803573 21600
# Node ID 2bf9ee63824624f3ce89622bd5e63c7397e23a8d
# Parent a1636a04cb68f5ba1a8889e583bfda8bc2f3b4b5
[ft1802] Add support for Yaesu FT-1802. #273
diff -r a1636a04cb68 -r 2bf9ee638246 chirp/ft1802.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/chirp/ft1802.py Tue Sep 04 18:06:13 2012 -0600
@@ -0,0 +1,226 @@
+# 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-1802 Clone Proceedure
+# 1. Turn radio off.
+# 2. Connect cable to mic jack.
+# 3. Press and hold in the [LOW(A/N)] key 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 import chirp_common, bitwise, directory, yaesu_clone
+
+MEM_FORMAT = """
+#seekto 0x06ea;
+struct {
+ u8 odd_pskip:1,
+ odd_skip:1,
+ odd_visible:1,
+ odd_valid:1,
+ even_pskip:1,
+ even_skip:1,
+ even_visible:1,
+ even_valid:1;
+} flags[100];
+
+#seekto 0x076a;
+struct {
+ u8 unknown1a:1,
+ step_changed:1,
+ narrow:1,
+ clk_shift:1,
+ unknown1b:4;
+ u8 unknown2a:2,
+ duplex:2,
+ unknown2b:1,
+ tune_step:3;
+ bbcd freq[3];
+ u8 power:2,
+ unknown3:3,
+ tmode:3;
+ u8 name[6];
+ bbcd offset[3];
+ u8 tone;
+ u8 dtcs;
+ u8 unknown4;
+} memory[200];
+"""
+
+
+MODES = ["FM", "NFM"]
+TMODES = ["", "Tone", "TSQL", "DTCS", "TSQL-R", "Cross"]
+CROSS_MODES = ["DTCS->", "Tone->DTCS", "DTCS->Tone"]
+DUPLEX = ["", "-", "+", "split"]
+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 FT1802Radio(yaesu_clone.YaesuCloneModeRadio):
+ """Yaesu FT-1802"""
+ VENDOR = "Yaesu"
+ MODEL = "FT-1802M"
+ BAUD_RATE = 19200
+
+ _block_lengths = [10, 8001]
+ _memsize = 8011
+
+ def get_features(self):
+ rf = chirp_common.RadioFeatures()
+
+ rf.memory_bounds = (0, 199)
+
+ rf.has_ctone = False
+ rf.has_tuning_step = True
+ rf.has_dtcs_polarity = False # in radio settings, not per memory
+ rf.has_bank = False # has banks, but not implemented
+
+ 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 = True
+ rf.valid_cross_modes = list(CROSS_MODES)
+
+ 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/2])
+
+ def get_memory(self, number):
+ _mem = self._memobj.memory[number]
+ _flag = self._memobj.flags[number/2]
+
+ nibble = (number % 2) and "odd" or "even"
+ visible = _flag["%s_visible" % nibble]
+ valid = _flag["%s_valid" % nibble]
+ pskip = _flag["%s_pskip" % nibble]
+ skip = _flag["%s_skip" % nibble]
+
+ 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) * 1000)
+ mem.duplex = DUPLEX[_mem.duplex]
+ mem.tuning_step = _mem.step_changed and STEPS[_mem.tune_step] or STEPS[0]
+ if _mem.tmode < TMODES.index("Cross"):
+ mem.tmode = TMODES[_mem.tmode]
+ mem.cross_mode = CROSS_MODES[0]
+ else:
+ mem.tmode = "Cross"
+ mem.cross_mode = CROSS_MODES[_mem.tmode - TMODES.index("Cross")]
+ mem.rtone = chirp_common.TONES[_mem.tone]
+ mem.dtcs = chirp_common.DTCS_CODES[_mem.dtcs]
+ for i in _mem.name:
+ if i == 0xFF:
+ break
+ if i & 0x80 == 0x80:
+ # first bit in name is "show name"
+ mem.name += CHARSET[0x80 ^ int(i)]
+ else:
+ mem.name += CHARSET[i]
+ mem.mode = _mem.narrow and "NFM" or "FM"
+ mem.skip = pskip and "P" or skip and "S" or ""
+ mem.power = POWER_LEVELS[_mem.power]
+
+ return mem
+
+ def set_memory(self, mem):
+ _mem = self._memobj.memory[mem.number]
+ _flag = self._memobj.flags[mem.number/2]
+
+ nibble = (mem.number % 2) and "odd" or "even"
+
+ valid = _flag["%s_valid" % nibble]
+ visible = _flag["%s_visible" % nibble]
+
+ if not mem.empty and not valid:
+ _flag["%s_valid" % nibble] = True
+ _mem.unknown1a = 0x00
+ _mem.clk_shift = 0x00
+ _mem.unknown1b = 0x00
+ _mem.unknown2a = 0x00
+ _mem.unknown2b = 0x00
+ _mem.unknown3 = 0x00
+ _mem.unknown4 = 0x00
+
+ if mem.empty and valid and not visible:
+ _flag["%s_valid" % nibble] = False
+ return
+ _flag["%s_visible" % nibble] = not mem.empty
+
+ if mem.empty:
+ return
+
+ _flag["%s_valid" % nibble] = True
+
+ _mem.freq = mem.freq / 1000
+ _mem.offset = mem.offset / 1000
+ _mem.duplex = DUPLEX.index(mem.duplex)
+ _mem.tune_step = STEPS.index(mem.tuning_step)
+ _mem.step_changed = mem.tuning_step != STEPS[0]
+ if mem.tmode != "Cross":
+ _mem.tmode = TMODES.index(mem.tmode)
+ else:
+ _mem.tmode = TMODES.index("Cross") + CROSS_MODES.index(mem.cross_mode)
+ _mem.tone = chirp_common.TONES.index(mem.rtone)
+ _mem.dtcs = chirp_common.DTCS_CODES.index(mem.dtcs)
+
+ _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")
+ if _mem.name[0] != 0xFF:
+ _mem.name[0] += 0x80 # show name instead of frequency
+
+ _mem.narrow = MODES.index(mem.mode)
+ _mem.power = POWER_LEVELS.index(mem.power)
+
+ _flag["%s_pskip" % nibble] = mem.skip == "P"
+ _flag["%s_skip" % nibble] = mem.skip == "S"
+
+
+ @classmethod
+ def match_model(cls, filedata, filename):
+ return len(filedata) == cls._memsize
More information about the chirp_devel
mailing list