[chirp_devel] TYT TH-UV8000 New Driver
I haven't seen this submission come back to my developer's inbox, so here it is again-- # HG changeset patch # User Rick DeWitt aa0rd@yahoo.com # Date 1559148360 25200 #?????????? Wed May 29 09:46:00 2019 -0700 # Node ID 0815b185dbcbaccb3590a95568a8da25e899f4b0 # 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 0815b185dbcb chirp/drivers/th_uv8000.py --- /dev/null?????? Thu Jan 01 00:00:00 1970 +0000 +++ b/chirp/drivers/th_uv8000.py?????? Wed May 29 09:46:00 2019 -0700 @@ -0,0 +1,1582 @@ +# 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 + +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 { +?? u8 modnum[7]; +} modcode; + +#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) + +?????? # 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
Hi Rick and Chirp-Devel,
I received both submissions. It just takes patience sometimes.
I don't know if it is just how my browser is displaying the submissions, but both appear to have a very large surplus of "question marks" throughout the patch.
Here is a sample...
<snip> +from chirp.settings import RadioSettingGroup, RadioSetting, \ +?????? RadioSettingValueBoolean, RadioSettingValueList, \ +?????? RadioSettingValueString, RadioSettingValueInteger, \ +?????? RadioSettingValueFloat, RadioSettings,InvalidValueError +from textwrap import dedent </snip>
I could be wrong (I've never seen this in any submitted patches before), but I would expect this to be an issue.
Jim KC9HI
I don't know if it is just how my browser is displaying the submissions, but both appear to have a very large surplus of "question marks" throughout the patch.
I see the same, and it's not just the display.
I could be wrong (I've never seen this in any submitted patches before), but I would expect this to be an issue.
Yep, it's totally un-applyable in its current state. I saw the submission come across in that mangled form and figured that a replacement was probably coming afterwards, and then forgot to follow up.
Rick, I'm not sure what happened here, but maybe if you could send it how you did before (which looked fine) or just attach it as a file (less ideal, but more likely to survive a bad mailer)?
--Dan
participants (3)
-
Dan Smith
-
Jim Unroe
-
Rick DeWitt