<div dir="ltr"><div class="gmail_signature"><div dir="ltr"><div dir="ltr"># HG changeset patch</div><div dir="ltr"># User Alexey K <<a href="mailto:lepik.stv@gmail.com">lepik.stv@gmail.com</a>></div><div dir="ltr"># Date 1444251379 -10800</div><div dir="ltr"># Wed Oct 07 23:56:19 2015 +0300</div><div dir="ltr"># Node ID 6213e68e50e323221bf1939101bfc4169621a8cd</div><div dir="ltr"># Parent 39ec1a8bc0b04f90f47e8e76795a7abbe5b1af40</div><div dir="ltr">[KYD IP-620] Add support for KYD IP-620 radio - issue #2033</div><div dir="ltr"><br></div><div dir="ltr">diff -r 39ec1a8bc0b0 -r 6213e68e50e3 chirp/drivers/kyd_IP620.py</div><div dir="ltr">--- /dev/null<span class="" style="white-space:pre">        </span>Thu Jan 01 00:00:00 1970 +0000</div><div dir="ltr">+++ b/chirp/drivers/kyd_IP620.py<span class="" style="white-space:pre">        </span>Wed Oct 07 23:56:19 2015 +0300</div><div dir="ltr">@@ -0,0 +1,619 @@</div><div dir="ltr">+# Copyright 2015 Lepik.stv <<a href="mailto:lepik.stv@gmail.com">lepik.stv@gmail.com</a>></div><div dir="ltr">+# based on modification of Dan Smith's and Jim Unroe original work</div><div dir="ltr">+#</div><div dir="ltr">+# This program is free software: you can redistribute it and/or modify</div><div dir="ltr">+# it under the terms of the GNU General Public License as published by</div><div dir="ltr">+# the Free Software Foundation, either version 2 of the License, or</div><div dir="ltr">+# (at your option) any later version.</div><div dir="ltr">+#</div><div dir="ltr">+# This program is distributed in the hope that it will be useful,</div><div dir="ltr">+# but WITHOUT ANY WARRANTY; without even the implied warranty of</div><div dir="ltr">+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the</div><div dir="ltr">+# GNU General Public License for more details.</div><div dir="ltr">+#</div><div dir="ltr">+# You should have received a copy of the GNU General Public License</div><div dir="ltr">+# along with this program. If not, see <<a href="http://www.gnu.org/licenses/">http://www.gnu.org/licenses/</a>>.</div><div dir="ltr">+</div><div dir="ltr">+"""KYD IP-620 radios management module"""</div><div dir="ltr">+</div><div dir="ltr">+# TODO: Power on message</div><div dir="ltr">+# TODO: Channel name</div><div dir="ltr">+# TODO: Tuning step</div><div dir="ltr">+</div><div dir="ltr">+import struct</div><div dir="ltr">+import time</div><div dir="ltr">+import os</div><div dir="ltr">+import logging</div><div dir="ltr">+from chirp import util, chirp_common, bitwise, memmap, errors, directory</div><div dir="ltr">+from chirp.settings import RadioSetting, RadioSettingGroup, \</div><div dir="ltr">+ RadioSettingValueBoolean, RadioSettingValueList, \</div><div dir="ltr">+ RadioSettingValueInteger, RadioSettingValueString, \</div><div dir="ltr">+ RadioSettings</div><div dir="ltr">+</div><div dir="ltr">+LOG = logging.getLogger(__name__)</div><div dir="ltr">+</div><div dir="ltr">+IP620_MEM_FORMAT = """</div><div dir="ltr">+#seekto 0x0000;</div><div dir="ltr">+struct { // Channel memory structure</div><div dir="ltr">+ lbcd rx_freq[4]; // RX frequency</div><div dir="ltr">+ lbcd tx_freq[4]; // TX frequency</div><div dir="ltr">+ ul16 rx_tone; // RX tone</div><div dir="ltr">+ ul16 tx_tone; // TX tone</div><div dir="ltr">+ u8 unknown_1:4 // n-a</div><div dir="ltr">+ busy_loc:2, // NO-00, Crrier wave-01, SM-10</div><div dir="ltr">+ n_a:2; // n-a</div><div dir="ltr">+ u8 unknown_2:1 // n-a</div><div dir="ltr">+ scan_add:1, // Scan add</div><div dir="ltr">+ n_a:1, // n-a</div><div dir="ltr">+ w_n:1, // Narrow-0 Wide-1</div><div dir="ltr">+ lout:1, // LOCKOUT OFF-0 ON-1</div><div dir="ltr">+ n_a_:1, // n-a</div><div dir="ltr">+ power:2; // Power low-00 middle-01 high-10</div><div dir="ltr">+ u8 unknown_3; // n-a</div><div dir="ltr">+ u8 unknown_4; // n-a</div><div dir="ltr">+} memory[200];</div><div dir="ltr">+</div><div dir="ltr">+#seekto 0x1000;</div><div dir="ltr">+struct {</div><div dir="ltr">+ u8 chan_name[6]; //Channel name</div><div dir="ltr">+ u8 unknown_1[10];</div><div dir="ltr">+} chan_names[200];</div><div dir="ltr">+</div><div dir="ltr">+#seekto 0x0C80;</div><div dir="ltr">+struct { // Settings memory structure ( A-Frequency mode )</div><div dir="ltr">+ lbcd freq_a_rx[4];</div><div dir="ltr">+ lbcd freq_a_tx[4];</div><div dir="ltr">+ ul16 freq_a_rx_tone; // RX tone</div><div dir="ltr">+ ul16 freq_a_tx_tone; // TX tone</div><div dir="ltr">+ u8 unknown_1_5:4</div><div dir="ltr">+ freq_a_busy_loc:2,</div><div dir="ltr">+ n_a:2;</div><div dir="ltr">+ u8 unknown_1_6:3</div><div dir="ltr">+ freq_a_w_n:1,</div><div dir="ltr">+ n_a:1,</div><div dir="ltr">+ na:1,</div><div dir="ltr">+ freq_a_power:2;</div><div dir="ltr">+ u8 unknown_1_7;</div><div dir="ltr">+ u8 unknown_1_8;</div><div dir="ltr">+} settings_freq_a;</div><div dir="ltr">+</div><div dir="ltr">+#seekto 0x0E20;</div><div dir="ltr">+struct {</div><div dir="ltr">+ u8 chan_disp_way; // Channel display way</div><div dir="ltr">+ u8 step_freq; // Step frequency KHz</div><div dir="ltr">+ u8 rf_sql; // Squelch level</div><div dir="ltr">+ u8 bat_save; // Battery Saver</div><div dir="ltr">+ u8 chan_pri; // Channel PRI</div><div dir="ltr">+ u8 end_beep; // End beep</div><div dir="ltr">+ u8 tot; // Time-out timer</div><div dir="ltr">+ u8 vox; // VOX Gain</div><div dir="ltr">+ u8 chan_pri_num; // Channel PRI time Sec</div><div dir="ltr">+ u8 n_a_2;</div><div dir="ltr">+ u8 ch_mode; // CH mode</div><div dir="ltr">+ u8 n_a_3;</div><div dir="ltr">+ u8 call_tone; // Call tone</div><div dir="ltr">+ u8 beep; // Beep</div><div dir="ltr">+ u8 unknown_1_1[2];</div><div dir="ltr">+ u8 unknown_1_2[8];</div><div dir="ltr">+ u8 scan_rev; // Scan rev</div><div dir="ltr">+ u8 unknown_1_3[2];</div><div dir="ltr">+ u8 enc; // Frequency lock</div><div dir="ltr">+ u8 vox_dly; // VOX Delay</div><div dir="ltr">+ u8 wait_back_light;// Wait back light</div><div dir="ltr">+ u8 unknown_1_4[2];</div><div dir="ltr">+} settings;</div><div dir="ltr">+</div><div dir="ltr">+#seekto 0x0E40;</div><div dir="ltr">+struct {</div><div dir="ltr">+ u8 fm_radio; // FM radio</div><div dir="ltr">+ u8 auto_lock; // Auto lock</div><div dir="ltr">+ u8 unknown_1[8];</div><div dir="ltr">+ u8 pon_msg[6]; //Power on msg</div><div dir="ltr">+} settings_misc;</div><div dir="ltr">+</div><div dir="ltr">+#seekto 0x1C80;</div><div dir="ltr">+struct {</div><div dir="ltr">+ u8 unknown_1[16];</div><div dir="ltr">+ u8 unknown_2[16];</div><div dir="ltr">+} settings_radio_3;</div><div dir="ltr">+"""</div><div dir="ltr">+</div><div dir="ltr">+CMD_ACK = "\x06"</div><div dir="ltr">+WRITE_BLOCK_SIZE = 0x10</div><div dir="ltr">+READ_BLOCK_SIZE = 0x40</div><div dir="ltr">+</div><div dir="ltr">+CHAR_LENGTH_MAX = 6</div><div dir="ltr">+</div><div dir="ltr">+OFF_ON_LIST = ["OFF", "ON"]</div><div dir="ltr">+ON_OFF_LIST = ["ON", "OFF"]</div><div dir="ltr">+NO_YES_LIST = ["NO", "YES"]</div><div dir="ltr">+STEP_LIST = ["5.0", "6.25", "10.0", "12.5", "25.0"]</div><div dir="ltr">+BAT_SAVE_LIST = ["OFF", "0.2 Sec", "0.4 Sec", "0.6 Sec", "0.8 Sec","1.0 Sec"]</div><div dir="ltr">+SHIFT_LIST = ["", "-", "+"]</div><div dir="ltr">+SCANM_LIST = ["Time", "Carrier wave", "Search"]</div><div dir="ltr">+ENDBEEP_LIST = ["OFF", "Begin", "End", "Begin/End"]</div><div dir="ltr">+POWER_LEVELS = [chirp_common.PowerLevel("Low", watts=1.00), chirp_common.PowerLevel("Medium", watts=2.50), chirp_common.PowerLevel("High", watts=5.00)]</div><div dir="ltr">+TIMEOUT_LIST = ["OFF", "1 Min", "3 Min", "10 Min"]</div><div dir="ltr">+TOTALERT_LIST = ["", "OFF"] + ["%s seconds" % x for x in range(1, 11)]</div><div dir="ltr">+VOX_LIST = ["OFF"] + ["%s" % x for x in range(1, 17)]</div><div dir="ltr">+VOXDELAY_LIST = ["0.3 Sec", "0.5 Sec", "1.0 Sec", "1.5 Sec", "2.0 Sec", "3.0 Sec", "4.0 Sec", "5.0 Sec"]</div><div dir="ltr">+PRI_NUM = [3, 5, 8, 10]</div><div dir="ltr">+PRI_NUM_LIST = [str(x) for x in PRI_NUM]</div><div dir="ltr">+CH_FLAG_LIST = ["Channel+Freq", "Channel+Name"]</div><div dir="ltr">+BACKLIGHT_LIST = ["Always Off", "Auto", "Always On"]</div><div dir="ltr">+BUSYLOCK_LIST = ["NO", "Carrier", "SM"]</div><div dir="ltr">+KEYBLOCK_LIST = ["Manual", "Auto"]</div><div dir="ltr">+CALLTONE_LIST = ["OFF", "1", "2", "3", "4", "5", "6", "7", "8", "1750"]</div><div dir="ltr">+RFSQL_LIST = ["OFF", "S-1", "S-2", "S-3", "S-4", "S-5", "S-6","S-7", "S-8", "S-FULL"]</div><div dir="ltr">+</div><div dir="ltr">+IP620_CHARSET = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ?+-* "</div><div dir="ltr">+</div><div dir="ltr">+IP620_BANDS = [</div><div dir="ltr">+ (136000000, 174000000),</div><div dir="ltr">+ (200000000, 260000000),</div><div dir="ltr">+ (300000000, 340000000), # <--- this band supports only Russian model (ARGUT A-36)</div><div dir="ltr">+ (350000000, 390000000),</div><div dir="ltr">+ (400000000, 480000000),</div><div dir="ltr">+ (420000000, 510000000),</div><div dir="ltr">+ (450000000, 520000000),</div><div dir="ltr">+]</div><div dir="ltr">+</div><div dir="ltr">+@directory.register</div><div dir="ltr">+class IP620Radio(chirp_common.CloneModeRadio,</div><div dir="ltr">+ chirp_common.ExperimentalRadio):</div><div dir="ltr">+ """KYD IP-620"""</div><div dir="ltr">+ VENDOR = "KYD"</div><div dir="ltr">+ MODEL = "IP-620"</div><div dir="ltr">+ BAUD_RATE = 9600</div><div dir="ltr">+</div><div dir="ltr">+ _ranges = [</div><div dir="ltr">+ (0x0000, 0x2000),</div><div dir="ltr">+ ]</div><div dir="ltr">+ _memsize = 0x2000</div><div dir="ltr">+</div><div dir="ltr">+ def _ip620_exit_programming_mode(self):</div><div dir="ltr">+ try:</div><div dir="ltr">+ self.pipe.write("\x06")</div><div dir="ltr">+ except errors.RadioError:</div><div dir="ltr">+ raise</div><div dir="ltr">+ except Exception, e:</div><div dir="ltr">+ raise errors.RadioError("Radio refused to exit programming mode: %s" % e)</div><div dir="ltr">+</div><div dir="ltr">+ def _ip620_enter_programming_mode(self):</div><div dir="ltr">+ try:</div><div dir="ltr">+ self.pipe.write("iUHOUXUN")</div><div dir="ltr">+ self.pipe.write("\x02")</div><div dir="ltr">+ time.sleep(0.2)</div><div dir="ltr">+ _ack = self.pipe.read(1)</div><div dir="ltr">+ except errors.RadioError:</div><div dir="ltr">+ raise</div><div dir="ltr">+ except Exception, e:</div><div dir="ltr">+ raise errors.RadioError("Error communicating with radio: %s" % e)</div><div dir="ltr">+ if not _ack:</div><div dir="ltr">+ raise errors.RadioError("No response from radio")</div><div dir="ltr">+ elif _ack != CMD_ACK:</div><div dir="ltr">+ raise errors.RadioError("Radio refused to enter programming mode")</div><div dir="ltr">+ try:</div><div dir="ltr">+ self.pipe.write("\x02")</div><div dir="ltr">+ _ident = self.pipe.read(8)</div><div dir="ltr">+ except errors.RadioError:</div><div dir="ltr">+ raise</div><div dir="ltr">+ except Exception, e:</div><div dir="ltr">+ raise errors.RadioError("Error communicating with radio: %s" % e)</div><div dir="ltr">+ if not _ident.startswith("\x06\x4B\x47\x36\x37\x01\x56\xF8"):</div><div dir="ltr">+ print util.hexprint(_ident)</div><div dir="ltr">+ raise errors.RadioError("Radio returned unknown identification string")</div><div dir="ltr">+ try:</div><div dir="ltr">+ self.pipe.write(CMD_ACK)</div><div dir="ltr">+ _ack = self.pipe.read(1)</div><div dir="ltr">+ except errors.RadioError:</div><div dir="ltr">+ raise</div><div dir="ltr">+ except Exception, e:</div><div dir="ltr">+ raise errors.RadioError("Error communicating with radio: %s" % e)</div><div dir="ltr">+ if _ack != CMD_ACK:</div><div dir="ltr">+ raise errors.RadioError("Radio refused to enter programming mode")</div><div dir="ltr">+</div><div dir="ltr">+ def _ip620_write_block(self, block_addr):</div><div dir="ltr">+ _cmd = struct.pack(">cHb", 'W', block_addr, WRITE_BLOCK_SIZE)</div><div dir="ltr">+ _data = self.get_mmap()[block_addr:block_addr + WRITE_BLOCK_SIZE]</div><div dir="ltr">+ LOG.debug("Writing Data:")</div><div dir="ltr">+ LOG.debug(util.hexprint(_cmd + _data))</div><div dir="ltr">+ try:</div><div dir="ltr">+ self.pipe.write(_cmd + _data)</div><div dir="ltr">+ if self.pipe.read(1) != CMD_ACK:</div><div dir="ltr">+ raise Exception("No ACK")</div><div dir="ltr">+ except:</div><div dir="ltr">+ raise errors.RadioError("Failed to send block "</div><div dir="ltr">+ "to radio at %04x" % block_addr)</div><div dir="ltr">+</div><div dir="ltr">+ def _ip620_read_block(self, block_addr):</div><div dir="ltr">+ _cmd = struct.pack(">cHb", 'R', block_addr, READ_BLOCK_SIZE)</div><div dir="ltr">+ _expectedresponse = "W" + _cmd[1:]</div><div dir="ltr">+ LOG.debug("Reading block %04x..." % (block_addr))</div><div dir="ltr">+ try:</div><div dir="ltr">+ self.pipe.write(_cmd)</div><div dir="ltr">+ _response = self.pipe.read(4 + READ_BLOCK_SIZE)</div><div dir="ltr">+ if _response[:4] != _expectedresponse:</div><div dir="ltr">+ raise Exception("Error reading block %04x." % (block_addr))</div><div dir="ltr">+ _block_data = _response[4:]</div><div dir="ltr">+ self.pipe.write(CMD_ACK)</div><div dir="ltr">+ _ack = self.pipe.read(1)</div><div dir="ltr">+ except:</div><div dir="ltr">+ raise errors.RadioError("Failed to read block at %04x" % block_addr)</div><div dir="ltr">+ if _ack != CMD_ACK:</div><div dir="ltr">+ raise Exception("No ACK reading block %04x." % (block_addr))</div><div dir="ltr">+ return _block_data</div><div dir="ltr">+</div><div dir="ltr">+ def _do_download(self):</div><div dir="ltr">+ self._ip620_enter_programming_mode()</div><div dir="ltr">+ _data = ""</div><div dir="ltr">+ _status = chirp_common.Status()</div><div dir="ltr">+ _status.msg = "Cloning from radio"</div><div dir="ltr">+ _status.cur = 0</div><div dir="ltr">+ _status.max = self._memsize</div><div dir="ltr">+ for _addr in range(0, self._memsize, READ_BLOCK_SIZE):</div><div dir="ltr">+ _status.cur = _addr + READ_BLOCK_SIZE</div><div dir="ltr">+ self.status_fn(_status)</div><div dir="ltr">+ _block = self._ip620_read_block(_addr)</div><div dir="ltr">+ _data += _block</div><div dir="ltr">+ LOG.debug("Address: %04x" % _addr)</div><div dir="ltr">+ LOG.debug(util.hexprint(_block))</div><div dir="ltr">+ self._ip620_exit_programming_mode()</div><div dir="ltr">+ return memmap.MemoryMap(_data)</div><div dir="ltr">+</div><div dir="ltr">+ def _do_upload(self):</div><div dir="ltr">+ _status = chirp_common.Status()</div><div dir="ltr">+ _status.msg = "Uploading to radio"</div><div dir="ltr">+ self._ip620_enter_programming_mode()</div><div dir="ltr">+ _status.cur = 0</div><div dir="ltr">+ _status.max = self._memsize</div><div dir="ltr">+ for _start_addr, _end_addr in self._ranges:</div><div dir="ltr">+ for _addr in range(_start_addr, _end_addr, WRITE_BLOCK_SIZE):</div><div dir="ltr">+ _status.cur = _addr + WRITE_BLOCK_SIZE</div><div dir="ltr">+ self.status_fn(_status)</div><div dir="ltr">+ self._ip620_write_block(_addr)</div><div dir="ltr">+ self._ip620_exit_programming_mode()</div><div dir="ltr">+</div><div dir="ltr">+ @classmethod</div><div dir="ltr">+ def get_prompts(cls):</div><div dir="ltr">+ rp = chirp_common.RadioPrompts()</div><div dir="ltr">+ rp.experimental = ("This radio driver is currently under development. "</div><div dir="ltr">+ "There are no known issues with it, but you should "</div><div dir="ltr">+ "proceed with caution. However, proceed at your own risk!")</div><div dir="ltr">+ return rp</div><div dir="ltr">+</div><div dir="ltr">+ def get_features(self):</div><div dir="ltr">+ rf = chirp_common.RadioFeatures()</div><div dir="ltr">+ rf.has_settings = True</div><div dir="ltr">+ rf.has_bank = False</div><div dir="ltr">+ rf.has_ctone = True</div><div dir="ltr">+ rf.has_cross = False</div><div dir="ltr">+ rf.has_rx_dtcs = True</div><div dir="ltr">+ rf.has_tuning_step = False</div><div dir="ltr">+ rf.can_odd_split = False</div><div dir="ltr">+ rf.has_name = False</div><div dir="ltr">+ rf.valid_skips = []</div><div dir="ltr">+ rf.valid_tmodes = ["", "Tone", "TSQL", "DTCS"]</div><div dir="ltr">+ rf.valid_power_levels = POWER_LEVELS</div><div dir="ltr">+ rf.valid_duplexes = SHIFT_LIST</div><div dir="ltr">+ rf.valid_modes = ["FM", "NFM"]</div><div dir="ltr">+ rf.memory_bounds = (1, 200)</div><div dir="ltr">+ rf.valid_bands = IP620_BANDS</div><div dir="ltr">+ rf.valid_characters = ''.join(set(IP620_CHARSET))</div><div dir="ltr">+ rf.valid_name_length = CHAR_LENGTH_MAX</div><div dir="ltr">+ return rf</div><div dir="ltr">+</div><div dir="ltr">+ def process_mmap(self):</div><div dir="ltr">+ self._memobj = bitwise.parse(IP620_MEM_FORMAT, self._mmap)</div><div dir="ltr">+</div><div dir="ltr">+ def sync_in(self):</div><div dir="ltr">+ try:</div><div dir="ltr">+ self._mmap = self._do_download()</div><div dir="ltr">+ except errors.RadioError:</div><div dir="ltr">+ raise</div><div dir="ltr">+ except Exception, e:</div><div dir="ltr">+ raise errors.RadioError("Failed to communicate with radio: %s" % e)</div><div dir="ltr">+ self.process_mmap()</div><div dir="ltr">+</div><div dir="ltr">+ def sync_out(self):</div><div dir="ltr">+ self._do_upload()</div><div dir="ltr">+</div><div dir="ltr">+ def get_raw_memory(self, number):</div><div dir="ltr">+ return repr(self._memobj.memory[number - 1])</div><div dir="ltr">+</div><div dir="ltr">+ def _get_tone(self, _mem, mem):</div><div dir="ltr">+ def _get_dcs(val):</div><div dir="ltr">+ code = int("%03o" % (val & 0x07FF))</div><div dir="ltr">+ pol = (val & 0x8000) and "R" or "N"</div><div dir="ltr">+ return code, pol</div><div dir="ltr">+</div><div dir="ltr">+ if _mem.tx_tone != 0xFFFF and _mem.tx_tone > 0x2800:</div><div dir="ltr">+ tcode, tpol = _get_dcs(_mem.tx_tone)</div><div dir="ltr">+ mem.dtcs = tcode</div><div dir="ltr">+ txmode = "DTCS"</div><div dir="ltr">+ elif _mem.tx_tone != 0xFFFF:</div><div dir="ltr">+ mem.rtone = _mem.tx_tone / 10.0</div><div dir="ltr">+ txmode = "Tone"</div><div dir="ltr">+ else:</div><div dir="ltr">+ txmode = ""</div><div dir="ltr">+</div><div dir="ltr">+ if _mem.rx_tone != 0xFFFF and _mem.rx_tone > 0x2800:</div><div dir="ltr">+ rcode, rpol = _get_dcs(_mem.rx_tone)</div><div dir="ltr">+ mem.rx_dtcs = rcode</div><div dir="ltr">+ rxmode = "DTCS"</div><div dir="ltr">+ elif _mem.rx_tone != 0xFFFF:</div><div dir="ltr">+ mem.ctone = _mem.rx_tone / 10.0</div><div dir="ltr">+ rxmode = "Tone"</div><div dir="ltr">+ else:</div><div dir="ltr">+ rxmode = ""</div><div dir="ltr">+</div><div dir="ltr">+ if txmode == "Tone" and not rxmode:</div><div dir="ltr">+ mem.tmode = "Tone"</div><div dir="ltr">+ elif txmode == rxmode and txmode == "Tone" and mem.rtone == mem.ctone:</div><div dir="ltr">+ mem.tmode = "TSQL"</div><div dir="ltr">+ elif txmode == rxmode and txmode == "DTCS" and mem.dtcs == mem.rx_dtcs:</div><div dir="ltr">+ mem.tmode = "DTCS"</div><div dir="ltr">+ elif rxmode or txmode:</div><div dir="ltr">+ mem.tmode = "Cross"</div><div dir="ltr">+ mem.cross_mode = "%s->%s" % (txmode, rxmode)</div><div dir="ltr">+</div><div dir="ltr">+ if mem.tmode == "DTCS":</div><div dir="ltr">+ mem.dtcs_polarity = "%s%s" % (tpol, rpol)</div><div dir="ltr">+</div><div dir="ltr">+ LOG.debug("Got TX %s (%i) RX %s (%i)" % (txmode, _mem.tx_tone,</div><div dir="ltr">+ rxmode, _mem.rx_tone))</div><div dir="ltr">+</div><div dir="ltr">+ def get_memory(self, number):</div><div dir="ltr">+ _mem = self._memobj.memory[number - 1]</div><div dir="ltr">+ _nam = self._memobj.chan_names[number - 1]</div><div dir="ltr">+</div><div dir="ltr">+ def _is_empty():</div><div dir="ltr">+ for i in range(0, 4):</div><div dir="ltr">+ if _mem.rx_freq[i].get_raw() != "\xFF":</div><div dir="ltr">+ return False</div><div dir="ltr">+ return True</div><div dir="ltr">+</div><div dir="ltr">+ mem = chirp_common.Memory()</div><div dir="ltr">+ mem.number = number</div><div dir="ltr">+</div><div dir="ltr">+ if _is_empty():</div><div dir="ltr">+ mem.empty = True</div><div dir="ltr">+ return mem</div><div dir="ltr">+</div><div dir="ltr">+ mem.freq = int(_mem.rx_freq) * 10</div><div dir="ltr">+</div><div dir="ltr">+ if int(_mem.rx_freq) == int(_mem.tx_freq):</div><div dir="ltr">+ mem.duplex = ""</div><div dir="ltr">+ mem.offset = 0</div><div dir="ltr">+ else:</div><div dir="ltr">+ mem.duplex = int(_mem.rx_freq) > int(_mem.tx_freq) and "-" or "+"</div><div dir="ltr">+ mem.offset = abs(int(_mem.rx_freq) - int(_mem.tx_freq)) * 10</div><div dir="ltr">+</div><div dir="ltr">+ mem.mode = _mem.w_n and "FM" or "NFM"</div><div dir="ltr">+ self._get_tone(_mem, mem)</div><div dir="ltr">+ mem.power = POWER_LEVELS[_mem.power]</div><div dir="ltr">+</div><div dir="ltr">+ mem.extra = RadioSettingGroup("Extra", "extra")</div><div dir="ltr">+ rs = RadioSetting("lout", "Lock out",</div><div dir="ltr">+ RadioSettingValueList(OFF_ON_LIST,</div><div dir="ltr">+ OFF_ON_LIST[_mem.lout]))</div><div dir="ltr">+ mem.extra.append(rs)</div><div dir="ltr">+</div><div dir="ltr">+ rs = RadioSetting("busy_loc", "Busy lock",</div><div dir="ltr">+ RadioSettingValueList(BUSYLOCK_LIST,</div><div dir="ltr">+ BUSYLOCK_LIST[_mem.busy_loc]))</div><div dir="ltr">+ mem.extra.append(rs)</div><div dir="ltr">+</div><div dir="ltr">+ rs = RadioSetting("scan_add", "Scan add",</div><div dir="ltr">+ RadioSettingValueList(NO_YES_LIST,</div><div dir="ltr">+ NO_YES_LIST[_mem.scan_add]))</div><div dir="ltr">+ mem.extra.append(rs)</div><div dir="ltr">+ #TODO: Show name channel</div><div dir="ltr">+## count = 0</div><div dir="ltr">+## for i in _nam.chan_name:</div><div dir="ltr">+## if i == 0xFF:</div><div dir="ltr">+## break</div><div dir="ltr">+## try:</div><div dir="ltr">+## <a href="http://mem.name">mem.name</a> += IP620_CHARSET[i]</div><div dir="ltr">+## except Exception:</div><div dir="ltr">+## LOG.error("Unknown name char %i: 0x%02x (mem %i)" %</div><div dir="ltr">+## (count, i, number - 1))</div><div dir="ltr">+## <a href="http://mem.name">mem.name</a> += " "</div><div dir="ltr">+## count += 1</div><div dir="ltr">+## <a href="http://mem.name">mem.name</a> = mem.name.rstrip()</div><div dir="ltr">+</div><div dir="ltr">+ return mem</div><div dir="ltr">+</div><div dir="ltr">+ def _set_tone(self, mem, _mem):</div><div dir="ltr">+ def _set_dcs(code, pol):</div><div dir="ltr">+ val = int("%i" % code, 8) + 0x2800</div><div dir="ltr">+ if pol == "R":</div><div dir="ltr">+ val += 0x8000</div><div dir="ltr">+ return val</div><div dir="ltr">+</div><div dir="ltr">+ if mem.tmode == "Cross":</div><div dir="ltr">+ tx_mode, rx_mode = mem.cross_mode.split("->")</div><div dir="ltr">+ elif mem.tmode == "Tone":</div><div dir="ltr">+ tx_mode = mem.tmode</div><div dir="ltr">+ rx_mode = None</div><div dir="ltr">+ else:</div><div dir="ltr">+ tx_mode = rx_mode = mem.tmode</div><div dir="ltr">+</div><div dir="ltr">+ if tx_mode == "DTCS":</div><div dir="ltr">+ _mem.tx_tone = mem.tmode != "DTCS" and \</div><div dir="ltr">+ _set_dcs(mem.dtcs, mem.dtcs_polarity[0]) or \</div><div dir="ltr">+ _set_dcs(mem.rx_dtcs, mem.dtcs_polarity[0])</div><div dir="ltr">+ elif tx_mode:</div><div dir="ltr">+ _mem.tx_tone = tx_mode == "Tone" and \</div><div dir="ltr">+ int(mem.rtone * 10) or int(mem.ctone * 10)</div><div dir="ltr">+ else:</div><div dir="ltr">+ _mem.tx_tone = 0xFFFF</div><div dir="ltr">+</div><div dir="ltr">+ if rx_mode == "DTCS":</div><div dir="ltr">+ _mem.rx_tone = _set_dcs(mem.rx_dtcs, mem.dtcs_polarity[1])</div><div dir="ltr">+ elif rx_mode:</div><div dir="ltr">+ _mem.rx_tone = int(mem.ctone * 10)</div><div dir="ltr">+ else:</div><div dir="ltr">+ _mem.rx_tone = 0xFFFF</div><div dir="ltr">+</div><div dir="ltr">+ LOG.debug("Set TX %s (%i) RX %s (%i)" % (tx_mode, _mem.tx_tone,</div><div dir="ltr">+ rx_mode, _mem.rx_tone))</div><div dir="ltr">+</div><div dir="ltr">+ def set_memory(self, mem):</div><div dir="ltr">+ _mem = self._memobj.memory[mem.number - 1]</div><div dir="ltr">+ if mem.empty:</div><div dir="ltr">+ _mem.set_raw("\xFF" * (_mem.size() / 8))</div><div dir="ltr">+ return</div><div dir="ltr">+</div><div dir="ltr">+ _mem.rx_freq = mem.freq / 10</div><div dir="ltr">+ if mem.duplex == "OFF":</div><div dir="ltr">+ for i in range(0, 4):</div><div dir="ltr">+ _mem.tx_freq[i].set_raw("\xFF")</div><div dir="ltr">+ elif mem.duplex == "+":</div><div dir="ltr">+ _mem.tx_freq = (mem.freq + mem.offset) / 10</div><div dir="ltr">+ elif mem.duplex == "-":</div><div dir="ltr">+ _mem.tx_freq = (mem.freq - mem.offset) / 10</div><div dir="ltr">+ else:</div><div dir="ltr">+ _mem.tx_freq = mem.freq / 10</div><div dir="ltr">+</div><div dir="ltr">+ _mem.w_n = mem.mode == "FM"</div><div dir="ltr">+ self._set_tone(mem, _mem)</div><div dir="ltr">+ _mem.power = mem.power == POWER_LEVELS[1]</div><div dir="ltr">+</div><div dir="ltr">+ for setting in mem.extra:</div><div dir="ltr">+ setattr(_mem, setting.get_name(), setting.value)</div><div dir="ltr">+</div><div dir="ltr">+ def get_settings(self):</div><div dir="ltr">+ _settings = self._memobj.settings</div><div dir="ltr">+ _settings_misc = self._memobj.settings_misc</div><div dir="ltr">+ basic = RadioSettingGroup("basic", "Basic Settings")</div><div dir="ltr">+ top = RadioSettings(basic)</div><div dir="ltr">+</div><div dir="ltr">+ rs = RadioSetting("rf_sql", "Squelch level (SQL)",</div><div dir="ltr">+ RadioSettingValueList(RFSQL_LIST,</div><div dir="ltr">+ RFSQL_LIST[_settings.rf_sql]))</div><div dir="ltr">+ basic.append(rs)</div><div dir="ltr">+</div><div dir="ltr">+ rs = RadioSetting("step_freq", "Step frequency KHz (STP)",</div><div dir="ltr">+ RadioSettingValueList(STEP_LIST,</div><div dir="ltr">+ STEP_LIST[_settings.step_freq]))</div><div dir="ltr">+ basic.append(rs)</div><div dir="ltr">+</div><div dir="ltr">+ rs = RadioSetting("fm_radio", "FM radio (DW)",</div><div dir="ltr">+ RadioSettingValueList(OFF_ON_LIST,</div><div dir="ltr">+ OFF_ON_LIST[_settings_misc.fm_radio]))</div><div dir="ltr">+ basic.append(rs)</div><div dir="ltr">+</div><div dir="ltr">+ rs = RadioSetting("call_tone", "Call tone (CK)",</div><div dir="ltr">+ RadioSettingValueList(CALLTONE_LIST,</div><div dir="ltr">+ CALLTONE_LIST[_settings.call_tone]))</div><div dir="ltr">+ basic.append(rs)</div><div dir="ltr">+</div><div dir="ltr">+ rs = RadioSetting("tot", "Time-out timer (TOT)",</div><div dir="ltr">+ RadioSettingValueList(TIMEOUT_LIST,</div><div dir="ltr">+ TIMEOUT_LIST[_settings.tot]))</div><div dir="ltr">+ basic.append(rs)</div><div dir="ltr">+</div><div dir="ltr">+ rs = RadioSetting("chan_disp_way", "Channel display way",</div><div dir="ltr">+ RadioSettingValueList(CH_FLAG_LIST,</div><div dir="ltr">+ CH_FLAG_LIST[_settings.chan_disp_way]))</div><div dir="ltr">+ basic.append(rs)</div><div dir="ltr">+</div><div dir="ltr">+ rs = RadioSetting("vox", "VOX Gain (VOX)",</div><div dir="ltr">+ RadioSettingValueList(VOX_LIST,</div><div dir="ltr">+ VOX_LIST[_settings.vox]))</div><div dir="ltr">+ basic.append(rs)</div><div dir="ltr">+</div><div dir="ltr">+ rs = RadioSetting("vox_dly", "VOX Delay",</div><div dir="ltr">+ RadioSettingValueList(VOXDELAY_LIST,</div><div dir="ltr">+ VOXDELAY_LIST[_settings.vox_dly]))</div><div dir="ltr">+ basic.append(rs)</div><div dir="ltr">+</div><div dir="ltr">+ rs = RadioSetting("beep", "Beep (BP)",</div><div dir="ltr">+ RadioSettingValueList(OFF_ON_LIST,</div><div dir="ltr">+ OFF_ON_LIST[_settings.beep]))</div><div dir="ltr">+ basic.append(rs)</div><div dir="ltr">+</div><div dir="ltr">+ rs = RadioSetting("auto_lock", "Auto lock (KY)",</div><div dir="ltr">+ RadioSettingValueList(NO_YES_LIST,</div><div dir="ltr">+ NO_YES_LIST[_settings_misc.auto_lock]))</div><div dir="ltr">+ basic.append(rs)</div><div dir="ltr">+</div><div dir="ltr">+ rs = RadioSetting("bat_save", "Battery Saver (SAV)",</div><div dir="ltr">+ RadioSettingValueList(BAT_SAVE_LIST,</div><div dir="ltr">+ BAT_SAVE_LIST[_settings.bat_save]))</div><div dir="ltr">+ basic.append(rs)</div><div dir="ltr">+</div><div dir="ltr">+ rs = RadioSetting("chan_pri", "Channel PRI (PRI)",</div><div dir="ltr">+ RadioSettingValueList(OFF_ON_LIST,</div><div dir="ltr">+ OFF_ON_LIST[_settings.chan_pri]))</div><div dir="ltr">+ basic.append(rs)</div><div dir="ltr">+</div><div dir="ltr">+ rs = RadioSetting("chan_pri_num", "Channel PRI time Sec (PRI)",</div><div dir="ltr">+ RadioSettingValueList(PRI_NUM_LIST,</div><div dir="ltr">+ PRI_NUM_LIST[_settings.chan_pri_num]))</div><div dir="ltr">+ basic.append(rs)</div><div dir="ltr">+</div><div dir="ltr">+ rs = RadioSetting("end_beep", "End beep (ET)",</div><div dir="ltr">+ RadioSettingValueList(ENDBEEP_LIST,</div><div dir="ltr">+ ENDBEEP_LIST[_settings.end_beep]))</div><div dir="ltr">+ basic.append(rs)</div><div dir="ltr">+</div><div dir="ltr">+ rs = RadioSetting("ch_mode", "CH mode",</div><div dir="ltr">+ RadioSettingValueList(ON_OFF_LIST,</div><div dir="ltr">+ ON_OFF_LIST[_settings.ch_mode]))</div><div dir="ltr">+ basic.append(rs)</div><div dir="ltr">+</div><div dir="ltr">+ rs = RadioSetting("scan_rev", "Scan rev (SCAN)",</div><div dir="ltr">+ RadioSettingValueList(SCANM_LIST,</div><div dir="ltr">+ SCANM_LIST[_settings.scan_rev]))</div><div dir="ltr">+ basic.append(rs)</div><div dir="ltr">+</div><div dir="ltr">+ rs = RadioSetting("enc", "Frequency lock (ENC)",</div><div dir="ltr">+ RadioSettingValueList(OFF_ON_LIST,</div><div dir="ltr">+ OFF_ON_LIST[_settings.enc]))</div><div dir="ltr">+ basic.append(rs)</div><div dir="ltr">+</div><div dir="ltr">+ rs = RadioSetting("wait_back_light", "Wait back light (LED)",</div><div dir="ltr">+ RadioSettingValueList(BACKLIGHT_LIST,</div><div dir="ltr">+ BACKLIGHT_LIST[_settings.wait_back_light]))</div><div dir="ltr">+ basic.append(rs)</div><div dir="ltr">+</div><div dir="ltr">+ return top</div><div dir="ltr">+</div><div dir="ltr">+ def _set_misc_settings(self, settings):</div><div dir="ltr">+ for element in settings:</div><div dir="ltr">+ try:</div><div dir="ltr">+ setattr(self._memobj.settings_misc,</div><div dir="ltr">+ element.get_name(),</div><div dir="ltr">+ element.value)</div><div dir="ltr">+ except Exception, e:</div><div dir="ltr">+ LOG.debug(element.get_name())</div><div dir="ltr">+ raise</div><div dir="ltr">+</div><div dir="ltr">+ def set_settings(self, settings):</div><div dir="ltr">+ _settings = self._memobj.settings</div><div dir="ltr">+ _settings_misc = self._memobj.settings_misc</div><div dir="ltr">+ for element in settings:</div><div dir="ltr">+ if not isinstance(element, RadioSetting):</div><div dir="ltr">+ self.set_settings(element)</div><div dir="ltr">+ continue</div><div dir="ltr">+ if not element.changed():</div><div dir="ltr">+ continue</div><div dir="ltr">+ try:</div><div dir="ltr">+ setting = element.get_name()</div><div dir="ltr">+ if setting in ["auto_lock","fm_radio"]:</div><div dir="ltr">+ oldval = getattr(_settings_misc, setting)</div><div dir="ltr">+ else:</div><div dir="ltr">+ oldval = getattr(_settings, setting)</div><div dir="ltr">+</div><div dir="ltr">+ newval = element.value</div><div dir="ltr">+</div><div dir="ltr">+ LOG.debug("Setting %s(%s) <= %s" % (setting, oldval, newval))</div><div dir="ltr">+ if setting in ["auto_lock","fm_radio"]:</div><div dir="ltr">+ setattr(_settings_misc, setting, newval)</div><div dir="ltr">+ else:</div><div dir="ltr">+ setattr(_settings, setting, newval)</div><div dir="ltr">+ except Exception, e:</div><div dir="ltr">+ LOG.debug(element.get_name())</div><div dir="ltr">+ raise</div><div><br></div></div></div>
</div>