<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body><div># HG changeset patch<br></div>
<div># User Eric Allen <<a href="mailto:eric@hackerengineer.net">eric@hackerengineer.net</a>><br></div>
<div># Date 1422752216 28800<br></div>
<div># Sat Jan 31 16:56:56 2015 -0800<br></div>
<div># Node ID 03cbc94e6b9097c38f38a7d50361a52c5dc808e2<br></div>
<div># Parent cfa8a356cf3867cb3df35c7d73193285cc2b50d1<br></div>
<div>Add support for new firmware in TYT TH-UV3R that supports 2.5kHz steps.<br></div>
<div> </div>
<div>This hopefully fixes #1227<br></div>
<div> </div>
<div>diff -r cfa8a356cf38 -r 03cbc94e6b90 chirp/th_uv3r25.py<br></div>
<div>--- /dev/nullThu Jan 01 00:00:00 1970 +0000<br></div>
<div>+++ b/chirp/th_uv3r25.pySat Jan 31 16:56:56 2015 -0800<br></div>
<div>@@ -0,0 +1,208 @@<br></div>
<div>+# Copyright 2015 Eric Allen <<a href="mailto:eric@hackerengineer.net">eric@hackerengineer.net</a>><br></div>
<div>+#<br></div>
<div>+# This program is free software: you can redistribute it and/or modify<br></div>
<div>+# it under the terms of the GNU General Public License as published by<br></div>
<div>+# the Free Software Foundation, either version 3 of the License, or<br></div>
<div>+# (at your option) any later version.<br></div>
<div>+#<br></div>
<div>+# This program is distributed in the hope that it will be useful,<br></div>
<div>+# but WITHOUT ANY WARRANTY; without even the implied warranty of<br></div>
<div>+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the<br></div>
<div>+# GNU General Public License for more details.<br></div>
<div>+#<br></div>
<div>+# You should have received a copy of the GNU General Public License<br></div>
<div>+# along with this program. If not, see <<a href="http://www.gnu.org/licenses/">http://www.gnu.org/licenses/</a>>.<br></div>
<div>+<br></div>
<div>+"""TYT uv3r (2.5kHz) radio management module"""<br></div>
<div>+<br></div>
<div>+from chirp import chirp_common, bitwise, directory<br></div>
<div>+from chirp.wouxun_common import do_download, do_upload<br></div>
<div>+<br></div>
<div>+from chirp.settings import RadioSetting, RadioSettingGroup, \<br></div>
<div>+ RadioSettingValueInteger, RadioSettingValueList, \<br></div>
<div>+ RadioSettingValueBoolean, RadioSettingValueString<br></div>
<div>+<br></div>
<div>+from th_uv3r import TYTUV3RRadio, tyt_uv3r_prep, THUV3R_CHARSET<br></div>
<div>+<br></div>
<div>+<br></div>
<div>+def tyt_uv3r_download(radio):<br></div>
<div>+ tyt_uv3r_prep(radio)<br></div>
<div>+ return do_download(radio, 0x0000, 0x0B30, 0x0010)<br></div>
<div>+<br></div>
<div>+<br></div>
<div>+def tyt_uv3r_upload(radio):<br></div>
<div>+ tyt_uv3r_prep(radio)<br></div>
<div>+ return do_upload(radio, 0x0000, 0x0B30, 0x0010)<br></div>
<div>+<br></div>
<div>+mem_format = """<br></div>
<div>+// 20 bytes per memory<br></div>
<div>+struct memory {<br></div>
<div>+ ul32 rx_freq; // 4 bytes<br></div>
<div>+ ul32 tx_freq; // 8 bytes<br></div>
<div>+<br></div>
<div>+ ul16 rx_tone; // 10 bytes<br></div>
<div>+ ul16 tx_tone; // 12 bytes<br></div>
<div>+<br></div>
<div>+ u8 unknown1a:1,<br></div>
<div>+ iswide:1,<br></div>
<div>+ bclo_n:1,<br></div>
<div>+ vox_n:1,<br></div>
<div>+ tail:1,<br></div>
<div>+ power_high:1,<br></div>
<div>+ voice_mode:2;<br></div>
<div>+ u8 name[6]; // 19 bytes<br></div>
<div>+ u8 unknown2; // 20 bytes<br></div>
<div>+};<br></div>
<div>+<br></div>
<div>+#seekto 0x0010;<br></div>
<div>+struct memory memory[128];<br></div>
<div>+<br></div>
<div>+#seekto 0x0A80;<br></div>
<div>+u8 emptyflags[16];<br></div>
<div>+u8 skipflags[16];<br></div>
<div>+"""<br></div>
<div>+<br></div>
<div>+VOICE_MODE_LIST = ["Compander", "Scrambler", "None"]<br></div>
<div>+<br></div>
<div><a href="mailto:+@directory.register">+@directory.register</a><br></div>
<div>+class TYTUV3R25Radio(TYTUV3RRadio):<br></div>
<div>+ MODEL = "TH-UV3R (2.5kHz)"<br></div>
<div>+ _memsize = 2864<br></div>
<div>+<br></div>
<div>+ POWER_LEVELS = [chirp_common.PowerLevel("High", watts=2.00),<br></div>
<div>+ chirp_common.PowerLevel("Low", watts=0.80)]<br></div>
<div>+<br></div>
<div>+ def get_features(self):<br></div>
<div>+ rf = super(TYTUV3R25Radio, self).get_features()<br></div>
<div>+<br></div>
<div>+ rf.valid_tuning_steps = [2.5, 5.0, 6.25, 10.0, 12.5, 25.0, 37.50,<br></div>
<div>+ 50.0, 100.0]<br></div>
<div>+ rf.valid_power_levels = self.POWER_LEVELS<br></div>
<div>+ return rf<br></div>
<div>+<br></div>
<div>+ def sync_in(self):<br></div>
<div>+ self.pipe.setTimeout(2)<br></div>
<div>+ self._mmap = tyt_uv3r_download(self)<br></div>
<div>+ self.process_mmap()<br></div>
<div>+<br></div>
<div>+ def sync_out(self):<br></div>
<div>+ tyt_uv3r_upload(self)<br></div>
<div>+<br></div>
<div>+ def process_mmap(self):<br></div>
<div>+ self._memobj = bitwise.parse(mem_format, self._mmap)<br></div>
<div>+<br></div>
<div>+ def get_raw_memory(self, number):<br></div>
<div>+ return repr(self._memobj.memory[number - 1])<br></div>
<div>+<br></div>
<div>+ def get_memory(self, number):<br></div>
<div>+ _mem = self._memobj.memory[number - 1]<br></div>
<div>+ mem = chirp_common.Memory()<br></div>
<div>+ mem.number = number<br></div>
<div>+<br></div>
<div>+ bit = 1 << ((number - 1) % 8)<br></div>
<div>+ byte = (number - 1) / 8<br></div>
<div>+<br></div>
<div>+ if self._memobj.emptyflags[byte] & bit:<br></div>
<div>+ mem.empty = True<br></div>
<div>+ return mem<br></div>
<div>+<br></div>
<div>+ mem.freq = _mem.rx_freq * 10<br></div>
<div>+ mem.offset = abs(_mem.rx_freq - _mem.tx_freq) * 10<br></div>
<div>+ if _mem.tx_freq == _mem.rx_freq:<br></div>
<div>+ mem.duplex = ""<br></div>
<div>+ elif _mem.tx_freq < _mem.rx_freq:<br></div>
<div>+ mem.duplex = "-"<br></div>
<div>+ elif _mem.tx_freq > _mem.rx_freq:<br></div>
<div>+ mem.duplex = "+"<br></div>
<div>+<br></div>
<div>+ mem.mode = _mem.iswide and "FM" or "NFM"<br></div>
<div>+ self._decode_tone(mem, _mem)<br></div>
<div>+ mem.skip = (self._memobj.skipflags[byte] & bit) and "S" or ""<br></div>
<div>+<br></div>
<div>+ for char in _mem.name:<br></div>
<div>+ try:<br></div>
<div>+ c = THUV3R_CHARSET[char]<br></div>
<div>+ except:<br></div>
<div>+ c = ""<br></div>
<div>+ mem.name += c<br></div>
<div>+ mem.name = mem.name.rstrip()<br></div>
<div>+<br></div>
<div>+ mem.power = self.POWER_LEVELS[not _mem.power_high]<br></div>
<div>+<br></div>
<div>+ mem.extra = RadioSettingGroup("extra", "Extra Settings")<br></div>
<div>+<br></div>
<div>+ rs = RadioSetting("bclo_n", "Busy Channel Lockout",<br></div>
<div>+ RadioSettingValueBoolean(not _mem.bclo_n))<br></div>
<div>+ mem.extra.append(rs)<br></div>
<div>+<br></div>
<div>+ rs = RadioSetting("vox_n", "VOX",<br></div>
<div>+ RadioSettingValueBoolean(not _mem.vox_n))<br></div>
<div>+ mem.extra.append(rs)<br></div>
<div>+<br></div>
<div>+ rs = RadioSetting("tail", "Squelch Tail Elimination",<br></div>
<div>+ RadioSettingValueBoolean(_mem.tail))<br></div>
<div>+ mem.extra.append(rs)<br></div>
<div>+<br></div>
<div>+ rs = RadioSetting("voice_mode", "Voice Mode",<br></div>
<div>+ RadioSettingValueList(VOICE_MODE_LIST,<br></div>
<div>+ VOICE_MODE_LIST[_mem.voice_mode-1]))<br></div>
<div>+ mem.extra.append(rs)<br></div>
<div>+<br></div>
<div>+ return mem<br></div>
<div>+<br></div>
<div>+ def set_memory(self, mem):<br></div>
<div>+ _mem = self._memobj.memory[mem.number - 1]<br></div>
<div>+ bit = 1 << ((mem.number - 1) % 8)<br></div>
<div>+ byte = (mem.number - 1) / 8<br></div>
<div>+<br></div>
<div>+ if mem.empty:<br></div>
<div>+ self._memobj.emptyflags[byte] |= bit<br></div>
<div>+ _mem.set_raw("\xFF" * 16)<br></div>
<div>+ return<br></div>
<div>+<br></div>
<div>+ self._memobj.emptyflags[byte] &= ~bit<br></div>
<div>+<br></div>
<div>+ _mem.rx_freq = mem.freq / 10<br></div>
<div>+<br></div>
<div>+ if mem.duplex == "":<br></div>
<div>+ _mem.tx_freq = _mem.rx_freq<br></div>
<div>+ elif mem.duplex == "-":<br></div>
<div>+ _mem.tx_freq = _mem.rx_freq - mem.offset / 10.0<br></div>
<div>+ elif mem.duplex == "+":<br></div>
<div>+ _mem.tx_freq = _mem.rx_freq + mem.offset / 10.0<br></div>
<div>+<br></div>
<div>+ _mem.iswide = mem.mode == "FM"<br></div>
<div>+<br></div>
<div>+ self._encode_tone(mem, _mem)<br></div>
<div>+<br></div>
<div>+ if mem.skip:<br></div>
<div>+ self._memobj.skipflags[byte] |= bit<br></div>
<div>+ else:<br></div>
<div>+ self._memobj.skipflags[byte] &= ~bit<br></div>
<div>+<br></div>
<div>+ name = []<br></div>
<div>+ for char in mem.name.ljust(6):<br></div>
<div>+ try:<br></div>
<div>+ c = THUV3R_CHARSET.index(char)<br></div>
<div>+ except:<br></div>
<div>+ c = THUV3R_CHARSET.index(" ")<br></div>
<div>+ name.append(c)<br></div>
<div>+ _mem.name = name<br></div>
<div>+<br></div>
<div>+ if mem.power == self.POWER_LEVELS[0]:<br></div>
<div>+ _mem.power_high = 1<br></div>
<div>+ else:<br></div>
<div>+ _mem.power_high = 0<br></div>
<div>+<br></div>
<div>+ for element in mem.extra:<br></div>
<div>+ if element.get_name() == 'voice_mode':<br></div>
<div>+ setattr(_mem, element.get_name(), int(element.value) + 1)<br></div>
<div>+ elif element.get_name().endswith('_n'):<br></div>
<div>+ setattr(_mem, element.get_name(), 1 - int(element.value))<br></div>
<div>+ else:<br></div>
<div>+ setattr(_mem, element.get_name(), element.value)<br></div>
<div>+<br></div>
<div>+<br></div>
<div>+ @classmethod<br></div>
<div>+ def match_model(cls, filedata, filename):<br></div>
<div>+ return len(filedata) == cls._memsize<br></div>
<div> </div>
</body>
</html>