# Copyright 2010 Dan Smith # Copyright 2017 Wade Simmons # # 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 . import logging from textwrap import dedent from chirp.drivers import yaesu_clone, ft1d from chirp import chirp_common, directory, bitwise from chirp.settings import RadioSettings LOG = logging.getLogger(__name__) POWER_LEVELS = [chirp_common.PowerLevel("Low", watts=5), chirp_common.PowerLevel("Mid", watts=25), chirp_common.PowerLevel("Hi", watts=50)] TMODES = ["", "Tone", "TSQL", "DTCS", "TSQL-R", None, None, "Pager", "Cross"] CROSS_MODES = [None, "DTCS->", "Tone->DTCS", "DTCS->Tone"] MODES = ["FM", "NFM"] STEPS = [0, 5, 6.25, 10, 12.5, 15, 20, 25, 50, 100] # 0 = auto RFSQUELCH = ["OFF", "S1", "S2", "S3", "S4", "S5", "S6", "S7", "S8"] # Charset is subset of ASCII + some unknown chars \x80-\x86 VALID_CHARS = ["%i" % int(x) for x in range(0, 10)] + \ list(":>=After clicking OK, press the [GM(AMS)] 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(SETUP)] key while turning the radio on ("CLONE" will appear on the display). 4. Press the [MHz(SETUP)] key ("-WAIT-" will appear on the LCD).""")) return rp def process_mmap(self): mem_format = ft1d.MEM_FORMAT + MEM_FORMAT self._memobj = bitwise.parse(mem_format % self._mem_params, self._mmap) def get_features(self): rf = chirp_common.RadioFeatures() rf.has_dtcs_polarity = False rf.valid_modes = list(MODES) rf.valid_tmodes = [x for x in TMODES if x is not None] rf.valid_cross_modes = [x for x in CROSS_MODES if x is not None] rf.valid_duplexes = list(ft1d.DUPLEX) rf.valid_tuning_steps = list(STEPS) rf.valid_bands = [(136000000, 174000000),(420000000, 450000000)] # rf.valid_skips = SKIPS rf.valid_power_levels = POWER_LEVELS rf.valid_characters = "".join(VALID_CHARS) rf.valid_name_length = 8 rf.memory_bounds = (1, 199) rf.can_odd_split = True rf.has_ctone = False rf.has_bank = False rf.has_bank_names = False # disable until implemented rf.has_settings = False return rf def _decode_label(self, mem): # TODO preserve the unknown \x80-x86 chars? return str(mem.label).rstrip("\xFF").decode('ascii', 'replace') def _encode_label(self, mem): label = mem.name.rstrip().encode('ascii', 'ignore') return self._add_ff_pad(label, 16) def _encode_charsetbits(self, mem): # TODO this is a setting to decide if the memory should be displayed # as a name or frequency. Should we expose this setting to the user # instead of autoselecting it (and losing their preference)? if mem.name.rstrip() == '': return [0x00, 0x00] return [0x00, 0x80] def _decode_power_level(self, mem): return POWER_LEVELS[mem.power - 1] def _encode_power_level(self, mem): return POWER_LEVELS.index(mem.power) + 1 def _decode_mode(self, mem): return MODES[mem.mode_alt] def _encode_mode(self, mem): return MODES.index(mem.mode) def _get_tmode(self, mem, _mem): if _mem.tone_mode > 8: tmode = "Cross" mem.cross_mode = CROSS_MODES[_mem.tone_mode - 8] else: tmode = TMODES[_mem.tone_mode] if tmode == "Pager": # TODO chirp_common does not allow 'Pager' # Expose as a different setting? mem.tmode = "" else: mem.tmode = tmode def _set_tmode(self, _mem, mem): if mem.tmode == "Cross": _mem.tone_mode = 8 + CROSS_MODES.index(mem.cross_mode) else: _mem.tone_mode = TMODES.index(mem.tmode) def _set_mode(self, _mem, mem): _mem.mode_alt = self._encode_mode(mem) def get_bank_model(self): return None def _debank(self, mem): return def _checksums(self): return [yaesu_clone.YaesuChecksum(0x064A, 0x06C8), yaesu_clone.YaesuChecksum(0x06CA, 0x0748), yaesu_clone.YaesuChecksum(0x074A, 0x07C8), yaesu_clone.YaesuChecksum(0x07CA, 0x0848), yaesu_clone.YaesuChecksum(0x0000, 0xFEC9)] def _get_settings(self): # TODO top = RadioSettings() return top @classmethod def _wipe_memory(cls, mem): mem.set_raw("\x00" * (mem.size() / 8)) def sync_out(self): # Need to give enough time for the radio to ACK after writes self.pipe.timeout = 1 return super(FTM7250Radio, self).sync_out()