# HG changeset patch
# User Jens Jensen <kd4tjx@yahoo.com>
# Date 1377497847 18000
# Node ID 7c95e9d39dfc07ea1e3192834d8a339e100347f6
# Parent 86910885e998d559dfdd6ba4c5fb0bf520fdee31
initial support for Yaesu FT-90R, revised #1087
diff -r 86910885e998 -r 7c95e9d39dfc chirp/ft90.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/chirp/ft90.py Mon Aug 26 01:17:27 2013 -0500
@@ -0,0 +1,379 @@
+# Copyright 2011 Dan Smith <dsmith@danplanet.com>
+# Copyright 2013 Jens Jensen <kd4tjx@yahoo.com>
+#
+# 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/>.
+
+from chirp import chirp_common, bitwise, memmap, directory, errors, util, yaesu_clone
+import time, os, traceback
+
+CHIRP_DEBUG=True
+CMD_ACK = chr(0x06)
+
+@directory.register
+class FT90Radio(yaesu_clone.YaesuCloneModeRadio):
+ VENDOR = "Yaesu"
+ MODEL = "FT-90"
+ ID = "\x8E\xF6"
+
+ STEPS = [5, 10, 12.5, 15, 20, 25, 50]
+ MODES = ["AM", "FM",
"Auto"]
+ TMODES = ["", "Tone", "TSQL", "", "DTCS"] # idx 3 (Bell) not supported yet
+
+ TONES = list(chirp_common.TONES)
+ for tone in [ 165.5, 171.3, 177.3 ]:
+ TONES.remove(tone)
+ POWER_LEVELS = ["Hi", "Mid1", "Mid2", "Low"]
+ DUPLEX = ["", "-", "+", "split"]
+
+ _memsize = 4063
+ # block 03 (200 Bytes long) repeats 18 times; channel memories
+ _block_lengths = [ 2, 232, 24, 200, 205]
+
+ mem_format = """
+ #seekto 0x22;
+ struct {
+ u8 dtmf_active;
+
u8 dtmf1_len;
+ u8 dtmf2_len;
+ u8 dtmf3_len;
+ u8 dtmf4_len;
+ u8 dtmf5_len;
+ u8 dtmf6_len;
+ u8 dtmf7_len;
+ u8 dtmf8_len;
+ bbcd dtmf1[8];
+ bbcd dtmf2[8];
+ bbcd dtmf3[8];
+ bbcd dtmf4[8];
+ bbcd dtmf5[8];
+ bbcd
dtmf6[8];
+ bbcd dtmf7[8];
+ bbcd dtmf8[8];
+ char cwid[7];
+ u8 unk1;
+ u8 unk2:2,
+ beep_dis:1,
+ unk3:1,
+ rfsqlvl:4;
+ u8 cwid_en:1,
+ unk4:3,
+ txnarrow:1,
+ dtmfspeed:1,
+ pttlock:2;
+
u8 dtmftxdelay:3,
+ fancontrol:2,
+ unk5:3;
+ u8 dimmer:3,
+ unk6:1,
+ lcdcontrast:4;
+ u8 tot;
+ u8 unk8:1,
+ ars:1,
+ lock:1,
+ txpwrsave:1,
+ apo:4;
+ u8 key_rt;
+ u8
key_lt;
+ u8 key_p1;
+ u8 key_p2;
+ u8 key_acc;
+ char demomsg1[32];
+ char demomsg2[32];
+
+ } settings;
+
+ struct mem_struct {
+ u8 mode:2,
+ isUhf1:1,
+ unknown1:2,
+ step:3;
+ u8 artsmode:2,
+ unknown2:1,
+
isUhf2:1
+ power:2,
+ shift:2;
+ u8 skip:1,
+ showname:1,
+ unknown3:1,
+ isUhfHi:1,
+ unknown4:1,
+ tmode:3;
+ u32 rxfreq;
+ u32 txfreqoffset;
+ u8 UseDefaultName:1,
+ ars:1,
+ tone:6;
+ u8 packetmode:1,
+ unknown5:1,
+
dcstone:6;
+ char name[7];
+ };
+
+ #seekto 0x86;
+ struct mem_struct vfo_v;
+ struct mem_struct call_v;
+ struct mem_struct vfo_u;
+ struct mem_struct call_u;
+
+ #seekto 0x102;
+ struct mem_struct memory[180];
+
+ #seekto 0xf12;
+ struct mem_struct pms_1L;
+ struct mem_struct pms_1U;
+ struct mem_struct pms_2L;
+ struct mem_struct pms_2U;
+ """
+
+ @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.has_dtcs_polarity = False
+ rf.has_dtcs = True
+ rf.valid_modes = self.MODES
+ rf.valid_tmodes = self.TMODES
+ rf.valid_duplexes = self.DUPLEX
+ rf.valid_tuning_steps = self.STEPS
+ rf.valid_power_levels = self.POWER_LEVELS
+ rf.valid_name_length = 7
+ rf.valid_characters =
chirp_common.CHARSET_ASCII
+ rf.valid_skips = ["", "S"]
+ rf.memory_bounds = (1, 180)
+ rf.valid_bands = [(100000000, 230000000),
+ (300000000, 530000000), (810000000, 999975000)]
+
+ return rf
+
+ def _read(self, blocksize, blocknum):
+ data = self.pipe.read(blocksize+2)
+
+ # chew echo'd ack
+ self.pipe.write(CMD_ACK)
+ time.sleep(0.02)
+ self.pipe.read(1) # chew echoed ACK from 1-wire
serial
+
+ if len(data) == blocksize+2 and data[0] == chr(blocknum):
+ checksum = yaesu_clone.YaesuChecksum(1, blocksize)
+ if checksum.get_existing(data) != checksum.get_calculated(data):
+ raise Exception("Checksum Failed [%02X<>%02X] block %02X, data len: %i" %
+
(checksum.get_existing(data),
+ checksum.get_calculated(data), blocknum, len(data) ))
+ data = data[1:blocksize+1] # Chew blocknum and checksum
+
+ else:
+ raise Exception("Unable to read blocknum %02X expected blocksize %i got %i." %
+ (blocknum, blocksize+2,
len(data)))
+
+ return data
+
+ def _clone_in(self):
+ # Be very patient with the radio
+ self.pipe.setTimeout(4)
+ start = time.time()
+
+ data = ""
+ blocknum = 0
+ status = chirp_common.Status()
+ status.msg = "Cloning from radio.\nPut radio into clone mode then\npress SET to send"
+ self.status_fn(status)
+ status.max = len(self._block_lengths) + 18
+ for
blocksize in self._block_lengths:
+ if blocksize == 200:
+ # repeated read of 200 block same size (memory area)
+ repeat = 18
+ else:
+ repeat = 1
+ for _i in range(0, repeat):
+ data += self._read(blocksize, blocknum)
+
+ blocknum +=
1
+ status.cur = blocknum
+ self.status_fn(status)
+
+ status.msg = "Clone completed."
+ self.status_fn(status)
+
+ print "Clone completed in %i seconds, blocks read: %i" % (time.time() - start, blocknum)
+
+ return memmap.MemoryMap(data)
+
+ def _clone_out(self):
+ delay = 0.2
+ start = time.time()
+
+ blocknum = 0
+ pos = 0
+ status = chirp_common.Status()
+ status.msg = "Cloning to radio.\nPut radio into clone mode and press DISP/SS\n to start receive within 3 secs..."
+ self.status_fn(status)
+ # radio likes to have port open
+ self.pipe.open()
+ time.sleep(3)
+ status.max = len(self._block_lengths) + 18
+
+
+ for blocksize in self._block_lengths:
+ if blocksize ==
200:
+ # repeat channel blocks
+ repeat = 18
+ else:
+ repeat = 1
+ for _i in range(0, repeat):
+ time.sleep(0.1)
+ checksum = yaesu_clone.YaesuChecksum(pos, pos+blocksize-1)
+ blocknumbyte =
chr(blocknum)
+ payloadbytes = self.get_mmap()[pos:pos+blocksize]
+ checksumbyte = chr(checksum.get_calculated(self.get_mmap()))
+ if os.getenv("CHIRP_DEBUG") or CHIRP_DEBUG:
+ print "Block %i - will send from %i to %i byte " % \
+ (blocknum, pos, pos + blocksize)
+ print
util.hexprint(blocknumbyte)
+ print util.hexprint(payloadbytes)
+ print util.hexprint(checksumbyte)
+ # send wrapped bytes
+ self.pipe.write(blocknumbyte)
+ self.pipe.write(payloadbytes)
+ self.pipe.write(checksumbyte)
+ tmp = self.pipe.read(blocksize+2) #chew
echo
+ if os.getenv("CHIRP_DEBUG") or CHIRP_DEBUG:
+ print "bytes echoed: "
+ print util.hexprint(tmp)
+ # radio is slow to write/ack:
+ time.sleep(0.9)
+ buf =
self.pipe.read(1)
+ if os.getenv("CHIRP_DEBUG") or CHIRP_DEBUG:
+ print "ack recd:"
+ print util.hexprint(buf)
+ if buf != CMD_ACK:
+ raise Exception("Radio did not ack block %i" % blocknum)
+ pos +=
blocksize
+ blocknum += 1
+ status.cur = blocknum
+ self.status_fn(status)
+
+ print "Clone completed in %i seconds" % (time.time() - start)
+
+ def sync_in(self):
+ try:
+ self._mmap = self._clone_in()
+ except errors.RadioError:
+ raise
+ except Exception,
e:
+ trace = traceback.format_exc()
+ raise errors.RadioError("Failed to communicate with radio: %s" % trace)
+ self.process_mmap()
+
+ def sync_out(self):
+ try:
+ self._clone_out()
+ except errors.RadioError:
+ raise
+ except Exception, e:
+ trace = traceback.format_exc()
+ raise errors.RadioError("Failed to communicate with radio: %s" %
trace)
+
+ def process_mmap(self):
+ self._memobj = bitwise.parse(self.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.rxfreq * 10
+ mem.offset = _mem.txfreqoffset * 10
+ if not _mem.tmode < len(self.TMODES):
+ _mem.tmode = 0
+ mem.tmode = self.TMODES[_mem.tmode]
+ mem.rtone =
self.TONES[_mem.tone]
+ mem.dtcs = chirp_common.DTCS_CODES[_mem.dcstone]
+ mem.mode = self.MODES[_mem.mode]
+
+ '''
+ # ars mode note yet working...
+ # ARS mode:
+ if _mem.ars and _mem.shift == 0:
+ mem.duplex = self.DUPLEX[4]
+ else:
+ mem.duplex = self.DUPLEX[_mem.shift]
+ '''
+
+ mem.duplex = self.DUPLEX[_mem.shift]
+ mem.power =
self.POWER_LEVELS[_mem.power]
+ # radio has a known bug with 5khz step and squelch
+ if _mem.step == 0:
+ _mem.step = 2
+ mem.tuning_step = self.STEPS[_mem.step]
+ mem.skip = _mem.skip and "S" or ""
+ mem.name = _mem.name
+ return mem
+
+ def get_raw_memory(self, number):
+ return repr(self._memobj.memory[number-1])
+
+ def set_memory(self, mem):
+
+ _mem = self._memobj.memory[mem.number - 1]
+ _mem.skip = mem.skip ==
"S"
+ # radio has a known bug with 5khz step and dead squelch
+ if not mem.tuning_step or mem.tuning_step == self.STEPS[0]:
+ _mem.step = 2
+ else:
+ _mem.step = self.STEPS.index(mem.tuning_step)
+ _mem.rxfreq = mem.freq / 10
+ # vfo will unlock if not in right band?
+ if mem.freq > 300000000:
+ # uhf
+ _mem.isUhf1 = 1
+ _mem.isUhf2 =
1
+ if mem.freq > 810000000:
+ # uhf hiband
+ _mem.isUhfHi = 1
+ else:
+ _mem.isUhfHi = 0
+ else:
+ # vhf
+ _mem.isUhf1 = 0
+ _mem.isUhf2 = 0
+ _mem.isUhfHi = 0
+ _mem.txfreqoffset
= mem.offset / 10
+ _mem.tone = self.TONES.index(mem.rtone)
+ _mem.tmode = self.TMODES.index(mem.tmode)
+ _mem.mode = self.MODES.index(mem.mode)
+ '''
+ # ars not yet working
+ # ARS mode:
+ if mem.duplex == 4:
+ _mem.shift = 0
+ _mem.ars = 1
+ else:
+ _mem.shift = self.DUPLEX.index(mem.duplex)
+ '''
+
_mem.shift = self.DUPLEX.index(mem.duplex)
+ _mem.dcstone = chirp_common.DTCS_CODES.index(mem.dtcs)
+ if self.get_features().has_tuning_step:
+ _mem.step = self.STEPS.index(mem.tuning_step)
+ _mem.shift = self.DUPLEX.index(mem.duplex)
+ if mem.power:
+ _mem.power = self.POWER_LEVELS.index(mem.power)
+ else:
+ _mem.power = 3 # default to low power
+ _mem.name = mem.name.ljust(7)
+
+
diff -r 86910885e998 -r 7c95e9d39dfc ft90.py
---
/dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/ft90.py Mon Aug 26 01:17:27 2013 -0500
@@ -0,0 +1,379 @@
+# Copyright 2011 Dan Smith <dsmith@danplanet.com>
+# Copyright 2013 Jens Jensen <kd4tjx@yahoo.com>
+#
+# 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/>.
+
+from chirp import chirp_common, bitwise, memmap, directory, errors, util, yaesu_clone
+import time, os, traceback
+
+CHIRP_DEBUG=True
+CMD_ACK = chr(0x06)
+
+@directory.register
+class FT90Radio(yaesu_clone.YaesuCloneModeRadio):
+ VENDOR = "Yaesu"
+ MODEL = "FT-90"
+ ID = "\x8E\xF6"
+
+ STEPS = [5, 10, 12.5, 15, 20, 25, 50]
+ MODES = ["AM", "FM", "Auto"]
+ TMODES = ["", "Tone", "TSQL", "", "DTCS"] # idx 3 (Bell) not supported yet
+
+ TONES = list(chirp_common.TONES)
+ for tone in [ 165.5, 171.3, 177.3 ]:
+ TONES.remove(tone)
+ POWER_LEVELS = ["Hi", "Mid1", "Mid2", "Low"]
+ DUPLEX
= ["", "-", "+", "split"]
+
+ _memsize = 4063
+ # block 03 (200 Bytes long) repeats 18 times; channel memories
+ _block_lengths = [ 2, 232, 24, 200, 205]
+
+ mem_format = """
+ #seekto 0x22;
+ struct {
+ u8 dtmf_active;
+ u8 dtmf1_len;
+ u8 dtmf2_len;
+ u8 dtmf3_len;
+ u8 dtmf4_len;
+ u8 dtmf5_len;
+ u8 dtmf6_len;
+
u8 dtmf7_len;
+ u8 dtmf8_len;
+ bbcd dtmf1[8];
+ bbcd dtmf2[8];
+ bbcd dtmf3[8];
+ bbcd dtmf4[8];
+ bbcd dtmf5[8];
+ bbcd dtmf6[8];
+ bbcd dtmf7[8];
+ bbcd dtmf8[8];
+ char cwid[7];
+ u8 unk1;
+ u8 unk2:2,
+ beep_dis:1,
+
unk3:1,
+ rfsqlvl:4;
+ u8 cwid_en:1,
+ unk4:3,
+ txnarrow:1,
+ dtmfspeed:1,
+ pttlock:2;
+ u8 dtmftxdelay:3,
+ fancontrol:2,
+ unk5:3;
+ u8 dimmer:3,
+ unk6:1,
+ lcdcontrast:4;
+
u8 tot;
+ u8 unk8:1,
+ ars:1,
+ lock:1,
+ txpwrsave:1,
+ apo:4;
+ u8 key_rt;
+ u8 key_lt;
+ u8 key_p1;
+ u8 key_p2;
+ u8 key_acc;
+ char demomsg1[32];
+ char demomsg2[32];
+
+ }
settings;
+
+ struct mem_struct {
+ u8 mode:2,
+ isUhf1:1,
+ unknown1:2,
+ step:3;
+ u8 artsmode:2,
+ unknown2:1,
+ isUhf2:1
+ power:2,
+ shift:2;
+ u8 skip:1,
+ showname:1,
+ unknown3:1,
+ isUhfHi:1,
+
unknown4:1,
+ tmode:3;
+ u32 rxfreq;
+ u32 txfreqoffset;
+ u8 UseDefaultName:1,
+ ars:1,
+ tone:6;
+ u8 packetmode:1,
+ unknown5:1,
+ dcstone:6;
+ char name[7];
+ };
+
+ #seekto 0x86;
+ struct mem_struct vfo_v;
+ struct mem_struct call_v;
+ struct mem_struct vfo_u;
+ struct mem_struct call_u;
+
+ #seekto 0x102;
+ struct mem_struct
memory[180];
+
+ #seekto 0xf12;
+ struct mem_struct pms_1L;
+ struct mem_struct pms_1U;
+ struct mem_struct pms_2L;
+ struct mem_struct pms_2U;
+ """
+
+ @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.has_dtcs_polarity = False
+ rf.has_dtcs = True
+ rf.valid_modes =
self.MODES
+ rf.valid_tmodes = self.TMODES
+ rf.valid_duplexes = self.DUPLEX
+ rf.valid_tuning_steps = self.STEPS
+ rf.valid_power_levels = self.POWER_LEVELS
+ rf.valid_name_length = 7
+ rf.valid_characters = chirp_common.CHARSET_ASCII
+ rf.valid_skips = ["", "S"]
+ rf.memory_bounds = (1, 180)
+ rf.valid_bands = [(100000000, 230000000),
+ (300000000, 530000000), (810000000, 999975000)]
+
+ return rf
+
+ def
_read(self, blocksize, blocknum):
+ data = self.pipe.read(blocksize+2)
+
+ # chew echo'd ack
+ self.pipe.write(CMD_ACK)
+ time.sleep(0.02)
+ self.pipe.read(1) # chew echoed ACK from 1-wire serial
+
+ if len(data) == blocksize+2 and data[0] == chr(blocknum):
+ checksum = yaesu_clone.YaesuChecksum(1, blocksize)
+ if checksum.get_existing(data) !=
checksum.get_calculated(data):
+ raise Exception("Checksum Failed [%02X<>%02X] block %02X, data len: %i" %
+ (checksum.get_existing(data),
+ checksum.get_calculated(data), blocknum, len(data) ))
+ data = data[1:blocksize+1] # Chew blocknum and checksum
+
+
else:
+ raise Exception("Unable to read blocknum %02X expected blocksize %i got %i." %
+ (blocknum, blocksize+2, len(data)))
+
+ return data
+
+ def _clone_in(self):
+ # Be very patient with the radio
+ self.pipe.setTimeout(4)
+ start = time.time()
+
+ data = ""
+ blocknum = 0
+
status = chirp_common.Status()
+ status.msg = "Cloning from radio.\nPut radio into clone mode then\npress SET to send"
+ self.status_fn(status)
+ status.max = len(self._block_lengths) + 18
+ for blocksize in self._block_lengths:
+ if blocksize == 200:
+ # repeated read of 200 block same size (memory area)
+ repeat = 18
+ else:
+ repeat =
1
+ for _i in range(0, repeat):
+ data += self._read(blocksize, blocknum)
+
+ blocknum += 1
+ status.cur = blocknum
+ self.status_fn(status)
+
+ status.msg = "Clone completed."
+ self.status_fn(status)
+
+ print "Clone completed in %i seconds, blocks read: %i" % (time.time() - start,
blocknum)
+
+ return memmap.MemoryMap(data)
+
+ def _clone_out(self):
+ delay = 0.2
+ start = time.time()
+
+ blocknum = 0
+ pos = 0
+ status = chirp_common.Status()
+ status.msg = "Cloning to radio.\nPut radio into clone mode and press DISP/SS\n to start receive within 3 secs..."
+ self.status_fn(status)
+ # radio likes to have port open
+ self.pipe.open()
+
time.sleep(3)
+ status.max = len(self._block_lengths) + 18
+
+
+ for blocksize in self._block_lengths:
+ if blocksize == 200:
+ # repeat channel blocks
+ repeat = 18
+ else:
+ repeat = 1
+ for _i in range(0, repeat):
+
time.sleep(0.1)
+ checksum = yaesu_clone.YaesuChecksum(pos, pos+blocksize-1)
+ blocknumbyte = chr(blocknum)
+ payloadbytes = self.get_mmap()[pos:pos+blocksize]
+ checksumbyte = chr(checksum.get_calculated(self.get_mmap()))
+ if os.getenv("CHIRP_DEBUG") or CHIRP_DEBUG:
+ print "Block %i - will send from %i to %i byte " %
\
+ (blocknum, pos, pos + blocksize)
+ print util.hexprint(blocknumbyte)
+ print util.hexprint(payloadbytes)
+ print util.hexprint(checksumbyte)
+ # send wrapped bytes
+
self.pipe.write(blocknumbyte)
+ self.pipe.write(payloadbytes)
+ self.pipe.write(checksumbyte)
+ tmp = self.pipe.read(blocksize+2) #chew echo
+ if os.getenv("CHIRP_DEBUG") or CHIRP_DEBUG:
+ print "bytes echoed: "
+ print
util.hexprint(tmp)
+ # radio is slow to write/ack:
+ time.sleep(0.9)
+ buf = self.pipe.read(1)
+ if os.getenv("CHIRP_DEBUG") or CHIRP_DEBUG:
+ print "ack recd:"
+ print
util.hexprint(buf)
+ if buf != CMD_ACK:
+ raise Exception("Radio did not ack block %i" % blocknum)
+ pos += blocksize
+ blocknum += 1
+ status.cur = blocknum
+ self.status_fn(status)
+
+ print "Clone completed in %i seconds" % (time.time() - start)
+
+ def
sync_in(self):
+ try:
+ self._mmap = self._clone_in()
+ except errors.RadioError:
+ raise
+ except Exception, e:
+ trace = traceback.format_exc()
+ raise errors.RadioError("Failed to communicate with radio: %s" % trace)
+ self.process_mmap()
+
+ def sync_out(self):
+ try:
+ self._clone_out()
+ except
errors.RadioError:
+ raise
+ except Exception, e:
+ trace = traceback.format_exc()
+ raise errors.RadioError("Failed to communicate with radio: %s" % trace)
+
+ def process_mmap(self):
+ self._memobj = bitwise.parse(self.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.rxfreq * 10
+ mem.offset = _mem.txfreqoffset * 10
+ if not _mem.tmode < len(self.TMODES):
+ _mem.tmode = 0
+ mem.tmode = self.TMODES[_mem.tmode]
+ mem.rtone = self.TONES[_mem.tone]
+ mem.dtcs = chirp_common.DTCS_CODES[_mem.dcstone]
+ mem.mode = self.MODES[_mem.mode]
+
+ '''
+ # ars mode note yet working...
+ # ARS mode:
+ if _mem.ars and _mem.shift == 0:
+ mem.duplex =
self.DUPLEX[4]
+ else:
+ mem.duplex = self.DUPLEX[_mem.shift]
+ '''
+
+ mem.duplex = self.DUPLEX[_mem.shift]
+ mem.power = self.POWER_LEVELS[_mem.power]
+ # radio has a known bug with 5khz step and squelch
+ if _mem.step == 0:
+ _mem.step = 2
+ mem.tuning_step = self.STEPS[_mem.step]
+ mem.skip = _mem.skip and "S" or ""
+ mem.name = _mem.name
+ return
mem
+
+ def get_raw_memory(self, number):
+ return repr(self._memobj.memory[number-1])
+
+ def set_memory(self, mem):
+
+ _mem = self._memobj.memory[mem.number - 1]
+ _mem.skip = mem.skip == "S"
+ # radio has a known bug with 5khz step and dead squelch
+ if not mem.tuning_step or mem.tuning_step == self.STEPS[0]:
+ _mem.step = 2
+ else:
+ _mem.step = self.STEPS.index(mem.tuning_step)
+ _mem.rxfreq = mem.freq /
10
+ # vfo will unlock if not in right band?
+ if mem.freq > 300000000:
+ # uhf
+ _mem.isUhf1 = 1
+ _mem.isUhf2 = 1
+ if mem.freq > 810000000:
+ # uhf hiband
+ _mem.isUhfHi = 1
+ else:
+ _mem.isUhfHi =
0
+ else:
+ # vhf
+ _mem.isUhf1 = 0
+ _mem.isUhf2 = 0
+ _mem.isUhfHi = 0
+ _mem.txfreqoffset = mem.offset / 10
+ _mem.tone = self.TONES.index(mem.rtone)
+ _mem.tmode = self.TMODES.index(mem.tmode)
+ _mem.mode = self.MODES.index(mem.mode)
+ '''
+ # ars not yet working
+ # ARS mode:
+ if
mem.duplex == 4:
+ _mem.shift = 0
+ _mem.ars = 1
+ else:
+ _mem.shift = self.DUPLEX.index(mem.duplex)
+ '''
+ _mem.shift = self.DUPLEX.index(mem.duplex)
+ _mem.dcstone = chirp_common.DTCS_CODES.index(mem.dtcs)
+ if self.get_features().has_tuning_step:
+ _mem.step = self.STEPS.index(mem.tuning_step)
+ _mem.shift = self.DUPLEX.index(mem.duplex)
+ if
mem.power:
+ _mem.power = self.POWER_LEVELS.index(mem.power)
+ else:
+ _mem.power = 3 # default to low power
+ _mem.name = mem.name.ljust(7)
+
+