<html><body><div style="color:#000; background-color:#fff; font-family:tahoma, new york, times, serif;font-size:12pt"><div><span>Whoops,</span></div><div style="color: rgb(0, 0, 0); font-size: 16px; font-family: tahoma,new york,times,serif; background-color: transparent; font-style: normal;"><span>got a stray copy of ft90.py in this patch somehow.</span></div><div style="color: rgb(0, 0, 0); font-size: 16px; font-family: tahoma,new york,times,serif; background-color: transparent; font-style: normal;"><span>Dan, can you exclude the ./ft90.py (wrong), but include the chirp/ft90.py (correct)?</span></div><div><br></div> <div style="font-family: tahoma, new york, times, serif; font-size: 12pt;"> <div style="font-family: times new roman, new york, times, serif; font-size: 12pt;"> <div dir="ltr"> <hr size="1"> <font face="Arial" size="2"> <b><span style="font-weight:bold;">From:</span></b> Jens J. <kd4tjx@yahoo.com><br> <b><span style="font-weight:
bold;">To:</span></b> "chirp_devel@intrepid.danplanet.com" <chirp_devel@intrepid.danplanet.com> <br> <b><span style="font-weight: bold;">Sent:</span></b> Monday, August 26, 2013 1:20 AM<br> <b><span style="font-weight: bold;">Subject:</span></b> [chirp_devel] [FT-90R] initial support for Yaesu FT-90R<br> </font> </div> <div class="y_msg_container"><br><div id="yiv2806167879"><div><div style="color:#000;background-color:#fff;font-family:tahoma, new york, times, serif;font-size:12pt;"><div># HG changeset patch<br># User Jens Jensen <kd4tjx@yahoo.com><br># Date 1377497847 18000<br># Node ID 7c95e9d39dfc07ea1e3192834d8a339e100347f6<br># Parent 86910885e998d559dfdd6ba4c5fb0bf520fdee31<br>initial support for Yaesu FT-90R, revised #1087<br><br>diff -r 86910885e998 -r 7c95e9d39dfc chirp/ft90.py<br>--- /dev/null Thu Jan 01 00:00:00 1970 +0000<br>+++ b/chirp/ft90.py Mon Aug 26 01:17:27 2013 -0500<br>@@ -0,0
+1,379 @@<br>+# Copyright 2011 Dan Smith <dsmith@danplanet.com><br>+# Copyright 2013 Jens Jensen <kd4tjx@yahoo.com><br>+#<br>+# This program is free software: you can redistribute it and/or modify<br>+# it under the terms of the GNU General Public License as published by<br>+# the Free Software Foundation, either version 3 of the License, or<br>+# (at your option)
any later version.<br>+#<br>+# This program is distributed in the hope that it will be useful,<br>+# but WITHOUT ANY WARRANTY; without even the implied warranty of<br>+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the<br>+# GNU General Public License for more details.<br>+#<br>+# You should have received a copy of the GNU General Public License<br>+# along with this program. If not, see <http://www.gnu.org/licenses/>.<br>+<br>+from chirp import chirp_common, bitwise, memmap, directory, errors, util, yaesu_clone<br>+import time, os, traceback<br>+<br>+CHIRP_DEBUG=True<br>+CMD_ACK = chr(0x06)<br>+<br>+@directory.register<br>+class FT90Radio(yaesu_clone.YaesuCloneModeRadio):<br>+ VENDOR = "Yaesu"<br>+ MODEL = "FT-90"<br>+ ID = "\x8E\xF6"<br>+ <br>+ STEPS = [5, 10, 12.5, 15, 20, 25, 50]<br>+ MODES = ["AM", "FM",
"Auto"]<br>+ TMODES = ["", "Tone", "TSQL", "", "DTCS"] # idx 3 (Bell) not supported yet<br>+<br>+ TONES = list(chirp_common.TONES)<br>+ for tone in [ 165.5, 171.3, 177.3 ]:<br>+ TONES.remove(tone) <br>+ POWER_LEVELS = ["Hi", "Mid1", "Mid2", "Low"]<br>+ DUPLEX = ["", "-", "+", "split"]<br>+ <br>+ _memsize = 4063<br>+ # block 03 (200 Bytes long) repeats 18 times; channel memories<br>+ _block_lengths = [ 2, 232, 24, 200, 205]<br>+ <br>+ mem_format = """<br>+ #seekto 0x22; <br>+ struct {<br>+ u8 dtmf_active;<br>+
u8 dtmf1_len;<br>+ u8 dtmf2_len;<br>+ u8 dtmf3_len;<br>+ u8 dtmf4_len;<br>+ u8 dtmf5_len;<br>+ u8 dtmf6_len;<br>+ u8 dtmf7_len;<br>+ u8 dtmf8_len;<br>+ bbcd dtmf1[8];<br>+ bbcd dtmf2[8];<br>+ bbcd dtmf3[8];<br>+ bbcd dtmf4[8]; <br>+ bbcd dtmf5[8];<br>+ bbcd
dtmf6[8];<br>+ bbcd dtmf7[8]; <br>+ bbcd dtmf8[8];<br>+ char cwid[7];<br>+ u8 unk1;<br>+ u8 unk2:2,<br>+ beep_dis:1,<br>+ unk3:1,<br>+ rfsqlvl:4;<br>+ u8 cwid_en:1,<br>+ unk4:3,<br>+ txnarrow:1,<br>+ dtmfspeed:1,<br>+ pttlock:2;<br>+
u8 dtmftxdelay:3,<br>+ fancontrol:2,<br>+ unk5:3;<br>+ u8 dimmer:3,<br>+ unk6:1,<br>+ lcdcontrast:4;<br>+ u8 tot;<br>+ u8 unk8:1,<br>+ ars:1,<br>+ lock:1,<br>+ txpwrsave:1,<br>+ apo:4;<br>+ u8 key_rt;<br>+ u8
key_lt;<br>+ u8 key_p1;<br>+ u8 key_p2;<br>+ u8 key_acc;<br>+ char demomsg1[32];<br>+ char demomsg2[32];<br>+ <br>+ } settings;<br>+ <br>+ struct mem_struct {<br>+ u8 mode:2,<br>+ isUhf1:1,<br>+ unknown1:2,<br>+ step:3;<br>+ u8 artsmode:2,<br>+ unknown2:1,<br>+
isUhf2:1<br>+ power:2,<br>+ shift:2;<br>+ u8 skip:1,<br>+ showname:1,<br>+ unknown3:1,<br>+ isUhfHi:1,<br>+ unknown4:1,<br>+ tmode:3;<br>+ u32 rxfreq;<br>+ u32 txfreqoffset;<br>+ u8 UseDefaultName:1,<br>+ ars:1,<br>+ tone:6;<br>+ u8 packetmode:1,<br>+ unknown5:1,<br>+
dcstone:6;<br>+ char name[7];<br>+ };<br>+<br>+ #seekto 0x86;<br>+ struct mem_struct vfo_v;<br>+ struct mem_struct call_v;<br>+ struct mem_struct vfo_u;<br>+ struct mem_struct call_u;<br>+ <br>+ #seekto 0x102;<br>+ struct mem_struct memory[180];<br>+<br>+ #seekto 0xf12;<br>+ struct mem_struct pms_1L;<br>+ struct mem_struct pms_1U;<br>+ struct mem_struct pms_2L; <br>+ struct mem_struct pms_2U;<br>+ """<br>+<br>+ @classmethod<br>+ def match_model(cls, filedata, filename):<br>+ return len(filedata) == cls._memsize<br>+<br>+ def
get_features(self):<br>+ rf = chirp_common.RadioFeatures()<br>+ rf.has_ctone = False<br>+ rf.has_bank = False<br>+ rf.has_dtcs_polarity = False<br>+ rf.has_dtcs = True<br>+ rf.valid_modes = self.MODES<br>+ rf.valid_tmodes = self.TMODES<br>+ rf.valid_duplexes = self.DUPLEX<br>+ rf.valid_tuning_steps = self.STEPS<br>+ rf.valid_power_levels = self.POWER_LEVELS<br>+ rf.valid_name_length = 7<br>+ rf.valid_characters =
chirp_common.CHARSET_ASCII<br>+ rf.valid_skips = ["", "S"]<br>+ rf.memory_bounds = (1, 180)<br>+ rf.valid_bands = [(100000000, 230000000), <br>+ (300000000, 530000000), (810000000, 999975000)]<br>+<br>+ return rf<br>+<br>+ def _read(self, blocksize, blocknum):<br>+ data = self.pipe.read(blocksize+2)<br>+ <br>+ # chew echo'd ack<br>+ self.pipe.write(CMD_ACK)<br>+ time.sleep(0.02)<br>+ self.pipe.read(1) # chew echoed ACK from 1-wire
serial<br>+ <br>+ if len(data) == blocksize+2 and data[0] == chr(blocknum):<br>+ checksum = yaesu_clone.YaesuChecksum(1, blocksize)<br>+ if checksum.get_existing(data) != checksum.get_calculated(data):<br>+ raise Exception("Checksum Failed [%02X<>%02X] block %02X, data len: %i" %<br>+
(checksum.get_existing(data),<br>+ checksum.get_calculated(data), blocknum, len(data) ))<br>+ data = data[1:blocksize+1] # Chew blocknum and checksum<br>+ <br>+ else:<br>+ raise Exception("Unable to read blocknum %02X expected blocksize %i got %i." %<br>+ (blocknum, blocksize+2,
len(data)))<br>+<br>+ return data <br>+ <br>+ def _clone_in(self):<br>+ # Be very patient with the radio<br>+ self.pipe.setTimeout(4)<br>+ start = time.time()<br>+ <br>+ data = ""<br>+ blocknum = 0<br>+ status = chirp_common.Status()<br>+ status.msg = "Cloning from radio.\nPut radio into clone mode then\npress SET to send"<br>+ self.status_fn(status)<br>+ status.max = len(self._block_lengths) + 18<br>+ for
blocksize in self._block_lengths:<br>+ if blocksize == 200:<br>+ # repeated read of 200 block same size (memory area)<br>+ repeat = 18<br>+ else:<br>+ repeat = 1<br>+ for _i in range(0, repeat): <br>+ data += self._read(blocksize, blocknum)<br>+<br>+ blocknum +=
1<br>+ status.cur = blocknum<br>+ self.status_fn(status)<br>+ <br>+ status.msg = "Clone completed."<br>+ self.status_fn(status)<br>+<br>+ print "Clone completed in %i seconds, blocks read: %i" % (time.time() - start, blocknum)<br>+ <br>+ return memmap.MemoryMap(data)<br>+ <br>+ def _clone_out(self):<br>+ delay = 0.2<br>+ start = time.time()<br>+
<br>+ blocknum = 0<br>+ pos = 0<br>+ status = chirp_common.Status()<br>+ status.msg = "Cloning to radio.\nPut radio into clone mode and press DISP/SS\n to start receive within 3 secs..."<br>+ self.status_fn(status)<br>+ # radio likes to have port open <br>+ self.pipe.open()<br>+ time.sleep(3)<br>+ status.max = len(self._block_lengths) + 18<br>+<br>+<br>+ for blocksize in self._block_lengths:<br>+ if blocksize ==
200:<br>+ # repeat channel blocks<br>+ repeat = 18<br>+ else:<br>+ repeat = 1<br>+ for _i in range(0, repeat):<br>+ time.sleep(0.1)<br>+ checksum = yaesu_clone.YaesuChecksum(pos, pos+blocksize-1)<br>+ blocknumbyte =
chr(blocknum)<br>+ payloadbytes = self.get_mmap()[pos:pos+blocksize]<br>+ checksumbyte = chr(checksum.get_calculated(self.get_mmap()))<br>+ if os.getenv("CHIRP_DEBUG") or CHIRP_DEBUG:<br>+ print "Block %i - will send from %i to %i byte " % \<br>+ (blocknum, pos, pos + blocksize)<br>+ print
util.hexprint(blocknumbyte)<br>+ print util.hexprint(payloadbytes)<br>+ print util.hexprint(checksumbyte)<br>+ # send wrapped bytes<br>+ self.pipe.write(blocknumbyte)<br>+ self.pipe.write(payloadbytes)<br>+ self.pipe.write(checksumbyte)<br>+ tmp = self.pipe.read(blocksize+2) #chew
echo<br>+ if os.getenv("CHIRP_DEBUG") or CHIRP_DEBUG: <br>+ print "bytes echoed: "<br>+ print util.hexprint(tmp)<br>+ # radio is slow to write/ack:<br>+ time.sleep(0.9) <br>+ buf =
self.pipe.read(1)<br>+ if os.getenv("CHIRP_DEBUG") or CHIRP_DEBUG: <br>+ print "ack recd:"<br>+ print util.hexprint(buf)<br>+ if buf != CMD_ACK:<br>+ raise Exception("Radio did not ack block %i" % blocknum)<br>+ pos +=
blocksize<br>+ blocknum += 1<br>+ status.cur = blocknum<br>+ self.status_fn(status)<br>+ <br>+ print "Clone completed in %i seconds" % (time.time() - start)<br>+ <br>+ def sync_in(self):<br>+ try:<br>+ self._mmap = self._clone_in()<br>+ except errors.RadioError:<br>+ raise<br>+ except Exception,
e:<br>+ trace = traceback.format_exc()<br>+ raise errors.RadioError("Failed to communicate with radio: %s" % trace)<br>+ self.process_mmap()<br>+<br>+ def sync_out(self):<br>+ try:<br>+ self._clone_out()<br>+ except errors.RadioError:<br>+ raise<br>+ except Exception, e:<br>+ trace = traceback.format_exc()<br>+ raise errors.RadioError("Failed to communicate with radio: %s" %
trace)<br>+<br>+ def process_mmap(self):<br>+ self._memobj = bitwise.parse(self.mem_format, self._mmap)<br>+<br>+ def get_memory(self, number):<br>+ _mem = self._memobj.memory[number-1]<br>+<br>+ mem = chirp_common.Memory()<br>+ mem.number = number<br>+ mem.freq = _mem.rxfreq * 10 <br>+ mem.offset = _mem.txfreqoffset * 10<br>+ if not _mem.tmode < len(self.TMODES):<br>+ _mem.tmode = 0<br>+ mem.tmode = self.TMODES[_mem.tmode]<br>+ mem.rtone =
self.TONES[_mem.tone]<br>+ mem.dtcs = chirp_common.DTCS_CODES[_mem.dcstone]<br>+ mem.mode = self.MODES[_mem.mode]<br>+<br>+ '''<br>+ # ars mode note yet working...<br>+ # ARS mode:<br>+ if _mem.ars and _mem.shift == 0:<br>+ mem.duplex = self.DUPLEX[4] <br>+ else:<br>+ mem.duplex = self.DUPLEX[_mem.shift]<br>+ '''<br>+<br>+ mem.duplex = self.DUPLEX[_mem.shift]<br>+ mem.power =
self.POWER_LEVELS[_mem.power]<br>+ # radio has a known bug with 5khz step and squelch<br>+ if _mem.step == 0:<br>+ _mem.step = 2<br>+ mem.tuning_step = self.STEPS[_mem.step]<br>+ mem.skip = _mem.skip and "S" or ""<br>+ mem.name = _mem.name<br>+ return mem<br>+<br>+ def get_raw_memory(self, number):<br>+ return repr(self._memobj.memory[number-1])<br>+ <br>+ def set_memory(self, mem):<br>+<br>+ _mem = self._memobj.memory[mem.number - 1]<br>+ _mem.skip = mem.skip ==
"S"<br>+ # radio has a known bug with 5khz step and dead squelch<br>+ if not mem.tuning_step or mem.tuning_step == self.STEPS[0]:<br>+ _mem.step = 2<br>+ else:<br>+ _mem.step = self.STEPS.index(mem.tuning_step)<br>+ _mem.rxfreq = mem.freq / 10<br>+ # vfo will unlock if not in right band?<br>+ if mem.freq > 300000000: <br>+ # uhf<br>+ _mem.isUhf1 = 1<br>+ _mem.isUhf2 =
1<br>+ if mem.freq > 810000000:<br>+ # uhf hiband<br>+ _mem.isUhfHi = 1<br>+ else:<br>+ _mem.isUhfHi = 0<br>+ else:<br>+ # vhf<br>+ _mem.isUhf1 = 0<br>+ _mem.isUhf2 = 0<br>+ _mem.isUhfHi = 0<br>+ _mem.txfreqoffset
= mem.offset / 10<br>+ _mem.tone = self.TONES.index(mem.rtone)<br>+ _mem.tmode = self.TMODES.index(mem.tmode)<br>+ _mem.mode = self.MODES.index(mem.mode)<br>+ '''<br>+ # ars not yet working<br>+ # ARS mode:<br>+ if mem.duplex == 4:<br>+ _mem.shift = 0<br>+ _mem.ars = 1<br>+ else:<br>+ _mem.shift = self.DUPLEX.index(mem.duplex)<br>+ '''<br>+
_mem.shift = self.DUPLEX.index(mem.duplex) <br>+ _mem.dcstone = chirp_common.DTCS_CODES.index(mem.dtcs)<br>+ if self.get_features().has_tuning_step:<br>+ _mem.step = self.STEPS.index(mem.tuning_step)<br>+ _mem.shift = self.DUPLEX.index(mem.duplex)<br>+ if mem.power:<br>+ _mem.power = self.POWER_LEVELS.index(mem.power)<br>+ else:<br>+ _mem.power = 3 # default to low power<br>+ _mem.name = mem.name.ljust(7)<br>+ <br>+<br>diff -r 86910885e998 -r 7c95e9d39dfc ft90.py<br>---
/dev/null Thu Jan 01 00:00:00 1970 +0000<br>+++ b/ft90.py Mon Aug 26 01:17:27 2013 -0500<br>@@ -0,0 +1,379 @@<br>+# Copyright 2011 Dan Smith <dsmith@danplanet.com><br>+# Copyright 2013 Jens Jensen <kd4tjx@yahoo.com><br>+#<br>+# This program is free software: you can redistribute it and/or modify<br>+# it under the terms of the GNU General Public License as published by<br>+# the Free Software Foundation, either version 3 of the License, or<br>+# (at your option) any later version.<br>+#<br>+# This program is distributed in the hope that it will be useful,<br>+# but WITHOUT ANY WARRANTY; without even the implied warranty of<br>+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the<br>+# GNU General Public License for more details.<br>+#<br>+# You should have received a copy of the GNU General Public License<br>+# along with this program. If not, see
<http://www.gnu.org/licenses/>.<br>+<br>+from chirp import chirp_common, bitwise, memmap, directory, errors, util, yaesu_clone<br>+import time, os, traceback<br>+<br>+CHIRP_DEBUG=True<br>+CMD_ACK = chr(0x06)<br>+<br>+@directory.register<br>+class FT90Radio(yaesu_clone.YaesuCloneModeRadio):<br>+ VENDOR = "Yaesu"<br>+ MODEL = "FT-90"<br>+ ID = "\x8E\xF6"<br>+ <br>+ STEPS = [5, 10, 12.5, 15, 20, 25, 50]<br>+ MODES = ["AM", "FM", "Auto"]<br>+ TMODES = ["", "Tone", "TSQL", "", "DTCS"] # idx 3 (Bell) not supported yet<br>+<br>+ TONES = list(chirp_common.TONES)<br>+ for tone in [ 165.5, 171.3, 177.3 ]:<br>+ TONES.remove(tone) <br>+ POWER_LEVELS = ["Hi", "Mid1", "Mid2", "Low"]<br>+ DUPLEX
= ["", "-", "+", "split"]<br>+ <br>+ _memsize = 4063<br>+ # block 03 (200 Bytes long) repeats 18 times; channel memories<br>+ _block_lengths = [ 2, 232, 24, 200, 205]<br>+ <br>+ mem_format = """<br>+ #seekto 0x22; <br>+ struct {<br>+ u8 dtmf_active;<br>+ u8 dtmf1_len;<br>+ u8 dtmf2_len;<br>+ u8 dtmf3_len;<br>+ u8 dtmf4_len;<br>+ u8 dtmf5_len;<br>+ u8 dtmf6_len;<br>+
u8 dtmf7_len;<br>+ u8 dtmf8_len;<br>+ bbcd dtmf1[8];<br>+ bbcd dtmf2[8];<br>+ bbcd dtmf3[8];<br>+ bbcd dtmf4[8]; <br>+ bbcd dtmf5[8];<br>+ bbcd dtmf6[8];<br>+ bbcd dtmf7[8]; <br>+ bbcd dtmf8[8];<br>+ char cwid[7];<br>+ u8 unk1;<br>+ u8 unk2:2,<br>+ beep_dis:1,<br>+
unk3:1,<br>+ rfsqlvl:4;<br>+ u8 cwid_en:1,<br>+ unk4:3,<br>+ txnarrow:1,<br>+ dtmfspeed:1,<br>+ pttlock:2;<br>+ u8 dtmftxdelay:3,<br>+ fancontrol:2,<br>+ unk5:3;<br>+ u8 dimmer:3,<br>+ unk6:1,<br>+ lcdcontrast:4;<br>+
u8 tot;<br>+ u8 unk8:1,<br>+ ars:1,<br>+ lock:1,<br>+ txpwrsave:1,<br>+ apo:4;<br>+ u8 key_rt;<br>+ u8 key_lt;<br>+ u8 key_p1;<br>+ u8 key_p2;<br>+ u8 key_acc;<br>+ char demomsg1[32];<br>+ char demomsg2[32];<br>+ <br>+ }
settings;<br>+ <br>+ struct mem_struct {<br>+ u8 mode:2,<br>+ isUhf1:1,<br>+ unknown1:2,<br>+ step:3;<br>+ u8 artsmode:2,<br>+ unknown2:1,<br>+ isUhf2:1<br>+ power:2,<br>+ shift:2;<br>+ u8 skip:1,<br>+ showname:1,<br>+ unknown3:1,<br>+ isUhfHi:1,<br>+
unknown4:1,<br>+ tmode:3;<br>+ u32 rxfreq;<br>+ u32 txfreqoffset;<br>+ u8 UseDefaultName:1,<br>+ ars:1,<br>+ tone:6;<br>+ u8 packetmode:1,<br>+ unknown5:1,<br>+ dcstone:6;<br>+ char name[7];<br>+ };<br>+<br>+ #seekto 0x86;<br>+ struct mem_struct vfo_v;<br>+ struct mem_struct call_v;<br>+ struct mem_struct vfo_u;<br>+ struct mem_struct call_u;<br>+ <br>+ #seekto 0x102;<br>+ struct mem_struct
memory[180];<br>+<br>+ #seekto 0xf12;<br>+ struct mem_struct pms_1L;<br>+ struct mem_struct pms_1U;<br>+ struct mem_struct pms_2L; <br>+ struct mem_struct pms_2U;<br>+ """<br>+<br>+ @classmethod<br>+ def match_model(cls, filedata, filename):<br>+ return len(filedata) == cls._memsize<br>+<br>+ def get_features(self):<br>+ rf = chirp_common.RadioFeatures()<br>+ rf.has_ctone = False<br>+ rf.has_bank = False<br>+ rf.has_dtcs_polarity = False<br>+ rf.has_dtcs = True<br>+ rf.valid_modes =
self.MODES<br>+ rf.valid_tmodes = self.TMODES<br>+ rf.valid_duplexes = self.DUPLEX<br>+ rf.valid_tuning_steps = self.STEPS<br>+ rf.valid_power_levels = self.POWER_LEVELS<br>+ rf.valid_name_length = 7<br>+ rf.valid_characters = chirp_common.CHARSET_ASCII<br>+ rf.valid_skips = ["", "S"]<br>+ rf.memory_bounds = (1, 180)<br>+ rf.valid_bands = [(100000000, 230000000), <br>+ (300000000, 530000000), (810000000, 999975000)]<br>+<br>+ return rf<br>+<br>+ def
_read(self, blocksize, blocknum):<br>+ data = self.pipe.read(blocksize+2)<br>+ <br>+ # chew echo'd ack<br>+ self.pipe.write(CMD_ACK)<br>+ time.sleep(0.02)<br>+ self.pipe.read(1) # chew echoed ACK from 1-wire serial<br>+ <br>+ if len(data) == blocksize+2 and data[0] == chr(blocknum):<br>+ checksum = yaesu_clone.YaesuChecksum(1, blocksize)<br>+ if checksum.get_existing(data) !=
checksum.get_calculated(data):<br>+ raise Exception("Checksum Failed [%02X<>%02X] block %02X, data len: %i" %<br>+ (checksum.get_existing(data),<br>+ checksum.get_calculated(data), blocknum, len(data) ))<br>+ data = data[1:blocksize+1] # Chew blocknum and checksum<br>+ <br>+
else:<br>+ raise Exception("Unable to read blocknum %02X expected blocksize %i got %i." %<br>+ (blocknum, blocksize+2, len(data)))<br>+<br>+ return data <br>+ <br>+ def _clone_in(self):<br>+ # Be very patient with the radio<br>+ self.pipe.setTimeout(4)<br>+ start = time.time()<br>+ <br>+ data = ""<br>+ blocknum = 0<br>+
status = chirp_common.Status()<br>+ status.msg = "Cloning from radio.\nPut radio into clone mode then\npress SET to send"<br>+ self.status_fn(status)<br>+ status.max = len(self._block_lengths) + 18<br>+ for blocksize in self._block_lengths:<br>+ if blocksize == 200:<br>+ # repeated read of 200 block same size (memory area)<br>+ repeat = 18<br>+ else:<br>+ repeat =
1<br>+ for _i in range(0, repeat): <br>+ data += self._read(blocksize, blocknum)<br>+<br>+ blocknum += 1<br>+ status.cur = blocknum<br>+ self.status_fn(status)<br>+ <br>+ status.msg = "Clone completed."<br>+ self.status_fn(status)<br>+<br>+ print "Clone completed in %i seconds, blocks read: %i" % (time.time() - start,
blocknum)<br>+ <br>+ return memmap.MemoryMap(data)<br>+ <br>+ def _clone_out(self):<br>+ delay = 0.2<br>+ start = time.time()<br>+ <br>+ blocknum = 0<br>+ pos = 0<br>+ status = chirp_common.Status()<br>+ status.msg = "Cloning to radio.\nPut radio into clone mode and press DISP/SS\n to start receive within 3 secs..."<br>+ self.status_fn(status)<br>+ # radio likes to have port open <br>+ self.pipe.open()<br>+
time.sleep(3)<br>+ status.max = len(self._block_lengths) + 18<br>+<br>+<br>+ for blocksize in self._block_lengths:<br>+ if blocksize == 200:<br>+ # repeat channel blocks<br>+ repeat = 18<br>+ else:<br>+ repeat = 1<br>+ for _i in range(0, repeat):<br>+
time.sleep(0.1)<br>+ checksum = yaesu_clone.YaesuChecksum(pos, pos+blocksize-1)<br>+ blocknumbyte = chr(blocknum)<br>+ payloadbytes = self.get_mmap()[pos:pos+blocksize]<br>+ checksumbyte = chr(checksum.get_calculated(self.get_mmap()))<br>+ if os.getenv("CHIRP_DEBUG") or CHIRP_DEBUG:<br>+ print "Block %i - will send from %i to %i byte " %
\<br>+ (blocknum, pos, pos + blocksize)<br>+ print util.hexprint(blocknumbyte)<br>+ print util.hexprint(payloadbytes)<br>+ print util.hexprint(checksumbyte)<br>+ # send wrapped bytes<br>+
self.pipe.write(blocknumbyte)<br>+ self.pipe.write(payloadbytes)<br>+ self.pipe.write(checksumbyte)<br>+ tmp = self.pipe.read(blocksize+2) #chew echo<br>+ if os.getenv("CHIRP_DEBUG") or CHIRP_DEBUG: <br>+ print "bytes echoed: "<br>+ print
util.hexprint(tmp)<br>+ # radio is slow to write/ack:<br>+ time.sleep(0.9) <br>+ buf = self.pipe.read(1)<br>+ if os.getenv("CHIRP_DEBUG") or CHIRP_DEBUG: <br>+ print "ack recd:"<br>+ print
util.hexprint(buf)<br>+ if buf != CMD_ACK:<br>+ raise Exception("Radio did not ack block %i" % blocknum)<br>+ pos += blocksize<br>+ blocknum += 1<br>+ status.cur = blocknum<br>+ self.status_fn(status)<br>+ <br>+ print "Clone completed in %i seconds" % (time.time() - start)<br>+ <br>+ def
sync_in(self):<br>+ try:<br>+ self._mmap = self._clone_in()<br>+ except errors.RadioError:<br>+ raise<br>+ except Exception, e:<br>+ trace = traceback.format_exc()<br>+ raise errors.RadioError("Failed to communicate with radio: %s" % trace)<br>+ self.process_mmap()<br>+<br>+ def sync_out(self):<br>+ try:<br>+ self._clone_out()<br>+ except
errors.RadioError:<br>+ raise<br>+ except Exception, e:<br>+ trace = traceback.format_exc()<br>+ raise errors.RadioError("Failed to communicate with radio: %s" % trace)<br>+<br>+ def process_mmap(self):<br>+ self._memobj = bitwise.parse(self.mem_format, self._mmap)<br>+<br>+ def get_memory(self, number):<br>+ _mem = self._memobj.memory[number-1]<br>+<br>+ mem = chirp_common.Memory()<br>+ mem.number = number<br>+ mem.freq = _mem.rxfreq * 10
<br>+ mem.offset = _mem.txfreqoffset * 10<br>+ if not _mem.tmode < len(self.TMODES):<br>+ _mem.tmode = 0<br>+ mem.tmode = self.TMODES[_mem.tmode]<br>+ mem.rtone = self.TONES[_mem.tone]<br>+ mem.dtcs = chirp_common.DTCS_CODES[_mem.dcstone]<br>+ mem.mode = self.MODES[_mem.mode]<br>+<br>+ '''<br>+ # ars mode note yet working...<br>+ # ARS mode:<br>+ if _mem.ars and _mem.shift == 0:<br>+ mem.duplex =
self.DUPLEX[4] <br>+ else:<br>+ mem.duplex = self.DUPLEX[_mem.shift]<br>+ '''<br>+<br>+ mem.duplex = self.DUPLEX[_mem.shift]<br>+ mem.power = self.POWER_LEVELS[_mem.power]<br>+ # radio has a known bug with 5khz step and squelch<br>+ if _mem.step == 0:<br>+ _mem.step = 2<br>+ mem.tuning_step = self.STEPS[_mem.step]<br>+ mem.skip = _mem.skip and "S" or ""<br>+ mem.name = _mem.name<br>+ return
mem<br>+<br>+ def get_raw_memory(self, number):<br>+ return repr(self._memobj.memory[number-1])<br>+ <br>+ def set_memory(self, mem):<br>+<br>+ _mem = self._memobj.memory[mem.number - 1]<br>+ _mem.skip = mem.skip == "S"<br>+ # radio has a known bug with 5khz step and dead squelch<br>+ if not mem.tuning_step or mem.tuning_step == self.STEPS[0]:<br>+ _mem.step = 2<br>+ else:<br>+ _mem.step = self.STEPS.index(mem.tuning_step)<br>+ _mem.rxfreq = mem.freq /
10<br>+ # vfo will unlock if not in right band?<br>+ if mem.freq > 300000000: <br>+ # uhf<br>+ _mem.isUhf1 = 1<br>+ _mem.isUhf2 = 1<br>+ if mem.freq > 810000000:<br>+ # uhf hiband<br>+ _mem.isUhfHi = 1<br>+ else:<br>+ _mem.isUhfHi =
0<br>+ else:<br>+ # vhf<br>+ _mem.isUhf1 = 0<br>+ _mem.isUhf2 = 0<br>+ _mem.isUhfHi = 0<br>+ _mem.txfreqoffset = mem.offset / 10<br>+ _mem.tone = self.TONES.index(mem.rtone)<br>+ _mem.tmode = self.TMODES.index(mem.tmode)<br>+ _mem.mode = self.MODES.index(mem.mode)<br>+ '''<br>+ # ars not yet working<br>+ # ARS mode:<br>+ if
mem.duplex == 4:<br>+ _mem.shift = 0<br>+ _mem.ars = 1<br>+ else:<br>+ _mem.shift = self.DUPLEX.index(mem.duplex)<br>+ '''<br>+ _mem.shift = self.DUPLEX.index(mem.duplex) <br>+ _mem.dcstone = chirp_common.DTCS_CODES.index(mem.dtcs)<br>+ if self.get_features().has_tuning_step:<br>+ _mem.step = self.STEPS.index(mem.tuning_step)<br>+ _mem.shift = self.DUPLEX.index(mem.duplex)<br>+ if
mem.power:<br>+ _mem.power = self.POWER_LEVELS.index(mem.power)<br>+ else:<br>+ _mem.power = 3 # default to low power<br>+ _mem.name = mem.name.ljust(7)<br>+ <br>+<br></div></div></div></div><br>_______________________________________________<br>chirp_devel mailing list<br><a ymailto="mailto:chirp_devel@intrepid.danplanet.com" href="mailto:chirp_devel@intrepid.danplanet.com">chirp_devel@intrepid.danplanet.com</a><br><a href="http://intrepid.danplanet.com/mailman/listinfo/chirp_devel" target="_blank">http://intrepid.danplanet.com/mailman/listinfo/chirp_devel</a><br>Developer docs: <a href="http://chirp.danplanet.com/projects/chirp/wiki/Developers"
target="_blank">http://chirp.danplanet.com/projects/chirp/wiki/Developers</a><br><br></div> </div> </div> </div></body></html>