Rick,
Thisis your original submission as received here on my gmail account. Scroll down below and you can see what I am talking about.
Jim
On Tue, Jun 4, 2019 at 1:46 PM Rick DeWitt AA0RD via chirp_devel chirp_devel@intrepid.danplanet.com wrote:
New driver for the TYT TH-UV8000 D/ D/SE. Re-submitted because I had the wrong email address.
# HG changeset patch # User Rick DeWitt aa0rd@yahoo.com # Date 1559226735 25200 #?????????? Thu May 30 07:32:15 2019 -0700 # Node ID 120e390016146e92f490619e4f7029ae60418d72 # Parent?? 76c88493bd3f873d355d08e66c624c6acf201b4d [th-uv8000] New driver for TYT TH-UV8000 family, fixes issue #2837
Submitting new driver in support of 11 issues 2837 ... 6183
diff -r 76c88493bd3f -r 120e39001614 chirp/drivers/th_uv8000.py --- /dev/null?????? Thu Jan 01 00:00:00 1970 +0000 +++ b/chirp/drivers/th_uv8000.py?????? Thu May 30 07:32:15 2019 -0700 @@ -0,0 +1,1598 @@ +# Copyright 2019: Rick DeWitt (RJD), aa0rd@yahoo.com +# Version 1.0 for TYT-UV8000D/E +# Thanks to Damon Schaefer (K9CQB)and the Loudoun County, VA ARES +#?????? club for the donated radio. +# And thanks to Ian Harris (W2OOT) for decoding the mamory map. +# +# 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 2 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/.
+import time +import struct +import logging +import re +import math +from datetime import datetime
+LOG = logging.getLogger(__name__)
+from chirp import chirp_common, directory, memmap +from chirp import bitwise, errors, util +from chirp.settings import RadioSettingGroup, RadioSetting, \ +?????? RadioSettingValueBoolean, RadioSettingValueList, \ +?????? RadioSettingValueString, RadioSettingValueInteger, \ +?????? RadioSettingValueFloat, RadioSettings,InvalidValueError +from textwrap import dedent
+MEM_FORMAT = """ +struct chns { +?? ul32 rxfreq; +?? ul32 txfreq; +?? u8 rxtone[2]; +?? u8 txtone[2]; +?? u8?? wide:1???? // 0x0c +?????????? vox_on:1 +?????????? chunk01:1 +?????????? bcl:1?????? // inv bool +?????????? epilogue:1 +?????????? power:1 +?????????? chunk02:1 +?????????? chunk03:1; +?? u8?? ani:1???????? // 0x0d inv +?????????? chunk08:1 +?????????? ptt:2 +?????????? chpad04:4; +?? u8?? chunk05;?? // 0x0e +?? u16 id_code; // 0x0f, 10 +?? u8?? chunk06; +?? u8?? name[7]; +?? ul32 chpad06; // Need 56 byte pad +?? ul16 chpad07; +?? u8?? chpad08; +};
+struct fm_chn { +?? ul16 rxfreq; +};
+struct frqx { +?? ul32 rxfreq; +?? ul24 ofst; +?? u8?? fqunk01:4?? // 0x07 +?????????? funk10:2 +?????????? duplx:2; +?? u8 rxtone[2]; // 0x08, 9 +?? u8 txtone[2]; // 0x0a, b +?? u8?? wide:1?????? // 0x0c +?????????? vox_on:1 +?????????? funk11:1 +?????????? bcl:1???????? // inv bool +?????????? epilogue:1 +?????????? power:1 +?????????? fqunk02:2; +?? u8?? ani:1???????? // 0x0d inv bool +?????????? fqunk03:1 +?????????? ptt:2 +?????????? fqunk12:1 +?????????? fqunk04:3; +?? u8?? fqunk07;?? // 0x0e +?? u16 id_code;?? // 0x0f, 0x10 +?? u8?? name[7];?????? // dummy +?? u8 fqunk09[8];?? // empty bytes after 1st entry +};
+struct bitmap { +?? u8?? map[16]; +};
+#seekto 0x0010; +struct chns chan_mem[128];
+#seekto 0x1010; +struct frqx frq[2];
+#seekto 0x1050; +struct fm_chn fm_stations[25];
+#seekto 0x1080; +struct { +?? u8?? fmunk01[14]; +?? ul16 fmcur; +} fmfrqs;
+#seekto 0x1190; +struct bitmap chnmap;
+#seekto 0x11a0; +struct bitmap skpchns;
+#seekto 0x011b0; +struct { +?? u8?? fmset[4]; +} fmmap;
+#seekto 0x011b4; +struct { +?? u8?? setunk01[4]; +?? u8?? setunk02[3]; +?? u8?? chs_name:1?????? // 0x11bb +?????????? txsel:1 +?????????? dbw:1 +?????????? setunk05:1 +?????????? ponfmchs:2 +?????????? ponchs:2; +?? u8?? voltx:2???????????? // 0x11bc +?????????? setunk04:1 +?????????? keylok:1 +?????????? setunk07:1 +?????????? batsav:3; +?? u8?? setunk09:1?????? // 0x11bd +?????????? rxinhib:1 +?????????? rgrbeep:1?????? // inv bool +?????????? lampon:2 +?????????? voice:2 +?????????? beepon:1; +?? u8?? setunk11:1?????? // 0x11be +?????????? manualset:1 +?????????? xbandon:1???????? // inv +?????????? xbandenable:1 +?????????? openmsg:2 +?????????? ledclr:2; +?? u8?? tot:4???????????????? // 0x11bf +?????????? sql:4; +?? u8?? setunk27:1???? // 0x11c0 +?????????? voxdelay:2 +?????????? setunk28:1 +?????????? voxgain:4; +?? u8?? fmstep:4?????????? // 0x11c1 +?????????? freqstep:4; +?? u8?? scanspeed:4???? // 0x11c2 +?????????? scanmode:4; +?? u8?? scantmo;?????????? // 0x11c3 +?? u8?? prichan;?????????? // 0x11c4 +?? u8?? setunk12:4?????? // 0x11c5 +?????????? supersave:4; +?? u8?? setunk13; +?? u8?? fmsclo;???????????? // 0x11c7 ??? placeholder +?? u8?? radioname[7]; // hex char codes, not true ASCII +?? u8?? fmschi;???????????? // ??? placeholder +?? u8?? setunk14[3];?? // 0x11d0 +?? u8 setunk17[2];???? // 0x011d3, 4 +?? u8?? setunk18:4 +?????????? dtmfspd:4; +?? u8?? dtmfdig1dly:4 // 0x11d6 +?????????? dtmfdig1time:4; +?? u8?? stuntype:1 +?????????? setunk19:1 +?????????? dtmfspms:2 +?????????? grpcode:4; +?? u8?? setunk20:1?????? // 0x11d8 +?????????? txdecode:1 +?????????? codeabcd:1 +?????????? idedit:1 +?????????? pttidon:2 +?????????? setunk40:1, +?????????? dtmfside:1; +?? u8?? setunk50:4, +?????????? autoresettmo:4; +?? u8?? codespctim:4, // 0x11da +?????????? decodetmo:4; +?? u8?? pttecnt:4???????? // 0x11db +?????????? pttbcnt:4; +?? lbcd?? dtmfdecode[3]; +?? u8?? setunk22; +?? u8?? stuncnt;?????????? // 0x11e0 +?? u8?? stuncode[5]; +?? u8?? setunk60; +?? u8?? setunk61; +?? u8?? pttbot[8];?????? // 0x11e8-f +?? u8?? ptteot[8];?????? // 0x11f0-7 +?? u8?? setunk62;???????? // 0x11f8 +?? u8?? setunk63; +?? u8?? setunk64;???????? // 0x11fa +?? u8?? setunk65; +?? u8?? setunk66; +?? u8?? manfrqyn;???????? // 0x11fd +?? u8?? setunk27:3 +?????????? frqr3:1 +?????????? setunk28:1 +?????????? frqr2:1 +?????????? setunk29:1 +?????????? frqr1:1; +?? u8?? setunk25; +?? ul32 frqr1lo;?? // 0x1200 +?? ul32 frqr1hi; +?? ul32 frqr2lo; +?? ul32 frqr2hi; +?? ul32 frqr3lo;?? // 0x1210 +?? ul32 frqr3hi; +?? u8 setunk26[8]; +} setstuf;
+#seekto 0x1260; +struct { +?? ul16 year; +?? u8?? month; +?? u8?? day; +?? u8?? hour; +?? u8?? min; +?? u8?? sec; +} moddate;
+#seekto 0x1300; +struct { +?? char?? mod_num[9]; +} mod_id; +"""
+MEM_SIZE = 0x1300 +BLOCK_SIZE = 0x10???? # can read 0x20, but must write 0x10 +STIMEOUT = 2 +BAUDRATE = 4800 +# Channel power: 2 levels +POWER_LEVELS = [chirp_common.PowerLevel("Low", watts=5.00), +?????????????????????????????? chirp_common.PowerLevel("High", watts=10.00)]
+LIST_RECVMODE = ["QT/DQT", "QT/DQT + Signaling"] +LIST_COLOR = ["Off", "Orange", "Blue", "Purple"] +LIST_LEDSW = ["Auto", "On"] +LIST_TIMEOUT = ["Off"] + ["%s" % x for x in range(30, 390, 30)] +LIST_VFOMODE = ["Frequency Mode", "Channel Mode"] +# Tones are numeric, Defined in \chirp\chirp_common.py +TONES_CTCSS = sorted(chirp_common.TONES) +# Converted to strings +LIST_CTCSS = ["Off"] + [str(x) for x in TONES_CTCSS] +# Now append the DxxxN and DxxxI DTCS codes from chirp_common +for x in chirp_common.DTCS_CODES: +?????? LIST_CTCSS.append("D{:03d}N".format(x)) +for x in chirp_common.DTCS_CODES: +?????? LIST_CTCSS.append("D{:03d}R".format(x)) +LIST_BW = ["Narrow", "Wide"] +LIST_SHIFT = ["off", "+", "-"] +STEPS = [0.5, 2.5, 5.0, 6.25, 10.0, 12.5, 25.0, 37.5, 50.0, 100.0] +LIST_STEPS = [str(x) for x in STEPS] +LIST_VOXDLY = ["0.5", "1.0", "2.0", "3.0"]?????????? # LISTS must be strings +LIST_PTT = ["Both", "EoT", "BoT", "Off"]
+SETTING_LISTS = { +"tot": LIST_TIMEOUT, +"wtled": LIST_COLOR, +"rxled": LIST_COLOR, +"txled": LIST_COLOR, +"ledsw": LIST_LEDSW, +"frq_chn_mode": LIST_VFOMODE, +"rx_tone": LIST_CTCSS, +"tx_tone": LIST_CTCSS, +"rx_mode": LIST_RECVMODE, +"fm_bw": LIST_BW, +"shift": LIST_SHIFT, +"step": LIST_STEPS, +"vox_dly": LIST_VOXDLY, +"ptt": LIST_PTT +}
+def _clean_buffer(radio): +?????? radio.pipe.timeout = 0.005 +?????? junk = radio.pipe.read(256) +?????? radio.pipe.timeout = STIMEOUT +?????? if junk: +?????????????? Log.debug("Got %i bytes of junk before starting" % len(junk))
+def _rawrecv(radio, amount): +?????? """Raw read from the radio device""" +?????? data = "" +?????? try: +?????????????? data = radio.pipe.read(amount) +?????? except: +?????????????? _exit_program_mode(radio) +?????????????? msg = "Generic error reading data from radio; check your cable." +?????????????? raise errors.RadioError(msg)
+?????? if len(data) != amount: +?????????????? _exit_program_mode(radio) +?????????????? msg = "Error reading from radio: not the amount of data we want." +?????????????? raise errors.RadioError(msg)
+?????? return data
+def _rawsend(radio, data): +?????? """Raw send to the radio device""" +?????? try: +?????????????? radio.pipe.write(data) +?????? except: +?????????????? raise errors.RadioError("Error sending data to radio")
+def _make_frame(cmd, addr, length, data=""): +?????? """Pack the info in the headder format""" +?????? frame = struct.pack(">shB", cmd, addr, length) +?????? # Add the data if set +?????? if len(data) != 0: +?????????????? frame += data +?????? # Return the data +?????? return frame
+def _recv(radio, addr, length): +?????? """Get data from the radio """
+?????? data = _rawrecv(radio, length)
+?????? # DEBUG +?????? LOG.info("Response:") +?????? LOG.debug(util.hexprint(data))
+?????? return data
+def _do_ident(radio): +?????? """Put the radio in PROGRAM mode & identify it""" +?????? radio.pipe.baudrate = BAUDRATE +?????? radio.pipe.parity = "N" +?????? radio.pipe.timeout = STIMEOUT
+?????? # Flush input buffer +?????? _clean_buffer(radio)
+?????? magic = "PROGRAMa" +?????? _rawsend(radio, magic) +?????? ack = _rawrecv(radio, 1) +?????? # LOG.warning("PROGa Ack:" + util.hexprint(ack)) +?????? if ack != "\x06": +?????????????? _exit_program_mode(radio) +?????????????? if ack: +?????????????????????? LOG.debug(repr(ack)) +?????????????? raise errors.RadioError("Radio did not respond") +?????? magic = "PROGRAMb" +?????? _rawsend(radio, magic) +?????? ack = _rawrecv(radio, 1) +?????? if ack != "\x06": +?????????????? _exit_program_mode(radio) +?????????????? if ack: +?????????????????????? LOG.debug(repr(ack)) +?????????????? raise errors.RadioError("Radio did not respond to B") +?????? magic = chr(0x02) +?????? _rawsend(radio, magic) +?????? ack = _rawrecv(radio, 1)?????? # s/b: 0x50 +?????? magic = _rawrecv(radio, 7)?? # s/b TC88... +?????? magic = "MTC88CUMHS3E7BN-" +?????? _rawsend(radio, magic) +?????? ack = _rawrecv(radio, 1)?????? # s/b 0x80 +?????? magic = chr(0x06) +?????? _rawsend(radio, magic) +?????? ack = _rawrecv(radio, 1)
+?????? return True
+def _exit_program_mode(radio): +?????? endframe = "E" +?????? _rawsend(radio, endframe)
+def _download(radio): +?????? """Get the memory map"""
+?????? # Put radio in program mode and identify it +?????? _do_ident(radio)
+?????? # UI progress +?????? status = chirp_common.Status() +?????? status.cur = 0 +?????? status.max = MEM_SIZE / BLOCK_SIZE +?????? status.msg = "Cloning from radio..." +?????? radio.status_fn(status)
+?????? data = "" +?????? for addr in range(0, MEM_SIZE, BLOCK_SIZE): +?????????????? frame = _make_frame("R", addr, BLOCK_SIZE) +?????????????? # DEBUG +?????????????? LOG.info("Request sent:") +?????????????? LOG.debug("Frame=" + util.hexprint(frame))
+?????????????? # Sending the read request +?????????????? _rawsend(radio, frame) +?????????????? dx = _rawrecv(radio, 4)
+?????????????? # Now we read data +?????????????? d = _recv(radio, addr, BLOCK_SIZE) +?????????????? # LOG.warning("Data= " + util.hexprint(d))
+?????????????? # Aggregate the data +?????????????? data += d
+?????????????? # UI Update +?????????????? status.cur = addr / BLOCK_SIZE +?????????????? status.msg = "Cloning from radio..." +?????????????? radio.status_fn(status)
+?????? _exit_program_mode(radio) +?????? # Append the model number to the downloaded memory +?????? data += radio.MODEL.ljust(9)
+?????? return data
+def _upload(radio): +?????? """Upload procedure""" +?????? # Put radio in program mode and identify it +?????? _do_ident(radio)
+?????? # Generate upload time stamp; not used by Chirp +?????? dnow = datetime.now() +?????? _mem = radio._memobj.moddate +?????? _mem.year = dnow.year +?????? _mem.month = dnow.month +?????? _mem.day = dnow.day +?????? _mem.hour = dnow.hour +?????? _mem.min = dnow.minute +?????? _mem.sec = dnow.second
+?????? # UI progress +?????? status = chirp_common.Status() +?????? status.cur = 0 +?????? status.max = MEM_SIZE / BLOCK_SIZE +?????? status.msg = "Cloning to radio..." +?????? radio.status_fn(status)
+?????? # The fun starts here +?????? for addr in range(0, MEM_SIZE, BLOCK_SIZE): +?????????????? # Sending the data +?????????????? data = radio.get_mmap()[addr:addr + BLOCK_SIZE]
+?????????????? frame = _make_frame("W", addr, BLOCK_SIZE, data) +?????????????? # LOG.warning("Frame:%s:" % util.hexprint(frame)) +?????????????? _rawsend(radio, frame)
+?????????????? # Receiving the response +?????????????? ack = _rawrecv(radio, 1) +?????????????? if ack != "\x06": +?????????????????????? _exit_program_mode(radio) +?????????????????????? msg = "Bad ack writing block 0x%04x" % addr +?????????????????????? raise errors.RadioError(msg)
+?????????????? # UI Update +?????????????? status.cur = addr / BLOCK_SIZE +?????????????? status.msg = "Cloning to radio..." +?????????????? radio.status_fn(status)
+?????? _exit_program_mode(radio)
+def force_odd(fmfrq): +?????? """Force FM Broadcast Frequency to have odd KHz """ +?????? oddfrq = int(fmfrq / 100000)?????? # remove 10Khz and lower +?????? if (oddfrq % 2) == 0:?????? # increment to odd +?????????????? oddfrq += 1 +?????? return (oddfrq * 100000)
+def set_tone(_mem, txrx, ctdt, tval, pol): +?????? """Set rxtone[] or txtone[] word values as decimal bytes""" +?????? # txrx: Boolean T= set Rx tones, F= set Tx tones +?????? # ctdt: Boolean T = CTCSS, F= DTCS +?????? # tval = integer tone freq (*10) or DTCS code +?????? # pol = string for DTCS polarity "R" or "N" +?????? xv = int(str(tval), 16) +?????? if txrx:?????????????? # True = set rxtones +?????????????? _mem.rxtone[0] = xv & 0xFF?? # Low byte +?????????????? _mem.rxtone[1] = (xv >> 8)???? # Hi byte +?????????????? if not ctdt:?????? # dtcs, +?????????????????????? if pol == "R": +?????????????????????????????? _mem.rxtone[1] = _mem.rxtone[1] | 0xC0 +?????????????????????? else: +?????????????????????????????? _mem.rxtone[1] = _mem.rxtone[1] | 0x80 +?????? else:???????????????????? # txtones +?????????????? _mem.txtone[0] = xv & 0xFF?? # Low byte +?????????????? _mem.txtone[1] = (xv >> 8) +?????????????? if not ctdt:?????? # dtcs +?????????????????????? if pol == "R": +?????????????????????????????? _mem.txtone[1] = _mem.txtone[1] | 0xC0 +?????????????????????? else: +?????????????????????????????? _mem.txtone[1] = _mem.txtone[1] | 0x80
+?????? return 0
+def model_match(cls, data): +?????? """Match the opened/downloaded image to the correct version""" +?????? if len(data) == 0x1307: +?????????????? rid = data[0x1300:0x1309] +?????????????? return rid.startswith(cls.MODEL) +?????? else: +?????????????? return False
+def _do_map(chn, sclr, mary): +?????? """Set or Clear the chn (1-128) bit in mary[] word array map""" +?????? # chn is 1-based channel, sclr:1 = set, 0= = clear, 2= return state +?????? # mary[] is u8 array, but the map is by nibbles +?????? ndx = int(math.floor((chn - 1) / 8)) +?????? bv = (chn -1) % 8 +?????? msk = 1 << bv +?????? mapbit = sclr +?????? if sclr == 1:?????? # Set the bit +?????????????? mary[ndx] = mary[ndx] | msk +?????? elif sclr == 0:?? # clear +?????????????? mary[ndx] = mary[ndx] & (~ msk)???????? # ~ is complement +?????? else:???????????? # return current bit state +?????????????? mapbit = 0 +?????????????? if (mary[ndx] & msk) > 0: mapbit = 1 +?????? # LOG.warning("-?? Do_Map chn %d, sclr= %d, ndx= %d" % (chn, sclr, ndx)) +?????? # LOG.warning("-?? bv= %d, msk = %02x, mapbit= %d" % (bv, msk, mapbit)) +?????? # LOG.warning("-?? mary[%d] = %02x" % (ndx, mary[ndx])) +?????? return mapbit
+@directory.register +class tyt_uv8000d(chirp_common.CloneModeRadio): +?????? """TYT UV8000D Radio""" +?????? VENDOR = "TYT" +?????? MODEL = "TH-UV8000" +?????? MODES = ["NFM", "FM"] +?????? TONES = chirp_common.TONES +?????? DTCS_CODES = sorted(chirp_common.DTCS_CODES + [645]) +?????? NAME_LENGTH = 7 +?????? DTMF_CHARS = list("0123456789ABCD*#") +?????? # NOTE: SE Model supports 220-260 MHz +?????? # The following bands are the the range the radio is capable of, +?????? #???? not the legal FCC amateur bands +?????? VALID_BANDS = [(87500000, 107900000), (136000000, 174000000), +???????????????????????????????????? (220000000, 260000000), (400000000, 520000000)]
+?????? # Valid chars on the LCD +?????? VALID_CHARS = chirp_common.CHARSET_ALPHANUMERIC + \ +???????????????????? "`!"#$%&'()*+,-./:;<=>?@[]^_"
+?????? # Special Channels Declaration +?????? # WARNING Indecis are hard wired in get/set_memory code !!! +?????? # Channels print in + increasing index order (most negative first) +?????? SPECIAL_MEMORIES = { +???????????? "FM 25": -3, +???????????? "FM 24": -4, +???????????? "FM 23": -5, +???????????? "FM 22": -6, +???????????? "FM 21": -7, +???????????? "FM 20": -8, +???????????? "FM 19": -9, +???????????? "FM 18": -10, +???????????? "FM 17": -11, +???????????? "FM 16": -12, +???????????? "FM 15": -13, +???????????? "FM 14": -14, +???????????? "FM 13": -15, +???????????? "FM 12": -16, +???????????? "FM 11": -17, +???????????? "FM 10": -18, +???????????? "FM 09": -19, +???????????? "FM 08": -20, +???????????? "FM 07": -21, +???????????? "FM 06": -22, +???????????? "FM 05": -23, +???????????? "FM 04": -24, +???????????? "FM 03": -25, +???????????? "FM 02": -26, +???????????? "FM 01": -27 +?????? } +?????? FIRST_FM_INDEX = -3 +?????? LAST_FM_INDEX = -27
+?????? SPECIAL_FREQ = { +???????????? "UpVFO": -2, +???????????? "LoVFO": -1 +?????? } +?????? FIRST_FREQ_INDEX = -1 +?????? LAST_FREQ_INDEX = -2 +?????? SPECIAL_MEMORIES.update(SPECIAL_FREQ)
+?????? SPECIAL_MEMORIES_REV = dict(zip(SPECIAL_MEMORIES.values(), +?????????????????????????????????????????????????????????????????????? SPECIAL_MEMORIES.keys()))
+?????? @classmethod +?????? def get_prompts(cls): +?????????????? rp = chirp_common.RadioPrompts() +?????????????? rp.info = \ +?????????????????????? ('NOTE 1: Some of these radios come shipped with the frequency ' +???????????????????????? 'ranges locked to comply with FCC band limitations.\n' +???????????????????????? 'This driver allows the user to program frequencies outside ' +???????????????????????? 'the legal amateur bands, so that they can receive on marine, ' +???????????????????????? 'aviation, FRS/GMRS and NOAA weather bands.\n' +???????????????????????? 'If these frequencies are locked out on your radio, ' +???????????????????????? 'you will receive an error beep when attempting to operate.\n' +???????????????????????? 'It is the users responsibility to only transmit on ' +???????????????????????? 'authorized freqencies. \n\n' +???????????????????????? 'NOTE 2: Click on the "Special Channels" tab of the layout ' +???????????????????????? 'screen to see/set the upper and lower frequency-mode values, ' +???????????????????????? 'as well as the 25 FM broadcast radio station channels.\n\n' +???????????????????????? 'NOTE 3: The PTT ID codes are 1-16 characters of DTMF (0-9, ' +???????????????????????? 'A-D,*,#). The per-channel ANI Id Codes are not implemented at ' +???????????????????????? 'this time. However they may be set manually by using the ' +???????????????????????? 'Browser developer tool. Contact Rick at AA0RD@Yahoo.com.\n\n' +???????????????????????? 'NOTE 4: To access the stored FM broadcast stations: activate ' +???????????????????????? 'FM mode (F, MONI), then # and up/down.' +?????????????????????? )
+?????????????? rp.pre_download = _(dedent("""\ +?????????????????????? Follow these instructions to download your config:
+?????????????????????? 1 - Turn off your radio +?????????????????????? 2 - Connect your interface cable +?????????????????????? 3 - Turn on your radio, volume @ 50% +?????????????????????? 4 - Radio > Download from radio +?????????????????????? """)) +?????????????? rp.pre_upload = _(dedent("""\ +?????????????????????? Follow this instructions to upload your config:
+?????????????????????? 1 - Turn off your radio +?????????????????????? 2 - Connect your interface cable +?????????????????????? 3 - Turn on your radio, volume @ 50% +?????????????????????? 4 - Radio > Upload to radio +?????????????????????? """)) +?????????????? return rp
+?????? def get_features(self): +?????????????? rf = chirp_common.RadioFeatures() +?????????????? # .has. attributes are boolean, .valid. are lists +?????????????? rf.has_settings = True +?????????????? rf.has_bank = False +?????????????? rf.has_comment = False +?????????????? rf.has_tuning_step = False?? # Not as chan feature +?????????????? rf.can_odd_split = False +?????????????? rf.has_name = True +?????????????? rf.has_offset = True +?????????????? rf.has_mode = True +?????????????? rf.has_dtcs = True +?????????????? rf.has_rx_dtcs = True +?????????????? rf.has_dtcs_polarity = True +?????????????? rf.has_ctone = True +?????????????? rf.has_cross = True +?????????????? rf.has_sub_devices = False +?????????????? rf.valid_name_length = self.NAME_LENGTH +?????????????? rf.valid_modes = self.MODES +?????????????? rf.valid_characters = self.VALID_CHARS +?????????????? rf.valid_duplexes = ["-", "+", "off", ""] +?????????????? rf.valid_tmodes = ['', 'Tone', 'TSQL', 'DTCS', 'Cross'] +?????????????? rf.valid_cross_modes = [ +?????????????????????? "Tone->Tone", +?????????????????????? "DTCS->", +?????????????????????? "->DTCS", +?????????????????????? "Tone->DTCS", +?????????????????????? "DTCS->Tone", +?????????????????????? "->Tone", +?????????????????????? "DTCS->DTCS"] +?????????????? rf.valid_skips = [] +?????????????? rf.valid_power_levels = POWER_LEVELS +?????????????? rf.valid_dtcs_codes = self.DTCS_CODES +?????????????? rf.valid_bands = self.VALID_BANDS +?????????????? rf.memory_bounds = (1, 128) +?????????????? rf.valid_skips = ["", "S"] +?????????????? rf.valid_special_chans = sorted(self.SPECIAL_MEMORIES.keys()) +?????????????? return rf
+?????? def sync_in(self): +?????????????? """Download from radio""" +?????????????? try: +?????????????????????? data = _download(self) +?????????????? except errors.RadioError: +?????????????????????? # Pass through any real errors we raise +?????????????????????? raise +?????????????? except: +?????????????????????? # If anything unexpected happens, make sure we raise +?????????????????????? # a RadioError and log the problem +?????????????????????? LOG.exception('Unexpected error during download') +?????????????????????? raise errors.RadioError('Unexpected error communicating ' +?????????????????????????????????????????????????????????????????????? 'with the radio') +?????????????? self._mmap = memmap.MemoryMap(data) +?????????????? self.process_mmap()
+?????? def sync_out(self): +?????????????? """Upload to radio"""
+?????????????? try: +?????????????????????? _upload(self) +?????????????? except: +?????????????????????? # If anything unexpected happens, make sure we raise +?????????????????????? # a RadioError and log the problem +?????????????????????? LOG.exception('Unexpected error during upload') +?????????????????????? raise errors.RadioError('Unexpected error communicating ' +?????????????????????????????????????????????????????????????????????? 'with the radio')
+?????? def process_mmap(self): +?????????????? """Process the mem map into the mem object""" +?????????????? self._memobj = bitwise.parse(MEM_FORMAT, self._mmap)
+?????? def get_raw_memory(self, number): +?????????????? return repr(self._memobj.memory[number - 1])
+?????? def get_memory(self, number): +?????????????? if isinstance(number, str): +?????????????????????? return self._get_special(number) +?????????????? elif number < 0: +?????????????????????? # I can't stop delete operation from loosing extd_number but +?????????????????????? # I know how to get it back +?????????????????????? return self._get_special(self.SPECIAL_MEMORIES_REV[number]) +?????????????? else: +?????????????????????? return self._get_normal(number)
+?????? def set_memory(self, memory): +?????????????? """A value in a UI column for chan 'number' has been modified.""" +?????????????? # update all raw channel memory values (_mem) from UI (mem) +?????????????? if memory.number < 0: +?????????????????????? return self._set_special(memory) +?????????????? else: +?????????????????????? return self._set_normal(memory)
+?????? def _get_fm_memory(self, mem, _mem): +?????????????? mem.name = "----" +?????????????? rx = self._memobj.fm_stations[mem.number + 2].rxfreq +?????????????? if rx == 0xFFFF: +?????????????????????? mem.empty = True +?????????????????????? return mem +?????????????? else: +?????????????????????? mem.freq = (float(int(rx)) / 40) * 1000000 +?????????????????????? mem.empty = False
+?????????????? mem.offset = 0.0 +?????????????? mem.power = 0 +?????????????? mem.duplex = "off"?????????? # inhibits tx +?????????????? mem.mode = self.MODES[1] +?????????????? dtcs_pol = ["N", "N"] +?????????????? mem.ctone = 88.5 +?????????????? mem.rtone = 88.5 +?????????????? mem.tmode = "" +?????????????? mem.cross_mode = "Tone->Tone" +?????????????? mem.skip = "" +?????????????? mem.comment = ""
+?????????????? return mem
+?????? def _get_normal(self, number): +?????????????? # radio first channel is 1, mem map is base 0 +?????????????? _mem = self._memobj.chan_mem[number - 1] +?????????????? mem = chirp_common.Memory() +?????????????? mem.number = number
+?????????????? return self._get_memory(mem, _mem)
+?????? def _get_memory(self, mem, _mem): +?????????????? """Convert raw channel memory data into UI columns""" +?????????????? mem.extra = RadioSettingGroup("extra", "Extra")
+?????????????? if _mem.get_raw()[0] == "\xff": +?????????????????????? mem.empty = True +?????????????????????? return mem
+?????????????? mem.empty = False +?????????????? # This function process both 'normal' and Freq up/down' entries +?????????????? mem.freq = int(_mem.rxfreq) * 10 +?????????????? mem.power = POWER_LEVELS[_mem.power] +?????????????? mem.mode = self.MODES[_mem.wide] +?????????????? dtcs_pol = ["N", "N"]
+?????????????? if _mem.rxtone[0] == 0xFF: +?????????????????????? rxmode = "" +?????????????? elif _mem.rxtone[1] < 0x26: +?????????????????????? # CTCSS +?????????????????????? rxmode = "Tone" +?????????????????????? tonehi = int(str(_mem.rxtone[1])[2:]) +?????????????????????? tonelo = int(str(_mem.rxtone[0])[2:]) +?????????????????????? mem.ctone = int(tonehi * 100 + tonelo) / 10.0 +?????????????? else: +?????????????????????? # Digital +?????????????????????? rxmode = "DTCS" +?????????????????????? tonehi = int(str(_mem.rxtone[1] & 0x3f)) +?????????????????????? tonelo = int(str(_mem.rxtone[0])[2:]) +?????????????????????? mem.rx_dtcs = int(tonehi * 100 + tonelo) +?????????????????????? if (_mem.rxtone[1] & 0x40) != 0: +?????????????????????????????? dtcs_pol[1] = "R"
+?????????????? if _mem.txtone[0] == 0xFF: +?????????????????????? txmode = "" +?????????????? elif _mem.txtone[1] < 0x26: +?????????????????????? # CTCSS +?????????????????????? txmode = "Tone" +?????????????????????? tonehi = int(str(_mem.txtone[1])[2:]) +?????????????????????? tonelo = int(str(_mem.txtone[0])[2:]) +?????????????????????? mem.rtone = int(tonehi * 100 + tonelo) / 10.0 +?????????????? else: +?????????????????????? # Digital +?????????????????????? txmode = "DTCS" +?????????????????????? tonehi = int(str(_mem.txtone[1] & 0x3f)) +?????????????????????? tonelo = int(str(_mem.txtone[0])[2:]) +?????????????????????? mem.dtcs = int(tonehi * 100 + tonelo) +?????????????????????? if (_mem.txtone[1] & 0x40) != 0: +?????????????????????????????? dtcs_pol[0] = "R"
+?????????????? mem.tmode = "" +?????????????? if txmode == "Tone" and not rxmode: +?????????????????????? mem.tmode = "Tone" +?????????????? elif txmode == rxmode and txmode == "Tone" and mem.rtone == mem.ctone: +?????????????????????? mem.tmode = "TSQL" +?????????????? elif txmode == rxmode and txmode == "DTCS" and mem.dtcs == mem.rx_dtcs: +?????????????????????? mem.tmode = "DTCS" +?????????????? elif rxmode or txmode: +?????????????????????? mem.tmode = "Cross" +?????????????????????? mem.cross_mode = "%s->%s" % (txmode, rxmode)
+?????????????? mem.dtcs_polarity = "".join(dtcs_pol)
+?????????????? # Now test the mem.number to process special vs normal +?????????????? if mem.number >=0:?????????? # Normal +?????????????????????? mem.name = "" +?????????????????????? for i in range(self.NAME_LENGTH):???? # 0 - 6 +?????????????????????????????? mem.name += chr(_mem.name[i] + 32) +?????????????????????? mem.name = mem.name.rstrip()?????? # remove trailing spaces
+?????????????????????? if _mem.txfreq == 0xFFFFFFFF: +?????????????????????????????? # TX freq not set +?????????????????????????????? mem.duplex = "off" +?????????????????????????????? mem.offset = 0 +?????????????????????? elif int(_mem.rxfreq) == int(_mem.txfreq): +?????????????????????????????? mem.duplex = "" +?????????????????????????????? mem.offset = 0 +?????????????????????? else: +?????????????????????????????? mem.duplex = int(_mem.rxfreq) > int(_mem.txfreq) and "-" or "+" +?????????????????????????????? mem.offset = abs(int(_mem.rxfreq) - int(_mem.txfreq)) * 10
+?????????????????????? if _do_map(mem.number, 2, self._memobj.skpchns.map) > 0: +?????????????????????????????? mem.skip = "S" +?????????????????????? else: +?????????????????????????????? mem.skip = ""
+?????????????? else:???????????? # specials VFO +?????????????????????? mem.name = "----" +?????????????????????? mem.duplex = LIST_SHIFT[_mem.duplx] +?????????????????????? mem.offset = int(_mem.ofst) * 10 +?????????????????????? mem.skip = "" +?????????????? # End if specials
+?????????????? # Channel Extra settings: Only Boolean & List methods, no call-backs +?????????????? rx = RadioSettingValueBoolean(bool(not _mem.bcl))???? # Inverted bool +?????????????? # NOTE: first param of RadioSetting is the object attribute name +?????????????? rset = RadioSetting("bcl", "Busy Channel Lockout", rx) +?????????????? mem.extra.append(rset)
+?????????????? rx = RadioSettingValueBoolean(bool(not _mem.vox_on)) +?????????????? rset = RadioSetting("vox_on", "Vox", rx) +?????????????? mem.extra.append(rset)
+?????????????? rx = RadioSettingValueBoolean(bool(not _mem.ani)) +?????????????? rset = RadioSetting("ani", "Auto Number ID (ANI)", rx) +?????????????? mem.extra.append(rset)
+?????????????? # ID code can't be done in extra - no Integer method or call-back
+?????????????? rx = RadioSettingValueList(LIST_PTT, LIST_PTT[_mem.ptt]) +?????????????? rset = RadioSetting("ptt", "Xmit PTT ID", rx) +?????????????? mem.extra.append(rset)
+?????????????? rx = RadioSettingValueBoolean(bool(_mem.epilogue)) +?????????????? rset = RadioSetting("epilogue", "Epilogue/Tail", rx) +?????????????? mem.extra.append(rset)
+?????????????? return mem
+?????? def _get_special(self, number): +?????????????? mem = chirp_common.Memory() +?????????????? mem.number = self.SPECIAL_MEMORIES[number] +?????????????? mem.extd_number = number +?????????????? # Unused attributes are ignored in Set_memory +?????????????? if (mem.number == -1) or (mem.number == -2): +?????????????????????? # Print Upper[1] first, and Lower[0] next +?????????????????????? rx = 0 +?????????????????????? if mem.number == -2: +?????????????????????????????? rx = 1 +?????????????????????? _mem = self._memobj.frq[rx] +?????????????????????? # immutable = ["number", "extd_number", "name"] +?????????????????????? mem = self._get_memory(mem, _mem) +?????????????? elif mem.number in range(self.FIRST_FM_INDEX, +?????????????????????????????????????? self.LAST_FM_INDEX - 1, -1): +?????????????????????? _mem = self._memobj.fm_stations[-self.LAST_FM_INDEX + mem.number] +?????????????????????? # immutable = ["number", "extd_number", "name", "power", "ctone", +?????????????????????? #?????????????????????? "rtone", "skip", "duplex", "offset", "mode"] +?????????????????????? mem = self._get_fm_memory(mem, _mem)?????????????? # special fnctn +?????????????? else: +?????????????????????? raise Exception("Sorry, you can't edit that special" +???????????????????????????????????? " memory channel %i." % mem.number)
+?????????????? # mem.immutable = immutable
+?????????????? return mem
+?????? def _set_memory(self, mem, _mem): +?????????????? """Convert UI column data (mem) into MEM_FORMAT memory (_mem).""" +?????????????? # At this point mem points to either normal, fm or Freq chans +?????????????? # These first attributes are common to all types +?????????????? if mem.empty: +?????????????????????? if mem.number > 0: +?????????????????????????????? _mem.rxfreq = 0xffffffff +?????????????????????????????? # Set 'empty' and 'skip' bits +?????????????????????????????? _do_map(mem.number, 1, self._memobj.chnmap.map) +?????????????????????????????? _do_map(mem.number, 1, self._memobj.skpchns.map) +?????????????????????? elif mem.number == -2:?? #?? upper VFO Freq +?????????????????????????????? _mem.rxfreq = 14652000???? # VHF National Calling freq +?????????????????????? elif mem.number == -1:?? #?? lower VFO +?????????????????????????????? _mem.rxfreq = 44600000???? # UHF National Calling freq +?????????????????????? else:???????????? # FM stations, mem.number -3 to -27 +?????????????????????????????? _mem.rxfreq = 0xffff +?????????????????????????????? _do_map(mem.number + 28, 1, self._memobj.fmmap.fmset) +?????????????????????? return
+?????????????? _mem.rxfreq = mem.freq / 10
+?????????????? if mem.number < -2:???????? # FM stations, only rxfreq +?????????????????????? _mem.rxfreq = (force_odd(mem.freq) * 40) / 1000000 +?????????????????????? _do_map(mem.number + 28, 0, self._memobj.fmmap.fmset) +?????????????????????? return
+?????????????? if str(mem.power) == "Low": +?????????????????????? _mem.power = 0 +?????????????? else: +?????????????????????? _mem.power = 1
+?????????????? _mem.wide = self.MODES.index(mem.mode)
+?????????????? rxmode = "" +?????????????? txmode = ""
+?????????????? if mem.tmode == "Tone": +?????????????????????? txmode = "Tone" +?????????????? elif mem.tmode == "TSQL": +?????????????????????? rxmode = "Tone" +?????????????????????? txmode = "TSQL" +?????????????? elif mem.tmode == "DTCS": +?????????????????????? rxmode = "DTCSSQL" +?????????????????????? txmode = "DTCS" +?????????????? elif mem.tmode == "Cross": +?????????????????????? txmode, rxmode = mem.cross_mode.split("->", 1)
+?????????????? sx = mem.dtcs_polarity[1] +?????????????? if rxmode == "": +?????????????????????? _mem.rxtone[0] = 0xFF +?????????????????????? _mem.rxtone[1] = 0xFF +?????????????? elif rxmode == "Tone": +?????????????????????? val = int(mem.ctone * 10) +?????????????????????? i = set_tone(_mem, True, True, val, sx) +?????????????? elif rxmode == "DTCSSQL": +?????????????????????? i = set_tone(_mem, True, False, mem.dtcs, sx) +?????????????? elif rxmode == "DTCS": +?????????????????????? i = set_tone(_mem, True, False, mem.rx_dtcs, sx)
+?????????????? sx = mem.dtcs_polarity[0] +?????????????? if txmode == "": +?????????????????????? _mem.txtone[0] = 0xFF +?????????????????????? _mem.txtone[1] = 0xFF +?????????????? elif txmode == "Tone": +?????????????????????? val = int(mem.rtone * 10) +?????????????????????? i = set_tone(_mem, False, True, val, sx) +?????????????? elif txmode == "TSQL": +?????????????????????? val = int(mem.ctone * 10) +?????????????????????? i = set_tone(_mem, False, True, val, sx) +?????????????? elif txmode == "DTCS": +?????????????????????? i = set_tone(_mem, False, False, mem.dtcs, sx)
+?????????????? if mem.number > 0:?????????? # Normal chans +?????????????????????? for i in range(self.NAME_LENGTH): +?????????????????????????????? pq = ord(mem.name.ljust(self.NAME_LENGTH)[i]) -32 +?????????????????????????????? if pq < 0: pq = 0 +?????????????????????????????? _mem.name[i] = pq
+?????????????????????? if mem.duplex == "off": +?????????????????????????????? _mem.txfreq = 0xFFFFFFFF +?????????????????????? elif mem.duplex == "+": +?????????????????????????????? _mem.txfreq = (mem.freq + mem.offset) / 10 +?????????????????????? elif mem.duplex == "-": +?????????????????????????????? _mem.txfreq = (mem.freq - mem.offset) / 10 +?????????????????????? else: +?????????????????????????????? _mem.txfreq = mem.freq / 10
+?????????????????????? # Set the channel map bit FALSE = Enabled +?????????????????????? _do_map(mem.number, 0, self._memobj.chnmap.map) +?????????????????????? # Skip +?????????????????????? if mem.skip == "S": +?????????????????????????????? _do_map(mem.number, 1, self._memobj.skpchns.map) +?????????????????????? else: +?????????????????????????????? _do_map(mem.number, 0, self._memobj.skpchns.map)
+?????????????? else:?????? # Freq (VFO) chans +?????????????????????? _mem.duplx = 0 +?????????????????????? _mem.ofst = 0 +?????????????????????? if mem.duplex == "+": +?????????????????????????????? _mem.duplx = 1 +?????????????????????????????? _mem.ofst = mem.offset / 10 +?????????????????????? elif mem.duplex == "-": +?????????????????????????????? _mem.duplx = 2 +?????????????????????????????? _mem.ofst = mem.offset / 10 +?????????????????????? for i in range(self.NAME_LENGTH): +?????????????????????????????? _mem.name[i] = 0xff
+?????????????? # All mem.extra << Once the channel is defined +?????????????? for setting in mem.extra: +?????????????????????? # Overide list strings with signed value +?????????????????????? if setting.get_name() == "ptt": +?????????????????????????????? sx = str(setting.value) +?????????????????????????????? for i in range(0, 4): +?????????????????????????????????????? if sx == LIST_PTT[i]: +?????????????????????????????????????????????? val = i +?????????????????????????????? setattr(_mem, "ptt", val) +?????????????????????? elif setting.get_name() == "epilogue":?? # not inverted bool +?????????????????????????????????????? setattr(_mem, setting.get_name(), setting.value) +?????????????????????? else:???????????? # inverted booleans +?????????????????????????????? setattr(_mem, setting.get_name(), not setting.value)
+?????? def _set_special(self, mem):
+?????????????? cur_mem = self._get_special(self.SPECIAL_MEMORIES_REV[mem.number])
+?????????????? if mem.number == -2:?????? # upper frq[1] +?????????????????????? _mem = self._memobj.frq[1] +?????????????? elif mem.number == -1:?? # lower frq[0] +?????????????????????? _mem = self._memobj.frq[0] +?????????????? elif mem.number in range(self.FIRST_FM_INDEX, +?????????????????????????????????????? self.LAST_FM_INDEX - 1, -1): +?????????????????????? _mem = self._memobj.fm_stations[-self.LAST_FM_INDEX + mem.number] +?????????????? else: +?????????????????????? raise Exception("Sorry, you can't edit that special memory.")
+?????????????? self._set_memory(mem, _mem)???????? # Now update the _mem
+?????? def _set_normal(self, mem): +?????????????? _mem = self._memobj.chan_mem[mem.number - 1]
+?????????????? self._set_memory(mem, _mem)
+?????? def get_settings(self): +?????????????? """Translate the MEM_FORMAT structs into setstuf in the UI""" +?????????????? # Define mem struct write-back shortcuts +?????????????? _sets = self._memobj.setstuf +?????????????? _fmx = self._memobj.fmfrqs
+?????????????? basic = RadioSettingGroup("basic", "Basic Settings") +?????????????? adv = RadioSettingGroup("adv", "Other Settings") +?????????????? fmb = RadioSettingGroup("fmb", "FM Broadcast") +?????????????? scn = RadioSettingGroup("scn", "Scan Settings") +?????????????? dtmf = RadioSettingGroup("dtmf", "DTMF Settings") +?????????????? frng = RadioSettingGroup("frng", "Frequency Ranges") +?????????????? group = RadioSettings(basic, adv, scn, fmb, dtmf, frng)
+?????????????? def my_val_list(setting, obj, atrb): +?????????????????????? """Callback:from ValueList with non-sequential, actual values.""" +?????????????????????? # This call back also used in get_settings +?????????????????????? value = int(str(setting.value)) # Get the integer value +?????????????????????? setattr(obj, atrb, value) +?????????????????????? return
+?????????????? def my_adjraw(setting, obj, atrb, fix): +?????????????????????? """Callback from Integer add or subtract fix from value.""" +?????????????????????? vx = int(str(setting.value)) +?????????????????????? value = vx?? + int(fix) +?????????????????????? if value < 0: +?????????????????????????????? value = 0 +?????????????????????? setattr(obj, atrb, value) +?????????????????????? return
+?????????????? def my_strnam(setting, obj, atrb, mln): +?????????????????????? """Callback from String to build u8 array with -32 offset.""" +?????????????????????? # mln is max string length +?????????????????????? ary = [] +?????????????????????? knt = mln +?????????????????????? for j in range (mln - 1, -1, -1):?? # Strip trailing spaces or nulls +?????????????????????????????? pq = str(setting.value)[j] +?????????????????????????????? if pq == "" or pq == " ": +?????????????????????????????????????? knt = knt - 1 +?????????????????????????????? else: +?????????????????????????????????????? break +?????????????????????? for j in range(mln):?? # 0 to mln-1 +?????????????????????????????? pq = str(setting.value).ljust(mln)[j] +?????????????????????????????? if j < knt: ary.append(ord(pq) - 32) +?????????????????????????????? else: ary.append(0) +?????????????????????? setattr(obj, atrb, ary) +?????????????????????? return
+?????????????? def unpack_str(cary, cknt, mxw): +?????????????????????? """Convert u8 nibble array to a string: NOT a callback.""" +?????????????????????? # cknt is char count, 2/word; mxw is max WORDS +?????????????????????? stx = "" +?????????????????????? mty = True +?????????????????????? for i in range(mxw):?????? # unpack entire array +?????????????????????????????? nib = (cary[i] & 0xf0) >> 4?? # LE, Hi nib first +?????????????????????????????? if nib != 0xf: mty = False +?????????????????????????????? stx += format(nib, '0X') +?????????????????????????????? nib = cary[i] & 0xf +?????????????????????????????? if nib != 0xf: mty = False +?????????????????????????????? stx += format(nib, '0X') +?????????????????????? stx = stx[:cknt] +?????????????????????? if mty:???????? # all ff, empty string +?????????????????????????????? sty = "" +?????????????????????? else: +?????????????????????????????? # Convert E to #, F to * +?????????????????????????????? sty = "" +?????????????????????????????? for i in range(cknt): +?????????????????????????????????????? if stx[i] == "E": +?????????????????????????????????????????????? sty += "#" +?????????????????????????????????????? elif stx[i] == "F": +?????????????????????????????????????????????? sty += "*" +?????????????????????????????????????? else: +?????????????????????????????????????????????? sty += stx[i]
+?????????????????????? return sty
+?????????????? def pack_chars(setting, obj, atrstr, atrcnt, mxl): +?????????????????????? """Callback to build 0-9,A-D,*# nibble array from string""" +?????????????????????? # cknt is generated char count, 2 chars per word +?????????????????????? # String will be f padded to mxl +?????????????????????? # Chars are stored as hex values +?????????????????????? # store cknt-1 in atrcnt, 0xf if empty +?????????????????????? cknt = 0 +?????????????????????? ary = [] +?????????????????????? stx = str(setting.value).upper() +?????????????????????? stx = stx.strip()???????????? # trim spaces +?????????????????????? # Remove illegal characters first +?????????????????????? sty = "" +?????????????????????? for j in range(0, len(stx)): +?????????????????????????????? if stx[j] in self.DTMF_CHARS: sty += stx[j] +?????????????????????? for j in range(mxl): +?????????????????????????????? if j < len(sty): +?????????????????????????????????????? if sty[j] == "#": +?????????????????????????????????????????????? chrv = 0xE +?????????????????????????????????????? elif sty[j] == "*": +?????????????????????????????????????????????? chrv = 0xF +?????????????????????????????????????? else: +?????????????????????????????????????????????? chrv = int(sty[j], 16) +?????????????????????????????????????? cknt += 1?????????? # char count +?????????????????????????????? else:???? # pad to mxl, cknt does not increment +?????????????????????????????????????? chrv = 0xF +?????????????????????????????? if (j % 2) == 0:?? # odd count (0-based), high nibble +?????????????????????????????????????? hi_nib = chrv +?????????????????????????????? else:???? # even count, lower nibble +?????????????????????????????????????? lo_nib = chrv +?????????????????????????????????????? nibs = lo_nib | (hi_nib << 4) +?????????????????????????????????????? ary.append(nibs)?????? # append word +?????????????????????? setattr(obj, atrstr, ary) +?????????????????????? if setting.get_name() != "setstuf.stuncode":?? # cknt is actual +?????????????????????????????? if cknt > 0: +?????????????????????????????????????? cknt = cknt - 1 +?????????????????????????????? else: +?????????????????????????????????????? cknt = 0xf +?????????????????????? setattr(obj, atrcnt, cknt) +?????????????????????? return
+?????????????? def myset_freq(setting, obj, atrb, mult): +?????????????????????? """ Callback to set frequency by applying multiplier""" +?????????????????????? value = int(float(str(setting.value)) * mult) +?????????????????????? setattr(obj, atrb, value) +?????????????????????? return
+?????????????? def my_invbool(setting, obj, atrb): +?????????????????????? """Callback to invert the boolean """ +?????????????????????? bval = not setting.value +?????????????????????? setattr(obj, atrb, bval) +?????????????????????? return
+?????????????? def my_batsav(setting, obj, atrb): +?????????????????????? """Callback to set batsav attribute """ +?????????????????????? stx = str(setting.value)?? # Off, 1:1... +?????????????????????? if stx == "Off": +?????????????????????????????? value = 0x1???????? # bit value 4 clear, ratio 1 = 1:2 +?????????????????????? elif stx == "1:1": +?????????????????????????????? value = 0x4???????? # On, ratio 0 = 1:1 +?????????????????????? elif stx == "1:2": +?????????????????????????????? value = 0x5???????? # On, ratio 1 = 1:2 +?????????????????????? elif stx == "1:3": +?????????????????????????????? value = 0x6???????? # On, ratio 2 = 1:3 +?????????????????????? else: +?????????????????????????????? value = 0x7???????? # On, ratio 3 = 1:4 +?????????????????????? # LOG.warning("Batsav stx:%s:, value= %x" % (stx, value)) +?????????????????????? setattr(obj, atrb, value) +?????????????????????? return
+?????????????? def my_manfrq(setting, obj, atrb): +?????????????????????? """Callback to set 2-byte manfrqyn yes/no """ +?????????????????????? # LOG.warning("Manfrq value = %d" % setting.value) +?????????????????????? if (str(setting.value)) == "No": +?????????????????????????????? value = 0xff +?????????????????????? else: +?????????????????????????????? value = 0xaa +?????????????????????? setattr(obj, atrb, value) +?????????????????????? return
+?????????????? rx = RadioSettingValueInteger(1, 9, _sets.voxgain + 1) +?????????????? rset = RadioSetting("setstuf.voxgain", "Vox Level", rx) +?????????????? rset.set_apply_callback(my_adjraw, _sets, "voxgain", -1) +?????????????? basic.append(rset)
+?????????????? rx = RadioSettingValueList(LIST_VOXDLY, LIST_VOXDLY[_sets.voxdelay]) +?????????????? rset = RadioSetting("setstuf.voxdelay", "Vox Delay (secs)", rx) +?????????????? basic.append(rset)
+?????????????? rx = RadioSettingValueInteger(0, 9, _sets.sql) +?????????????? rset = RadioSetting("setstuf.sql", "Squelch", rx) +?????????????? basic.append(rset)
+?????????????? rx = RadioSettingValueList(LIST_STEPS, LIST_STEPS[_sets.freqstep]) +?????????????? rset = RadioSetting("setstuf.freqstep", "VFO Tune Step (KHz))", rx) +?????????????? basic.append(rset)
+?????????????? rx = RadioSettingValueBoolean(bool(_sets.dbw))???????? # true logic +?????????????? rset = RadioSetting("setstuf.dbw", "Dual Band Watch (D.WAIT)", rx) +?????????????? basic.append(rset)
+?????????????? options = ["Off", "On", "Auto"] +?????????????? rx = RadioSettingValueList(options, options[_sets.lampon]) +?????????????? rset = RadioSetting("setstuf.lampon", "Backlight (LED)", rx) +?????????????? basic.append(rset)
+?????????????? options = ["Orange", "Purple", "Blue"] +?????????????? rx = RadioSettingValueList(options, options[_sets.ledclr]) +?????????????? rset = RadioSetting("setstuf.ledclr", "Backlight Color (LIGHT)", rx) +?????????????? basic.append(rset)
+?????????????? rx = RadioSettingValueBoolean(bool(_sets.beepon)) +?????????????? rset = RadioSetting("setstuf.beepon", "Keypad Beep", rx) +?????????????? basic.append(rset)
+?????????????? rx = RadioSettingValueBoolean(bool(_sets.xbandenable)) +?????????????? rset = RadioSetting("setstuf.xbandenable", "Cross Band Allowed", rx) +?????????????? basic.append(rset)
+?????????????? rx = RadioSettingValueBoolean(bool(not _sets.xbandon)) +?????????????? rset = RadioSetting("setstuf.xbandon", "Cross Band On", rx) +?????????????? rset.set_apply_callback(my_invbool, _sets, "xbandon") +?????????????? basic.append(rset)
+?????????????? rx = RadioSettingValueList(LIST_TIMEOUT, LIST_TIMEOUT[_sets.tot]) +?????????????? rset = RadioSetting("setstuf.tot", "TX Timeout (Secs)", rx) +?????????????? basic.append(rset)
+?????????????? rx = RadioSettingValueBoolean(bool(not _sets.rgrbeep))?? # Invert +?????????????? rset = RadioSetting("setstuf.rgrbeep", "Beep at Eot (Roger)", rx) +?????????????? rset.set_apply_callback(my_invbool, _sets, "rgrbeep") +?????????????? basic.append(rset)
+?????????????? rx = RadioSettingValueBoolean(bool(not _sets.keylok)) +?????????????? rset = RadioSetting("setstuf.keylok", "Keypad AutoLock", rx) +?????????????? rset.set_apply_callback(my_invbool, _sets, "keylok") +?????????????? basic.append(rset)
+?????????????? options = ["None", "Message", "DC Volts"] +?????????????? rx = RadioSettingValueList(options, options[_sets.openmsg]) +?????????????? rset = RadioSetting("setstuf.openmsg", "Power-On Display", rx) +?????????????? basic.append(rset)
+?????????????? options = ["Channel Name", "Frequency"] +?????????????? rx = RadioSettingValueList(options, options[_sets.chs_name]) +?????????????? rset = RadioSetting("setstuf.chs_name", "Display Name/Frq", rx) +?????????????? basic.append(rset)
+?????????????? sx = "" +?????????????? for i in range(7): +?????????????????????? if _sets.radioname[i] != 0: +?????????????????????????????? sx += chr(_sets.radioname[i] + 32) +?????????????? rx = RadioSettingValueString(0, 7, sx) +?????????????? rset = RadioSetting("setstuf.radioname", "Power-On Message", rx) +?????????????? rset.set_apply_callback(my_strnam, _sets, "radioname", 7) +?????????????? basic.append(rset)
+?????????????? # Advanced (Strange) Settings +?????????????? options = ["Busy: Last Tx Band", "Edit: Current Band"] +?????????????? rx?? = RadioSettingValueList(options, options[_sets.txsel]) +?????????????? rset = RadioSetting("setstuf.txsel", "Transmit Priority", rx) +?????????????? rset.set_doc("'Busy' transmits on last band used, not current one.") +?????????????? adv.append(rset)
+?????????????? options = ["Off", "English", "Unk", "Chinese"] +?????????????? val = _sets.voice +?????????????? rx = RadioSettingValueList(options, options[val]) +?????????????? rset = RadioSetting("setstuf.voice", "Voice", rx) +?????????????? adv.append(rset)
+?????????????? options = ["Off", "1:1", "1:2", "1:3", "1:4"] +?????????????? val = (_sets.batsav & 0x3) +1???????? # ratio +?????????????? if (_sets.batsav & 0x4) == 0:?????? # Off +?????????????????????? val = 0 +?????????????? rx = RadioSettingValueList(options, options[val]) +?????????????? rset = RadioSetting("setstuf.batsav", "Battery Saver", rx) +?????????????? rset.set_apply_callback(my_batsav, _sets, "batsav") +?????????????? adv.append(rset)
+?????????????? # Find out what & where SuperSave is +?????????????? options = ["Off", "1", "2", "3", "4", "5", "6", "7", "8", "9"] +?????????????? rx = RadioSettingValueList(options, options[_sets.supersave]) +?????????????? rset = RadioSetting("setstuf.supersave", "Super Save (Secs)", rx) +?????????????? rset.set_doc("Unknown radio attribute??") +?????????????? adv.append(rset)
+?????????????? sx = unpack_str(_sets.pttbot, _sets.pttbcnt + 1, 8) +?????????????? rx = RadioSettingValueString(0, 16, sx) +?????????????? rset = RadioSetting("setstuf.pttbot", "PTT BoT Code", rx) +?????????????? rset.set_apply_callback(pack_chars, _sets, "pttbot", "pttbcnt", 16) +?????????????? adv.append(rset)
+?????????????? sx = unpack_str(_sets.ptteot, _sets.pttecnt + 1, 8) +?????????????? rx = RadioSettingValueString(0, 16, sx) +?????????????? rset = RadioSetting("setstuf.ptteot", "PTT EoT Code", rx) +?????????????? rset.set_apply_callback(pack_chars, _sets, "ptteot", "pttecnt", 16) +?????????????? adv.append(rset)
+?????????????? options = ["None", "Low", "High", "Both"] +?????????????? rx = RadioSettingValueList(options, options[_sets.voltx]) +?????????????? rset = RadioSetting("setstuf.voltx", "Transmit Inhibit Voltage", rx) +?????????????? rset.set_doc("Block Transmit if battery volts are too high or low,") +?????????????? adv.append(rset)
+?????????????? val = 0???????? # No = 0xff +?????????????? if _sets.manfrqyn == 0xaa: val = 1 +?????????????? options = ["No", "Yes"] +?????????????? rx = RadioSettingValueList(options, options[val]) +?????????????? rset = RadioSetting("setstuf.manfrqyn", "Manual Frequency", rx) +?????????????? rset.set_apply_callback(my_manfrq, _sets, "manfrqyn") +?????????????? adv.append(rset)
+?????????????? rx = RadioSettingValueBoolean(bool(_sets.manualset)) +?????????????? rset = RadioSetting("setstuf.manualset", "Manual Setting", rx) +?????????????? adv.append(rset)
+?????????????? # Scan Settings +?????????????? options = ["CO: During Rx", "TO: Timed", "SE: Halt"] +?????????????? rx = RadioSettingValueList(options, options[_sets.scanmode]) +?????????????? rset = RadioSetting("setstuf.scanmode", +???????????????????????????????????? "Scan Mode (Scan Pauses When)", rx) +?????????????? scn.append(rset)
+?????????????? options = ["100", "150", "200", "250", +???????????????????????????????????? "300", "350", "400", "450"] +?????????????? rx = RadioSettingValueList(options, options[_sets.scanspeed]) +?????????????? rset = RadioSetting("setstuf.scanspeed", "Scan Speed (ms)", rx) +?????????????? scn.append(rset)
+?????????????? val =_sets.scantmo + 3 +?????????????? rx = RadioSettingValueInteger(3, 30, val) +?????????????? rset = RadioSetting("setstuf.scantmo", +?????????????????????????????? "TO Mode Timeout (secs)", rx) +?????????????? rset.set_apply_callback(my_adjraw, _sets, "scantmo", -3) +?????????????? scn.append(rset)
+?????????????? val = _sets.prichan +?????????????? if val <= 0: val = 1 +?????????????? rx = RadioSettingValueInteger(1, 128, val) +?????????????? rset = RadioSetting("setstuf.prichan", "Priority Channel", rx) +?????????????? scn.append(rset)
+?????????????? # FM Broadcast Settings +?????????????? val =_fmx.fmcur +?????????????? val = val / 40.0 +?????????????? if val < 87.5 or val > 107.9: val = 88.0 +?????????????? rx = RadioSettingValueFloat(87.5, 107.9, val, 0.1, 1) +?????????????? rset = RadioSetting("fmfrqs.fmcur", "Manual FM Freq (MHz)", rx) +?????????????? rset.set_apply_callback(myset_freq, _fmx, "fmcur", 40) +?????????????? fmb.append(rset)
+?????????????? options = ["5", "50", "100", "200(USA)"]?????? # 5 is not used +?????????????? rx = RadioSettingValueList(options, options[_sets.fmstep]) +?????????????? rset = RadioSetting("setstuf.fmstep", "FM Freq Step (KHz)", rx) +?????????????? fmb.append(rset)
+?????????????? if False:???? # Skip these unknowns +?????????????????????? # FM Scan Range lo and Hi ??? MEM +?????????????????????? val = 87.5 +?????????????????????? rx = RadioSettingValueFloat(87.5, 107.9, val, 0.1, 1) +?????????????????????? rset = RadioSetting("setstuf.fmsclo", +???????????????????????????????????? "Low FM Scan Bound (MHz)", rx) +?????????????????????? rset.set_apply_callback(myset_freq, _sets, "fmsclo", 40) +?????????????????????? fmb.append(rset)
+?????????????????????? val = 107.9???????? # ??? @@@ where +?????????????????????? rx = RadioSettingValueFloat(87.5, 107.9, val, 0.1, 1) +?????????????????????? rset = RadioSetting("setstuf.fmschi", +???????????????????????????????????? "High FM Scan Freq (MHz)", rx) +?????????????????????? rset.set_apply_callback(myset_freq, _sets, "fmschi", 40) +?????????????????????? fmb.append(rset)
+?????????????? rx = RadioSettingValueBoolean(bool(_sets.rxinhib)) +?????????????? rset = RadioSetting("setstuf.rxinhib", +?????????????????????????????? "Rcvr Will Interupt FM (DW)", rx) +?????????????? fmb.append(rset)
+?????????????? options = [str(x) for x in range(4, 16)] +?????????????? rx = RadioSettingValueList(options, options[_sets.dtmfspd]) +?????????????? rset = RadioSetting("setstuf.dtmfspd", +???????????????????????????????????? "Tx Speed (digits/sec)", rx) +?????????????? dtmf.append(rset)
+?????????????? options = [str(x) for x in range(0, 1100, 100)] +?????????????? rx = RadioSettingValueList(options, options[_sets.dtmfdig1time]) +?????????????? rset = RadioSetting("setstuf.dtmfdig1time", +?????????????????????????????? "Tx 1st Digit Time (ms)", rx) +?????????????? dtmf.append(rset)
+?????????????? options = [str(x) for x in range(100, 1100, 100)] +?????????????? rx = RadioSettingValueList(options, options[_sets.dtmfdig1dly]) +?????????????? rset = RadioSetting("setstuf.dtmfdig1dly", +???????????????????????????????????? "Tx 1st Digit Delay (ms)", rx) +?????????????? dtmf.append(rset)
+?????????????? options = ["0", "100", "500", "1000"] +?????????????? rx = RadioSettingValueList(options, options[_sets.dtmfspms]) +?????????????? rset = RadioSetting("setstuf.dtmfspms", +???????????????????????????????????? "Tx Star & Pound Time (ms)", rx) +?????????????? dtmf.append(rset)
+?????????????? options = ["None"] + [str(x) for x in range(600, 2100, 100)] +?????????????? rx = RadioSettingValueList(options, options[_sets.codespctim]) +?????????????? rset = RadioSetting("setstuf.codespctim", +???????????????????????????????????? "Tx Code Space Time (ms)", rx) +?????????????? dtmf.append(rset)
+?????????????? rx = RadioSettingValueBoolean(bool(_sets.codeabcd)) +?????????????? rset = RadioSetting("setstuf.codeabcd", "Tx Codes A,B,C,D", rx) +?????????????? dtmf.append(rset)
+?????????????? rx = RadioSettingValueBoolean(bool(_sets.dtmfside)) +?????????????? rset = RadioSetting("setstuf.dtmfside", "DTMF Side Tone", rx) +?????????????? dtmf.append(rset)
+?????????????? options = ["Off", "A", "B", "C", "D"] +?????????????? rx = RadioSettingValueList(options, options[_sets.grpcode]) +?????????????? rset = RadioSetting("setstuf.grpcode", "Rx Group Code", rx) +?????????????? dtmf.append(rset)
+?????????????? options = ["Off"] + [str(x) for x in range(1, 16)] +?????????????? rx = RadioSettingValueList(options, options[_sets.autoresettmo]) +?????????????? rset = RadioSetting("setstuf.autoresettmo", +???????????????????????????????????? "Rx Auto Reset Timeout (secs)", rx) +?????????????? dtmf.append(rset)
+?????????????? rx = RadioSettingValueBoolean(bool(_sets.txdecode)) +?????????????? rset = RadioSetting("setstuf.txdecode", "Tx Decode", rx) +?????????????? dtmf.append(rset)
+?????????????? rx = RadioSettingValueBoolean(bool(_sets.idedit)) +?????????????? rset = RadioSetting("setstuf.idedit", "Allow ANI Code Edit", rx) +?????????????? dtmf.append(rset)
+?????????????? options = [str(x) for x in range(500, 1600, 100)] +?????????????? rx = RadioSettingValueList(options, options[_sets.decodetmo]) +?????????????? rset = RadioSetting("setstuf.decodetmo", +?????????????????????????????? "Rx Decode Timeout (ms)", rx) +?????????????? dtmf.append(rset)
+?????????????? options = ["Tx & Rx Inhibit", "Tx Inhibit"] +?????????????? rx = RadioSettingValueList(options, options[_sets.stuntype]) +?????????????? rset = RadioSetting("setstuf.stuntype", "Stun Type", rx) +?????????????? dtmf.append(rset)
+?????????????? sx = unpack_str(_sets.stuncode, _sets.stuncnt, 5) +?????????????? rx = RadioSettingValueString(0, 10, sx) +?????????????? rset = RadioSetting("setstuf.stuncode", "Stun Code", rx) +?????????????? rset.set_apply_callback(pack_chars, _sets, +???????????????????????????????????? "stuncode", "stuncnt", 10) +?????????????? dtmf.append(rset)
+?????????????? # Frequency ranges +?????????????? rx = RadioSettingValueBoolean(bool(_sets.frqr1)) +?????????????? rset = RadioSetting("setstuf.frqr1", "Freq Range 1 (UHF)", rx) +?????????????? rset.set_doc("Enable the UHF frequency bank.") +?????????????? frng.append(rset)
+?????????????? rx = RadioSettingValueBoolean(bool(_sets.frqr2)) +?????????????? rset = RadioSetting("setstuf.frqr2", "Freq Range 2 (VHF)", rx) +?????????????? rset.set_doc("Enable the VHF frequency bank.") +?????????????? frng.append(rset)
+?????????????? mod_se = True???????? # UV8000SE has 3rd freq bank +?????????????? if mod_se: +?????????????????????? rx = RadioSettingValueBoolean(bool(_sets.frqr3)) +?????????????????????? rset = RadioSetting("setstuf.frqr3", "Freq Range 3 (220Mhz)", rx) +?????????????????????? rset.set_doc("Enable the 220MHz frequency bank.") +?????????????????????? frng.append(rset)
+?????????????? frqm = 100000 +?????????????? val = _sets.frqr1lo / frqm +?????????????? rx = RadioSettingValueFloat(400.0, 520.0, val, 0.005, 3) +?????????????? rset = RadioSetting("setstuf.frqr1lo", +???????????????????????????????????? "UHF Range Low Limit (MHz)", rx) +?????????????? rset.set_apply_callback(myset_freq, _sets, "frqr1lo", frqm) +?????????????? rset.set_doc("Low limit of the UHF frequency bank.") +?????????????? frng.append(rset)
+?????????????? val = _sets.frqr1hi / frqm +?????????????? rx = RadioSettingValueFloat(400.0, 520.0, val, 0.005, 3) +?????????????? rset = RadioSetting("setstuf.frqr1hi", +?????????????????????? "UHF Range High Limit (MHz)", rx) +?????????????? rset.set_apply_callback(myset_freq, _sets, "frqr1hi", frqm) +?????????????? rset.set_doc("High limit of the UHF frequency bank.") +?????????????? frng.append(rset)
+?????????????? val = _sets.frqr2lo / frqm +?????????????? rx = RadioSettingValueFloat(136.0, 174.0, val, 0.005, 3) +?????????????? rset = RadioSetting("setstuf.frqr2lo", +???????????????????????????????????? "VHF Range Low Limit (MHz)", rx) +?????????????? rset.set_apply_callback(myset_freq, _sets, "frqr2lo", frqm) +?????????????? rset.set_doc("Low limit of the VHF frequency bank.") +?????????????? frng.append(rset)
+?????????????? val = _sets.frqr2hi / frqm +?????????????? rx = RadioSettingValueFloat(136.0, 174.0, val, 0.005, 3) +?????????????? rset = RadioSetting("setstuf.frqr2hi", +?????????????????????????????? "VHF Range High Limit (MHz)", rx) +?????????????? rset.set_apply_callback(myset_freq, _sets, "frqr2hi", frqm) +?????????????? rset.set_doc("High limit of the VHF frequency bank.") +?????????????? frng.append(rset)
+?????????????? if mod_se: +?????????????????????? val = _sets.frqr3lo / frqm +?????????????????????? if val == 0: val = 222.0 +?????????????????????? rx = RadioSettingValueFloat(220.0, 260.0, val, 0.005, 3) +?????????????????????? rset = RadioSetting("setstuf.frqr3lo", +???????????????????????????????????? "1.25m Range Low Limit (MHz)", rx) +?????????????????????? rset.set_apply_callback(myset_freq, _sets, "frqr3lo", frqm) +?????????????????????? frng.append(rset)
+?????????????????????? val = _sets.frqr3hi / frqm +?????????????????????? if val == 0: val = 225.0 +?????????????????????? rx = RadioSettingValueFloat(220.0, 260.0, val, 0.005, 3) +?????????????????????? rset = RadioSetting("setstuf.frqr3hi", +?????????????????????????????????????? "1.25m Range High Limit (MHz)", rx) +?????????????????????? rset.set_apply_callback(myset_freq, _sets, "frqr3hi", 1000) +?????????????????????? frng.append(rset)
+?????????????? return group???????????? # END get_settings()
+?????? def set_settings(self, settings): +?????????????? _settings = self._memobj.setstuf +?????????????? _mem = self._memobj +?????????????? for element in settings: +?????????????????????? if not isinstance(element, RadioSetting): +?????????????????????????????? self.set_settings(element) +?????????????????????????????? continue +?????????????????????? else: +?????????????????????????????? try: +?????????????????????????????????????? name = element.get_name() +?????????????????????????????????????? if "." in name: +?????????????????????????????????????????????? bits = name.split(".") +?????????????????????????????????????????????? obj = self._memobj +?????????????????????????????????????????????? for bit in bits[:-1]: +?????????????????????????????????????????????????????? if "/" in bit: +?????????????????????????????????????????????????????????????? bit, index = bit.split("/", 1) +?????????????????????????????????????????????????????????????? index = int(index) +?????????????????????????????????????????????????????????????? obj = getattr(obj, bit)[index] +?????????????????????????????????????????????????????? else: +?????????????????????????????????????????????????????????????? obj = getattr(obj, bit) +?????????????????????????????????????????????? setting = bits[-1] +?????????????????????????????????????? else: +?????????????????????????????????????????????? obj = _settings +?????????????????????????????????????????????? setting = element.get_name()
+?????????????????????????????????????? if element.has_apply_callback(): +?????????????????????????????????????????????? LOG.debug("Using apply callback") +?????????????????????????????????????????????? element.run_apply_callback() +?????????????????????????????????????? elif element.value.get_mutable(): +?????????????????????????????????????????????? LOG.debug("Setting %s = %s" % (setting, element.value)) +?????????????????????????????????????????????? setattr(obj, setting, element.value) +?????????????????????????????? except Exception, e: +?????????????????????????????????????? LOG.debug(element.get_name()) +?????????????????????????????????????? raise
+?????? @classmethod +?????? def match_model(cls, filedata, filename): +?????????????? match_size = False +?????????????? match_model = False
+?????????????? # Testing the file data size +?????????????? if len(filedata) == MEM_SIZE + 10: +?????????????????????? match_size = True
+?????????????? # Testing the firmware model fingerprint +?????????????? match_model = model_match(cls, filedata)
+?????????????? if match_size and match_model: +?????????????????????? return True +?????????????? else: +?????????????????????? return False
-- Rick DeWitt AA0RD Sequim, Washington, USA 98382 (360) 681-3494
chirp_devel mailing list chirp_devel@intrepid.danplanet.com http://intrepid.danplanet.com/mailman/listinfo/chirp_devel Developer docs: http://chirp.danplanet.com/projects/chirp/wiki/Developers