# Copyright 2011 Dan Smith # # 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 . from chirp import chirp_common, memmap, directory from chirp import bitwise from chirp.yaesu_clone import YaesuCloneModeRadio def send(s, data, blocksize=8): echo = "" for i in range(0, len(data), blocksize): chunk = data[i:i+blocksize] s.write(chunk) echo += s.read(len(chunk)) if echo != data: raise Exception("Radio echo was incorrect") def clonein(radio): data = "" while True: chunk = radio.pipe.read(256) data += chunk if chunk: radio.pipe.write("\x06") radio.pipe.read(1) elif not chunk and data: break if radio.status_fn: s = chirp_common.Status() s.cur = len(data) s.max = radio._memsize s.msg = "Cloning from radio" radio.status_fn(s) return memmap.MemoryMap(data) def cloneout(radio, blockmap): offset = 0 radio.pipe.setTimeout(2) for blocksize in blockmap: block = radio._mmap[offset:offset+blocksize] offset += blocksize send(radio.pipe, block) ack = radio.pipe.read(1) if not ack: raise Exception("Did not get ack") elif ack != "\x06": raise Exception("Did not get ack (%02x)" % ord(ack)) if radio.status_fn: s = chirp_common.Status() s.cur = offset s.max = radio._memsize s.msg = "Cloning to radio" radio.status_fn(s) mem_format = """ #seekto 0x010B; struct { u8 unknown4:5, tmode:3; u32 freq; u8 unknown[4]; u8 nameempty:1, showfreq:1, tone:6; u8 unknown3; char name[7]; u8 unknown2[1]; u8 unknown3:5, isnarrow:1, unknown5:2; } memory[180]; """ # DCS for mem 1 at 0xF9C? # Also see it at 0x095. Looks like 0x09* is the VFO. So is 0xF9C? # When I change mem 2, I see an incr at 0x0ED and at 0x1D1 FT90_BLOCKS = [4, 234, 26] + ([202] * 18) + [207] # Index 3 is BELL FT90_TMODES = ["", "Tone", "TSQL", "", "DTCS"] #@directory.register class FT90Radio(YaesuCloneModeRadio): VENDOR = "Yaesu" MODEL = "FT-90R" ID = "ft90" ID = "" ID = "" ID = "" _memsize = 4107 @classmethod def match_model(cls, filedata, filename): return len(filedata) == cls._memsize def get_features(self): rf = chirp_common.RadioFeatures() rf.has_ctone = False rf.has_bank = False rf.valid_tmodes = FT90_TMODES rf.memory_bounds = (1, 15) return rf def sync_in(self): self._mmap = clonein(self) self.process_mmap() def sync_out(self): cloneout(self, self._mmap, FT90_BLOCKS) def process_mmap(self): self._memobj = bitwise.parse(mem_format, self._mmap) def get_memory(self, number): _mem = self._memobj.memory[number-1] mem = chirp_common.Memory() mem.number = number mem.freq = _mem.freq * 10 mem.tmode = FT90_TMODES[_mem.tmode] mem.rtone = chirp_common.TONES[_mem.tone] if _mem.isnarrow: mem.mode = "NFM" if not _mem.nameempty: mem.name = _mem.name return mem def get_raw_memory(self, number): return repr(self._memobj.memory[number-1])