From 4921e8d0cf1897cebc048475cf32b4d1424b922d Mon Sep 17 00:00:00 2001 From: Old-Phart Date: Wed, 17 Apr 2024 10:47:46 -0700 Subject: [PATCH 01/11] New Yaesu driver for FTM-6000 (issue 9719) and FTM-200 (11137) --- chirp/drivers/ftm6000.py | 2877 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 2877 insertions(+) create mode 100644 chirp/drivers/ftm6000.py diff --git a/chirp/drivers/ftm6000.py b/chirp/drivers/ftm6000.py new file mode 100644 index 000000000..d3e3c2fe5 --- /dev/null +++ b/chirp/drivers/ftm6000.py @@ -0,0 +1,2877 @@ +# Copyright 2018 by Rick DeWitt (aa0rd@yahoo.com) V1.0 +# Issues 9719 for FTM-6000 and 11137 for FTM-200 +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +"""FTM-6000 Yaesu Radio Driver""" + +from ast import Bytes +from asyncio.windows_events import NULL +from operator import indexOf +from pickle import FALSE +from unittest.util import _MAX_LENGTH +from chirp.drivers import yaesu_clone +from chirp import chirp_common, util, memmap, errors, directory, bitwise +from chirp.settings import RadioSetting, RadioSettingGroup, \ + RadioSettingValueInteger, RadioSettingValueList, \ + RadioSettingValueBoolean, RadioSettingValueString, \ + RadioSettingValueFloat, RadioSettings +import time +import struct +import logging +import itertools +import math +import sys + +LOG = logging.getLogger(__name__) + +CMD_ACK = b'\x06' + +def dbg_dump(stz, kn=32, cptn="DBG", ax=False, lgx=1): + """ Debugging tool to print up to kn hex values of string stz """ + # ax: flag to append ascii, lgx: Log code (bits) 1=Warning, 2=Debug + # print 16 bytes (+ ascii) per line + bn = 0 + an = 0 + sx = "" + kx = len(stz) + for ix in range(kx): + sx += "%02x " % stz[ix] + bn += 1 + if bn == 16: + # if ax: # append as ascii + # sx += " [" + # for ix in range(kx): + # if stz[ix] > 31 and stz[ix] < 127: + # sx += "%s" % chr(stz[ix]) + # else: + # sx += "." + # sx += "]" + sx += "\n " + bn = 0 + if lgx & 1: + LOG.warning("Block length: %d" % len(stz)) + LOG.warning("%s: %s" % (cptn, sx)) + if lgx & 2: + LOG.debug("Block length: %d" % len(stz)) + LOG.debug("%s: %s" % (cptn, sx)) + return + + +class Ftm6000RAlias(chirp_common.Alias): + Vendor = "Yaesu" + MODEL = "FTM-6000R" + + +@directory.register +class FTM6000Radio(yaesu_clone.YaesuCloneModeRadio): + """Yaesu FTM-6000""" + FTM200 = False + # TESTME = False + BAUD_RATE = 38400 + COM_BITS = 8 # number of data bitsTMODEW + COM_PRTY = 'N' # parity checking + COM_STOP = 1 # stop bits + MODEL = "FTM-6000" + NAME_LEN = 6 # Valid Name Length + ALIASES = [Ftm6000RAlias] + MODES = ["FM", "AM", "NFM"] + TMODES = ["", "Tone", "TSQL", "TSQL-R", "DTCS", "Cross"] + CROSS_MODES = ["->DTCS", "Tone->DTCS", "DTCS->Tone"] + DUPLEX = ["", "n/a", "-", "+", "split"] + T_STEPS = [2.5, 5.0, 6.25, 10.0, 12.5, 15.0, 20.0, 25.0, 50.0, 100.0] + VALID_BANDS = [(108000000, 137000000), + (137000000, 174000000), + (174000000, 400000000), + (400000000, 480000000), + (480000000, 999999999)] + POWER_LEVELS = [chirp_common.PowerLevel("Hi", watts=50), + chirp_common.PowerLevel("Mid", watts=20), + chirp_common.PowerLevel("Low", watts=5)] + SKIPS = ["", "S"] + # No lowercase,{} or ~ + CHARSET = [chr(x) for x in list(range(ord(" "), ord("_") + 1)) + + [ord("|")]] + DTMF_CHARS = list("0123456789ABCD*#") + MEM_FORMAT = """ + struct memdat { // 16 bytes per chan + u8 used:1, // 00 + skip:2, + unk1:2, + band:3; + u8 clks:1, // 01 + xx:1, + mode:2, + duplex:4; + u24 freq; // 02-04 + u8 tmode:4, // 05 + step:4; + u24 frqtx; // 06-08 + u8 power:2, // 09 + rtone:6; + u8 clktyp:1, // 0A, + dtcs:7; + u8 prfreq; // 0B + u16 offset; // 0C-0D 0-99.95 MHz in 0.5 steps 06.0 is 00 0c + u8 unk3; // 0E + u8 unk4; // 0F + }; + + struct tag { + u8 chname[16]; + }; + + struct pmgx { + u8 za; // 0x00 + u8 fb; // 0xff + u16 chnp; // 0-based pmg channel number + }; + + struct { // In 1st block + u8 id[6]; + } model; + #seekto 0x080; + struct memdat vfo_air; // 080 + struct memdat vfo_144; // 090 + struct memdat vfo_vhf; // 0a0 + struct memdat vfo_430; // 0b0 + struct memdat vfo_uhf; // 0c0 + struct memdat unkc1[5]; // 0d0 - 0110 repeats vfo entries + u8 120[16]; // 0x120 all ff + struct memdat home; // 0x130 + u8 ff2[64]; // 0x140 - 0x17f; ff's' + struct memdat unkc2; // 0x180 possible last chan accessed? + #seekto 0x200; + struct { + u8 20axd[14]; // 0x200 - 0x20d + u8 xm0au:5, // 0x20e + bell:3; + u8 xm0bu:6, // 020f + lcd:2; + u8 210xd[14]; // 0210 - 021d + u8 21ea:5, + bellb:3; + u8 wrxdid; // 21f + u8 220x1[2]; // 220 -221 + u8 fkp1; // 0x222: FTM-200 keypad quick access 1 + u8 fhm1; // 0x223: FTM-200 home qa 1 + u8 fkp2; + u8 fhm2; + u8 fkp3; + u8 fhm3; + u8 fkp4; + u8 fhm4; // 0x229 + u8 22axf[6]; + u8 230x7[8]; // 230-237 + u24 wrxvfrq; + u8 23b; + u24 wrxufrq; + u8 23f; + u8 240a:6, + wrxbsel:1, + 240b:1; + u8 241x7[7]; // 24-247 + u8 csign[10]; // 248 - 251 + u8 pgrcdr1; // 0252 + u8 pgrcdr2; + u8 pgrcdt1; + u8 pgrcdt2; // 0255 + u8 256a:7, + compass:1; + u8 257a:7, + usbcamsz:1; + u8 258a:6, + usbcamql:2; + u8 259; + u8 25a; + u8 25ba:4, + wrxpop:4; + u8 25c; + u8 micgain; // 25d + u8 25e; + u8 micp1; // 25f + u8 micp2; // 260 + u8 micp3; + u8 micp4; + u8 263xf[13]; // 0x263 - 026f + u8 270xf[16]; // 0x270 - 27f + } micset; + struct { + u8 codes[16]; // 0x280-30f + } dtmfcode[9]; + #seekto 0x400; + struct { + u8 400a:7, // 0400 + aprbupo:1; + u8 401a:7, + aprbudi:1; + u8 402a:6, + aprbusp:2; + u8 403a:7, // 0403 + aprbual:1; + u8 404a:5, + aprbubo:3; + u8 405a:7, + aprbutp:1; + u8 406a:7, + aprburn:1; + u8 407a:5, + aprbuwd:3; + u8 aprcsgn[6]; // 0408-040d + u8 aprcsfx; + u8 400f; + u8 410a:3, + aprltns:1, + 410b:4; + u8 aprlad; // 0411 + u8 aprlam; + u16 aprlas; // 0413-0414 + u8 415a:3, + aprlgew:1, + 415b:4; + u8 aprlgd; + u8 aprlgm; + u16 aprlgs; + u8 aprrcsn[6]; // 041a-41f + u8 aprrcfx; // 0420 + u8 421; + u8 aprsym1[2]; // 0422, 423 + u8 aprsym2[2]; + u8 aprsym3[2]; + u8 aprsym4a; + u8 aprsym4b; // 0429 + u16 aprbfrl; // 042a & 042b + u8 42ca:4, + aprsym:4; + u8 42da:4, // 042d + aprdig:4; + u8 42ea:4, + aprstxi:4; + u8 aprsrate; // 042f + u8 aprslow; // 0430 + u8 431a:5, + aprbamb:3; + u8 432a:4, + aprcmt:4; + u8 aprspro:1, // 0433 + aprbaut:1, + 433b:1, + aprsdcy:1, + aprspdc:1, + aprsalt:1, + 433c:1, + aprrply:1; + u8 434a:1, // 0434 + dspda:1, // FTM-200 APRS + pktspd:1, // Both + 434b:3, + aprmut:1, + aprson:1; + u8 435a:2, + datsql:1, + 435b:5; + u8 436a:5, + bcnstat:3; + u8 437a:4, // 0x437 + bcntxra:4; + u8 438a:1, + aprbfot:1, + aprbfst:1, + aprbfit:1, + aprbfob:1, + aprbfwx:1, + aprbfpo:1, + aprbfme:1; + u8 439a:7, + aprbrtb:1; + u8 43aa:7, + aprbrtm:1; + u8 43ba:7, + aprbrrb:1; + u8 43ca:7, + aprbrrm:1; + u8 43da:7, + aprbrmp:1; + u8 43ea:7, + aprbrcr:1; + u8 aprbrrr; // 043f + u8 440a:7, + aprbrmv:1; + u8 441a:7, + aprmpos:1; + u8 442; + u8 443a:4, + dbsela:4; + u8 444a:4, + dbseld:4; + u8 aprpopb; // 0445 + u8 aprpopm; + u8 447a:4, + aprtxd:4; + u8 448a:4, + comout:4; + u8 449a:4, + comspd:4; + u8 44aa:5, + bcnsmart:3; + u8 typ1val0; // 044b -> 045f + u8 typ1val1; // Smart Beaconing type settings + u8 typ1val2; + u8 typ1val3; + u8 typ1val4; + u8 typ1val5; + u8 typ1val6; + u8 typ2val0; + u8 typ2val1; + u8 typ2val2; + u8 typ2val3; + u8 typ2val4; + u8 typ2val5; + u8 typ2val6; + u8 typ3val0; + u8 typ3val1; + u8 typ3val2; + u8 typ3val3; + u8 typ3val4; + u8 typ3val5; + u8 typ3val6; // 045f + u8 460a:4, + aprstxn:4; + u8 461a:1, + aprmpkt:1, + aprbfan:1, + 461b:5; + u8 462a:4, + comwpf:4; + u8 463a:4, + comflt:4; + u8 464; + u8 465; + u8 466; + u8 467; + u8 468; + u8 469; + u8 46a; + u8 46b; + u8 46c; + u8 46da:5, + aprvlrt:3; + u8 aprtsql; + u8 aprvdcs; // 046f + u8 470a:6, + aprsfs:2; + u8 471a:4, + aprsff:4; + u8 472xf[14]; // -> 047f + u8 aprrtxt[64]; // 0480 - 04BF + } wierd; + #seekto 0x500; + struct { + u8 grp1[9]; + u8 509; + u8 grp2[9]; + u8 514; + u8 grp3[9]; + u8 51d; + u8 grp4[9]; + u8 527; + u8 grp5[9]; + u8 532; + u8 grp6[9]; + u8 53b; + u8 blt1[9]; + u8 545; + u8 blt2[9]; + u8 554; + u8 blt3[9]; + u8 559; + } aprsmsg; + #seekto 0x580; + struct { // FMT-6000 Menu item Fntcn mode set table + u8 shbyt; // FTM-200 Digipath, RingerCS data + } share1[256]; // -> 0x67f + struct { // 0x680 + u8 txt1[16]; + u8 txt2[16]; + u8 txt3[16]; + u8 txt4[16]; + u8 txt5[16]; + u8 txt6[16]; + u8 txt7[16]; + u8 txt8[16]; + } aprstxt; + struct memdat main[999]; // 0x700 16 bytes each, up to 4570 + struct memdat pms[100]; // up to 0x4bb0 + struct memdat unkc3[5]; // unknown, up to 0x4c00 + #seekto 0x4c10; + struct pmgx pmg[6]; // 6th element is change record + #seekto 0x6980; + struct { // WIRES-X Messages + u8 msg01[128]; + u8 msg02[128]; + u8 msg03[128]; + u8 msg04[128]; + u8 msg05[128]; + u8 msg06[128]; + u8 msg07[128]; + u8 msg08[128]; + u8 msg09[128]; + u8 msg10[128]; + } wrxmsg; + struct { // 0x6e80 + u8 c1[16]; + u8 c2[16]; + u8 c3[16]; + u8 c4[16]; + u8 c5[16]; + } wrxcat; + #seekto 0x7d00; + struct { // --> 07e3f + u8 msg[60]; + u8 mode; + u8 nax[3]; + } bcntxt[5]; + #seekto 0xff00; + struct tag names[999]; // 16 bytes each, up to 0x13d6f (83055.) + struct tag pms_name[100]; // 13d70 - 143af + #seekto 0x17f00; + struct { // Settings + u8 f00xf[16]; // 17f00-0f + u8 f10xf[16]; // 17f10-1f + u8 f20; // 17f20 + u8 f21a:7, + unit:1; + u8 f22; + u8 f23; + u8 f24a:2, // 17f24 + apo:5, + apo1:1; + u8 bclo:1, // 17f25 + f25a:4, + arts_int:1, + arts_mode:2; + u8 f26:4, // 17f26 + airb:1, + vhfb:1, + uhfb:1, + otrb:1; + u8 f27; + u8 tzone; + u8 f29a:6, + fvsvol:2; + u8 f2au:4, // 17f2a + tot:4; + u8 f2b; + u8 f2c; + u8 f2d:6, + dspmode:2; + u8 f2ea:6, + fvsanc:2; + u8 f2fa:6, // 17f2f + gpsdtm:1, + f2fb:1; + u8 lastmnu; // 17f30 + u8 f31; // 17f31 + u8 f1key; // 17f32 + u8 f33; + u8 f34; + u8 f35a:4, + gpslog:4; + u8 f36a:6, + voxsen:2; // FTM-200 + u8 f37a:5, + voxdly:3; + u8 f38a:6, // 17f38 + audrec:2; + u8 lastfunc; // 17f39 + u8 f3a:6, // 17f3a + lcd_clr:2; + u8 f3bxf[5]; // 17f3b-3f + u8 f40x2[3]; // 7f40-42 + u8 a_chan; // FTM-200 17f43 + u8 f44; + u8 f45u:5, // 17f45 + scnrsm:3; + u8 f46; + u8 f47; + u8 f48u:4, // 17f48 + sql:4; + u8 f49:4, + scnrsm2a:4; // FTM-200 A + u8 f4a; // 17f4a + u8 f4ba:4, + scndria:4; + u8 f4c; + u8 f4d; + u8 f4e; + u8 f4f; + u8 f50x2[3]; // 17f50-52 + u8 b_chan; // FTM-200 17f53 + u8 f54; + u8 f55; + u8 f56; + u8 f57; + u8 f58; + u8 f59:4, + scnrsm2b:4; // FTM-200 B + u8 f5a; // 17f5a + u8 f5ba:4, + scndrib:4; + u8 f5c; + u8 f5d; + u8 f5e; + u8 f5f; + u8 f60; // 17f60 + u8 f61; + u8 scndrm1:1, // 17f62 + wxalrt:1, + f62b:5, + dwrvt:1; + u8 f63a:7, // 17f63 + sqlexp1:1; + u8 f64a:5, // 17f64 + rpt_ars:1, + f64b:2; + u8 f65a:2, + bscope:1, + f65b:5; + u8 f66; + u8 f67; + u8 f68a:3, + wrxstb:1, + f68b:1, + locinfo:1, + wrxdvw:1, + f68c:1; + u8 f69; + u8 f6aa:4, + audmic:1, + f6ab:2, + btsave:1; + u8 wrxloc:1, // 17f6b + fvslan:1, + f6bb:2, + beep1:1, // Stupid split beep: this is Off/Low + fvsrxm:1, + f6bc:2; + u8 gpsdev:1, // 17f6c + memlist:1, + wrxrng:1, + wrxrwf:1, + wrxsrch:1, + f6cb:2, + scndrm2:1; + u8 bskpax:3, // 17f6d + bskpa0:1, + bskpa4:1, + bskpa3:1, + bskpa2:1, + bskpa1:1; + u8 f6e; + u8 f6f; + u8 f70; // 17f70 + u8 f71; + u8 f72a:7, + dwrvtb:1; + u8 f73a:7, + sqlexp2:1; + u8 f74a:5, + rpt_arsb:1, + f74b:2; + u8 f75a:2, + bscopeb:1, + f75b:5; + u8 f76; + u8 f77; + u8 f78a:5, // 17f78 + dtmf_auto:1, + bton:1, + btaud:1; + u8 f79a:3, // 17f79 + timefmt:1, + datefmt:4; + u8 f7aa:3, + beep2:1, // Split beep: High + f7ab:3, + fvsrec:1; + u8 f7ba:6, + wrxams:2; + u8 f7c; + u8 bskpbx:3, // 17f7d + bskpb0:1, + bskpb4:1, + bskpb3:1, + bskpb2:1, + bskpb1:1; + u8 f7e; + u8 f7f; + u8 f80[16]; // 17f80 + u8 f90[16]; // 17f90 + u8 fA0[16]; // 17fA0 + u8 fB0[16]; // 17fB0 + u8 FC0[16]; // 17fC0 + u8 FD0[16]; // 17fD0 + u8 FE0[16]; // 17fE0 + u8 FF0[16]; // 17fF0 + } setts; + """ + + @classmethod + def get_prompts(cls): + rp = chirp_common.RadioPrompts() + rp.info = ( + "The duplex setting 'split' allows for non-standard offsets " + "by configuring both a\n" + "receive and transmit frequency. Set the receive frequency, " + "then the duplex mode,\n" + "then the desired transmit frequency as the offset.\n" + "The offset value of a split channel is the transmit frequency, " + "and can be modified.\n" + "PMS (Programmable Memory Channel Scan) pairs are displayed " + "as memory channels 1000-1099.\n" + "The Clock Shift Function can be set in the Properties " + "> Extra tab.\n" + "The radio special tone modes (REV, PR, PAGER) can also be set " + "in the Properties > Extra tab,\n" + "but will be displayed as Tone in CHIRP.") + if cls.FTM200: + rp.pre_download = ( + "(OK then TX)\n" + "With the USB cable connected to the radio rear data port, " + "and the radio powered off-\n" + "1. Long-Press F-Menu.\n" + "2. Rotate the dial knob to menu 116: 'This -> Other'.\n" + "3. Press the dial knob.\n" + "4. Rotate to select OK, but don't press yet.\n" + "5. Press the OK button below.\n" + "6. Press the dial knob to begin sending data.\n" + "7. Wait for Complete.\n") + rp.pre_upload = ( + "(Rx then OK)\n" + "With the USB cable connected to the radio rear data port, " + "and the radio powered off-\n" + "1. Long-Press F-Menu.\n" + "2. Rotate the dial knob to menu 117: 'Other -> This'.\n" + "3. Press the dial knob.\n" + "4. Rotate to select OK, and press the knob.\n" + "5. Press the OK button below.\n" + "6. Wait for Complete.\n") + else: + rp.pre_download = ( + "(OK then TX)\n" + "With the USB cable connected to the radio rear data port, " + "and the radio powered off-\n" + "1. Press both the power ON and F1 keys.\n" + "2. Press the dial knob.\n" + "3. Rotate the dial to show CLN TX.\n" + "4. Press the OK button below/\n" + "5. Press the dial knob to begin sending data.\n" + "6. Wait for Complete.\n" + "7. Long-press the power On button to leave the clone mode.") + rp.pre_upload = ( + "(Rx then OK)\n" + "With the USB cable connected to the radio rear data port, " + "and the radio powered off-\n" + "1. Press both the power ON and F1 keys.\n" + "2. Press the dial knob, CLN RX is displayed.\n" + "3. Press the dial knob again to put the radio in the " + "receiving state.\n" + "4. Press the OK button below.\n" + "5. Wait for Complete.\n" + "6. Long-press the power On button to leave the clone mode.") + return rp + + def _read(self, blck, blsz): + # be very patient at first block + if blck == 0: + attempts = 60 + else: + attempts = 5 + for _i in range(0, attempts): + data = self.pipe.read(blsz) + if data: + break + time.sleep(0.5) + if len(data) == blsz: + LOG.debug("Received block %s, sub %s" % (hex(data[0]), hex(data[1]))) + checksum = data[blsz - 1] + cs = 0 + for i in data[:-1]: + cs = (cs + i) % 256 + if cs != checksum: + raise Exception("Checksum Failed [%02X<>%02X] block %02X" % + (checksum, cs, blck)) + # Remove the 2-byte block header and checksum + data = data[2:blsz - 1] + else: + raise Exception("Unable to read block %i expected %i got %i" + % (blck, blsz, len(data))) + return data + + def _clone_in(self): + # Be very patient with the radio + self.pipe.timeout = 2 + self.pipe.baudrate = self.BAUD_RATE + self.pipe.bytesize = self.COM_BITS + self.pipe.parity = self.COM_PRTY + self.pipe.stopbits = self.COM_STOP + self.pipe.rtscts = False + start = time.time() + data = b"" + status = chirp_common.Status() + status.msg = "Cloning from radio" + nblocks = 768 + status.max = nblocks - 1 + blksz = 131 + for block in range(0, nblocks): # SPS - reads to nblocks-1 + LOG.debug("Reading packet %d" % block) + data += self._read(block, blksz) + self.pipe.write(CMD_ACK) + status.cur = block + self.status_fn(status) + return memmap.MemoryMapBytes(data) + + def _write(self, nblk, nsub, pntr, bksz, zblk): + LOG.debug("Block %02X %02X" % (nblk, nsub)) + # if self.TESTME: LOG.warning("Block %02X %02X" % (nblk, nsub)) + data = struct.pack('B', nblk) + data += struct.pack('B', nsub) + if zblk: + blkdat = bytearray(bksz) # All Zeros + else: + blkdat = self.get_mmap()[pntr:pntr + bksz] + data += blkdat + cs = 0 + for i in data: + cs = (cs + i) % 256 + LOG.debug("Checksum %s" % hex(cs)) + # if self.TESTME: LOG.warning("Checksum %s" % hex(cs)) + data += struct.pack('B', cs) + LOG.debug("Writing %d bytes:\n%s" % (len(data), + util.hexprint(data))) + # if self.TESTME: # Dont send data yet + # LOG.warning("Writing %d bytes:\n%s" % (len(data), + # util.hexprint(data))) + # buf = CMD_ACK + # else: + self.pipe.write(data) + buf = self.pipe.read(1) + if not buf or buf[:1] != CMD_ACK: + time.sleep(0.5) + buf = self.pipe.read(1) + if not buf or buf[:1] != CMD_ACK: + return False + return True + + def _clone_out(self): + self.pipe.baudrate = self.BAUD_RATE + self.pipe.bytesize = self.COM_BITS + self.pipe.parity = self.COM_PRTY + self.pipe.stopbits = self.COM_STOP + self.pipe.rtscts = False + + start = time.time() + status = chirp_common.Status() + status.msg = "Cloning to radio" + blksz = 128 # actual data; excluding block, sub, checksum + pkt = 0 + pos = 0 + block = 0 + wrtzero = False # Special last block flag + nblocks = 767 # last block number + status.max = nblocks - 2 + # This sucker took FOREVER to figure out the repeating block + # + sub-block + special EoD numbering! + while pkt <= nblocks: + LOG.debug("Writing packet #: %d." % pkt) + # if self.TESTME: LOG.warning("Writing packet #: %d , pos %x." + # % (pkt, pos)) + time.sleep(0.01) + sub2 = True + sublk = 0 + if pkt == 0: + block = pkt + sub2 = False + elif pkt == 1: + block = pkt + elif pkt == 7: # Block 04 00 is skipped !!?? + block = 0x04 + sublk = 0x80 + sub2 = False # block increments to 05 00 + elif pkt == 510: # Reset to block 0 + block = 0 + elif pkt == 766: + block = 0xff + sublk = 0xfd + sub2 = False + elif pkt == 767: + block = 0xff + sublk = 0xfe + sub2 = False + # pkt 767, block ff fe must be all zeros!!??? + wrtzero = True + rslt = self._write(block, sublk, pos, blksz, wrtzero) + if rslt and sub2: # write same block, new sublk + sublk = 0x80 + pkt += 1 + pos += blksz + LOG.debug("Writing packet #: %.d" % pkt) + # if self.TESTME: LOG.warning("Writing packet #: %d , + # pos %x." % (pkt, pos)) + rslt = self._write(block, sublk, pos, blksz, wrtzero) + if not rslt: + raise Exception("Radio did not ack block %i %1" % + (block, sublk)) + pos += blksz + block += 1 + pkt += 1 + status.cur = pkt + self.status_fn(status) + return + + def sync_in(self): + try: + self._mmap = self._clone_in() + except errors.RadioError: + raise + except Exception as e: + raise errors.RadioError("Failed to communicate with radio: %s" + % e) + self.process_mmap() + + def sync_out(self): + try: + self._clone_out() + except errors.RadioError: + raise + except Exception as e: + raise errors.RadioError("Failed to communicate with radio: %s" + % e) + + def process_mmap(self): + self._memobj = bitwise.parse(self.MEM_FORMAT, self._mmap) + + def get_features(self): + rf = chirp_common.RadioFeatures() + rf.has_dtcs_polarity = False + rf.has_bank = False + rf.has_dtcs = True + rf.has_cross = True + rf.has_tuning_step = True + rf.has_ctone = False # Common Tones + rf.has_rx_dtcs = False # Common codes + rf.has_settings = True + rf.can_odd_split = True + rf.valid_modes = [x for x in self.MODES if x in chirp_common.MODES] + rf.valid_tmodes = self.TMODES + rf.valid_cross_modes = self.CROSS_MODES + rf.valid_duplexes = self.DUPLEX + rf.valid_tuning_steps = self.T_STEPS + rf.valid_bands = self.VALID_BANDS + rf.valid_power_levels = self.POWER_LEVELS + rf.valid_characters = "".join(self.CHARSET) + rf.valid_name_length = self.NAME_LEN + rf.valid_skips = self.SKIPS + + + rf.memory_bounds = (1, 1099) + return rf + + def get_raw_memory(self, number): + return repr(self._memobj.main[number - 1]) + + def validate_memory(self, mem): + msgs = yaesu_clone.YaesuCloneModeRadio.validate_memory(self, mem) + return msgs + + def filter_name(self, namsx): + """Name must be <= NAME_LEN and contain only CHARSET chars""" + tx = namsx.strip() + sx = "" + if self.FTM200 == False: tx = tx.upper() + for i in range(0, len(tx)): + if i >= self.NAME_LEN: break + if tx[i] in self.CHARSET: + sx += tx[i] + else: + sx = "?" + return sx + + def _freqdcode(self, frqb): + """Decode .0025 Mhz upper 2 MSB of freq""" + # frqb is u24: 2bits suffix, 22 bits bcd + sx = "%06X" % frqb + v0 = int(sx[0], 16) * 625 + v1 = int(sx[1]) # 100 Mhz + v2 = int(sx[2:4]) # 10 Mhz + v3 = int(sx[4:]) # 100 Khz + vx = (v1 * 10000) + (v2 * 100) + v3 + vx = vx * 10000 + v0 + return vx + + def _freqncode(self, frq): + """Encode .0625 Mhz in upper MSB of u24 bcd freq""" + v0 = frq % 10000 # .025 value + bx = v0 // 625 + bx = bx * 0x100000 + vx = int((frq - v0) / 10000) + sx = "%06d" % vx # Ex: 012345 for frq = 123.45 MHz + v1 = int("0x" + sx[0:2], 16) + v2 = int("0x" + sx[2:4], 16) + v3 = int("0x" + sx[4:], 16) + frqb = bx + v1 * 0x10000 + v2 * 0x100 + v3 + return frqb + + def _b2s(self, bary, term = 0xff): + """Convert byte array into string """ + strx = "" + for i in bary: + if i == term: + break + strx += chr(i) + return strx + + def _s2b(self, setting, obj, atrb, mxk, pad = 0xff, upc = True): + """Callback: Convert string to byte array, pad to mxk chars""" + sx = str(setting.value) + sx = sx.strip() + if upc: sx = sx.upper() + ary = b"" + v1 = len(sx) + for vx in range(0, mxk): + if vx < v1: + ary += bytes(sx[vx], 'utf-8') + else: + ary += pad.to_bytes(1, sys.byteorder) + setattr(obj, atrb, ary) + return + + def _c2u8(self, setting, obj, atrb): + """Callback: Convert single char string to u8""" + b0 = str(setting.value) + vx = ord(b0) + setattr(obj, atrb, vx) + return + + def get_memory(self, number): + mem = chirp_common.Memory() + if number < 1000: # channel memory + _mem = self._memobj.main[number - 1] + _tag = self._memobj.names[number - 1] + else: + _mem = self._memobj.pms[number - 1000] + _tag = self._memobj.pms_name[number - 1000] + mem.number = number + if mem.number == 1: + mem.immutable += ["empty"] + if not _mem.used: + mem.empty = True + return mem + mem.freq = self._freqdcode(_mem.freq) + mem.rtone = chirp_common.TONES[_mem.rtone] + mem.mode = self.MODES[_mem.mode] + mem.duplex = self.DUPLEX[_mem.duplex] + if (_mem.duplex == 4): # Split mode + mem.offset = self._freqdcode(_mem.frqtx) + else: + mem.offset = int(_mem.offset) * 50000 + # Re-map funky radio tone and cross-modes + tmd = _mem.tmode # 0,1,2 + cmx = 0 + if _mem.tmode == 3: # DCS + tmd = 5 # Cross + cmx = 0 # -> DTCS + if _mem.tmode == 4: # Rev Tone + tmd = 3 # TSQL-R + if _mem.tmode == 5: # PR Freq + tmd = 1 + if _mem.tmode == 6: # Pager + tmd = 1 + if _mem.tmode == 7: # Tx DTCS, Open RX + tmd = 4 # DTCS + elif _mem.tmode == 8: # Tone - DCS + tmd = 5 # Cross + cmx = 1 # Tone -> DTCS + elif _mem.tmode == 9: # D CD-> Tone + tmd = 5 # Cross + cmx = 2 # DTCS->Tone + mem.tmode = self.TMODES[tmd] + mem.cross_mode = self.CROSS_MODES[cmx] + mem.skip = self.SKIPS[_mem.skip] + mem.dtcs = chirp_common.DTCS_CODES[_mem.dtcs] + vx = _mem.power + mem.power = self.POWER_LEVELS[vx] + mem.tuning_step = self.T_STEPS[_mem.step] + tx = self._b2s(_tag.chname, 0xff).strip() + if self.FTM200 == False: tx = tx.upper() + mem.name = tx + # Echo name string back into memory. + # In case it got loaded flakey in radio; trailing spaces + for i in range(0, self.NAME_LEN): + if i < len(mem.name): + _tag.chname[i] = ord(mem.name[i]) + else: + _tag.chname[i] = 0xff + # mem.extra: Clock Type A/B + mem.extra = RadioSettingGroup("extra", "Extra") + options = ["Auto", "On"] + rx = RadioSettingValueList(options, options[_mem.clktyp]) + rs = RadioSetting("clktyp", "Clock Shift (CLK.TYP)", rx) + mem.extra.append(rs) + + options = ["None", "REV Tone", "PR Freq", "Pager"] + tmd = _mem.tmode - 3 + if _mem.tmode < 4: tmd = 0 + if _mem.tmode > 6: tmd = 0 + rx = RadioSettingValueList(options, options[tmd]) + rs = RadioSetting("spclmode", "Radio Special Tone Mode", rx) + mem.extra.append(rs) + + options = [] + for vx in range(300, 3100, 100): + sx = str(vx) + options.append(sx) + if _mem.prfreq > 30: _mem.prfreq = 30 # Can get loaded wrong...? + if _mem.prfreq < 3: _mem.prfreq = 3 + v0 =_mem.prfreq * 100 # .prfreq is 0x03 - 0x1E (3 -30 decimal) + sx = str(v0) + rx = RadioSettingValueList(options, sx) + rs = RadioSetting("prfreq", "PR (User) Freq Htz", rx) + mem.extra.append(rs) + return mem + + def set_memory(self, mem): + if mem.number < 1000: + _mem = self._memobj.main[mem.number - 1] + _tag = self._memobj.names[mem.number - 1] + else: + _mem = self._memobj.pms[mem.number - 1000] + _tag = self._memobj.pms_name[mem.number - 1000] + if mem.empty: # Chan 1 is immutable for empty + _mem.used = 0 + return mem + _mem.used = 1 + _mem.freq = self._freqncode(mem.freq) + _mem.mode = self.MODES.index(mem.mode) + _mem.duplex = self.DUPLEX.index(mem.duplex) + if _mem.duplex == 4: # split mode + _mem.frqtx = self._freqncode(mem.offset) + else: + _mem.offset = mem.offset / 50000 + tmd = 0 # no tone + sqlx = 0 + # Re-map Tmode and Cross mode to radio combined + # Using MY TMODE list index + tx = mem.tmode.strip() + cmx = mem.cross_mode.strip() + if tx == "Cross": + if cmx == "->DTCS": tmd = 3 + if cmx == "Tone->DTCS": tmd = 8 + if cmx == "DTCS->Tone": tmd = 9 + sqlx = 1 + else: + if tx == "Tone": tmd = 1 + if tx == "TSQL": tmd = 2 + if tx == "TSQL-R": tmd = 4 + if tx == "DTCS": tmd = 7 + _mem.tmode = tmd + _mem.rtone = chirp_common.TONES.index(mem.rtone) + _mem.step = self.T_STEPS.index(mem.tuning_step) + _mem.skip = self.SKIPS.index(mem.skip) + _mem.dtcs = chirp_common.DTCS_CODES.index(mem.dtcs) + sx = mem.power + if sx == None: sx = self.POWER_LEVELS[1] # Mid + _mem.power = self.POWER_LEVELS.index(sx) + setattr(self._memobj.setts, "sqlexp1", sqlx) + setattr(self._memobj.setts, "sqlexp2", sqlx) + tx = self.filter_name(mem.name) + for i in range(0, self.NAME_LEN): + if i < len(tx): + _tag.chname[i] = ord(tx[i]) + else: + _tag.chname[i] = 0xff + for setting in mem.extra: + if setting.get_name() == "clktyp": + sx = str(setting.value) + vx = 0 + if sx == "On": vx = 1 + setattr(_mem, "clktyp", vx) + if setting.get_name() == "spclmode": + sx = str(setting.value) + tmd = 0 + tx = mem.tmode + if sx == "None": + if tx == "PR Freq" or tx == "Pager": + tmd = 0 # Reset from special to none + else: + tmd = _mem.tmode # no change + if sx == "PR Freq": tmd = 5 + if sx == "Pager": tmd = 6 + setattr(_mem, "tmode", tmd) + if setting.get_name() == "prfreq": + sx = str(setting.value) + vx = int(sx) // 100 + setattr(_mem, "prfreq", vx) + return + + def _micpkey(self, setting, obj, atrb, opts): + """Callback: Adjust stored value for microphone P keys""" + sx = str(setting.value) # the list string + v0 = opts.index(sx) # the options array index, 0-based + v1 = v0 + 0xdc + if self.FTM200 == False: + v1 = v0 + 0xdd + if v1 == 0xe6: v1 = 0xe7 # skip e6 + setattr(obj, atrb, v1) + return + + def _setfunc(self, setting, obj, atrb, ndx): + """Callback: Convert boolean to function setting""" + # Stored in shared memory 'share1' as 2 bytes. + # When set: first byte is menu number, 2nd is 00 + # Unset: ff, ff + bx = bool(setting.value) # boolean + # ndx is 0-based menu number + x1 = ndx * 2 # _shr index of first byte + v0 = 0xff # disabled + v1 = 0xff + if bx: + v0 = ndx + v1 = 0 + setattr(obj[x1], atrb, v0) + setattr(obj[x1 + 1], atrb, v1) + return + + def _setQA(self, setting, obj, atrb, opts): + """Callback: FTM-200 menu list selection to menu code""" + sx = str(setting.value) + v0 = opts.index(sx) + setattr(obj, atrb, v0) + return + + def _sqlexp1(self, setting, obj, atrb): + """ Callback: SQL.EXP requires setting two objects """ + sx = str(setting.value) + bx = False + if sx == "On": bx = True + setattr(obj, atrb, bx) # sqlexp1 + setattr(obj, "sqlexp2", bx) + return + + def _settot(self, setting, obj, atrb, opts): + """Callback: convert non-linear TOT values""" + sx = str(setting.value) + v0 = opts.index(sx) + v1 = v0 + if v0 > 0: v1 = v0 + 5 + if v0 > 3: v1 = v0 - 3 + setattr(obj, atrb, v1) + return + + def _adjint(self, setting, obj, atrb): + """Callback: decrement integer value to 0-based""" + v0 = int(setting.value) + v1 = v0 - 1 + setattr(obj, atrb, v1) + return + + def _unpack_str(self, codestr): + """Convert u8 DTMF array to a string: NOT a callback.""" + sx = "" + for i in range(0, 16): # unpack up to ff + if codestr[i] != 0xff: + if codestr[i] == 0x0E: + sx += "*" + elif codestr[i] == 0x0F: + sx += "#" + else: + sx += format(int(codestr[i]), '0X') + return sx + + def _pack_chars(self, setting, obj, atrb, ndx): + """Callback to build 0-9,A-D,*# nibble array from string""" + # String will be ff padded to 16 bytes + # Chars are stored as hex values + ary = [] + sx = str(setting.value).upper().strip() + sx = sx.strip() # trim spaces + # Remove illegal characters first + sty = "" + for j in range(0, len(sx)): + if sx[j] in self.DTMF_CHARS: + sty += sx[j] + for j in range(0, 16): + if j < len(sty): + if sty[j] == "*": + chrv = 0xE + elif sty[j] == "#": + chrv = 0xF + else: + chrv = int(sty[j], 16) + else: # pad to 16 bytes + chrv = 0xFF + ary.append(chrv) # append byte + setattr(obj[ndx], atrb, ary) + return + + def _pmgset(self, setting, obj, ndx): + """Callback: Convert pmg chan to 0-based, and store """ + v0 = int(setting.value) + if v0 == 0: # Deleted + setattr(obj[ndx], "za", 0xff) + setattr(obj[ndx], "fb", 0xff) + setattr(obj[ndx], "chnp", 0) + return + v1 = v0 - 1 # 0-based + setattr(obj[ndx], "za", 0) + setattr(obj[ndx], "fb", 0xff) + setattr(obj[ndx], "chnp", v1) + return + + def _adjlist(self, setting, obj, atrb, opts, ofst): + """Callback: Universal add/subtract list index""" + sx = str(setting.value) # the list string + vx = opts.index(sx) + ofst + if atrb == "tzone": # special case for time zone + if vx < 0 : vx = abs(vx) + 0x80 + setattr(obj, atrb, vx) + return + + def _ft2apo(self, setting, obj): + """Callback: Set FTM-200 APO coded decimal in 2 bytes""" + sx = str(setting.value) # Ex '1.5 Hours' + if sx == "Off": + setattr(obj, "apo", 0) + setattr(obj, "apo1", 0) + return + if "." in sx: + vx = sx.index(".") + v1 = int("0x" + sx[:vx], 16) # encode as hcd + v2 = 1 + else: + vx = sx.index(" H") + v1 = int(sx[:vx]) + v2 = 0 + setattr(obj, "apo", v1) + setattr(obj, "apo1", v2) + return + + def _ft2lcd(self, setting, obj, atrb): + """Callback: to set LCD Display Brightness""" + sx = str(setting.value) + v0 = 0 + if sx == "Mid": v0 = 1 + if sx == "Max": vo = 2 + setattr(obj, atrb, v0) + return + + def _scndrm(self, setting, obj): + """Callback:FTM-200 Scan Dual Rcv Mode """ + # Requires setting a bit in 2 bytes + sx = str(setting.value) + v0 = 0 + v1 = 0 + if "Pri" in sx: v0 = 1 + if "A-B" in sx: v1 = 1 + setattr(obj, "scndrm1", v0) + setattr(obj, "scndrm2", v1) + return + + def _skp_other(self, setting, obj, bnd, opts): + """Callback: FTM-200 Band Skip Other requires 2 bits""" + sx = str(setting.value) #Off/On + v0 = 0 + if "On" in sx: v0 = 1 + b0 = "bskpa0" + b3 = "bskpa3" + if "B" in bnd: + b0 = "bskpb0" + b3 = "bskpb3" + setattr(obj, b0, v0) + setattr(obj, b3, v0) + return + + def _beepset(self, setting, obj, optns): + """Callback: Stupid split-beep""" + sx = str(setting.value) + vx = optns.index(sx) # 0,1,2 + v0 = vx & 1 # Off/Low + v1 = 0 # High + if vx == 2: + v0 = 1 + v1 = 1 + setattr(obj, "beep1", v0) + setattr(obj, "beep2", v1) + return + + def _xmsg(self, setting, obj, indx, xmp, mode = 0): + """Callback: Wires-X message # indx, text encoder """ + # mode=0 is GM Message, mode=1 is Category + sx = str(setting.value).strip() + tx = b"" + v0 = 128 + v1 = 0xff + hx = "msg%02d" % indx + if mode == 1: + v0 =16 + v1 = 0xca + hx = "c%d" % indx + for cx in range(0, v0): + if cx < len(sx): + vx = sx[cx] + try: + v2 = xmp.index(vx) + except: + raise Exception("Unable to decode character hex %x at " + "index %d of %s" % (vx, cx, hx)) + tx += util.int_to_byte(v2) + else: + tx += util.int_to_byte(v1) # pad + setattr(obj, hx, tx) + return + + def _wrxfrq(self, setting, obj, atrb): + """Callback: Encode the 3-byte non-mem channel frequency""" + vx = float(setting.value) * 1000000 + bx = self._freqncode(vx) + setattr(obj, atrb, bx) + return + + def _aprsfx(self, setting, obj, atrb, pad): + """Callback: Trap the APRS callsign SSID""" + v0 = int(setting.value) + vx = v0 + if (pad == 0xca) and (v0 == 0): vx = pad + if (pad == 0x2a) and (v0 == 16): vx = pad + setattr(obj, atrb, vx) + return + + def _aprspop(self, setting, obj, atrb): + """Callback: APRS Beacon and Message Popup times; not 1:1""" + # Can these radiso get any wierder? + vx = int(setting.value) + v0 = 0 # Off + if vx == 1: v0 = 3 + if vx == 2: v0 = 5 + if vx == 3: v0 = 10 + if vx == 4: v0 = 0xff # Hold + setattr(obj, atrb, v0) + return + + def _enchcd(self, setting, obj, atrb): + """Callback: Generic convert 1-byte decimal value to hex-coded""" + sx = str(setting.value) # Decimal value, Ex: "33" + v0 = int("0x" + sx, 16) # encode as hcd 0x33 + setattr(obj, atrb, v0) + return + + def _mdot(self, setting, obj, atrb1, atrb2): + """Callback: Convert lat/long mm/mm to u8 and u16""" + # Half as hex coded decimal, half as binary !!?? + vx = float(setting.value) # mm.mm + tx = math.modf(vx) + sx= str(int(tx[1])) + v0 = int("0x" + sx, 16) # hcd + v1 = int(tx[0] * 1000) # 2-byte binary + setattr(obj, atrb1, v0) + setattr(obj, atrb2, v1) + return + + def _getdgpath(self, pn): + """Method for extracting Digipeater route paths""" + # pn is path number 0 - 5 + _shr = self._memobj.share1 + sx = "" + x1 = pn * 8 + for i in range(x1, x1 + 6): # route name: 6 bytes + v0 = _shr[i].shbyt + if v0 != 0xca: sx += chr(v0) + vx = _shr[x1 + 6].shbyt # route suffix 0-15 + if vx == 0xca: vx = 0 + return sx, vx + + def _putdgpname(self, setting, pn): + """Callback: store Digipath name""" + # Stored in 'share1' shared memory + # pn is path number 0-5 + _shr = self._memobj.share1 + sx = str(setting.value) # modified path name; 0-6 chars + sx = sx.upper().strip() + x1 = pn * 8 # starting position in _shr + sp = 0 + for i in range(x1, x1 + 6): + if sp >= len(sx): + v1 = 0xca + else: + v1 = ord(sx[sp]) + setattr(_shr[i], "shbyt", v1) + sp +=1 + return + + def _putdgpsfx(self, setting, pn): + """Callback: Digipath, Ringer SSID""" + _shr = self._memobj.share1 + v1 = int(setting.value) + x1 = pn * 8 + 6 + setattr(_shr[x1], "shbyt", v1) + return + + def _rnglmt(self, setting, obj, atrb): + """Callback: APRS Beacon Range Limits""" + v1 = int(setting.value) # index + vx = v1 # for 0, 1 + if atrb == "aprbrrr": # Range Ringer + if v1 == 2: vx = 5 + if v1 == 3: vx = 10 + if v1 == 4: vx = 50 + if v1 == 5: vx = 100 + else: # Filter Range + if v1 == 2: vx = 10 + if v1 == 3: vx = 100 + if v1 == 4: vx = 1000 + if v1 == 5: vx = 3000 + setattr(obj, atrb, vx) + return + + def _datefmt(self, setting, obj, atrb): + """Callback: Stupid index jump in date format list""" + vx = int(setting.value) + if vx == 3: vx = 4 + setattr(obj, atrb, vx) + return + + def get_settings(self): + _setx = self._memobj.setts + _mic = self._memobj.micset + _wierd = self._memobj.wierd + _dtm = self._memobj.dtmfcode + _pmg = self._memobj.pmg + + cfg = RadioSettingGroup("cfg", "Config") + dsp = RadioSettingGroup("dsp", "Display") + fmenu = RadioSettingGroup("fmnu", "Quick Functions") + mic = RadioSettingGroup("mic", "Microphone") + sig = RadioSettingGroup("sig", "Signalling") + dat = RadioSettingGroup("dat", "Data") + opts = RadioSettingGroup("opts", "Options") + dtmf = RadioSettingGroup("dtmf", "DTMF") + scan = RadioSettingGroup("scan", "Scanning") + wires = RadioSettingGroup("wires", "GM/WIRES-X") + aprscom = RadioSettingGroup("aprscom", "APRS Settings") + aprsdgp = RadioSettingGroup("aprsdgp", "APRS Digipeater") + aprsmsg = RadioSettingGroup("aprsmsg", "APRS Messages") + bcnfltr = RadioSettingGroup("bcnfltr", "APRS Beacon Filter") + bcnunit = RadioSettingGroup("bcnunit", "APRS Beacon Units") + bcnrngr = RadioSettingGroup("bcnrngr", "APRS Beacon Ringer") + bcnstat = RadioSettingGroup("bcnstat", "APRS Beacon Status") + bcnsmrt = RadioSettingGroup("bcnsmrt", "APRS Smart Beaconing") + other = RadioSettingGroup("other", "Other") + + if self.FTM200: + group = RadioSettings(cfg, dsp, fmenu, mic, sig, opts, dtmf, + scan, dat, wires, aprscom, aprsmsg, + aprsdgp, bcnfltr, bcnunit, bcnrngr, + bcnstat, bcnsmrt, other) + else: + group = RadioSettings(cfg, dsp, fmenu, mic, sig, opts, dtmf, + scan) + + menu_items = ["01: Auto Power Off (APO)", "02: ARTS Mode", + "03: ARTS Interval", "04: Busy Channel Lockout (BCLO)", + "05: Beep", "06: Bell", "07: Clock Type","08: LCD Dimmer", + "09: DTMF Manual/Auto", "10: DTMF TX", "11:DTMF Codes", + "12: Home", "13: Microphone Gain", "14: Microphone P Keys", + "15: Pager TX/RX","16: Packet Speed", "17:RX Mode", + "18: Band Select", "19: Repeater Reverse", + "20: Repeater Set", "21: Repeater Other", "22: Scan On", + "23: Scan Type", "24: Squelch Type", "25:Squelch Code", + "26: Squelch Expansion", "27: Step", + "28: Radio Temperature", "29: Time Out Timer (TOT)", + "30: TX Power", "31: Version", "32: Voltage", "33: Width", + "34: Weather Alert", "35: Bluetooth"] + offon = ["Off", "On"] + onoff = ["On", "Off"] # Inverted logic + + # Begin Config settings + if self.FTM200: + + sx = self._b2s(_mic.csign, 0xff) + rx = RadioSettingValueString(0,10, sx, False) + rs = RadioSetting("micset.csign", "Call Sign Label", rx) + rs.set_apply_callback(self._s2b, _mic, "csign", 10) + cfg.append(rs) + + options = ["yyyy/mmm/dd", "yyyy/dd/mmm", "mmm/dd/yyyy", + "dd/mmm/yyyy"] + vx = _setx.datefmt + if vx == 4: vx = 3 # Just to make my life difficult! + rx = RadioSettingValueList(options, options[vx]) + rs = RadioSetting("setts.datefmt", "Date Format", rx) + rs.set_apply_callback(self._datefmt, _setx, "datefmt") + cfg.append(rs) + + options = ["24 Hour", "12 Hour"] + rx = RadioSettingValueList(options, options[_setx.timefmt]) + rs = RadioSetting("setts.timefmt", "Time Format", rx) + cfg.append(rs) + + options = [] + v0 = -14.0 + for vx in range(0, 57): + options.append(str(v0)) + v0 += 0.5 + v0 = _setx.tzone + v1 = v0 + 28 # positive offset; index 28 is GMT + if v0 & 0x80: # negative, before GMT + v1 = 28 - (v0 & 0x1f) + rx = RadioSettingValueList(options, options[v1]) + rs = RadioSetting("setts.tzone", "Time Zone GMT +/- hours", rx) + rs.set_apply_callback(self._adjlist, _setx, "tzone", options, -28) + cfg.append(rs) + + rx = RadioSettingValueList(offon, offon[_setx.rpt_ars]) + rs = RadioSetting("setts.rpt_ars", + "A: Repeater Auto Offset Enabled", rx) + cfg.append(rs) + rx = RadioSettingValueList(offon, offon[_setx.rpt_arsb]) + rs = RadioSetting("setts.rpt_arsb", + "B: Repeater Auto Offset Enabled", rx) + cfg.append(rs) + + options = ["Off", "0.5 Hours", "1 Hours", "1.5 Hours", "2 Hours", + "3 Hours", "4 Hours", "5 Hours", "6 Hours", "7 Hours", + "8 Hours", "9 Hours", "10 Hours", "11 Hours", "12 Hours"] + v0 = _setx.apo # Hours BCD + v1 = _setx.apo1 # 0.5 hours yes/no + sx = "%d" % v0 + if v1: sx += ".5" + if sx == "0": + sx = "Off" + else: + sx += " Hours" + rx = RadioSettingValueList(options, sx.strip()) + rs = RadioSetting("setts.apo", "Auto Power Off time (APO)", rx) + rs.set_apply_callback(self._ft2apo, _setx) + cfg.append(rs) + + else: # FTM-6000, different than 200 + rx = RadioSettingValueList(menu_items, menu_items[_setx.f1key]) + rs = RadioSetting("setts.f1key", "F1 Key Assignment", rx) + cfg.append(rs) + + options = ["Off", "1 Hours", "1.5 Hours", "2 Hours", "3 Hours", + "4 Hours", "5 Hours", "6 Hours", "7 Hours", "8 Hours", + "9 Hours", "10 Hours", "11 Hours", "12 Hours"] + rx = RadioSettingValueList(options, options[_setx.apo]) + rs = RadioSetting("setts.apo", "Auto Power Off time (APO)", rx) + cfg.append(rs) + + rx = RadioSettingValueList(offon, offon[_setx.rpt_ars]) + rs = RadioSetting("setts.rpt_ars", "Repeater Auto Offset Enabled", + rx) + cfg.append(rs) + + # Config - Common to all radios + + options = ["Off", "Low", "High"] + # Yaesu splits the beep!!! + vx = _setx.beep1 # Off/Low + if _setx.beep2: vx = 2 # High + rx = RadioSettingValueList(options, options[vx]) + rs = RadioSetting("setts.beep1", "Beep", rx) + rs.set_apply_callback(self._beepset, _setx, options) + cfg.append(rs) + + options = ["Off", "1 minute", "2 minutes", "3 minutes", "5 minutes", + "10 minutes", "15 minutes", "20 minutes", "30 minutes"] + vx = _setx.tot # non-sequential index + if vx >= 6: bx = vx - 5 + if vx >= 1: bx = vx + 3 + if vx == 0: bx = 0 + rx = RadioSettingValueList(options, options[bx]) + rs = RadioSetting("setts.tot", "Transmit Time Out Timer (TOT)", rx) + rs.set_apply_callback(self._settot, _setx, "tot", options) + cfg.append(rs) + + if self.FTM200: # Stuff at the end of Config + options = ["Metric", "Imperial (Inch)"] + rx = RadioSettingValueList(options, options[_setx.unit]) + rs = RadioSetting("setts.unit", "Units", rx) + cfg.append(rs) + + options = ["WGS 84", "Tokyo Mean"] + rx = RadioSettingValueList(options, options[_setx.gpsdtm]) + rs = RadioSetting("setts.gpsdtm", "GPS Datum", rx) + cfg.append(rs) + + options = ["Internal", "External"] + rx = RadioSettingValueList(options, options[_setx.gpsdev]) + rs = RadioSetting("setts.gpsdev", "GPS Device", rx) + cfg.append(rs) + + options = ["Off", "1 second", "2 sec", "5 sec", "10 sec", + "30 sec", "60 sec"] + rx = RadioSettingValueList(options, options[_setx.gpslog]) + rs = RadioSetting("setts.gpslog", "GPS Log Interval", rx) + cfg.append(rs) + + else: + options = ["30 Seconds", "1 Minute"] + rx = RadioSettingValueList(options, options[_setx.arts_int]) + rs = RadioSetting("setts.arts_int", "ARTS Interval", rx) + cfg.append(rs) + + options = ["Off", "In Range", "Out Range"] + rx = RadioSettingValueList(options, options[_setx.arts_mode]) + rs = RadioSetting("setts.arts_mode", "ARTS Mode", rx) + cfg.append(rs) + + rx = RadioSettingValueList(offon, offon[_setx.bclo]) + rs = RadioSetting("setts.bclo", "Busy Channel Lockout (BCLO)", + rx) + cfg.append(rs) + + # End of Config settings + + # Start of Display settings + if self.FTM200: + options = ["Backtrack", "Altitude", "Timer/Clock", "GPS Info"] + rx = RadioSettingValueList(options, options[_setx.dspmode]) + rs = RadioSetting("setts.dspmode", "Display Select", rx) + dsp.append(rs) + + options = ["Compass", "Numeric Lat/Long"] + rx = RadioSettingValueList(options, options[_setx.locinfo]) + rs = RadioSetting("setts.locinfo", "Location Info", rx) + dsp.append(rs) + + options = ["North Up", "Heading Up"] + rx = RadioSettingValueList(options, options[_mic.compass]) + rs = RadioSetting("micset.compass", "Compass Display", rx) + dsp.append(rs) + + options = ["Wide", "Narrow"] + rx = RadioSettingValueList(options, options[_setx.bscope]) + rs = RadioSetting("setts.bscope", "A: Display Scope", rx) + dsp.append(rs) + rx = RadioSettingValueList(options, options[_setx.bscopeb]) + rs = RadioSetting("setts.bscopeb", "B: Display Scope", rx) + dsp.append(rs) + + rx = RadioSettingValueList(offon, offon[_setx.memlist]) + rs = RadioSetting("setts.memlist", "Memory List Mode", rx) + dsp.append(rs) + + options = ["Min", "Mid", "Max"] + vx = _mic.lcd # stupid indexing: 3,1,2 + v0 = vx # Mid: vx = 1, Max: vx = 2 + if vx == 3: v0 = 0 + rx = RadioSettingValueList(options, options[v0]) + rs = RadioSetting("micset.lcd", "Display Brightness", rx) + rs.set_apply_callback(self._ft2lcd, _mic, "lcd") + dsp.append(rs) + + options = ["White", "Blue", "Red"] + rx = RadioSettingValueList(options, options[_setx.lcd_clr]) + rs = RadioSetting("setts.lcd_clr", "LCD Upper Band Color", rx) + dsp.append(rs) + + else: # FTM-6000 + options = ["Dim", "Mid", "Full"] + rx = RadioSettingValueList(options, options[_mic.lcd]) + rs = RadioSetting("micset.lcd", "Display Brightness", rx) + dsp.append(rs) + + # End of Display settings + + # Start of Signalling settings + options = ["Off", "1 Time", "3 Times", "5 Times", "8 Times", + "Continous"] + if self.FTM200: + rx = RadioSettingValueList(options, options[_mic.bell]) + rs = RadioSetting("micset.bell", + "A: Remote Station Calling Bell", rx) + sig.append(rs) + rx = RadioSettingValueList(options, options[_mic.bellb]) + rs = RadioSetting("micset.bellb", + "B: Remote Station Calling Bell", rx) + sig.append(rs) + else: + rx = RadioSettingValueList(options, options[_mic.bell]) + rs = RadioSetting("micset.bell", "Remote Station Calling Bell", + rx) + sig.append(rs) + + # All radios, Signalling opetions + vx = _mic.pgrcdr1 + 1 + rx = RadioSettingValueInteger(1, 50, vx) + rs = RadioSetting("micset.pcrcdr1", "Pager Receive First Code", rx) + rs.set_apply_callback(self._adjint, _mic, "pgrcdr1") + sig.append(rs) + + vx = _mic.pgrcdr2 + 1 + rx = RadioSettingValueInteger(1, 50, vx) + rs = RadioSetting("micset.pcrcdr2", "Pager Receive Second Code", rx) + rs.set_apply_callback(self._adjint, _mic, "pgrcdr2") + sig.append(rs) + + rx = RadioSettingValueInteger(1, 50, vx) + rs = RadioSetting("micset.pgrcdt1", "Pager Transmit First Code", rx) + rs.set_apply_callback(self._adjint, _mic, "pgrcdt1") + sig.append(rs) + + vx = _mic.pgrcdt2 + 1 + rx = RadioSettingValueInteger(1, 50, vx) + rs = RadioSetting("micset.pgrcdt2", "Pager Transmit Second Code", rx) + rs.set_apply_callback(self._adjint, _mic, "pgrcdt2") + sig.append(rs) + + rx = RadioSettingValueList(offon, offon[_setx.wxalrt]) + rs = RadioSetting("setts.wxalrt", "Weather Alert Enabled", rx) + sig.append(rs) + + # End of Signalling settings + + # Begin fmenu settings For each entry in menu_Items + if self.FTM200: # 124 menu options possible + options = ["1:Freq Input", "2:LCD Brightness", "3:Freq Color", + "4:Band Scope", "5:Location Info", "6:Compass", + "7:Display Mode"] + more = ("8:TX Power", "9:AMS TX Mode", "10:Mic Gain", "11:VOX", + "12:Auto Dialer", "13:Time Out Timer (TOT)", + "14:Digital VW") + options.extend(more) + more = ("15:FM Bandwidth", "16:RX Mode", "17:Home", + "18:Memory List", "19:Memory List Mode", "20:PMG Clear") + options.extend(more) + more = ("21:Beep", "22:Band Skip", "23:RPT ARS", "24:RPT Shift", + "25:RPT Shift Freq", "26:Rpt Reverse", "27:Mic P Key", + "28:Date & Time Adjust", "29:Date &Time Format", + "30:Time Zone", "31:Step", "32:Clock Type", "33:Unit", + "34:Auto Power Off (APO)", "35:GPS Datum", + "36:GPS Device", "37:GPS Log") + options.extend(more) + more = ("38:Audio Recording", "39:Audio Rec Stop") + options.extend(more) + more = ("40:DTMF Mode", "41:DTMF Memory", "42:SQL Type", + "43:Tone Freq / DCS Code", "44:SQL Expansion", + "45:Pager Code", "46:PR Freq", "47:Bell Ringer", + "48:WX Alert") + options.extend(more) + more = ("49:Scan", "50:Dual Rcv Mode", "51:Dual Rx Interval", + "52:Priority Revert", "53:Scan Resume") + options.extend(more) + more = ("54:Digital Popup", "55:Location Service", + "56:Standy Beep", "57:GM FP-ID List", "58:Range Ringer", + "59:Radio ID", "60:Log List", "61:Rpt / WIRES Freq", + "62:Search Step", "63:Edit Category Tag", + "64:Delete Room/Mode", "65:WIRES Dg-ID", "66:Com Port", + "67:Data Band", "68:Data Speed", "69:Data SQL") + options.extend(more) + more = ("70:APRS Destination", "71:Filter", "72:Msg Text", + "73:APRS On/Off", "74:Mute", "75:Popup", "76:Ringer", + "77:Ringer CS", "78:TX Delay", "79:Units", + "80:Beacon Info", "81:Beacon Status Txt", + "82:Beacon TX Set", "83:DIGI Path", "84:DIGI Path 1", + "85:DIGI Path 2", "86:DIGI Path 3", "87:DIGI Path 4", + "88:DIGI Path Full 1", "89: DIGI Path Full 2") + options.extend(more) + more = ("90:APRS Call Sign", "91:Msg Group", "92:Msg Reply", + "93:My Position Set", "94:My Position", "95:My Symbol", + "96:Position Comment", "97:Smart Beaconing", + "98:Sort Filter", "99:Voice alert", "100:Station List", + "101:Msg List", "102:Beacon TX Select", "103:Beacon TX") + options.extend(more) + more = ("104:SD Card Backup", "105:SD Card Mem Info", + "106:SD Card Format", "107:Bluetooth", "108:Voice Memory", + "109:FVS Rec", "110:Track Select", "111:Play", + "112:Stop", "113:Clear", "114:Voice Guide", + "115:USB Camera") + options.extend(more) + more = ("116:This->Other", "117:Other->This", "118:Call Sign", + "119:Mem Chn Reset", "120:APRS Reset", "121:Config Set", + "122:Config Recall", "123:SW Version", + "124:Factory Reset") + options.extend(more) + rx = RadioSettingValueList(options, options[_mic.fkp1]) + rs = RadioSetting("micset.fkp1", "Keypad Slot 1", rx) + rs.set_apply_callback(self._setQA, _mic, "fkp1", options) + fmenu.append(rs) + rx = RadioSettingValueList(options, options[_mic.fkp2]) + rs = RadioSetting("micset.fkp2", "Keypad Slot 2", rx) + rs.set_apply_callback(self._setQA, _mic, "fkp2", options) + fmenu.append(rs) + rx = RadioSettingValueList(options, options[_mic.fkp3]) + rs = RadioSetting("micset.fkp3", "Keypad Slot 3", rx) + rs.set_apply_callback(self._setQA, _mic, "fkp3", options) + fmenu.append(rs) + rx = RadioSettingValueList(options, options[_mic.fkp4]) + rs = RadioSetting("micset.fkp4", "Keypad Slot 4", rx) + rs.set_apply_callback(self._setQA, _mic, "fkp4", options) + fmenu.append(rs) + + rx = RadioSettingValueList(options, options[_mic.fhm1]) + rs = RadioSetting("micset.fhm1", "Home Slot 1", rx) + rs.set_apply_callback(self._setQA, _mic, "fhm1", options) + fmenu.append(rs) + rx = RadioSettingValueList(options, options[_mic.fhm2]) + rs = RadioSetting("micset.fhm2", "Home Slot 2", rx) + rs.set_apply_callback(self._setQA, _mic, "fhm2", options) + fmenu.append(rs) + rx = RadioSettingValueList(options, options[_mic.fhm3]) + rs = RadioSetting("micset.fhm3", "Home Slot 3", rx) + rs.set_apply_callback(self._setQA, _mic, "fhm3", options) + fmenu.append(rs) + rx = RadioSettingValueList(options, options[_mic.fhm4]) + rs = RadioSetting("micset.fhm4", "Home Slot 4", rx) + rs.set_apply_callback(self._setQA, _mic, "fhm4", options) + fmenu.append(rs) + else: # FTM-6000 + _shr = self._memobj.share1 + for mnu in range(0, 35): + x1 = mnu * 2 # _shr index of first byte + vx = _shr[x1].shbyt + bx = False + if vx != 0xff: bx = True + sx = "share1/%d.shbyt" % mnu + rx = RadioSettingValueBoolean(bx) + rs = RadioSetting(sx, menu_items[mnu], rx) + fmenu.append(rs) + rs.set_apply_callback(self._setfunc, _shr, "shbyt", mnu) + # End fmenu settings + + # Begin microphone settings + options = ["Min", "Low", "Normal", "High", "Max"] + rx = RadioSettingValueList(options, options[_mic.micgain]) + rs = RadioSetting("micset.micgain", "Microphone Gain", rx) + mic.append(rs) + + options = ["ARTS", "SCAN On", "HOME Recall", "Repeater Duplex", + "Repeater Reverse", "Transmit Power", "Squelch Off", + "T-Call", "Dual Watch", "Weather Channel"] + if self.FTM200: + options = ["Off", "Band Scope", "Scan", "Home", "Rpt Shift", + "Reverse", "TX Power", "SQL Off", "T-Call", "Voice", + "D_X", "WX", "Stn_List", "Msg List", "Reply", + "M-Edit"] + + else: # FTM200- P1 is fixed as GM, immutable + vx = _mic.micp1- 0xdd + if vx == 10: vx = 9 # stupid index jump + rx = RadioSettingValueList(options, options[vx]) + rs = RadioSetting("micset.micp1", "Microphone Key P1", rx) + rs.set_apply_callback(self._micpkey, _mic, "micp1", options) + mic.append(rs) + + vx = _mic.micp2 - 0xdd + if vx == 10: vx = 9 + if self.FTM200: + vx = _mic.micp2 - 0xdc + rx = RadioSettingValueList(options, options[vx]) + rs = RadioSetting("micset.micp2", "Microphone Key P2", rx) + rs.set_apply_callback(self._micpkey, _mic, "micp2", options) + mic.append(rs) + + vx = _mic.micp3 - 0xdd + if vx == 10: vx = 9 + if self.FTM200: + vx = _mic.micp3 - 0xdc + rx = RadioSettingValueList(options, options[vx]) + rs = RadioSetting("micset.micp3", "Microphone Key P3", rx) + rs.set_apply_callback(self._micpkey, _mic, "micp3", options) + mic.append(rs) + + vx = _mic.micp4 - 0xdd + if vx == 10: vx = 9 + if self.FTM200: + vx = _mic.micp4 - 0xdc + rx = RadioSettingValueList(options, options[vx]) + rs = RadioSetting("micset.micp4", "Microphone Key P4", rx) + rs.set_apply_callback(self._micpkey, _mic, "micp4", options) + mic.append(rs) + # End mic settings + + # Begin DTMF settings + options = ["Manual", "Auto"] + rx = RadioSettingValueList(options, options[_setx.dtmf_auto]) + rs = RadioSetting("setts.dtmf_auto", "DTMF Transmit Mode", rx) + dtmf.append(rs) + + for kx in range(0, 9): + sx = self._unpack_str(_dtm[kx].codes) + rx = RadioSettingValueString(0, 16, sx, False) + # NOTE the / to indicate indexed array + vx = kx + 1 + rs = RadioSetting("dtmfcode/%d.codes" % kx, + "DTMF Code %d" % vx, rx) + rs.set_apply_callback(self._pack_chars, _dtm, "codes", kx) + dtmf.append(rs) + # End of dtmf settings + + # Begin Scan settings + if self.FTM200: + options = ["Busy", "Hold", "1 Second", "3 Seconds", "5 Seconds"] + rx = RadioSettingValueList(options, options[_setx.scnrsm2a]) + rs = RadioSetting("setts.scnrsm2a", "A: Scan Resume Mode", rx) + scan.append(rs) + rx = RadioSettingValueList(options, options[_setx.scnrsm2b]) + rs = RadioSetting("setts.scnrsm2b", "B: Scan Resume Mode", rx) + scan.append(rs) + + options = ["0.5 seconds","1 sec","2 sec" ,"3 sec", "5 sec", + "7 sec", "10 secs"] + rx = RadioSettingValueList(options, options[_setx.scndria]) + rs = RadioSetting("setts.scndria", "A: Dual Receive Interval", + rx) + scan.append(rs) + rx = RadioSettingValueList(options, options[_setx.scndrib]) + rs = RadioSetting("setts.scndrib", "B: Dual Receive Interval", + rx) + scan.append(rs) + + rx = RadioSettingValueList(offon, offon[_setx.dwrvt]) + rs = RadioSetting("setts.dwrvt", "A: Priority Revert", rx) + scan.append(rs) + rx = RadioSettingValueList(offon, offon[_setx.dwrvtb]) + rs = RadioSetting("setts.dwrvtb", "B: Priority Revert", rx) + scan.append(rs) + + options = ["Off", "Priority Scan", "A-B Dual Receive"] + # unbelievable 2- byte configuration + v0 = _setx.scndrm1 # at 17f62 bit 8 + v1 = _setx.scndrm2 # at 17f6b bit 1 + vx =0 + if v0 == 1: + vx = 1 + elif v1 == 1: vx =2 + rx = RadioSettingValueList(options, options[vx]) + rs = RadioSetting("setts.scndrm1", "Scan Dual Receive Mode", rx) + rs.set_apply_callback(self._scndrm, _setx) + scan.append(rs) + + else: + options = ["Busy", "Hold", "1 Second", "3 Seconds", "5 Seconds"] + rx = RadioSettingValueList(options, options[_setx.scnrsm]) + rs = RadioSetting("setts.scnrsm", "Scan Resume Mode", rx) + scan.append(rs) + + rx = RadioSettingValueList(offon, offon[_setx.dwrvt]) + rs = RadioSetting("setts.dwrvt", "Dual Watch Revert", rx) + scan.append(rs) + # End of Scan settings + + # Begin Data settings + options = ["4700 bps", "9600 bps", "19200 bps", "38400 bps", + "57600 bps"] + rx = RadioSettingValueList(options, options[_wierd.comspd]) + rs = RadioSetting("wierd.comspd", "COM Port Speed", rx) + dat.append(rs) + + options = ["Off", "GPS Out", "Packet", "Waypoint"] + rx = RadioSettingValueList(options, options[_wierd.comout]) + rs = RadioSetting("wierd.comout", "COM Port Output", rx) + dat.append(rs) + + options = ["NMEA9", "NMEA8", "NMEA7", "NMEA6"] + rx = RadioSettingValueList(options, options[_wierd.comwpf]) + rs = RadioSetting("wierd.comwpf", "COM Port Waypoint Format", rx) + dat.append(rs) + + options = ["All", "Mobile", "Frequency", "Object/Item", "Digipeater", + "VoIP", "Weather", "Yaesu", "Call Ringer", "Rng Ringer"] + rx = RadioSettingValueList(options, options[_wierd.comflt]) + rs = RadioSetting("wierd.comflt", "COM Port Waypoint Filter", rx) + dat.append(rs) + + options = ["Main Band", "Sub Band", "A-Band Fix", "B-Band Fix"] + rx = RadioSettingValueList(options, options[_wierd.dbsela]) + rs = RadioSetting("wierd.dbsela", "Data Band Select: APRS", rx) + dat.append(rs) + rx = RadioSettingValueList(options, options[_wierd.dbseld]) + rs = RadioSetting("wierd.dbseld", "Data Band Select: Data", rx) + dat.append(rs) + + options = ["1200 bps", "9600 bps"] + rx = RadioSettingValueList(options, options[_wierd.dspda]) + rs = RadioSetting("wierd.dspda", "Data Speed: APRS", rx) + dat.append(rs) + rx = RadioSettingValueList(options, options[_wierd.pktspd]) + rs = RadioSetting("wierd.pktspd", "Data Speed: Data", rx) + dat.append(rs) + + rx = RadioSettingValueList(offon, offon[_wierd.datsql]) + rs = RadioSetting("wierd.datsql", "Data Squelch", rx) + dat.append(rs) + # End of Data Settings + + # Begin Options settings + if self.FTM200: + options = ["FREE 5 min", "LAST 30 sec"] + rx = RadioSettingValueList(options, options[_setx.fvsrec]) + rs = RadioSetting("setts.fvsrec", "FVS-2: Play/Record", rx) + opts.append(rs) + + options = ["Off", "Manual", "Auto"] + rx = RadioSettingValueList(options, options[_setx.fvsanc]) + rs = RadioSetting("setts.fvsanc", "FVS-2: Announce Mode", rx) + opts.append(rs) + + options = ["English", "Japanese"] + rx = RadioSettingValueList(options, options[_setx.fvslan]) + rs = RadioSetting("setts.fvslan", "FVS-2: Language", rx) + opts.append(rs) + + options = ["Low", "Mid", "High"] + rx = RadioSettingValueList(options, options[_setx.fvsvol]) + rs = RadioSetting("setts.fvsvol", "FVS-2: Volume", rx) + opts.append(rs) + + # Yaesu split the FTM-200 BEEP 0/1/2 into 2 byte locations!! + # and assigned this bit to the upper Beep of the FTM-6000!! + rx = RadioSettingValueList(onoff, onoff[_setx.fvsrxm]) + rs = RadioSetting("setts.fvsrxm", "FVS-2: RX Mute", rx) + opts.append(rs) + + # Common Options - BLUETOOTH + rx = RadioSettingValueList(offon, offon[_setx.bton]) + rs = RadioSetting("setts.bton", "Bluetooth: Enabled", rx) + opts.append(rs) + + rx = RadioSettingValueList(offon, offon[_setx.btsave]) + rs = RadioSetting("setts.btsave", "Bluetooth: Save", rx) + opts.append(rs) + + options = ["Auto", "Fix"] + rx = RadioSettingValueList(options, options[_setx.btaud]) + rs = RadioSetting("setts.btaud", "Bluetooth: Audio", rx) + opts.append(rs) + + if self.FTM200: + options = ["320 x 240", "160 x 120"] + rx = RadioSettingValueList(options, options[_mic.usbcamsz]) + rs = RadioSetting("micset.usbcamsz", "USB Camera: Image Size", rx) + opts.append(rs) + + options = ["Low", "Normal", "High"] + rx = RadioSettingValueList(options, options[_mic.usbcamql]) + rs = RadioSetting("micset.usbcamql", "USB Camera: Image Quality", rx) + opts.append(rs) + + # End of Options settings + + # Begin Other settings + + if self.FTM200: + options = ["A", "B", "A+B"] + rx = RadioSettingValueList(options, options[_setx.audrec - 1]) + rs = RadioSetting("setts.audrec", "Audio Recording Band", rx) + rs.set_apply_callback(self._adjlist, _setx, "audrec", options, + 1) + other.append(rs) + + rx = RadioSettingValueList(offon, offon[_setx.audmic]) + rs = RadioSetting("setts.audmic", "Microphone", rx) + other.append(rs) + + options = ["Off", "Low", "High"] + rx = RadioSettingValueList(options, options[_setx.voxsen]) + rs = RadioSetting("setts.voxsen", "VOX Sensitivity", rx) + other.append(rs) + options = ["0.5 seconds", "1 sec", "1.5 sec", "2.0 sec", + "2.5sec", "3 sec"] + rx = RadioSettingValueList(options, options[_setx.voxdly]) + rs = RadioSetting("setts.voxdly", "VOX Delay", rx) + other.append(rs) + + rx = RadioSettingValueList(offon, offon[_setx.bskpa1]) + rs = RadioSetting("setts.bskpa1", "A: Air Band Enabled", rx) + other.append(rs) + rx = RadioSettingValueList(offon, offon[_setx.bskpa2]) + rs = RadioSetting("setts.bskpa2", "A: VHF Band Enabled", rx) + other.append(rs) + rx = RadioSettingValueList(offon, offon[_setx.bskpa4]) + rs = RadioSetting("setts.bskpa4", "A: UHF Band Enabled", rx) + other.append(rs) + rx = RadioSettingValueList(offon, offon[_setx.bskpa3]) + rs = RadioSetting("setts.bskpa3", "A: Other Band Enabled", rx) + rs.set_apply_callback(self._skp_other, _setx, "A", options) + other.append(rs) + + rx = RadioSettingValueList(offon, offon[_setx.bskpb1]) + rs = RadioSetting("setts.bskpb1", "B: Air Band Enabled", rx) + other.append(rs) + rx = RadioSettingValueList(offon, offon[_setx.bskpb2]) + rs = RadioSetting("setts.bskpb2", "B: VHF Band Enabled", rx) + other.append(rs) + rx = RadioSettingValueList(offon, offon[_setx.bskpb4]) + rs = RadioSetting("setts.bskpb4", "B: UHF Band Enabled", rx) + other.append(rs) + rx = RadioSettingValueList(offon, offon[_setx.bskpb3]) + rs = RadioSetting("setts.bskpb3", "B: Other Band Enabled", rx) + rs.set_apply_callback(self._skp_other, _setx, "B", options) + other.append(rs) + + else: + options = ["1200 bps", "9600 bps"] + rx = RadioSettingValueList(options, options[_wierd.pktspd]) + rs = RadioSetting("wierd.pktspd", "Data Port Packet Baud Rate", + rx) + other.append(rs) + + rx = RadioSettingValueList(offon, offon[_setx.airb]) + rs = RadioSetting("setts.airb", "Air Band Enabled", rx) + other.append(rs) + + rx = RadioSettingValueList(offon, offon[_setx.vhfb]) + rs = RadioSetting("setts.vhfb", "VHF Band Enabled", rx) + other.append(rs) + + rx = RadioSettingValueList(offon, offon[_setx.uhfb]) + rs = RadioSetting("setts.uhfb", "UHF Band Enabled", rx) + other.append(rs) + + rx = RadioSettingValueList(offon, offon[_setx.otrb]) + rs = RadioSetting("setts.otrb", "Other Band Enabled", rx) + other.append(rs) + # End of Other Settings + + # Start FTM200 Unique settings + if self.FTM200: + _wrx = self._memobj.wrxmsg + xmap = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnop" + xmap += "qrstuvwxyz!\"#$%&\\()*+,-./:;<=>?@[']^_`{|}~****** " + # NOTE: Unknown characters at index 94-99; replaced with * + for ix in range(1, 11): + atr = "msg%02d" % ix + sx = getattr(_wrx, atr) + tx = "" + for cx in sx: + if cx == 0xff: break + tx += xmap[cx] + tx = tx.strip() + rx = RadioSettingValueString(0,128, tx, False) + atr = "wrxmsg.msg%02d" % ix + rs = RadioSetting(atr, "Message M%02d" % ix, rx) + rs.set_apply_callback(self._xmsg, _wrx, ix, xmap) + wires.append(rs) + + rx = RadioSettingValueList(offon, offon[_setx.wrxrng]) + rs = RadioSetting("setts.wrxrng", "Range Ringer", rx) + wires.append(rs) + + options = ["Auto", "TX FM Fixed", "TX DN Fixed"] + rx = RadioSettingValueList(options, options[_setx.wrxams]) + rs = RadioSetting("setts.wrxams", "AMS TX Mode", rx) + wires.append(rs) + + options = ["Off", "2 seconds", "4 sec", "6 sec", "8 sec", + "10 sec", "20 sec", "30 sec", "60 sec", "Continuous"] + rx = RadioSettingValueList(options, options[_mic.wrxpop]) + rs = RadioSetting("micset.wrxpop", "Digital Popup", rx) + wires.append(rs) + + rx = RadioSettingValueList(offon, offon[_setx.wrxloc]) + rs = RadioSetting("setts.wrxloc", "Location Service", rx) + wires.append(rs) + + rx = RadioSettingValueList(onoff, onoff[_setx.wrxstb]) + rs = RadioSetting("setts.wrxstb", "Standby Beep", rx) + wires.append(rs) + + rx = RadioSettingValueList(offon, offon[_setx.wrxdvw]) + rs = RadioSetting("setts.wrxdvw", "Digital VW Enable", rx) + wires.append(rs) + + options = ["Manual", "Preset"] + rx = RadioSettingValueList(options, options[_setx.wrxrwf]) + rs = RadioSetting("setts.wrxrwf", "RPT/WIRES Frequency Mode", rx) + wires.append(rs) + + options = ["VHF Preset", "UHF Preset"] + rx = RadioSettingValueList(options, options[_mic.wrxbsel]) + rs = RadioSetting("micset.wrxbsel", "RPT/WIRES Preset Band Select", + rx) + wires.append(rs) + + vx = self._freqdcode(_mic.wrxvfrq) / 1000000 + rx = RadioSettingValueFloat(144.0, 149.0, vx, 0.001, 3) + rs = RadioSetting("micset.wrxvfrq", "RPT/WIRES VHF Preset Freq", + rx) + rs.set_apply_callback(self._wrxfrq, _mic, "wrxvfrq") + wires.append(rs) + + vx = self._freqdcode(_mic.wrxufrq) / 1000000 + rx = RadioSettingValueFloat(420.0, 460.0, vx, 0.001, 3) + rs = RadioSetting("micset.wrxufrq", "RPT/WIRES UHF Preset Freq", + rx) + rs.set_apply_callback(self._wrxfrq, _mic, "wrxufrq") + wires.append(rs) + + options = ["History", "Activity"] + rx = RadioSettingValueList(options, options[_setx.wrxsrch]) + rs = RadioSetting("setts.wrxsrch", "RPT/WIRES Search Setup", rx) + wires.append(rs) + + options = ["Auto"] + for vx in range(1,100): + options.append("%02d" % vx) + rx = RadioSettingValueList(options, options[_mic.wrxdid]) + rs = RadioSetting("micset.wrxdid", "RPT/WIRES Radio Digital ID", + rx) + wires.append(rs) + + _wrxc = self._memobj.wrxcat + for ix in range(1, 6): + atr = "c%d" % ix + sx = getattr(_wrxc, atr) + tx = "" + for cx in sx: + if cx == 0xca: break + tx += xmap[cx] + tx = tx.strip() + rx = RadioSettingValueString(0,16, tx, False) + atr = "wrxcat.c%d" % ix + rs = RadioSetting(atr, "Category Text C%d" % ix, rx) + rs.set_apply_callback(self._xmsg, _wrxc, ix, xmap, 1) + wires.append(rs) + + rx = RadioSettingValueList(offon, offon[_wierd.aprson]) + rs = RadioSetting("wierd.aprson", "APRS Enabled", rx) + aprscom.append(rs) + + rx = RadioSettingValueList(offon, offon[_wierd.aprmut]) + rs = RadioSetting("wierd.aprmut", "Mute", rx) + aprscom.append(rs) + + options = ["100ms", "150ms", "200ms", "250ms", "300ms", "400ms", + "500ms", "750ms", "1000ms"] + rx = RadioSettingValueList(options, options[_wierd.aprtxd]) + rs = RadioSetting("wierd.aprtxd", "TX Delay", rx) + aprscom.append(rs) + + options = ["Off", "1 digit", "2 digits", "3 digits", "4 digits"] + rx = RadioSettingValueList(options, options[_wierd.aprbamb]) + rs = RadioSetting("wierd.aprbamb", "Beacon Ambiguity", rx) + aprscom.append(rs) + + rx = RadioSettingValueList(offon, offon[_wierd.aprspdc]) + rs = RadioSetting("wierd.aprspdc", "Beacon Speed/Course", rx) + aprscom.append(rs) + + rx = RadioSettingValueList(offon, offon[_wierd.aprsalt]) + rs = RadioSetting("wierd.aprsalt", "Beacon Altitude", rx) + aprscom.append(rs) + + options = ["Off", "On", "Smart"] + rx = RadioSettingValueList(options, options[_wierd.aprbaut]) + rs = RadioSetting("wierd.aprbaut", "Beacon TX Mode", rx) + aprscom.append(rs) + + options = ["30 sec", "1 minute", "2 mins", "3 mins", "5 mins", + "10 mins", "15 mins", "20 mins", "30 mins", "60 mins"] + rx = RadioSettingValueList(options, options[_wierd.aprstxi]) + rs = RadioSetting("wierd.aprstxi", "Beacon TX Interval", rx) + aprscom.append(rs) + + rx = RadioSettingValueList(offon, offon[_wierd.aprspro]) + rs = RadioSetting("wierd.aprspro", "Beacon TX Proportional", rx) + aprscom.append(rs) + + rx = RadioSettingValueList(offon, offon[_wierd.aprsdcy]) + rs = RadioSetting("wierd.aprsdcy", "Beacon TX Decay", rx) + aprscom.append(rs) + + #Lets try using integer values instead of list; just for kicks + rx = RadioSettingValueInteger(1, 99, _wierd.aprslow) + rs = RadioSetting("wierd.aprslow", "TX Low Speed (mph)", rx) + aprscom.append(rs) + + rx = RadioSettingValueInteger(5, 180, _wierd.aprsrate) + rs = RadioSetting("wierd.aprsrate", "TX Rate Limit (secs)", rx) + aprscom.append(rs) + + sx = self._b2s(_wierd.aprcsgn, 0xca) + rx = RadioSettingValueString(0, 6, sx, False) + rs = RadioSetting("wierd.aprcsgn", "APRS Callsign", rx) + rs.set_apply_callback(self._s2b, _wierd, "aprcsgn", 6, 0xca) + aprscom.append(rs) + + options = [""] + for i in range(1, 16): + options.append("-%d" % i) + vx = _wierd.aprcsfx + if vx == 0xca: vx = 0 + rx = RadioSettingValueList(options, options[vx]) + rs = RadioSetting("wierd.aprcsfx", "Call Sign SSID ", rx) + rs.set_apply_callback(self._aprsfx, _wierd, "aprcsfx", 0xca) + aprscom.append(rs) + + options = ["Off Duty", "En Route", "In Service", "Returning", + "Committed", "Special", "Priority", "Sustom 0", + "Custom 1", "Custom 2", "Custom 3","Custom 4", + "Custom 5", "Custom 6", "EMERGENCY!"] + rx = RadioSettingValueList(options, options[_wierd.aprcmt]) + rs = RadioSetting("wierd.aprcmt", "Position Comment", rx) + aprscom.append(rs) + + options = ["Off", "3 secs", " 5 secs", "10 secs", "HOLD"] + vx = _wierd.aprpopb # hex encoded decimal plus ff= hold + v1 = 0 + if vx == 3: v1 = 1 + if vx == 5: v1 = 2 + if vx == 10: v1 = 3 + if vx == 0xff: v1 = 4 + rx = RadioSettingValueList(options, options[v1]) + rs = RadioSetting("wierd.aprpopb", "Beacon Popup Display Time", + rx) + rs.set_apply_callback(self._aprspop, _wierd, "aprpopb") + aprscom.append(rs) + + vx = _wierd.aprpopm + v1 = 0 + if vx == 3: v1 = 1 + if vx == 5: v1 = 2 + if vx == 10: v1 = 3 + if vx == 0xff: v1 = 4 + rx = RadioSettingValueList(options, options[v1]) + rs = RadioSetting("wierd.aprpopm", + "Message Popup Display Time", rx) + rs.set_apply_callback(self._aprspop, _wierd, "aprpopm") + aprscom.append(rs) + + rx = RadioSettingValueList(offon, offon[_wierd.aprmpkt]) + rs = RadioSetting("wierd.aprmpkt", "My Packet", rx) + aprscom.append(rs) + + options = ["Time", "Call Sign", "Distance"] + rx = RadioSettingValueList(options, options[_wierd.aprsfs]) + rs = RadioSetting("wierd.aprsfs", "Sort Filter: Sort By", rx) + aprscom.append(rs) + + options = ["All", "Mobile", "Frequency", "Object/Item", + "Digipeater", "VoIP", "Weather", "Yaesu", + "Other Packet", " Call Ringer", "Range Ringer", + "1200 bps", "9600 bps"] + rx = RadioSettingValueList(options, options[_wierd.aprsff]) + rs = RadioSetting("wierd.aprsff", "Sort Filter: Filter Type", rx) + aprscom.append(rs) + + options = ["Normal", "Tone-SQL", "DCS", "Rx-TSQL", "Rx-DCS"] + rx = RadioSettingValueList(options, options[_wierd.aprvlrt]) + rs = RadioSetting("wierd.aprvlrt", "Voice Alert: Mode", rx) + aprscom.append(rs) + + options = [] + for vx in chirp_common.TONES: + options.append("%.1f" % vx) + rx = RadioSettingValueList(options, options[_wierd.aprtsql]) + rs = RadioSetting("wierd.aprtsql", "Voice Alert: TSQL Tone", rx) + aprscom.append(rs) + + options = [] + for vx in chirp_common.DTCS_CODES: + options.append("%03d" % vx) + rx = RadioSettingValueList(options, options[_wierd.aprvdcs]) + rs = RadioSetting("wierd.aprvdcs", "Voice Alert: DCS Code", rx) + aprscom.append(rs) + + options = ["GPS", "Manual"] + rx = RadioSettingValueList(options, options[_wierd.aprmpos]) + rs = RadioSetting("wierd.aprmpos", "My Position Mode", rx) + aprscom.append(rs) + + optns = ["North", "South"] + rx = RadioSettingValueList(optns, optns[_wierd.aprltns]) + rs = RadioSetting("wierd.aprltns", + "My Position Manual Lat N/S", rx) + aprscom.append(rs) + + v0 = int("%X" % _wierd.aprlad) # Hex coded Decimal + rx = RadioSettingValueInteger(0, 90, v0) + rs = RadioSetting("wierd.aprlad", + "My Position Manual Lat Degrees", rx) + rs.set_apply_callback(self._enchcd, _wierd, "aprlad") + aprscom.append(rs) + + v0 = int("%X" % _wierd.aprlam) # Whole Minutes, HCD + v1 = _wierd.aprlas + v1 = v1 / 1000 + vx = v0 + v1 + rx = RadioSettingValueFloat(0, 59.99, vx, 0.01, 2) + rs = RadioSetting("wierd.aprlas", + "My Position Manual Lat Minutes", rx) + rs.set_apply_callback(self._mdot, _wierd, "aprlam", "aprlas") + aprscom.append(rs) + + optns = ["East", "West"] + rx = RadioSettingValueList(optns, optns[_wierd.aprlgew]) + rs = RadioSetting("wierd.aprlgew", + "My Position Manual Long N/S", rx) + aprscom.append(rs) + + v0 = int("%X" % _wierd.aprlgd) + rx = RadioSettingValueInteger(0, 180, v0) + rs = RadioSetting("wierd.aprlgd", + "My Position Manual Long Degrees", rx) + rs.set_apply_callback(self._enchcd, _wierd, "aprlgd") + aprscom.append(rs) + + v0 = int("%X" % _wierd.aprlgm) + v1 = _wierd.aprlgs + v1 = v1 / 1000 + vx = v0 + v1 + rx = RadioSettingValueFloat(0, 59.99, vx, 0.01, 2) + rs = RadioSetting("wierd.aprlgs", + "My Position Manual Long Minutes", rx) + rs.set_apply_callback(self._mdot, _wierd, "aprlgm", "aprlgs") + aprscom.append(rs) + + # APRS Digipeater Settings + + options = ["Off", "Wide 1-1", "Wide 1-1, 1-2", "Path 1", + "Path 2", "Path 3", "Path 4", "Full 1", "Full2"] + rx = RadioSettingValueList(options, options[_wierd.aprdig]) + rs = RadioSetting("wierd.aprdig", "Digipeater Route Selection", + rx) + aprsdgp.append(rs) + + # Using shared memory 'share1'; extracting Digipath data + _shr = self._memobj.share1 + optsfx = [""] # List for path suffix + for i in range(1, 16): + optsfx.append("-%d" % i) + py = 0 # route index 0-7 for 'paths' + pz = 0 # index to _shr array for dummy memobj + for px in range(0, 4): # Path 1 - 4 + sx, sfx = self._getdgpath(py) + rx = RadioSettingValueString(0, 6, sx, False) + tx = "Path-%d First Route Callsign" % (px + 1) + rs = RadioSetting("share1/%d.shbyte" % pz, tx, rx) + rs.set_apply_callback(self._putdgpname, py) + aprsdgp.append(rs) + pz += 1 + rx = RadioSettingValueList(optsfx, optsfx[sfx]) + tx = "Path-%d First Route SSID" % (px + 1) + rs = RadioSetting("share1/%d.shbyte" % pz, tx, rx) + rs.set_apply_callback(self._putdgpsfx, py) + aprsdgp.append(rs) + py += 1 + pz += 1 + sx, sfx = self._getdgpath(py) + rx = RadioSettingValueString(0, 6, sx, False) + tx ="Path-%d Second Route Callsign" % (px + 1) + rs = RadioSetting("share1/%d.shbyte" % pz, tx, rx) + rs.set_apply_callback(self._putdgpname, py) + aprsdgp.append(rs) + pz += 1 + rx = RadioSettingValueList(optsfx, optsfx[sfx]) + tx = "Path-%d Second Route SSID" % (px + 1) + rs = RadioSetting("share1/%d.shbyte" % pz,tx, rx) + rs.set_apply_callback(self._putdgpsfx, py) + aprsdgp.append(rs) + py += 1 + pz += 1 + # Now 8 routes for 'Full1' + for px in range(0, 8): + sx, sfx = self._getdgpath(py) + rx = RadioSettingValueString(0, 6, sx, False) + tx = "Full-1 Route %d Callsign" % (px + 1) + rs = RadioSetting("share1/%d.shbyte" % pz, tx, rx) + rs.set_apply_callback(self._putdgpname, py) + aprsdgp.append(rs) + pz += 1 + rx = RadioSettingValueList(optsfx, optsfx[sfx]) + tx = "Full-1 Route %d SSID" % (px + 1) + rs = RadioSetting("share1/%d.shbyte" % pz, tx, rx) + rs.set_apply_callback(self._putdgpsfx, py) + aprsdgp.append(rs) + py += 1 + pz += 1 + # and 8 more for 'Full2' + for px in range(0, 8): + sx, sfx = self._getdgpath(py) + rx = RadioSettingValueString(0, 6, sx, False) + tx = "Full-2 Route %d Callsign" % (px + 1) + rs = RadioSetting("share1/%d.shbyte" % pz, tx, rx) + rs.set_apply_callback(self._putdgpname, py) + aprsdgp.append(rs) + pz += 1 + rx = RadioSettingValueList(optsfx, optsfx[sfx]) + tx = "Full-2 Route %d SSID" % (px + 1) + rs = RadioSetting("share1/%d.shbyte" % pz, tx, rx) + rs.set_apply_callback(self._putdgpsfx, py) + aprsdgp.append(rs) + py += 1 + pz += 1 + + # --- APRS Messages ===== + + _apmsg = self._memobj.aprsmsg + for vx in range(1, 7): + tx = "grp%d" % vx + bx = getattr(_apmsg, tx) + sx = self._b2s(bx, 0xca) + qx = "aprsmsg.grp%d" % vx + rx = RadioSettingValueString(0, 9, sx, False) + rs = RadioSetting(qx, "Message Group %d Text" % vx, rx) + rs.set_apply_callback(self._s2b, _apmsg, tx, 9, 0xca) + aprsmsg.append(rs) + + for vx in range(1, 4): + tx = "blt%d" % vx + bx = getattr(_apmsg, tx) + sx = self._b2s(bx, 0xca) + qx = "aprsmsg.blt%d" % vx + rx = RadioSettingValueString(0, 9, sx, False) + rs = RadioSetting(qx, "Message Bulletin %d Text" % vx, rx) + rs.set_apply_callback(self._s2b, _apmsg, tx, 9, 0xca) + aprsmsg.append(rs) + + _aptxt = self._memobj.aprstxt + for vx in range(1, 9): + tx = "txt%d" % vx + bx = getattr(_aptxt, tx) + sx = self._b2s(bx, 0xca) + qx = "aprstxt.txt%d" % vx + rx = RadioSettingValueString(0, 16, sx, False) + rs = RadioSetting(qx, "Message %d Text" % vx, rx) + rs.set_apply_callback(self._s2b, _aptxt, tx, 16, 0xca) + aprsmsg.append(rs) + + options = [] + for i in range(1, 9): options.append("%d" % i) + rx = RadioSettingValueList(options, options[_wierd.aprstxn]) + rs = RadioSetting("wierd.aprstxn", "Message # Selected", rx) + aprsmsg.append(rs) + + rx = RadioSettingValueList(offon, offon[_wierd.aprrply]) + rs = RadioSetting("wierd.aprrply", "Message Reply Enabled", rx) + aprsmsg.append(rs) + + sx = self._b2s(_wierd.aprrcsn, 0x2a) + rx = RadioSettingValueString(0, 6, sx, False) + rs = RadioSetting("wierd.aprrcsn", "Message Reply Callsign", rx) + rs.set_apply_callback(self._s2b, _wierd, "aprrcsn", 6, 0x2a) + aprsmsg.append(rs) + + options = [" "] + for i in range(1, 16): + options.append("-%d" % i) + options.append("-**") # index 16 + vx = _wierd.aprrcfx + if vx == 0x2a: vx = 16 + rx = RadioSettingValueList(options, options[vx]) + rs = RadioSetting("wierd.aprrcfx", "Reply Call Sign SSID", rx) + rs.set_apply_callback(self._aprsfx, _wierd, "aprrcfx", 0x2a) + aprsmsg.append(rs) + + sx = self._b2s(_wierd.aprrtxt, 0xca) + rx = RadioSettingValueString(0, 64, sx, False) + rs = RadioSetting("wierd.aprrtxt", "Message Reply Text", rx) + rs.set_apply_callback(self._s2b, _wierd, "aprrtxt", 64, 0xca) + aprsmsg.append(rs) + + options = ["/#", "/&", "/'", "/-", "/.", "/0", "/:", "/;", "/<", + "/=", "/>", "/C", "/E", "/I", "/K", "/O", "/P", "/R", + "/T", "/U", "/V", "/W", "/X", "Y", "/[", "/\\", "/^", + "/_", "/a", "/b", "/f", "/g", "/j", "/k", "/m", "/r", + "/s", "/u", "/v", "/y", "\\#", "\\&", "\\-", "\\.", + "\\0", "E0", "IO", "W0", "\\;", "\\>", "\\A", "\\K", + "\\W", "\\Y", "KY", "YY", "\\^", "\\_", "\\m", "\\n", + "\\s", "\\u", "\\v", "\\x"] + for i in range(1,4): + tx = "aprsym%d" % i + bx = getattr(_wierd, tx) + sx = self._b2s(bx, 0) # 2-byte char string + qx = "wierd.aprsym%d" % i + rx = RadioSettingValueList(options, sx) + rs = RadioSetting(qx, "My Symbol #%d" % i, rx) + rs.set_apply_callback(self._s2b, _wierd, tx, 2, 0) + aprsmsg.append(rs) + + options = ["/"] + for i in range(48, 58): options.append(chr(i)) # numerals + for i in range(65, 91): options.append(chr(i)) # Cap letters + options.append("\\") + sx = chr(_wierd.aprsym4a) + rx = RadioSettingValueList(options, sx) + rs = RadioSetting("wierd.aprsym4a", "My Symbol #4 First Value", rx) + rs.set_apply_callback(self._c2u8, _wierd, "aprsym4a") + aprsmsg.append(rs) + + options = [] + for i in range(33, 127): options.append(chr(i)) # full ascii + sx = chr(_wierd.aprsym4b) + rx = RadioSettingValueList(options, sx) + rs = RadioSetting("wierd.aprsym4b", "My Symbol #4 Second Value", rx) + rs.set_apply_callback(self._c2u8, _wierd, "aprsym4b") + aprsmsg.append(rs) + + options = ["#1", "#2", "#3", "#4"] + rx = RadioSettingValueList(options, options[_wierd.aprsym]) + rs = RadioSetting("wierd.aprsym", "My Symbol Selected", rx) + aprsmsg.append(rs) + + # --- APRS Beacon Settings ----- + rx = RadioSettingValueList(offon, offon[_wierd.aprbfme]) + rs = RadioSetting("wierd.aprbfme", "Filter: MIC-E", rx) + bcnfltr.append(rs) + + rx = RadioSettingValueList(offon, offon[_wierd.aprbfpo]) + rs = RadioSetting("wierd.aprbfpo", "Filter: Position", rx) + bcnfltr.append(rs) + + rx = RadioSettingValueList(offon, offon[_wierd.aprbfwx]) + rs = RadioSetting("wierd.aprbfwx", "Filter: Weather", rx) + bcnfltr.append(rs) + + rx = RadioSettingValueList(offon, offon[_wierd.aprbfob]) + rs = RadioSetting("wierd.aprbfob", "Filter: Object", rx) + bcnfltr.append(rs) + + rx = RadioSettingValueList(offon, offon[_wierd.aprbfit]) + rs = RadioSetting("wierd.aprbfit", "Filter: Item", rx) + bcnfltr.append(rs) + + rx = RadioSettingValueList(offon, offon[_wierd.aprbfst]) + rs = RadioSetting("wierd.aprbfst", "Filter: Status", rx) + bcnfltr.append(rs) + + rx = RadioSettingValueList(offon, offon[_wierd.aprbfot]) + rs = RadioSetting("wierd.aprbfot", "Filter: Other", rx) + bcnfltr.append(rs) + + options = ["Off", "1", "10", "100", "1000", "3000"] + v0 = int(_wierd.aprbfrl) # u16 int: 0,1,10,100,1000,3000 + if v0 == 0: + vx = 0 + else: + vx = options.index(str(v0)) + rx = RadioSettingValueList(options, options[vx]) + rs = RadioSetting("wierd.aprbfrl", + "Filter: Range Limit (km:miles)", rx) + rs.set_apply_callback(self._rnglmt, _wierd, "aprbfrl") + bcnfltr.append(rs) + + rx = RadioSettingValueList(offon, offon[_wierd.aprbfan]) + rs = RadioSetting("wierd.aprbfan", "Filter: AltNet", rx) + bcnfltr.append(rs) + + options = ["dd mm ss", "dd mm.mm"] + rx = RadioSettingValueList(options, options[_wierd.aprbupo]) + rs = RadioSetting("wierd.aprbupo", "Units: Position Format", rx) + bcnunit.append(rs) + + options = ["kilometers", "miles"] + rx = RadioSettingValueList(options, options[_wierd.aprbudi]) + rs = RadioSetting("wierd.aprbudi", "Units: Distance", rx) + bcnunit.append(rs) + + options = ["km/h", "mph", "knots"] + rx = RadioSettingValueList(options, options[_wierd.aprbusp]) + rs = RadioSetting("wierd.aprbusp", "Units: Speed", rx) + bcnunit.append(rs) + + options = ["meters", "feet"] + rx = RadioSettingValueList(options, options[_wierd.aprbual]) + rs = RadioSetting("wierd.aprbual", "Units: Altitude", rx) + bcnunit.append(rs) + + options = ["hPa", "mb", "mmHg", "inHg"] + rx = RadioSettingValueList(options, options[_wierd.aprbubo]) + rs = RadioSetting("wierd.aprbubo", "Units: Barometric Pressure", + rx) + bcnunit.append(rs) + + options = ["Celsius", "Farenheit"] + rx = RadioSettingValueList(options, options[_wierd.aprbutp]) + rs = RadioSetting("wierd.aprbutp", "Units: Temperature", rx) + bcnunit.append(rs) + + options = ["mm", "inch"] + rx = RadioSettingValueList(options, options[_wierd.aprburn]) + rs = RadioSetting("wierd.aprburn", "Units: Rain", rx) + bcnunit.append(rs) + + options = ["m/s", "mph", "knots"] + rx = RadioSettingValueList(options, options[_wierd.aprbuwd]) + rs = RadioSetting("wierd.aprbuwd", "Units: Wind Speed", rx) + bcnunit.append(rs) + + rx = RadioSettingValueList(offon, offon[_wierd.aprbrtb]) + rs = RadioSetting("wierd.aprbrtb", "Ringer: TX Beacon", rx) + bcnrngr.append(rs) + + rx = RadioSettingValueList(offon, offon[_wierd.aprbrtm]) + rs = RadioSetting("wierd.aprbrtm", "Ringer: TX Message", rx) + bcnrngr.append(rs) + + rx = RadioSettingValueList(offon, offon[_wierd.aprbrrb]) + rs = RadioSetting("wierd.aprbrrb", "Ringer: RX Beacon", rx) + bcnrngr.append(rs) + + rx = RadioSettingValueList(offon, offon[_wierd.aprbrrm]) + rs = RadioSetting("wierd.aprbrrm", "Ringer: RX Message", rx) + bcnrngr.append(rs) + + rx = RadioSettingValueList(offon, offon[_wierd.aprbrmp]) + rs = RadioSetting("wierd.aprbrmp", "Ringer: My Packet", rx) + bcnrngr.append(rs) + + rx = RadioSettingValueList(offon, offon[_wierd.aprbrcr]) + rs = RadioSetting("wierd.aprbrcr", "Ringer: Call Ringer", rx) + bcnrngr.append(rs) + + options = ["Off", "1", "5", "10", "50", "100"] + v0 = int(_wierd.aprbrrr) # u8 int: 0,1,5,10,50,100 + if v0 == 0: + vx = 0 + else: + vx = options.index(str(v0)) + rx = RadioSettingValueList(options, options[vx]) + rs = RadioSetting("wierd.aprbrrr", "Ringer: Range Ringer", rx) + rs.set_apply_callback(self._rnglmt, _wierd, "aprbrrr") + bcnrngr.append(rs) + + rx = RadioSettingValueList(offon, offon[_wierd.aprbrmv]) + rs = RadioSetting("wierd.aprbrmv", "Ringer: Message Voice", rx) + bcnrngr.append(rs) + + # --- APRS Ringer Call Signs and SSID Suffix --- + py = 0x18 # Share1 cs index + pz = 0x30 # dummy share1 index + for px in range(0, 8): # Calls 1-8 + sx, sfx = self._getdgpath(py) + rx = RadioSettingValueString(0, 6, sx, False) + tx = "Ringer Callsign %d" % (px + 1) + rs = RadioSetting("share1/%d.shbyte" % pz, tx, rx) + rs.set_apply_callback(self._putdgpname, py) + bcnrngr.append(rs) + pz += 1 + rx = RadioSettingValueList(optsfx, optsfx[sfx]) + tx = "Ringer Callsign %d SSID" % (px + 1) + rs = RadioSetting("share1/%d.shbyte" % pz, tx, rx) + rs.set_apply_callback(self._putdgpsfx, py) + bcnrngr.append(rs) + py += 1 + pz += 1 + + # --- Beacon Status Text ---- + _bstat = self._memobj.bcntxt + options = ["Off", "Text 1", "Text 2", "Text 3", "Text 4", + "Text 5"] + rx = RadioSettingValueList(options, options[_wierd.bcnstat]) + rs = RadioSetting("wierd.bcnstat", "APRS Beacon Text Select", rx) + bcnstat.append(rs) + + options = ["1/1", "1/2", "1/3", "1/4", "1/5", "1/6", "1/7", "1/8", + "1/2(Freq)", "1/3(Freq)", "1/4(Freq)", "1/5(Freq)", + "1/6(Freq)", "1/7(Freq)", "1/8(Freq)"] + rx = RadioSettingValueList(options, options[_wierd.bcntxra]) + rs = RadioSetting("wierd.bcntxra", "Beacon Text Rate", rx) + bcnstat.append(rs) + + options = ["None", "Frequency", "Freq & SQL & Shift"] + + for i in range(0, 5): + vx = i + 1 + sx = self._b2s(_bstat[i].msg, 0xca) + rx = RadioSettingValueString(0, 60, sx) + rs = RadioSetting("bcntxt/%d.msg" %i, + "Status Text %d" % vx, rx) + rs.set_apply_callback(self._s2b, _bstat[i], "msg", 60, 0xca) + bcnstat.append(rs) + + rx = RadioSettingValueList(options, options[_bstat[i].mode]) + rs = RadioSetting("bcntxt/%d.mode" % i, + "Status Text %d Mode" % vx, rx) + bcnstat.append(rs) + + # --- Smart Beaconing + + options = ["Off", "Type 1", "Type 2", "Type 3"] + rx = RadioSettingValueList(options, options[_wierd.bcnsmart]) + rs = RadioSetting("wierd.bcnsmart", "Smart Beaconing Status", rx) + bcnsmrt.append(rs) + + labls = ["Low Speed (2-30)", "High Speed (3-90)", + "Slow Rate (1-100 min)", "Fast Rate (10-180 sec)", + "Turn Angle (5-90 deg)", "Turn Slope (1-255)", + "Turn Time (5-180 sec)"] + minvals = [2, 3, 1, 10, 5, 1, 5] + maxvals = [30, 90, 100, 180, 90, 255, 180] + for v0 in range(1,4): # Type + sx = "Type %d" % v0 + for v1 in range(0, 7): # Parameters + v2 = getattr(_wierd, "typ%dval%d" % (v0, v1)) + rx =RadioSettingValueInteger(minvals[v1], maxvals[v1], v2) + rs = RadioSetting("wierd.typ%dval%d" % (v0, v1), + "%s %s" % (sx, labls[v1]), rx) + bcnsmrt.append(rs) + # End If FTM-200 Unique settings + return group # End get_settings() + + def set_settings(self, settings): + _setx = self._memobj.setts + _mic = self._memobj.micset + _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 = _setx + 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: + LOG.debug(element.get_name()) + raise + + +class Ftm200dAlias(chirp_common.Alias): + VENDOR = "Yaesu" + MODEL = "FTM-200D" + + +@directory.register +class FTM200radio(FTM6000Radio): + """Yaesu FTM-200""" + FTM200= True + MODEL = "FTM-200" + NAME_LEN = 16 # Valid name length + ALIASES = [Ftm200dAlias] + CHARSET = list(chirp_common.CHARSET_ASCII) + MODES = ["AM", "FM", "NFM", "DN"] + # TESTME = False + \ No newline at end of file From ee24be26bfc678e565510ce6a8723aaafa6eb2d1 Mon Sep 17 00:00:00 2001 From: Old-Phart Date: Wed, 17 Apr 2024 10:49:20 -0700 Subject: [PATCH 02/11] Added yaesu ftm6000 --- tests/py3_driver_testers.txt | 30 +----------------------------- 1 file changed, 1 insertion(+), 29 deletions(-) diff --git a/tests/py3_driver_testers.txt b/tests/py3_driver_testers.txt index e2fbfe20f..f54a2b93c 100644 --- a/tests/py3_driver_testers.txt +++ b/tests/py3_driver_testers.txt @@ -11,7 +11,6 @@ Abbree_AR-518,@KC9HI,16-Dec-2022 Abbree_AR-63,@KC9HI,30-Nov-2022 Abbree_AR-730,@KC9HI,17-Aug-2023 -Abbree_AR-869,+Radtel_RT-490,11-Nov-2023 Abbree_AR-F5,@KC9HI,09-Aug-2023 Alinco_DJ175,+Alinco_DR235T,12-Dec-2022 Alinco_DJ596,+Alinco_DR235T,12-Dec-2022 @@ -22,7 +21,6 @@ Alinco_DR06T,+Alinco_DR235T,12-Dec-2022 Alinco_DR135T,+Alinco_DR235T,12-Dec-2022 Alinco_DR235T,@kk7ds,12-Dec-2022 Alinco_DR435T,+Alinco_DR235T,12-Dec-2022 -Alinco_DR735T,@jacobcalvert,03-April-2024 Anysecu_UV-A37,@KC9HI,5-Jun-2023 Anysecu_WP-9900,@KC9HI,11-Nov-2022 Anysecu_AC-580,+Radioddity_GS-5B,17-Mar-2023 @@ -52,8 +50,6 @@ BTECH_UV-50X2,@KC9HI,11-Nov-2022 BTECH_UV-50X2_G2,@KC9HI,30-Nov-2022 BTECH_UV-50X3,@KC9HI,10-Dec-2022 BTECH_UV-5X3,@KC9HI,9-Dec-2022 -Baofeng_5RM,@vdwel,7-Dec-2023 -Baofeng_5RX,@KC9HI,16-Jan-2024 Baofeng_BF-1901,@cetinajero,3-Jul-2023 Baofeng_BF-1904,@cetinajero,3-Jul-2023 Baofeng_BF-888,@kk7ds,13-Feb-2019 @@ -62,12 +58,9 @@ Baofeng_BF-A58S,@KC9HI,3-Dec-2022 Baofeng_BF-F8HP,@KC9HI,18-Nov-2022 Baofeng_BF-M4,@cetinajero,8-May-2023 Baofeng_BF-T1,@KC9HI,10-Dec-2022 -Baofeng_BF-T20,@KC9HI,15-Dec-2023 -Baofeng_BF-T20FRS,@KC9HI,17-Dec-2023 Baofeng_BF-T8,@KC9HI,30-Nov-2022 Baofeng_BF-V8A,@KC9HI,28-Nov-2022 Baofeng_F-11,+Baofeng_UV-5R,18-Nov-2022 -Baofeng_GM-5RH,@KC9HI,21-Mar-2024 Baofeng_GT-3WP,@KC9HI,3-Dec-2022 Baofeng_GT-5R,@KC9HI,18-Nov-2022 Baofeng_UV-3R,@yarda,26-Sep-2022 @@ -79,22 +72,16 @@ Baofeng_UV-82HP,@KC9HI,18-Nov-2022 Baofeng_UV-82WP,@KC9HI,3-Dec-2022 Baofeng_UV-9G,@KC9HI,3-Dec-2022 Baofeng_UV-9R,@KC9HI,3-Dec-2022 -Baofeng_UV-13Pro,@vdwel,21-Feb-2024 -Baofeng_UV-17,@vdwel,27-Nov-2023 -Baofeng_UV-17Pro,@vdwel,27-Nov-2023 -Baofeng_UV-17ProGPS,@vdwel,27-Nov-2023 Baofeng_UV-B5,@KC9HI,18-Nov-2022 Baofeng_UV-S9X3,@KC9HI,22-Aug-2023 Baofeng_W31E,@KC9HI,14-Aug-2023 Baojie_BJ-218,+LUITON_LT-725UV,16-Feb-2023 Baojie_BJ-318,@KC9HI,2-Jan-2023 -Boristone_8RS,+Radtel_RT-490,11-Nov-2023 Cignus_XTR-5,+Radioddity_GS-5B,17-Mar-2023 CRT_Micron_UV,+Retevis_RT95,13-Nov-2022 CRT_Micron_UV_V2,+Retevis_RT95,13-Nov-2022 Explorer_QRZ-1,+TYT_TH-UV88,5-Dec-2022 Generic_CSV,@kk7ds,4-Dec-2022 -HamGeek_HG-590,+Radtel_RT-490,11-Nov-2023 Hiroyasu_HI-8811,@KC9HI,4-Jun-2023 HobbyPCB_RS-UV3,@kk7ds,9-Dec-2022 Icom_IC-208H,*icf,12-Dec-2022 @@ -138,8 +125,6 @@ Intek_HR-2040,+AnyTone_5888UV,9-Dec-2022 Jetstream_JT220M,+Alinco_DR235T,12-Dec-2022 Jetstream_JT270M,+Jetstream_JT270M,13-Dec-2022 Jetstream_JT270MH,@kk7ds,13-Dec-2022 -Jianpai_8800_Plus,+Radtel_RT-490,11-Nov-2023 -JJCC_JC-8629,+Radtel_RT-490,11-Nov-2023 Kenwood_HMK,+Generic_CSV,4-Dec-2022 Kenwood_TH-D7,*kenwood_live,12-Dec-2022 Kenwood_TH-D7G,*kenwood_live,12-Dec-2022 @@ -147,7 +132,6 @@ Kenwood_TH-D72_clone_mode,@kk7ds,28-Nov-2022 Kenwood_TH-D72_live_mode,@kk7ds,21-Oct-2022 Kenwood_TH-D74_clone_mode,@kk7ds,30-Nov-2022 Kenwood_TH-D74_live_mode,@kk7ds,20-Oct-2022 -Kenwood_TH-D75,#11122,114-Feb-2024 Kenwood_TH-F6,@KC9HI,30-Nov-2022 Kenwood_TH-F7,@sv1,19-Oct-2022 Kenwood_TH-G71,*kenwood_live,12-Dec-2022 @@ -203,11 +187,8 @@ Kenwood_TK-860,+Kenwood_TK-760,5-Dec-2022 Kenwood_TK-862,+Kenwood_TK-760,5-Dec-2022 Kenwood_TK-868,+Kenwood_TK-760,5-Dec-2022 Kenwood_TS-2000,ZS6CRW,10-Jan-2022 -Lanchonlh_HG-UV98,#11179,23-Feb-2024 Leixen_VV-898,+Jetstream_JT270MH,13-Dec-2022 Leixen_VV-898S,@READ10,19-Dec-2022 -Leixen_VV-898S_Dual_Bank,#4069,10-Feb-2024 -Leixen_VV-898E_Dual_Bank,+Leixen_VV-898S_Dual_Bank,10-Feb-2024 LUITON_LT-316,+Retevis_RT22,9-Dec-2022 LUITON_LT-580_UHF,@KC9HI,8-Dec-2022 LUITON_LT-580_VHF,@KC9HI,8-Dec-2022 @@ -215,7 +196,6 @@ LUITON_LT-588UV,@KC9HI,11-Nov-2022 LUITON_LT-725UV,@KC9HI,11-Dec-2022 Maverick_RA-100,@cetinajero,7-Jul-2023 Maverick_RA-425,@cetinajero,7-Jul-2023 -MMLradio_JC-8629,@KC9HI,11-Nov-2023 MTC_UV-5R-3,+BTECH_UV-5X3,9-Dec-2022 Midland_DBR2500,+Retevis_RT95,13-Nov-2022 Polmar_DB-50M,+AnyTone_5888UV,9-Dec-2022 @@ -225,7 +205,6 @@ Q-MAC_HF-90_v300_or_earlier,@fthain,9-Mar-2023 Q-MAC_HF-90_v301_or_later,@fthain,9-Mar-2023 Quansheng_TG-UV2+,#10398,26-Feb-2023 Quansheng_UV-K5,@sq5bpf,29-May-2023 -Quansheng_UV-K5_egzumer,@egzumer,23-Jan-2024 QYT_KT-8R,@KC9HI,11-Nov-2022 QYT_KT-UV980,+WACCOM_MINI-8900,11-Nov-2022 QYT_KT-WP12,+Anysecu_WP-9900,11-Nov-2022 @@ -246,14 +225,12 @@ Radioddity_UV-82X3,@KC9HI,18-Nov-2022 Radtel_RT-470,@KC9HI,2-Apr-2023 Radtel_RT-470L,@KC9HI,5-May-2023 Radtel_RT-470X,@KC9HI,10-Aug-2023 -Radtel_RT-490,@KC9HI,11-Nov-2023 Radtel_T18,@KC9HI,28-Nov-2022 Retevis_H777S,@KC9HI,22-Dec-2022 Retevis_H777_Plus,@KC9HI,4-Dec-2022 Retevis_RA685,@KC9HI,19-Nov-2022 Retevis_RA79,@KC9HI,27-Oct-2023 Retevis_RA85,@KC9HI,19-Nov-2022 -Retevis_RA89,@KC9HI,23-Nov-2023 Retevis_RB15,@KC9HI,18-Dec-2022 Retevis_RB17,@KC9HI,28-Nov-2022 Retevis_RB17A,@KC9HI,30-Nov-2022 @@ -320,10 +297,7 @@ Retevis_RT9000D_400-490,@KC9HI,8-Dec-2022 Retevis_RT9000D_66-88,@KC9HI,8-Dec-2022 Ruyage_UV58Plus,@KC9HI,18-Mar-2023 SenhaiX_8800,+Radioddity_GS-5B,17-Mar-2023 -Socotran_FB-8629,+Radtel_RT-490,11-Nov-2023 -Socotran_JC-8629,+Radtel_RT-490,11-Nov-2023 Talkpod_A36plus,@KC9HI,12-Jun-2023 -Talkpod_A36plus_8w,@KC9HI,16-Feb-2024 TDXone_TD-Q8A,@KC9HI,18-Dec-2022 TIDRADIO_TD-H6,@kk7ds,21-Oct-2022 TIDRADIO_TD-H8,@Sandmann34,7-Feb-2023 @@ -331,9 +305,6 @@ TIDRADIO_TD-H8-GMRS,@Sandmann34,7-Feb-2023 TIDRADIO_TD-H8-HAM,@Sandmann34,7-Feb-2023 TID_TD-M8,+Retevis_RT22,9-Dec-2022 TID_TD-UV68,@Sandmann34,7-Feb-2023 -TIDRADIO_TD-H3,@songjunbiao,1-Dec-2023 -TIDRADIO_TD-H3-GMRS,@songjunbiao,1-Dec-2023 -TIDRADIO_TD-H3-HAM,@songjunbiao,1-Dec-2023 TYT_TH-UVF1,@kk7ds,13-Dec-2022 TYT_TH-UVF8D,@MELERIX,2-Feb-2023 TYT_TH-UV8000,@KC9HI,6-Jan-2023 @@ -396,6 +367,7 @@ Yaesu_FT-857_897,+Yaesu_FT-817,14-Feb-2019 Yaesu_FT-857_897_US,+Yaesu_FT-817,14-Feb-2019 Yaesu_FT-90,#10386,22-Feb-2023 Yaesu_FTM-350,@kk7ds,4-Dec-2022 +Yaesu_FTM-6000,@Old-Phart,16-Apr-2024 Yaesu_VX-2,@thomasrussellmurphy,20-Jan-2023 Yaesu_VX-3,@kk7ds,15-Feb-2019 Yaesu_VX-5,*yaesu_clone,12-Dec-2022 From be130749da4111b695f1d36d51f0b785770fe988 Mon Sep 17 00:00:00 2001 From: Old-Phart Date: Wed, 17 Apr 2024 10:49:47 -0700 Subject: [PATCH 03/11] New makesupported, annotated FTM-200 entry. --- tests/Python3_Driver_Testing.md | 47 +++++++-------------------------- 1 file changed, 9 insertions(+), 38 deletions(-) diff --git a/tests/Python3_Driver_Testing.md b/tests/Python3_Driver_Testing.md index 68276b95a..44eb45029 100644 --- a/tests/Python3_Driver_Testing.md +++ b/tests/Python3_Driver_Testing.md @@ -5,7 +5,6 @@ | Abbree_AR-518 | [@KC9HI](https://github.com/KC9HI) | 16-Dec-2022 | Yes | 0.24% | | Abbree_AR-63 | [@KC9HI](https://github.com/KC9HI) | 30-Nov-2022 | Yes | 0.03% | | Abbree_AR-730 | [@KC9HI](https://github.com/KC9HI) | 17-Aug-2023 | Yes | | -| Abbree_AR-869 | [Implied by Radtel_RT-490](#user-content-Radtel_RT-490) | 11-Nov-2023 | Yes | 0.01% | | Abbree_AR-F5 | [@KC9HI](https://github.com/KC9HI) | 09-Aug-2023 | Yes | | | Alinco_DJ-G7EG | [@HB9UF](https://github.com/HB9UF) | 09-Dec-2022 | Yes | 0.44% | | Alinco_DJ-G7T | [Reported working](https://chirp.danplanet.com/issues/10567) | 09-May-2023 | Yes | | @@ -16,7 +15,6 @@ | Alinco_DR135T | [Implied by Alinco_DR235T](#user-content-Alinco_DR235T) | 12-Dec-2022 | Yes | 0.04% | | Alinco_DR235T | [@kk7ds](https://github.com/kk7ds) | 12-Dec-2022 | Yes | 0.02% | | Alinco_DR435T | [Implied by Alinco_DR235T](#user-content-Alinco_DR235T) | 12-Dec-2022 | Yes | 0.02% | -| Alinco_DR735T | [@jacobcalvert](https://github.com/jacobcalvert) | 03-April-2024 | Yes | | | AnyTone_5888UV | [@kk7ds](https://github.com/kk7ds) | 9-Dec-2022 | Yes | 0.14% | | AnyTone_5888UVIII | [@bschuler42](https://github.com/bschuler42) | 9-Jan-2023 | Yes | 0.04% | | AnyTone_778UV | [Implied by Retevis_RT95](#user-content-Retevis_RT95) | 13-Nov-2022 | Yes | 0.17% | @@ -46,8 +44,6 @@ | BTECH_UV-50X2_G2 | [@KC9HI](https://github.com/KC9HI) | 30-Nov-2022 | Yes | 0.00% | | BTECH_UV-50X3 | [@KC9HI](https://github.com/KC9HI) | 10-Dec-2022 | Yes | 0.06% | | BTECH_UV-5X3 | [@KC9HI](https://github.com/KC9HI) | 9-Dec-2022 | Yes | 0.43% | -| Baofeng_5RM | [@vdwel](https://github.com/vdwel) | 7-Dec-2023 | Yes | | -| Baofeng_5RX | [@KC9HI](https://github.com/KC9HI) | 16-Jan-2024 | Yes | | | Baofeng_BF-1901 | [@cetinajero](https://github.com/cetinajero) | 3-Jul-2023 | Yes | | | Baofeng_BF-1904 | [@cetinajero](https://github.com/cetinajero) | 3-Jul-2023 | Yes | | | Baofeng_BF-888 | [@kk7ds](https://github.com/kk7ds) | 13-Feb-2019 | Yes | **15.53%** | @@ -56,19 +52,11 @@ | Baofeng_BF-F8HP | [@KC9HI](https://github.com/KC9HI) | 18-Nov-2022 | Yes | **6.33%** | | Baofeng_BF-M4 | [@cetinajero](https://github.com/cetinajero) | 8-May-2023 | Yes | | | Baofeng_BF-T1 | [@KC9HI](https://github.com/KC9HI) | 10-Dec-2022 | Yes | 0.76% | -| Baofeng_BF-T20 | [@KC9HI](https://github.com/KC9HI) | 15-Dec-2023 | Yes | | -| Baofeng_BF-T20FRS | [@KC9HI](https://github.com/KC9HI) | 17-Dec-2023 | Yes | | | Baofeng_BF-T8 | [@KC9HI](https://github.com/KC9HI) | 30-Nov-2022 | Yes | 0.42% | | Baofeng_BF-V8A | [@KC9HI](https://github.com/KC9HI) | 28-Nov-2022 | Yes | 0.03% | | Baofeng_F-11 | [Implied by Baofeng_UV-5R](#user-content-Baofeng_UV-5R) | 18-Nov-2022 | Yes | 0.12% | -| Baofeng_GM-5RH | [@KC9HI](https://github.com/KC9HI) | 21-Mar-2024 | Yes | | | Baofeng_GT-3WP | [@KC9HI](https://github.com/KC9HI) | 3-Dec-2022 | Yes | 0.43% | | Baofeng_GT-5R | [@KC9HI](https://github.com/KC9HI) | 18-Nov-2022 | Yes | 0.68% | -| Baofeng_K5-Plus | | | Yes | | -| Baofeng_UV-13Pro | [@vdwel](https://github.com/vdwel) | 21-Feb-2024 | Yes | | -| Baofeng_UV-17 | [@vdwel](https://github.com/vdwel) | 27-Nov-2023 | Yes | | -| Baofeng_UV-17Pro | [@vdwel](https://github.com/vdwel) | 27-Nov-2023 | Yes | | -| Baofeng_UV-17ProGPS | [@vdwel](https://github.com/vdwel) | 27-Nov-2023 | Yes | | | Baofeng_UV-3R | [@yarda](https://github.com/yarda) | 26-Sep-2022 | Yes | 0.45% | | Baofeng_UV-5R | [@lekv](https://github.com/lekv) | 23-Oct-2022 | Yes | **28.81%** | | Baofeng_UV-6 | [Implied by Baofeng_UV-5R](#user-content-Baofeng_UV-5R) | 18-Nov-2022 | Yes | 0.46% | @@ -83,10 +71,9 @@ | Baofeng_W31E | [@KC9HI](https://github.com/KC9HI) | 14-Aug-2023 | Yes | | | Baojie_BJ-218 | [Implied by LUITON_LT-725UV](#user-content-LUITON_LT-725UV) | 16-Feb-2023 | Yes | 0.29% | | Baojie_BJ-318 | [@KC9HI](https://github.com/KC9HI) | 2-Jan-2023 | Yes | 0.10% | -| Baojie_BJ-9900 | | | Yes | 0.02% | +| Baojie_BJ-9900 | | | | 0.02% | | Baojie_BJ-UV55 | | | Yes | 0.03% | | Boblov_X3Plus | | | | 0.02% | -| Boristone_8RS | [Implied by Radtel_RT-490](#user-content-Radtel_RT-490) | 11-Nov-2023 | Yes | 0.00% | | CRT_Micron_UV | [Implied by Retevis_RT95](#user-content-Retevis_RT95) | 13-Nov-2022 | Yes | 0.08% | | CRT_Micron_UV_V2 | [Implied by Retevis_RT95](#user-content-Retevis_RT95) | 13-Nov-2022 | Yes | 0.10% | | Cignus_XTR-5 | [Implied by Radioddity_GS-5B](#user-content-Radioddity_GS-5B) | 17-Mar-2023 | Yes | | @@ -102,7 +89,6 @@ | Feidaxin_FD-460A | | | | 0.01% | | Feidaxin_FD-460UH | | | | 0.01% | | Generic_CSV | [@kk7ds](https://github.com/kk7ds) | 4-Dec-2022 | | | -| HamGeek_HG-590 | [Implied by Radtel_RT-490](#user-content-Radtel_RT-490) | 11-Nov-2023 | Yes | 0.00% | | Hiroyasu_HI-8811 | [@KC9HI](https://github.com/KC9HI) | 4-Jun-2023 | Yes | | | HobbyPCB_RS-UV3 | [@kk7ds](https://github.com/kk7ds) | 9-Dec-2022 | Yes | 0.02% | | Icom_IC-208H | [Probably works](https://github.com/kk7ds/chirp/blob/py3/chirp/drivers/icf.py) | 12-Dec-2022 | Yes | 0.05% | @@ -116,7 +102,6 @@ | Icom_IC-7100 | Mike W | 16-Feb-2023 | Yes | 0.06% | | Icom_IC-7200 | [@kk7ds](https://github.com/kk7ds) | 22-Oct-2022 | Yes | | | Icom_IC-7300 | [@kk7ds](https://github.com/kk7ds) | 22-Oct-2022 | Yes | 0.03% | -| Icom_IC-7400 | | | Yes | | | Icom_IC-746 | [Reported working](https://chirp.danplanet.com/issues/10346) | 3-Feb-2023 | Yes | | | Icom_IC-7610 | [@kk7ds](https://github.com/kk7ds) | 24-Oct-2022 | Yes | 0.00% | | Icom_IC-910 | [@mfncooper](https://github.com/mfncooper) | 1-Oct-2021 | Yes | 0.00% | @@ -144,11 +129,9 @@ | Icom_ID-880H | [@kk7ds](https://github.com/kk7ds) | 22-Oct-2022 | Yes | 0.02% | | Intek_HR-2040 | [Implied by AnyTone_5888UV](#user-content-AnyTone_5888UV) | 9-Dec-2022 | Yes | 0.02% | | Intek_KT-980HP | [Implied by Baofeng_BF-F8HP](#user-content-Baofeng_BF-F8HP) | 18-Nov-2022 | Yes | 0.04% | -| JJCC_JC-8629 | [Implied by Radtel_RT-490](#user-content-Radtel_RT-490) | 11-Nov-2023 | Yes | | | Jetstream_JT220M | [Implied by Alinco_DR235T](#user-content-Alinco_DR235T) | 12-Dec-2022 | Yes | 0.01% | | Jetstream_JT270M | [Implied by Jetstream_JT270M](#user-content-Jetstream_JT270M) | 13-Dec-2022 | Yes | 0.01% | | Jetstream_JT270MH | [@kk7ds](https://github.com/kk7ds) | 13-Dec-2022 | Yes | 0.01% | -| Jianpai_8800_Plus | [Implied by Radtel_RT-490](#user-content-Radtel_RT-490) | 11-Nov-2023 | Yes | 0.01% | | KYD_IP-620 | | | | 0.02% | | KYD_NC-630A | | | | 0.02% | | Kenwood_HMK | [Implied by Generic_CSV](#user-content-Generic_CSV) | 4-Dec-2022 | | 0.00% | @@ -158,7 +141,6 @@ | Kenwood_TH-D72_live_mode | [@kk7ds](https://github.com/kk7ds) | 21-Oct-2022 | Yes | 0.00% | | Kenwood_TH-D74_clone_mode | [@kk7ds](https://github.com/kk7ds) | 30-Nov-2022 | Yes | 0.00% | | Kenwood_TH-D74_live_mode | [@kk7ds](https://github.com/kk7ds) | 20-Oct-2022 | Yes | 0.00% | -| Kenwood_TH-D75 | [Reported working](https://chirp.danplanet.com/issues/11122) | 114-Feb-2024 | Yes | | | Kenwood_TH-D7G | [Probably works](https://github.com/kk7ds/chirp/blob/py3/chirp/drivers/kenwood_live.py) | 12-Dec-2022 | Yes | 0.00% | | Kenwood_TH-F6 | [@KC9HI](https://github.com/KC9HI) | 30-Nov-2022 | Yes | 0.03% | | Kenwood_TH-F7 | [@sv1](https://github.com/sv1) | 19-Oct-2022 | Yes | 0.03% | @@ -235,13 +217,9 @@ | LUITON_LT-580_VHF | [@KC9HI](https://github.com/KC9HI) | 8-Dec-2022 | Yes | 0.01% | | LUITON_LT-588UV | [@KC9HI](https://github.com/KC9HI) | 11-Nov-2022 | Yes | 0.01% | | LUITON_LT-725UV | [@KC9HI](https://github.com/KC9HI) | 11-Dec-2022 | Yes | 0.02% | -| Lanchonlh_HG-UV98 | [Reported working](https://chirp.danplanet.com/issues/11179) | 23-Feb-2024 | Yes | 0.00% | -| Leixen_VV-898 | [Implied by Jetstream_JT270MH](#user-content-Jetstream_JT270MH) | 13-Dec-2022 | Yes | 0.16% | -| Leixen_VV-898E | | | Yes | 0.02% | -| Leixen_VV-898E_Dual_Bank | [Implied by Leixen_VV-898S_Dual_Bank](#user-content-Leixen_VV-898S_Dual_Bank) | 10-Feb-2024 | Yes | | -| Leixen_VV-898S | [@READ10](https://github.com/READ10) | 19-Dec-2022 | Yes | 0.08% | -| Leixen_VV-898S_Dual_Bank | [Reported working](https://chirp.danplanet.com/issues/4069) | 10-Feb-2024 | Yes | | -| MMLradio_JC-8629 | [@KC9HI](https://github.com/KC9HI) | 11-Nov-2023 | Yes | 0.01% | +| Lanchonlh_HG-UV98 | | | Yes | 0.00% | +| Leixen_VV-898 | [Implied by Jetstream_JT270MH](#user-content-Jetstream_JT270MH) | 13-Dec-2022 | Yes | 0.18% | +| Leixen_VV-898S | [@READ10](https://github.com/READ10) | 19-Dec-2022 | Yes | 0.10% | | MTC_UV-5R-3 | [Implied by BTECH_UV-5X3](#user-content-BTECH_UV-5X3) | 9-Dec-2022 | Yes | 0.02% | | Maverick_RA-100 | [@cetinajero](https://github.com/cetinajero) | 7-Jul-2023 | Yes | | | Maverick_RA-425 | [@cetinajero](https://github.com/cetinajero) | 7-Jul-2023 | Yes | | @@ -264,7 +242,6 @@ | QYT_KT980PLUS | [Implied by BTECH_UV-25X2](#user-content-BTECH_UV-25X2) | 11-Nov-2022 | Yes | 0.09% | | Quansheng_TG-UV2+ | [Reported working](https://chirp.danplanet.com/issues/10398) | 26-Feb-2023 | Yes | 0.05% | | Quansheng_UV-K5 | [@sq5bpf](https://github.com/sq5bpf) | 29-May-2023 | Yes | | -| Quansheng_UV-K5_egzumer | [@egzumer](https://github.com/egzumer) | 23-Jan-2024 | Yes | | | RT_Systems_CSV | | | | | | Radioddity_DB25-G | [@KC9HI](https://github.com/KC9HI) | 11-Nov-2022 | Yes | 0.17% | | Radioddity_GA-2S | [@KC9HI](https://github.com/KC9HI) | 4-Dec-2022 | Yes | 0.19% | @@ -277,14 +254,12 @@ | Radtel_RT-470 | [@KC9HI](https://github.com/KC9HI) | 2-Apr-2023 | Yes | 0.00% | | Radtel_RT-470L | [@KC9HI](https://github.com/KC9HI) | 5-May-2023 | Yes | | | Radtel_RT-470X | [@KC9HI](https://github.com/KC9HI) | 10-Aug-2023 | Yes | | -| Radtel_RT-490 | [@KC9HI](https://github.com/KC9HI) | 11-Nov-2023 | Yes | 0.08% | | Radtel_T18 | [@KC9HI](https://github.com/KC9HI) | 28-Nov-2022 | Yes | 0.07% | | Retevis_H777S | [@KC9HI](https://github.com/KC9HI) | 22-Dec-2022 | Yes | | | Retevis_H777_Plus | [@KC9HI](https://github.com/KC9HI) | 4-Dec-2022 | Yes | 0.06% | | Retevis_RA685 | [@KC9HI](https://github.com/KC9HI) | 19-Nov-2022 | Yes | 0.25% | | Retevis_RA79 | [@KC9HI](https://github.com/KC9HI) | 27-Oct-2023 | Yes | | | Retevis_RA85 | [@KC9HI](https://github.com/KC9HI) | 19-Nov-2022 | Yes | 0.05% | -| Retevis_RA89 | [@KC9HI](https://github.com/KC9HI) | 23-Nov-2023 | Yes | | | Retevis_RB15 | [@KC9HI](https://github.com/KC9HI) | 18-Dec-2022 | Yes | 0.01% | | Retevis_RB17 | [@KC9HI](https://github.com/KC9HI) | 28-Nov-2022 | Yes | 0.02% | | Retevis_RB17A | [@KC9HI](https://github.com/KC9HI) | 30-Nov-2022 | Yes | 0.01% | @@ -353,12 +328,7 @@ | Ruyage_UV58Plus | [@KC9HI](https://github.com/KC9HI) | 18-Mar-2023 | Yes | | | Sainsonic_AP510 | | | | 0.00% | | SenhaiX_8800 | [Implied by Radioddity_GS-5B](#user-content-Radioddity_GS-5B) | 17-Mar-2023 | Yes | | -| Socotran_FB-8629 | [Implied by Radtel_RT-490](#user-content-Radtel_RT-490) | 11-Nov-2023 | Yes | 0.00% | -| Socotran_JC-8629 | [Implied by Radtel_RT-490](#user-content-Radtel_RT-490) | 11-Nov-2023 | Yes | | | TDXone_TD-Q8A | [@KC9HI](https://github.com/KC9HI) | 18-Dec-2022 | | 0.02% | -| TIDRADIO_TD-H3 | [@songjunbiao](https://github.com/songjunbiao) | 1-Dec-2023 | Yes | | -| TIDRADIO_TD-H3-GMRS | [@songjunbiao](https://github.com/songjunbiao) | 1-Dec-2023 | Yes | | -| TIDRADIO_TD-H3-HAM | [@songjunbiao](https://github.com/songjunbiao) | 1-Dec-2023 | Yes | | | TIDRADIO_TD-H6 | [@kk7ds](https://github.com/kk7ds) | 21-Oct-2022 | Yes | 0.43% | | TIDRADIO_TD-H8 | [@Sandmann34](https://github.com/Sandmann34) | 7-Feb-2023 | Yes | | | TIDRADIO_TD-H8-GMRS | [@Sandmann34](https://github.com/Sandmann34) | 7-Feb-2023 | Yes | | @@ -380,7 +350,6 @@ | TYT_TH9000_220 | [Implied by Retevis_RT9000D_220-260](#user-content-Retevis_RT9000D_220-260) | 8-Dec-2022 | Yes | 0.04% | | TYT_TH9000_440 | [Implied by Retevis_RT9000D_400-490](#user-content-Retevis_RT9000D_400-490) | 8-Dec-2022 | Yes | 0.04% | | Talkpod_A36plus | [@KC9HI](https://github.com/KC9HI) | 12-Jun-2023 | Yes | | -| Talkpod_A36plus_8w | [@KC9HI](https://github.com/KC9HI) | 16-Feb-2024 | Yes | | | Vertex_Standard_FTL-1011 | | | | 0.02% | | Vertex_Standard_FTL-2011 | | | | 0.05% | | Vertex_Standard_FTL-7011 | | | | 0.03% | @@ -440,8 +409,10 @@ | Yaesu_FT2D_R | [Implied by Yaesu_FT3D_R](#user-content-Yaesu_FT3D_R) | 30-Dec-2022 | Yes | 0.02% | | Yaesu_FT2D_Rv2 | [Implied by Yaesu_FT3D_R](#user-content-Yaesu_FT3D_R) | 30-Dec-2022 | Yes | | | Yaesu_FT3D_R | [@kk7ds](https://github.com/kk7ds) | 30-Dec-2022 | Yes | 0.03% | +| Yaesu_FTM-200 | [@Old-Phart](https://github.com/Old-Phart) | 16-Apr-2024 | Yes | | | Yaesu_FTM-3200D_R | | | Yes | 0.02% | | Yaesu_FTM-350 | [@kk7ds](https://github.com/kk7ds) | 4-Dec-2022 | Yes | 0.02% | +| Yaesu_FTM-6000 | [@Old-Phart](https://github.com/Old-Phart) | 16-Apr-2024 | Yes | | | Yaesu_FTM-7250D_R | | | Yes | 0.04% | | Yaesu_VX-170 | | | Yes | 0.03% | | Yaesu_VX-2 | [@thomasrussellmurphy](https://github.com/thomasrussellmurphy) | 20-Jan-2023 | Yes | 0.04% | @@ -456,11 +427,11 @@ | Zastone_ZT-X6 | [Implied by Retevis_RT22](#user-content-Retevis_RT22) | 9-Dec-2022 | Yes | 0.11% | ## Stats -**Drivers:** 453 +**Drivers:** 424 -**Tested:** 87% (398/55) (93% of usage stats) +**Tested:** 87% (370/54) (93% of usage stats) -**Byte clean:** 91% (414/39) +**Byte clean:** 90% (384/40) ## Meaning of this testing From 73e131a1420a9ba9c475e191553facee3ba97648 Mon Sep 17 00:00:00 2001 From: Old-Phart Date: Wed, 17 Apr 2024 12:02:32 -0700 Subject: [PATCH 04/11] Test image for Yaesu FTM-200 clone mode --- tests/images/Yaesu_FTM-200.img | Bin 0 -> 98489 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 tests/images/Yaesu_FTM-200.img diff --git a/tests/images/Yaesu_FTM-200.img b/tests/images/Yaesu_FTM-200.img new file mode 100644 index 0000000000000000000000000000000000000000..d52457dc40707bc0d26f081a8faa518cedd2eef1 GIT binary patch literal 98489 zcmeI5-)%cZmuMN%YXN&*7Nk{w&N zoErXH=c+~ov{!|bqAddS3Gxs{uYJ`wDB1$;U0;DcbGXYrJ5pfFvTDix76`fDo|!Xe zelt6Jgm^jbOlf@Nj8f`57Ja;gqhRG#j@lhkM|JDglvU;^v>sB*R`%(>E-ICoa!UR3 zmz8om<)<1;(b zN)_(heebQ~@1N6SBn~TBP)?h(MKlx6KPd{o~f0V_J5L`O2j@Ar-;=RZ2%JU_g=Omo|IPG*$) z^C}hknCnHQj~vO+fM+Wwe|6%AC(~bvKYd0wv~k4k?&W(g2;6El>ZiXD_jsYzj;<}c zL2FT;?--s}t$oY|pXjq*k>u>zqUzOBk^k5Adq=$gmy3^VEBJnaCS|qvym{nV!7;5H zi9W7%E73pJdOp%qR`3ojT4{m1c=zOQvTipP$0+#dD+9U0#g*|oo!e*Bd!X(xZTv~DN%ue5F^`j1-2 z?Nj`1l6`+u*7TCpzBT=pEKmBh)-j)0$MKW?NxHq>c*f&L_EBw5;t$Sh9oMILF3R?) zzsx@_Pw_RhJ?29?H9pFk=Kcsf`xDxe^@;EI((zUvi}>it*~@=uxz*L64>ylTzE$D* z9Lc?;vZ~IaL()LBqao=#8{4|30mQD`{PxH1yX( z?>FBsysf}~n;O*X3;q4^g}*hG){d9ecD>%Q-SG-qYaUupk=B5s^@ZwtUb?)mQvRKC z+TT|BH`-q7`!7G%TCcx7|GmFI`u-h%Oxxr3{Vn&l)^U7O&g7zwCmJt`Z*tYpR}6j6 z(7!fx*3jHv;s2OnFB-ZewZB#V%7~wN)uaCE@i<5EN8_>I;}8EF^}oH8>0j#Io_~8QiDkDw zQ62<900ck)1bPH|&yvGVL-*qF_TkH}nv>C!PW6WLsI;eyWH7ZXi*pbF0T2KI5C8!X z009sH0T2KI5C8!X009sH0T2KI5C8!XcpVA6=uLiJM~3J#2!H?xJP(1wkA86S_+{1K zhcVK2>?_h4Lpz4f8hXIcIYZ|SJ($*(_}}UUYnGy;Pl|~?DH8gm_UV&aE!b?e*=n=Z zW~&3 z?-w2Y`+fa>R=oeTL;u80>mt2`yzBj^_vY^ny}`2HV9&Pb{a^bSo$;YB$A>F2QI+^>AU^4T7fLza|9Pf=g-@)?Vru{Agtzm7 z^8vjD67B!|_kaI~pXGZ0XSKur&%4=wSVj8}t72;Z;Y{Ww?LQpv*89AF!@dgjlW{+s zXAOOnl*@00@8p2!H?xfB*=900@8p2!H?xfB*=900@8p2!H?x zfB*=9K&LX%krW#3dZ%_Vxzd_*r^9xly{a45f<#y5>h)G4yB9-$ctq&1xv*ou^`6P@Qo_{mx8S_Jse1 znp|lZHQ%jPg@5MXNF3H(;+@ho9w|-yQ<}z8 zXl`EsWGw?unmQ0?b=T}qdVXp9qUaxMF@MeZ=2e$#vSXxE^J{K=UJkb`%I9!Hjf5{_W39enAJ#9Ymd=~SMwP>I9g``>5FY*3JBH5p_ zdAC^_5d)(2sNk_bt-|X;A+X#0*v!B5{VZ;$u9+X3`LLP4?l#{v*H3dj+?H?Zd_v4; zGygQ#pN?1ZS44h)P{s*yfB*=900@8p2!H?xfB*=900@8p2!H?xfB*=900@8p2!H?x zfB*=900@8p2!H?xfB*=900@8p2!H?xfB*=900@8p2!H?xJR1RjhF-9nob12h*qCn( z%lC`5UX(AyJeymT0s#;J0T6h_2=Mb^EO`N*pASO6V%zsqYUpoUv9^_(`FWX&slOJt3a7eMDc{p)=-R37H!rRI zkzV_%yMArs_O1VJ+`Ou+D-UPyu5?B|U0J$TTE7`=)Hl3|Pg@VJhM&z|Uz@IczWy*A z5B=HTN@wiaT4(e6;?2s9OPxt?ZF=(>+3t{Sbfq(PW9>pnb={3lr?RsxGC8`kH2XQVagS}E Pd1LdV&CSajvy=Y=0p1Mv literal 0 HcmV?d00001 From eea90e1cf521d24c441fc0698ccbc59a23f609b3 Mon Sep 17 00:00:00 2001 From: Old-Phart Date: Wed, 17 Apr 2024 12:02:56 -0700 Subject: [PATCH 05/11] Test image for Yaesu FTM-6000 clone mode --- tests/images/Yaesu_FTM-6000.img | Bin 0 -> 98493 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 tests/images/Yaesu_FTM-6000.img diff --git a/tests/images/Yaesu_FTM-6000.img b/tests/images/Yaesu_FTM-6000.img new file mode 100644 index 0000000000000000000000000000000000000000..318e7d694f4f56b7552039b69acce3728bc53178 GIT binary patch literal 98493 zcmeI5ZEqCU702)Fj-P-Q8UhI+A%>)CQpv$HJBRk~7%;nj@Ix7&1Fs!?{f$F3PUU&y zmm34oQYa=9Vul`(ypjQQ(7{`GHRXn1&c?0)(1J0labjn8iWdhO0{zWl~p$2Y0x z#XM`Zo0Uds>wRDU#6G+(&mQ;fkqrJ%!{h$ZpC4@=9a&r?C*vQ=8uRC2I{irQv!!?J z$kKrKl@Hx~{k22sU$%t(MHA3DqIMtW_rrVma5tz{Z9fYqq8^`Uwe7XVpwyb@^9P2P zuhu@2g7^6>ERvi(yxq;XFPXh|p1fjSm9vBN`3C*GX|HdlwshGCcI*YZxSH`wd)0cr zYP`}u){Ss|zfJxD)~!Up#ddaW(^X0(^muc9@3Q|3>ytjl`b=_vfwj#aT>lhn zTR+z)`M~_@aCk$A37CFVwWsOMTOE|H^CH zr~0n2ZYTcNtec7chV`7)6n~o}<@c!msgqh~y{Y|SdCC8)q>r$U_(VF2pY%Inds3cx z%6LZONB$W5c0a-Xk6GLMZ&N&azd?M%e5~SYaD2&lOxf{?*csTy1r`eEj#TkJMAqy z?Jeu}_y-9f!=v?IujihVKiJpnIs1A&XJ4=9?CbTM zbSi&P`BeU3U*`|@o%T}sgMFvHRQ{mnC6zxsCx5Vint9s%$iB`W?Cbo&zVMIBdquvT z4q0}e_WHJg`b+ybnrME|enIb#dH#^D|+43~MReARH{xeJSKhJ(WT+dm*#JU;k4e;A; zt*P z%mMpX%m>T|A%Oh?)&s1E*e~Gk55k0i^$_bJ)<6BM{Q&*{ByW}Y{jy#3z6c!|vyP7cJ)kY$=lK1O z9&q%aqleO3e=p=7Z-%0yPl|~?DH8gm_UV&a-IEbFBW_0AjJO$bv*KpO&5D~9H!H3$ zt}m`Ht}m`HZlAb);`WK#CvKm({o?kE+b?dvxc%Y|h&v$efVczV4v0G_?x47X;tq;C zDDIHBL*fpJJ0$LqxJFzft`XOWYuLpB0w4eaAh1yaPx||!pLBhDJ$?y>UKPuD^gd8# z-%hhrUWeez(IG|ntFZ0CFAmYQNdJsZJoDY~U3%G!k5C_>vyAyxt|TA*$!U1D`R{-B z-}B$2w-UndfBxs+|MnmGj@tkC{m)zZ{$Y-6JAD7JdCWh&J`eYAbe^Fc2!H?xfB*=9 z00@8p2!H?xfB*=900@8p2!H?xfB*=900@8p2!H?xfB*=900@8p2!H?xfB*=900@8p z2!H?xfB*=900@8p2!H?xfB*=900@8p2!H?xfB*=900@8p2!H?xfB*=900@8p2!H?x zfB*=900@8p2!H?xfB*=900@8p2!H?xfB*=900@8p2!H?xfB*=900@8p2!H?xfB*=9 z00@8p2!H?xfB*=900@8p2!H?xfB*=9!1g83DNl5Cbd7esQ(H)`v}S{;N;}c{YEY?_ z5?!9H*IS9~EmR64Ii)MD;KY28Tws4Jk-g%4t&lGy7wSQ6WI;<5fU8zW0;ndMzrh`O5vOe2d~y zvR5kv)vBsr_&1UY>jCjjX&R4|CjKc+9?|0~T8(ee-~oxd*AuPcO`NB5)+{ZIoXjV6 zpB%{twPK=Y>&GjJqV=r0SaWo0J?%_1S|!z=LZR7cHy)R)p!UrJMbDNXe$&HYu6Q%~}N zivMJucqPsCHpEY@Z^BP$cYZt<{8axQ$WQqSx*c$zOdHoi)bgl?UX+fGTY;9v-@Lr|HboJ;qJNnV|PF7?q4^% z-*neccRsJ%FY$V;o=CT@{ezb5(?e8BoN`>i>u~D@@cvN}#AOHd&00JQJAOe(6 zjv=2shzzcQ00@8p2xtP7FWyJK&_r+!0w4eaAg~bvlt0FiKQ=-NWk3J~KmY_Z0m>i8 zkv}vMoPz)efB*<=g#hJ~3FMQlki$J700JQJViBNx@d5J1i#6uxEeL=B2s{k}luss+ zPo4%@)CmG000Pf80nQJT>iwg}Tx&$XU(9-5zYz0mcNfuv00@8p2yBr6<%8mzRxq?$*q;Q=Q!TQztKsE?q9I z)K~Ho=UX?HE1%AM(w!>*YUx(xc%?8?I@cM$(Cu9MWd3sb;+f85zB_g40(qa2H+HHs zezAM3LiYwMolg1E(y{rKY9UzZb|x>L>fDg)%}dQ%wY_*_t{8}S_Hy~wnNIohvjwid qBG(qjE?imqG=Ki=<%L^IW0$UXSETJ5=i0T4r%o=eoImm5hyMeduUY^A literal 0 HcmV?d00001 From 0b0a632c1597081bf221df7f76c488f97e8a43fb Mon Sep 17 00:00:00 2001 From: Old-Phart Date: Sat, 20 Apr 2024 06:18:48 -0700 Subject: [PATCH 06/11] Corrected style errors, logic change for _ft2lcd, removed dbg_dump. --- chirp/drivers/ftm6000.py | 1077 ++++++++++++++++++++------------------ 1 file changed, 558 insertions(+), 519 deletions(-) diff --git a/chirp/drivers/ftm6000.py b/chirp/drivers/ftm6000.py index d3e3c2fe5..a725f7a8f 100644 --- a/chirp/drivers/ftm6000.py +++ b/chirp/drivers/ftm6000.py @@ -1,5 +1,7 @@ # Copyright 2018 by Rick DeWitt (aa0rd@yahoo.com) V1.0 # Issues 9719 for FTM-6000 and 11137 for FTM-200 +# Note: 'TESTME' flags are intended for use with future sub-models +# FTM-100, FTM-300 and FTM-500 can probably be supported # # 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 @@ -16,11 +18,6 @@ """FTM-6000 Yaesu Radio Driver""" -from ast import Bytes -from asyncio.windows_events import NULL -from operator import indexOf -from pickle import FALSE -from unittest.util import _MAX_LENGTH from chirp.drivers import yaesu_clone from chirp import chirp_common, util, memmap, errors, directory, bitwise from chirp.settings import RadioSetting, RadioSettingGroup, \ @@ -30,48 +27,15 @@ import time import struct import logging -import itertools import math import sys LOG = logging.getLogger(__name__) - CMD_ACK = b'\x06' -def dbg_dump(stz, kn=32, cptn="DBG", ax=False, lgx=1): - """ Debugging tool to print up to kn hex values of string stz """ - # ax: flag to append ascii, lgx: Log code (bits) 1=Warning, 2=Debug - # print 16 bytes (+ ascii) per line - bn = 0 - an = 0 - sx = "" - kx = len(stz) - for ix in range(kx): - sx += "%02x " % stz[ix] - bn += 1 - if bn == 16: - # if ax: # append as ascii - # sx += " [" - # for ix in range(kx): - # if stz[ix] > 31 and stz[ix] < 127: - # sx += "%s" % chr(stz[ix]) - # else: - # sx += "." - # sx += "]" - sx += "\n " - bn = 0 - if lgx & 1: - LOG.warning("Block length: %d" % len(stz)) - LOG.warning("%s: %s" % (cptn, sx)) - if lgx & 2: - LOG.debug("Block length: %d" % len(stz)) - LOG.debug("%s: %s" % (cptn, sx)) - return - - class Ftm6000RAlias(chirp_common.Alias): Vendor = "Yaesu" - MODEL = "FTM-6000R" + MODEL = "FTM-6000R" @directory.register @@ -92,18 +56,18 @@ class FTM6000Radio(yaesu_clone.YaesuCloneModeRadio): DUPLEX = ["", "n/a", "-", "+", "split"] T_STEPS = [2.5, 5.0, 6.25, 10.0, 12.5, 15.0, 20.0, 25.0, 50.0, 100.0] VALID_BANDS = [(108000000, 137000000), - (137000000, 174000000), - (174000000, 400000000), - (400000000, 480000000), - (480000000, 999999999)] + (137000000, 174000000), + (174000000, 400000000), + (400000000, 480000000), + (480000000, 999999999)] POWER_LEVELS = [chirp_common.PowerLevel("Hi", watts=50), chirp_common.PowerLevel("Mid", watts=20), chirp_common.PowerLevel("Low", watts=5)] SKIPS = ["", "S"] # No lowercase,{} or ~ - CHARSET = [chr(x) for x in list(range(ord(" "), ord("_") + 1)) + + CHARSET = [chr(x) for x in list(range(ord(" "), ord("_") + 1)) + [ord("|")]] - DTMF_CHARS = list("0123456789ABCD*#") + DTMF_CHARS = list("0123456789ABCD*#") MEM_FORMAT = """ struct memdat { // 16 bytes per chan u8 used:1, // 00 @@ -119,7 +83,7 @@ class FTM6000Radio(yaesu_clone.YaesuCloneModeRadio): step:4; u24 frqtx; // 06-08 u8 power:2, // 09 - rtone:6; + rtone:6; u8 clktyp:1, // 0A, dtcs:7; u8 prfreq; // 0B @@ -131,14 +95,14 @@ class FTM6000Radio(yaesu_clone.YaesuCloneModeRadio): struct tag { u8 chname[16]; }; - + struct pmgx { u8 za; // 0x00 u8 fb; // 0xff u16 chnp; // 0-based pmg channel number }; - - struct { // In 1st block + + struct { // In 1st block u8 id[6]; } model; #seekto 0x080; @@ -373,7 +337,7 @@ class FTM6000Radio(yaesu_clone.YaesuCloneModeRadio): aprsfs:2; u8 471a:4, aprsff:4; - u8 472xf[14]; // -> 047f + u8 472xf[14]; // -> 047f u8 aprrtxt[64]; // 0480 - 04BF } wierd; #seekto 0x500; @@ -485,7 +449,7 @@ class FTM6000Radio(yaesu_clone.YaesuCloneModeRadio): u8 f31; // 17f31 u8 f1key; // 17f32 u8 f33; - u8 f34; + u8 f34; u8 f35a:4, gpslog:4; u8 f36a:6, @@ -494,7 +458,7 @@ class FTM6000Radio(yaesu_clone.YaesuCloneModeRadio): voxdly:3; u8 f38a:6, // 17f38 audrec:2; - u8 lastfunc; // 17f39 + u8 lastfunc; // 17f39 u8 f3a:6, // 17f3a lcd_clr:2; u8 f3bxf[5]; // 17f3b-3f @@ -559,13 +523,13 @@ class FTM6000Radio(yaesu_clone.YaesuCloneModeRadio): audmic:1, f6ab:2, btsave:1; - u8 wrxloc:1, // 17f6b + u8 wrxloc:1, // 17f6b fvslan:1, f6bb:2, beep1:1, // Stupid split beep: this is Off/Low - fvsrxm:1, - f6bc:2; - u8 gpsdev:1, // 17f6c + fvsrxm:1, + f6bc:2; + u8 gpsdev:1, // 17f6c memlist:1, wrxrng:1, wrxrwf:1, @@ -691,7 +655,7 @@ def get_prompts(cls): "5. Wait for Complete.\n" "6. Long-press the power On button to leave the clone mode.") return rp - + def _read(self, blck, blsz): # be very patient at first block if blck == 0: @@ -704,7 +668,8 @@ def _read(self, blck, blsz): break time.sleep(0.5) if len(data) == blsz: - LOG.debug("Received block %s, sub %s" % (hex(data[0]), hex(data[1]))) + LOG.debug("Received block %s, sub %s" % (hex(data[0]), + hex(data[1]))) checksum = data[blsz - 1] cs = 0 for i in data[:-1]: @@ -727,7 +692,6 @@ def _clone_in(self): self.pipe.parity = self.COM_PRTY self.pipe.stopbits = self.COM_STOP self.pipe.rtscts = False - start = time.time() data = b"" status = chirp_common.Status() status.msg = "Cloning from radio" @@ -744,35 +708,37 @@ def _clone_in(self): def _write(self, nblk, nsub, pntr, bksz, zblk): LOG.debug("Block %02X %02X" % (nblk, nsub)) - # if self.TESTME: LOG.warning("Block %02X %02X" % (nblk, nsub)) + if self.TESTME: + LOG.warning("Block %02X %02X" % (nblk, nsub)) data = struct.pack('B', nblk) data += struct.pack('B', nsub) if zblk: blkdat = bytearray(bksz) # All Zeros else: blkdat = self.get_mmap()[pntr:pntr + bksz] - data += blkdat + data += blkdat cs = 0 for i in data: - cs = (cs + i) % 256 - LOG.debug("Checksum %s" % hex(cs)) - # if self.TESTME: LOG.warning("Checksum %s" % hex(cs)) + cs = (cs + i) % 256 + LOG.debug("Checksum %s" % hex(cs)) + if self.TESTME: + LOG.warning("Checksum %s" % hex(cs)) data += struct.pack('B', cs) LOG.debug("Writing %d bytes:\n%s" % (len(data), util.hexprint(data))) - # if self.TESTME: # Dont send data yet - # LOG.warning("Writing %d bytes:\n%s" % (len(data), - # util.hexprint(data))) - # buf = CMD_ACK - # else: - self.pipe.write(data) - buf = self.pipe.read(1) + if self.TESTME: # Dont send data yet + LOG.warning("Writing %d bytes:\n%s" % (len(data), + util.hexprint(data))) + buf = CMD_ACK + else: + self.pipe.write(data) + buf = self.pipe.read(1) if not buf or buf[:1] != CMD_ACK: time.sleep(0.5) buf = self.pipe.read(1) if not buf or buf[:1] != CMD_ACK: return False - return True + return True def _clone_out(self): self.pipe.baudrate = self.BAUD_RATE @@ -780,14 +746,13 @@ def _clone_out(self): self.pipe.parity = self.COM_PRTY self.pipe.stopbits = self.COM_STOP self.pipe.rtscts = False - - start = time.time() + status = chirp_common.Status() status.msg = "Cloning to radio" blksz = 128 # actual data; excluding block, sub, checksum pkt = 0 pos = 0 - block = 0 + block = 0 wrtzero = False # Special last block flag nblocks = 767 # last block number status.max = nblocks - 2 @@ -795,8 +760,8 @@ def _clone_out(self): # + sub-block + special EoD numbering! while pkt <= nblocks: LOG.debug("Writing packet #: %d." % pkt) - # if self.TESTME: LOG.warning("Writing packet #: %d , pos %x." - # % (pkt, pos)) + if self.TESTME: + LOG.warning("Writing packet #: %d , pos %x." % (pkt, pos)) time.sleep(0.01) sub2 = True sublk = 0 @@ -827,11 +792,11 @@ def _clone_out(self): pkt += 1 pos += blksz LOG.debug("Writing packet #: %.d" % pkt) - # if self.TESTME: LOG.warning("Writing packet #: %d , - # pos %x." % (pkt, pos)) + if self.TESTME: + LOG.warning("Writing packet #: %d , pos %x." % (pkt, pos)) rslt = self._write(block, sublk, pos, blksz, wrtzero) if not rslt: - raise Exception("Radio did not ack block %i %1" % + raise Exception("Radio did not ack block %i %i" % (block, sublk)) pos += blksz block += 1 @@ -839,7 +804,7 @@ def _clone_out(self): status.cur = pkt self.status_fn(status) return - + def sync_in(self): try: self._mmap = self._clone_in() @@ -868,7 +833,7 @@ def get_features(self): rf.has_bank = False rf.has_dtcs = True rf.has_cross = True - rf.has_tuning_step = True + rf.has_tuning_step = True rf.has_ctone = False # Common Tones rf.has_rx_dtcs = False # Common codes rf.has_settings = True @@ -882,44 +847,44 @@ def get_features(self): rf.valid_power_levels = self.POWER_LEVELS rf.valid_characters = "".join(self.CHARSET) rf.valid_name_length = self.NAME_LEN - rf.valid_skips = self.SKIPS - - rf.memory_bounds = (1, 1099) + rf.valid_skips = self.SKIPS return rf def get_raw_memory(self, number): return repr(self._memobj.main[number - 1]) - + def validate_memory(self, mem): msgs = yaesu_clone.YaesuCloneModeRadio.validate_memory(self, mem) return msgs - + def filter_name(self, namsx): """Name must be <= NAME_LEN and contain only CHARSET chars""" tx = namsx.strip() sx = "" - if self.FTM200 == False: tx = tx.upper() + if self.FTM200 is False: + tx = tx.upper() for i in range(0, len(tx)): - if i >= self.NAME_LEN: break + if i >= self.NAME_LEN: + break if tx[i] in self.CHARSET: sx += tx[i] else: sx = "?" - return sx - + return sx + def _freqdcode(self, frqb): """Decode .0025 Mhz upper 2 MSB of freq""" # frqb is u24: 2bits suffix, 22 bits bcd sx = "%06X" % frqb - v0 = int(sx[0], 16) * 625 + v0 = int(sx[0], 16) * 625 v1 = int(sx[1]) # 100 Mhz v2 = int(sx[2:4]) # 10 Mhz v3 = int(sx[4:]) # 100 Khz vx = (v1 * 10000) + (v2 * 100) + v3 vx = vx * 10000 + v0 return vx - + def _freqncode(self, frq): """Encode .0625 Mhz in upper MSB of u24 bcd freq""" v0 = frq % 10000 # .025 value @@ -929,11 +894,11 @@ def _freqncode(self, frq): sx = "%06d" % vx # Ex: 012345 for frq = 123.45 MHz v1 = int("0x" + sx[0:2], 16) v2 = int("0x" + sx[2:4], 16) - v3 = int("0x" + sx[4:], 16) + v3 = int("0x" + sx[4:], 16) frqb = bx + v1 * 0x10000 + v2 * 0x100 + v3 return frqb - - def _b2s(self, bary, term = 0xff): + + def _b2s(self, bary, term=0xff): """Convert byte array into string """ strx = "" for i in bary: @@ -941,12 +906,13 @@ def _b2s(self, bary, term = 0xff): break strx += chr(i) return strx - - def _s2b(self, setting, obj, atrb, mxk, pad = 0xff, upc = True): + + def _s2b(self, setting, obj, atrb, mxk, pad=0xff, upc=True): """Callback: Convert string to byte array, pad to mxk chars""" sx = str(setting.value) sx = sx.strip() - if upc: sx = sx.upper() + if upc: + sx = sx.upper() ary = b"" v1 = len(sx) for vx in range(0, mxk): @@ -956,7 +922,7 @@ def _s2b(self, setting, obj, atrb, mxk, pad = 0xff, upc = True): ary += pad.to_bytes(1, sys.byteorder) setattr(obj, atrb, ary) return - + def _c2u8(self, setting, obj, atrb): """Callback: Convert single char string to u8""" b0 = str(setting.value) @@ -968,7 +934,7 @@ def get_memory(self, number): mem = chirp_common.Memory() if number < 1000: # channel memory _mem = self._memobj.main[number - 1] - _tag = self._memobj.names[number - 1] + _tag = self._memobj.names[number - 1] else: _mem = self._memobj.pms[number - 1000] _tag = self._memobj.pms_name[number - 1000] @@ -1014,13 +980,14 @@ def get_memory(self, number): mem.power = self.POWER_LEVELS[vx] mem.tuning_step = self.T_STEPS[_mem.step] tx = self._b2s(_tag.chname, 0xff).strip() - if self.FTM200 == False: tx = tx.upper() + if self.FTM200 is False: + tx = tx.upper() mem.name = tx - # Echo name string back into memory. - # In case it got loaded flakey in radio; trailing spaces + # Echo name string back into memory. + # In case it got loaded flakey in radio; trailing spaces for i in range(0, self.NAME_LEN): if i < len(mem.name): - _tag.chname[i] = ord(mem.name[i]) + _tag.chname[i] = ord(mem.name[i]) else: _tag.chname[i] = 0xff # mem.extra: Clock Type A/B @@ -1029,26 +996,30 @@ def get_memory(self, number): rx = RadioSettingValueList(options, options[_mem.clktyp]) rs = RadioSetting("clktyp", "Clock Shift (CLK.TYP)", rx) mem.extra.append(rs) - + options = ["None", "REV Tone", "PR Freq", "Pager"] tmd = _mem.tmode - 3 - if _mem.tmode < 4: tmd = 0 - if _mem.tmode > 6: tmd = 0 + if _mem.tmode < 4: + tmd = 0 + if _mem.tmode > 6: + tmd = 0 rx = RadioSettingValueList(options, options[tmd]) rs = RadioSetting("spclmode", "Radio Special Tone Mode", rx) mem.extra.append(rs) - + options = [] for vx in range(300, 3100, 100): sx = str(vx) options.append(sx) - if _mem.prfreq > 30: _mem.prfreq = 30 # Can get loaded wrong...? - if _mem.prfreq < 3: _mem.prfreq = 3 - v0 =_mem.prfreq * 100 # .prfreq is 0x03 - 0x1E (3 -30 decimal) + if _mem.prfreq > 30: + _mem.prfreq = 30 # Can get loaded wrong...? + if _mem.prfreq < 3: + _mem.prfreq = 3 + v0 = _mem.prfreq * 100 # .prfreq is 0x03 - 0x1E (3 -30 decimal) sx = str(v0) rx = RadioSettingValueList(options, sx) rs = RadioSetting("prfreq", "PR (User) Freq Htz", rx) - mem.extra.append(rs) + mem.extra.append(rs) return mem def set_memory(self, mem): @@ -1076,22 +1047,30 @@ def set_memory(self, mem): tx = mem.tmode.strip() cmx = mem.cross_mode.strip() if tx == "Cross": - if cmx == "->DTCS": tmd = 3 - if cmx == "Tone->DTCS": tmd = 8 - if cmx == "DTCS->Tone": tmd = 9 + if cmx == "->DTCS": + tmd = 3 + if cmx == "Tone->DTCS": + tmd = 8 + if cmx == "DTCS->Tone": + tmd = 9 sqlx = 1 else: - if tx == "Tone": tmd = 1 - if tx == "TSQL": tmd = 2 - if tx == "TSQL-R": tmd = 4 - if tx == "DTCS": tmd = 7 + if tx == "Tone": + tmd = 1 + if tx == "TSQL": + tmd = 2 + if tx == "TSQL-R": + tmd = 4 + if tx == "DTCS": + tmd = 7 _mem.tmode = tmd _mem.rtone = chirp_common.TONES.index(mem.rtone) _mem.step = self.T_STEPS.index(mem.tuning_step) _mem.skip = self.SKIPS.index(mem.skip) _mem.dtcs = chirp_common.DTCS_CODES.index(mem.dtcs) sx = mem.power - if sx == None: sx = self.POWER_LEVELS[1] # Mid + if sx is None: + sx = self.POWER_LEVELS[1] # Mid _mem.power = self.POWER_LEVELS.index(sx) setattr(self._memobj.setts, "sqlexp1", sqlx) setattr(self._memobj.setts, "sqlexp2", sqlx) @@ -1105,7 +1084,8 @@ def set_memory(self, mem): if setting.get_name() == "clktyp": sx = str(setting.value) vx = 0 - if sx == "On": vx = 1 + if sx == "On": + vx = 1 setattr(_mem, "clktyp", vx) if setting.get_name() == "spclmode": sx = str(setting.value) @@ -1116,29 +1096,32 @@ def set_memory(self, mem): tmd = 0 # Reset from special to none else: tmd = _mem.tmode # no change - if sx == "PR Freq": tmd = 5 - if sx == "Pager": tmd = 6 + if sx == "PR Freq": + tmd = 5 + if sx == "Pager": + tmd = 6 setattr(_mem, "tmode", tmd) if setting.get_name() == "prfreq": sx = str(setting.value) vx = int(sx) // 100 setattr(_mem, "prfreq", vx) return - + def _micpkey(self, setting, obj, atrb, opts): """Callback: Adjust stored value for microphone P keys""" sx = str(setting.value) # the list string v0 = opts.index(sx) # the options array index, 0-based v1 = v0 + 0xdc - if self.FTM200 == False: + if self.FTM200 is False: v1 = v0 + 0xdd - if v1 == 0xe6: v1 = 0xe7 # skip e6 + if v1 == 0xe6: + v1 = 0xe7 # skip e6 setattr(obj, atrb, v1) return def _setfunc(self, setting, obj, atrb, ndx): """Callback: Convert boolean to function setting""" - # Stored in shared memory 'share1' as 2 bytes. + # Stored in shared memory 'share1' as 2 bytes. # When set: first byte is menu number, 2nd is 00 # Unset: ff, ff bx = bool(setting.value) # boolean @@ -1152,7 +1135,7 @@ def _setfunc(self, setting, obj, atrb, ndx): setattr(obj[x1], atrb, v0) setattr(obj[x1 + 1], atrb, v1) return - + def _setQA(self, setting, obj, atrb, opts): """Callback: FTM-200 menu list selection to menu code""" sx = str(setting.value) @@ -1164,28 +1147,31 @@ def _sqlexp1(self, setting, obj, atrb): """ Callback: SQL.EXP requires setting two objects """ sx = str(setting.value) bx = False - if sx == "On": bx = True + if sx == "On": + bx = True setattr(obj, atrb, bx) # sqlexp1 setattr(obj, "sqlexp2", bx) return - + def _settot(self, setting, obj, atrb, opts): """Callback: convert non-linear TOT values""" sx = str(setting.value) v0 = opts.index(sx) v1 = v0 - if v0 > 0: v1 = v0 + 5 - if v0 > 3: v1 = v0 - 3 + if v0 > 0: + v1 = v0 + 5 + if v0 > 3: + v1 = v0 - 3 setattr(obj, atrb, v1) return - + def _adjint(self, setting, obj, atrb): """Callback: decrement integer value to 0-based""" v0 = int(setting.value) v1 = v0 - 1 setattr(obj, atrb, v1) return - + def _unpack_str(self, codestr): """Convert u8 DTMF array to a string: NOT a callback.""" sx = "" @@ -1244,10 +1230,11 @@ def _adjlist(self, setting, obj, atrb, opts, ofst): sx = str(setting.value) # the list string vx = opts.index(sx) + ofst if atrb == "tzone": # special case for time zone - if vx < 0 : vx = abs(vx) + 0x80 + if vx < 0: + vx = abs(vx) + 0x80 setattr(obj, atrb, vx) return - + def _ft2apo(self, setting, obj): """Callback: Set FTM-200 APO coded decimal in 2 bytes""" sx = str(setting.value) # Ex '1.5 Hours' @@ -1262,7 +1249,7 @@ def _ft2apo(self, setting, obj): else: vx = sx.index(" H") v1 = int(sx[:vx]) - v2 = 0 + v2 = 0 setattr(obj, "apo", v1) setattr(obj, "apo1", v2) return @@ -1270,9 +1257,11 @@ def _ft2apo(self, setting, obj): def _ft2lcd(self, setting, obj, atrb): """Callback: to set LCD Display Brightness""" sx = str(setting.value) - v0 = 0 - if sx == "Mid": v0 = 1 - if sx == "Max": vo = 2 + v0 = 3 + if sx == "Mid": + v0 = 1 + if sx == "Full": + v0 = 2 setattr(obj, atrb, v0) return @@ -1282,17 +1271,20 @@ def _scndrm(self, setting, obj): sx = str(setting.value) v0 = 0 v1 = 0 - if "Pri" in sx: v0 = 1 - if "A-B" in sx: v1 = 1 + if "Pri" in sx: + v0 = 1 + if "A-B" in sx: + v1 = 1 setattr(obj, "scndrm1", v0) setattr(obj, "scndrm2", v1) return - + def _skp_other(self, setting, obj, bnd, opts): """Callback: FTM-200 Band Skip Other requires 2 bits""" - sx = str(setting.value) #Off/On + sx = str(setting.value) # Off/On v0 = 0 - if "On" in sx: v0 = 1 + if "On" in sx: + v0 = 1 b0 = "bskpa0" b3 = "bskpa3" if "B" in bnd: @@ -1301,7 +1293,7 @@ def _skp_other(self, setting, obj, bnd, opts): setattr(obj, b0, v0) setattr(obj, b3, v0) return - + def _beepset(self, setting, obj, optns): """Callback: Stupid split-beep""" sx = str(setting.value) @@ -1314,8 +1306,8 @@ def _beepset(self, setting, obj, optns): setattr(obj, "beep1", v0) setattr(obj, "beep2", v1) return - - def _xmsg(self, setting, obj, indx, xmp, mode = 0): + + def _xmsg(self, setting, obj, indx, xmp, mode=0): """Callback: Wires-X message # indx, text encoder """ # mode=0 is GM Message, mode=1 is Category sx = str(setting.value).strip() @@ -1323,8 +1315,8 @@ def _xmsg(self, setting, obj, indx, xmp, mode = 0): v0 = 128 v1 = 0xff hx = "msg%02d" % indx - if mode == 1: - v0 =16 + if mode == 1: + v0 = 16 v1 = 0xca hx = "c%d" % indx for cx in range(0, v0): @@ -1332,75 +1324,83 @@ def _xmsg(self, setting, obj, indx, xmp, mode = 0): vx = sx[cx] try: v2 = xmp.index(vx) - except: + except Exception: raise Exception("Unable to decode character hex %x at " "index %d of %s" % (vx, cx, hx)) tx += util.int_to_byte(v2) else: - tx += util.int_to_byte(v1) # pad + tx += util.int_to_byte(v1) # pad setattr(obj, hx, tx) return - + def _wrxfrq(self, setting, obj, atrb): """Callback: Encode the 3-byte non-mem channel frequency""" vx = float(setting.value) * 1000000 bx = self._freqncode(vx) setattr(obj, atrb, bx) return - + def _aprsfx(self, setting, obj, atrb, pad): """Callback: Trap the APRS callsign SSID""" v0 = int(setting.value) vx = v0 - if (pad == 0xca) and (v0 == 0): vx = pad - if (pad == 0x2a) and (v0 == 16): vx = pad + if (pad == 0xca) and (v0 == 0): + vx = pad + if (pad == 0x2a) and (v0 == 16): + vx = pad setattr(obj, atrb, vx) return - + def _aprspop(self, setting, obj, atrb): """Callback: APRS Beacon and Message Popup times; not 1:1""" # Can these radiso get any wierder? vx = int(setting.value) v0 = 0 # Off - if vx == 1: v0 = 3 - if vx == 2: v0 = 5 - if vx == 3: v0 = 10 - if vx == 4: v0 = 0xff # Hold + if vx == 1: + v0 = 3 + if vx == 2: + v0 = 5 + if vx == 3: + v0 = 10 + if vx == 4: + v0 = 0xff # Hold setattr(obj, atrb, v0) return - + def _enchcd(self, setting, obj, atrb): """Callback: Generic convert 1-byte decimal value to hex-coded""" sx = str(setting.value) # Decimal value, Ex: "33" v0 = int("0x" + sx, 16) # encode as hcd 0x33 setattr(obj, atrb, v0) return - + def _mdot(self, setting, obj, atrb1, atrb2): """Callback: Convert lat/long mm/mm to u8 and u16""" # Half as hex coded decimal, half as binary !!?? vx = float(setting.value) # mm.mm tx = math.modf(vx) - sx= str(int(tx[1])) + sx = str(int(tx[1])) v0 = int("0x" + sx, 16) # hcd v1 = int(tx[0] * 1000) # 2-byte binary setattr(obj, atrb1, v0) setattr(obj, atrb2, v1) return - + def _getdgpath(self, pn): """Method for extracting Digipeater route paths""" # pn is path number 0 - 5 _shr = self._memobj.share1 sx = "" x1 = pn * 8 - for i in range(x1, x1 + 6): # route name: 6 bytes + for i in range(x1, x1 + 6): # route name: 6 bytes v0 = _shr[i].shbyt - if v0 != 0xca: sx += chr(v0) + if v0 != 0xca: + sx += chr(v0) vx = _shr[x1 + 6].shbyt # route suffix 0-15 - if vx == 0xca: vx = 0 + if vx == 0xca: + vx = 0 return sx, vx - + def _putdgpname(self, setting, pn): """Callback: store Digipath name""" # Stored in 'share1' shared memory @@ -1416,9 +1416,9 @@ def _putdgpname(self, setting, pn): else: v1 = ord(sx[sp]) setattr(_shr[i], "shbyt", v1) - sp +=1 + sp += 1 return - + def _putdgpsfx(self, setting, pn): """Callback: Digipath, Ringer SSID""" _shr = self._memobj.share1 @@ -1426,38 +1426,46 @@ def _putdgpsfx(self, setting, pn): x1 = pn * 8 + 6 setattr(_shr[x1], "shbyt", v1) return - + def _rnglmt(self, setting, obj, atrb): """Callback: APRS Beacon Range Limits""" v1 = int(setting.value) # index vx = v1 # for 0, 1 if atrb == "aprbrrr": # Range Ringer - if v1 == 2: vx = 5 - if v1 == 3: vx = 10 - if v1 == 4: vx = 50 - if v1 == 5: vx = 100 + if v1 == 2: + vx = 5 + if v1 == 3: + vx = 10 + if v1 == 4: + vx = 50 + if v1 == 5: + vx = 100 else: # Filter Range - if v1 == 2: vx = 10 - if v1 == 3: vx = 100 - if v1 == 4: vx = 1000 - if v1 == 5: vx = 3000 + if v1 == 2: + vx = 10 + if v1 == 3: + vx = 100 + if v1 == 4: + vx = 1000 + if v1 == 5: + vx = 3000 setattr(obj, atrb, vx) return - + def _datefmt(self, setting, obj, atrb): """Callback: Stupid index jump in date format list""" vx = int(setting.value) - if vx == 3: vx = 4 + if vx == 3: + vx = 4 setattr(obj, atrb, vx) return - + def get_settings(self): _setx = self._memobj.setts _mic = self._memobj.micset _wierd = self._memobj.wierd _dtm = self._memobj.dtmfcode - _pmg = self._memobj.pmg - + cfg = RadioSettingGroup("cfg", "Config") dsp = RadioSettingGroup("dsp", "Display") fmenu = RadioSettingGroup("fmnu", "Quick Functions") @@ -1479,53 +1487,55 @@ def get_settings(self): other = RadioSettingGroup("other", "Other") if self.FTM200: - group = RadioSettings(cfg, dsp, fmenu, mic, sig, opts, dtmf, - scan, dat, wires, aprscom, aprsmsg, - aprsdgp, bcnfltr, bcnunit, bcnrngr, + group = RadioSettings(cfg, dsp, fmenu, mic, sig, opts, dtmf, + scan, dat, wires, aprscom, aprsmsg, + aprsdgp, bcnfltr, bcnunit, bcnrngr, bcnstat, bcnsmrt, other) else: - group = RadioSettings(cfg, dsp, fmenu, mic, sig, opts, dtmf, + group = RadioSettings(cfg, dsp, fmenu, mic, sig, opts, dtmf, scan) - + menu_items = ["01: Auto Power Off (APO)", "02: ARTS Mode", "03: ARTS Interval", "04: Busy Channel Lockout (BCLO)", - "05: Beep", "06: Bell", "07: Clock Type","08: LCD Dimmer", - "09: DTMF Manual/Auto", "10: DTMF TX", "11:DTMF Codes", - "12: Home", "13: Microphone Gain", "14: Microphone P Keys", - "15: Pager TX/RX","16: Packet Speed", "17:RX Mode", - "18: Band Select", "19: Repeater Reverse", - "20: Repeater Set", "21: Repeater Other", "22: Scan On", + "05: Beep", "06: Bell", "07: Clock Type", + "08: LCD Dimmer", "09: DTMF Manual/Auto", + "10: DTMF TX", "11:DTMF Codes", "12: Home", + "13: Microphone Gain", "14: Microphone P Keys", + "15: Pager TX/RX", "16: Packet Speed", "17:RX Mode", + "18: Band Select", "19: Repeater Reverse", + "20: Repeater Set", "21: Repeater Other", "22: Scan On", "23: Scan Type", "24: Squelch Type", "25:Squelch Code", "26: Squelch Expansion", "27: Step", "28: Radio Temperature", "29: Time Out Timer (TOT)", - "30: TX Power", "31: Version", "32: Voltage", "33: Width", - "34: Weather Alert", "35: Bluetooth"] + "30: TX Power", "31: Version", "32: Voltage", + "33: Width", "34: Weather Alert", "35: Bluetooth"] offon = ["Off", "On"] onoff = ["On", "Off"] # Inverted logic - + # Begin Config settings if self.FTM200: sx = self._b2s(_mic.csign, 0xff) - rx = RadioSettingValueString(0,10, sx, False) + rx = RadioSettingValueString(0, 10, sx, False) rs = RadioSetting("micset.csign", "Call Sign Label", rx) - rs.set_apply_callback(self._s2b, _mic, "csign", 10) + rs.set_apply_callback(self._s2b, _mic, "csign", 10) cfg.append(rs) - options = ["yyyy/mmm/dd", "yyyy/dd/mmm", "mmm/dd/yyyy", + options = ["yyyy/mmm/dd", "yyyy/dd/mmm", "mmm/dd/yyyy", "dd/mmm/yyyy"] vx = _setx.datefmt - if vx == 4: vx = 3 # Just to make my life difficult! + if vx == 4: + vx = 3 # Just to make my life difficult! rx = RadioSettingValueList(options, options[vx]) rs = RadioSetting("setts.datefmt", "Date Format", rx) rs.set_apply_callback(self._datefmt, _setx, "datefmt") cfg.append(rs) - + options = ["24 Hour", "12 Hour"] rx = RadioSettingValueList(options, options[_setx.timefmt]) rs = RadioSetting("setts.timefmt", "Time Format", rx) cfg.append(rs) - + options = [] v0 = -14.0 for vx in range(0, 57): @@ -1534,28 +1544,30 @@ def get_settings(self): v0 = _setx.tzone v1 = v0 + 28 # positive offset; index 28 is GMT if v0 & 0x80: # negative, before GMT - v1 = 28 - (v0 & 0x1f) + v1 = 28 - (v0 & 0x1f) rx = RadioSettingValueList(options, options[v1]) rs = RadioSetting("setts.tzone", "Time Zone GMT +/- hours", rx) rs.set_apply_callback(self._adjlist, _setx, "tzone", options, -28) cfg.append(rs) - + rx = RadioSettingValueList(offon, offon[_setx.rpt_ars]) - rs = RadioSetting("setts.rpt_ars", + rs = RadioSetting("setts.rpt_ars", "A: Repeater Auto Offset Enabled", rx) cfg.append(rs) rx = RadioSettingValueList(offon, offon[_setx.rpt_arsb]) - rs = RadioSetting("setts.rpt_arsb", + rs = RadioSetting("setts.rpt_arsb", "B: Repeater Auto Offset Enabled", rx) cfg.append(rs) - - options = ["Off", "0.5 Hours", "1 Hours", "1.5 Hours", "2 Hours", - "3 Hours", "4 Hours", "5 Hours", "6 Hours", "7 Hours", - "8 Hours", "9 Hours", "10 Hours", "11 Hours", "12 Hours"] + + options = ["Off", "0.5 Hours", "1 Hours", "1.5 Hours", "2 Hours", + "3 Hours", "4 Hours", "5 Hours", "6 Hours", "7 Hours", + "8 Hours", "9 Hours", "10 Hours", "11 Hours", + "12 Hours"] v0 = _setx.apo # Hours BCD v1 = _setx.apo1 # 0.5 hours yes/no sx = "%d" % v0 - if v1: sx += ".5" + if v1: + sx += ".5" if sx == "0": sx = "Off" else: @@ -1564,52 +1576,56 @@ def get_settings(self): rs = RadioSetting("setts.apo", "Auto Power Off time (APO)", rx) rs.set_apply_callback(self._ft2apo, _setx) cfg.append(rs) - + else: # FTM-6000, different than 200 rx = RadioSettingValueList(menu_items, menu_items[_setx.f1key]) rs = RadioSetting("setts.f1key", "F1 Key Assignment", rx) cfg.append(rs) - options = ["Off", "1 Hours", "1.5 Hours", "2 Hours", "3 Hours", + options = ["Off", "1 Hours", "1.5 Hours", "2 Hours", "3 Hours", "4 Hours", "5 Hours", "6 Hours", "7 Hours", "8 Hours", "9 Hours", "10 Hours", "11 Hours", "12 Hours"] rx = RadioSettingValueList(options, options[_setx.apo]) rs = RadioSetting("setts.apo", "Auto Power Off time (APO)", rx) - cfg.append(rs) - + cfg.append(rs) + rx = RadioSettingValueList(offon, offon[_setx.rpt_ars]) rs = RadioSetting("setts.rpt_ars", "Repeater Auto Offset Enabled", rx) cfg.append(rs) # Config - Common to all radios - + options = ["Off", "Low", "High"] # Yaesu splits the beep!!! vx = _setx.beep1 # Off/Low - if _setx.beep2: vx = 2 # High + if _setx.beep2: + vx = 2 # High rx = RadioSettingValueList(options, options[vx]) rs = RadioSetting("setts.beep1", "Beep", rx) rs.set_apply_callback(self._beepset, _setx, options) cfg.append(rs) - + options = ["Off", "1 minute", "2 minutes", "3 minutes", "5 minutes", "10 minutes", "15 minutes", "20 minutes", "30 minutes"] vx = _setx.tot # non-sequential index - if vx >= 6: bx = vx - 5 - if vx >= 1: bx = vx + 3 - if vx == 0: bx = 0 + if vx >= 6: + bx = vx - 5 + if vx >= 1: + bx = vx + 3 + if vx == 0: + bx = 0 rx = RadioSettingValueList(options, options[bx]) rs = RadioSetting("setts.tot", "Transmit Time Out Timer (TOT)", rx) - rs.set_apply_callback(self._settot, _setx, "tot", options) + rs.set_apply_callback(self._settot, _setx, "tot", options) cfg.append(rs) - + if self.FTM200: # Stuff at the end of Config options = ["Metric", "Imperial (Inch)"] rx = RadioSettingValueList(options, options[_setx.unit]) rs = RadioSetting("setts.unit", "Units", rx) cfg.append(rs) - + options = ["WGS 84", "Tokyo Mean"] rx = RadioSettingValueList(options, options[_setx.gpsdtm]) rs = RadioSetting("setts.gpsdtm", "GPS Datum", rx) @@ -1619,48 +1635,48 @@ def get_settings(self): rx = RadioSettingValueList(options, options[_setx.gpsdev]) rs = RadioSetting("setts.gpsdev", "GPS Device", rx) cfg.append(rs) - - options = ["Off", "1 second", "2 sec", "5 sec", "10 sec", + + options = ["Off", "1 second", "2 sec", "5 sec", "10 sec", "30 sec", "60 sec"] rx = RadioSettingValueList(options, options[_setx.gpslog]) rs = RadioSetting("setts.gpslog", "GPS Log Interval", rx) cfg.append(rs) - + else: options = ["30 Seconds", "1 Minute"] rx = RadioSettingValueList(options, options[_setx.arts_int]) rs = RadioSetting("setts.arts_int", "ARTS Interval", rx) cfg.append(rs) - + options = ["Off", "In Range", "Out Range"] rx = RadioSettingValueList(options, options[_setx.arts_mode]) rs = RadioSetting("setts.arts_mode", "ARTS Mode", rx) cfg.append(rs) - + rx = RadioSettingValueList(offon, offon[_setx.bclo]) rs = RadioSetting("setts.bclo", "Busy Channel Lockout (BCLO)", rx) cfg.append(rs) # End of Config settings - - # Start of Display settings + + # Start of Display settings if self.FTM200: options = ["Backtrack", "Altitude", "Timer/Clock", "GPS Info"] rx = RadioSettingValueList(options, options[_setx.dspmode]) rs = RadioSetting("setts.dspmode", "Display Select", rx) dsp.append(rs) - + options = ["Compass", "Numeric Lat/Long"] rx = RadioSettingValueList(options, options[_setx.locinfo]) rs = RadioSetting("setts.locinfo", "Location Info", rx) dsp.append(rs) - + options = ["North Up", "Heading Up"] rx = RadioSettingValueList(options, options[_mic.compass]) rs = RadioSetting("micset.compass", "Compass Display", rx) dsp.append(rs) - + options = ["Wide", "Narrow"] rx = RadioSettingValueList(options, options[_setx.bscope]) rs = RadioSetting("setts.bscope", "A: Display Scope", rx) @@ -1668,43 +1684,44 @@ def get_settings(self): rx = RadioSettingValueList(options, options[_setx.bscopeb]) rs = RadioSetting("setts.bscopeb", "B: Display Scope", rx) dsp.append(rs) - + rx = RadioSettingValueList(offon, offon[_setx.memlist]) rs = RadioSetting("setts.memlist", "Memory List Mode", rx) dsp.append(rs) - - options = ["Min", "Mid", "Max"] + + options = ["Dim", "Mid", "Full"] vx = _mic.lcd # stupid indexing: 3,1,2 v0 = vx # Mid: vx = 1, Max: vx = 2 - if vx == 3: v0 = 0 + if vx == 3: + v0 = 0 rx = RadioSettingValueList(options, options[v0]) rs = RadioSetting("micset.lcd", "Display Brightness", rx) rs.set_apply_callback(self._ft2lcd, _mic, "lcd") dsp.append(rs) - + options = ["White", "Blue", "Red"] rx = RadioSettingValueList(options, options[_setx.lcd_clr]) rs = RadioSetting("setts.lcd_clr", "LCD Upper Band Color", rx) - dsp.append(rs) - + dsp.append(rs) + else: # FTM-6000 options = ["Dim", "Mid", "Full"] rx = RadioSettingValueList(options, options[_mic.lcd]) rs = RadioSetting("micset.lcd", "Display Brightness", rx) - dsp.append(rs) + dsp.append(rs) # End of Display settings - + # Start of Signalling settings options = ["Off", "1 Time", "3 Times", "5 Times", "8 Times", - "Continous"] + "Continous"] if self.FTM200: rx = RadioSettingValueList(options, options[_mic.bell]) - rs = RadioSetting("micset.bell", + rs = RadioSetting("micset.bell", "A: Remote Station Calling Bell", rx) sig.append(rs) rx = RadioSettingValueList(options, options[_mic.bellb]) - rs = RadioSetting("micset.bellb", + rs = RadioSetting("micset.bellb", "B: Remote Station Calling Bell", rx) sig.append(rs) else: @@ -1712,97 +1729,97 @@ def get_settings(self): rs = RadioSetting("micset.bell", "Remote Station Calling Bell", rx) sig.append(rs) - + # All radios, Signalling opetions vx = _mic.pgrcdr1 + 1 rx = RadioSettingValueInteger(1, 50, vx) rs = RadioSetting("micset.pcrcdr1", "Pager Receive First Code", rx) - rs.set_apply_callback(self._adjint, _mic, "pgrcdr1") + rs.set_apply_callback(self._adjint, _mic, "pgrcdr1") sig.append(rs) - + vx = _mic.pgrcdr2 + 1 rx = RadioSettingValueInteger(1, 50, vx) rs = RadioSetting("micset.pcrcdr2", "Pager Receive Second Code", rx) - rs.set_apply_callback(self._adjint, _mic, "pgrcdr2") + rs.set_apply_callback(self._adjint, _mic, "pgrcdr2") sig.append(rs) - + rx = RadioSettingValueInteger(1, 50, vx) rs = RadioSetting("micset.pgrcdt1", "Pager Transmit First Code", rx) - rs.set_apply_callback(self._adjint, _mic, "pgrcdt1") + rs.set_apply_callback(self._adjint, _mic, "pgrcdt1") sig.append(rs) - + vx = _mic.pgrcdt2 + 1 rx = RadioSettingValueInteger(1, 50, vx) rs = RadioSetting("micset.pgrcdt2", "Pager Transmit Second Code", rx) rs.set_apply_callback(self._adjint, _mic, "pgrcdt2") sig.append(rs) - + rx = RadioSettingValueList(offon, offon[_setx.wxalrt]) rs = RadioSetting("setts.wxalrt", "Weather Alert Enabled", rx) sig.append(rs) # End of Signalling settings - + # Begin fmenu settings For each entry in menu_Items if self.FTM200: # 124 menu options possible - options = ["1:Freq Input", "2:LCD Brightness", "3:Freq Color", - "4:Band Scope", "5:Location Info", "6:Compass", + options = ["1:Freq Input", "2:LCD Brightness", "3:Freq Color", + "4:Band Scope", "5:Location Info", "6:Compass", "7:Display Mode"] - more = ("8:TX Power", "9:AMS TX Mode", "10:Mic Gain", "11:VOX", - "12:Auto Dialer", "13:Time Out Timer (TOT)", + more = ("8:TX Power", "9:AMS TX Mode", "10:Mic Gain", "11:VOX", + "12:Auto Dialer", "13:Time Out Timer (TOT)", "14:Digital VW") options.extend(more) - more = ("15:FM Bandwidth", "16:RX Mode", "17:Home", + more = ("15:FM Bandwidth", "16:RX Mode", "17:Home", "18:Memory List", "19:Memory List Mode", "20:PMG Clear") options.extend(more) more = ("21:Beep", "22:Band Skip", "23:RPT ARS", "24:RPT Shift", - "25:RPT Shift Freq", "26:Rpt Reverse", "27:Mic P Key", - "28:Date & Time Adjust", "29:Date &Time Format", + "25:RPT Shift Freq", "26:Rpt Reverse", "27:Mic P Key", + "28:Date & Time Adjust", "29:Date &Time Format", "30:Time Zone", "31:Step", "32:Clock Type", "33:Unit", - "34:Auto Power Off (APO)", "35:GPS Datum", - "36:GPS Device", "37:GPS Log") + "34:Auto Power Off (APO)", "35:GPS Datum", + "36:GPS Device", "37:GPS Log") options.extend(more) more = ("38:Audio Recording", "39:Audio Rec Stop") options.extend(more) more = ("40:DTMF Mode", "41:DTMF Memory", "42:SQL Type", "43:Tone Freq / DCS Code", "44:SQL Expansion", - "45:Pager Code", "46:PR Freq", "47:Bell Ringer", + "45:Pager Code", "46:PR Freq", "47:Bell Ringer", "48:WX Alert") options.extend(more) more = ("49:Scan", "50:Dual Rcv Mode", "51:Dual Rx Interval", "52:Priority Revert", "53:Scan Resume") options.extend(more) - more = ("54:Digital Popup", "55:Location Service", - "56:Standy Beep", "57:GM FP-ID List", "58:Range Ringer", - "59:Radio ID", "60:Log List", "61:Rpt / WIRES Freq", - "62:Search Step", "63:Edit Category Tag", - "64:Delete Room/Mode", "65:WIRES Dg-ID", "66:Com Port", + more = ("54:Digital Popup", "55:Location Service", + "56:Standy Beep", "57:GM FP-ID List", "58:Range Ringer", + "59:Radio ID", "60:Log List", "61:Rpt / WIRES Freq", + "62:Search Step", "63:Edit Category Tag", + "64:Delete Room/Mode", "65:WIRES Dg-ID", "66:Com Port", "67:Data Band", "68:Data Speed", "69:Data SQL") options.extend(more) - more = ("70:APRS Destination", "71:Filter", "72:Msg Text", - "73:APRS On/Off", "74:Mute", "75:Popup", "76:Ringer", - "77:Ringer CS", "78:TX Delay", "79:Units", - "80:Beacon Info", "81:Beacon Status Txt", - "82:Beacon TX Set", "83:DIGI Path", "84:DIGI Path 1", + more = ("70:APRS Destination", "71:Filter", "72:Msg Text", + "73:APRS On/Off", "74:Mute", "75:Popup", "76:Ringer", + "77:Ringer CS", "78:TX Delay", "79:Units", + "80:Beacon Info", "81:Beacon Status Txt", + "82:Beacon TX Set", "83:DIGI Path", "84:DIGI Path 1", "85:DIGI Path 2", "86:DIGI Path 3", "87:DIGI Path 4", "88:DIGI Path Full 1", "89: DIGI Path Full 2") options.extend(more) - more = ("90:APRS Call Sign", "91:Msg Group", "92:Msg Reply", - "93:My Position Set", "94:My Position", "95:My Symbol", - "96:Position Comment", "97:Smart Beaconing", - "98:Sort Filter", "99:Voice alert", "100:Station List", + more = ("90:APRS Call Sign", "91:Msg Group", "92:Msg Reply", + "93:My Position Set", "94:My Position", "95:My Symbol", + "96:Position Comment", "97:Smart Beaconing", + "98:Sort Filter", "99:Voice alert", "100:Station List", "101:Msg List", "102:Beacon TX Select", "103:Beacon TX") options.extend(more) more = ("104:SD Card Backup", "105:SD Card Mem Info", "106:SD Card Format", "107:Bluetooth", "108:Voice Memory", - "109:FVS Rec", "110:Track Select", "111:Play", - "112:Stop", "113:Clear", "114:Voice Guide", + "109:FVS Rec", "110:Track Select", "111:Play", + "112:Stop", "113:Clear", "114:Voice Guide", "115:USB Camera") options.extend(more) - more = ("116:This->Other", "117:Other->This", "118:Call Sign", - "119:Mem Chn Reset", "120:APRS Reset", "121:Config Set", - "122:Config Recall", "123:SW Version", - "124:Factory Reset") + more = ("116:This->Other", "117:Other->This", "118:Call Sign", + "119:Mem Chn Reset", "120:APRS Reset", "121:Config Set", + "122:Config Recall", "123:SW Version", + "124:Factory Reset") options.extend(more) rx = RadioSettingValueList(options, options[_mic.fkp1]) rs = RadioSetting("micset.fkp1", "Keypad Slot 1", rx) @@ -1820,7 +1837,7 @@ def get_settings(self): rs = RadioSetting("micset.fkp4", "Keypad Slot 4", rx) rs.set_apply_callback(self._setQA, _mic, "fkp4", options) fmenu.append(rs) - + rx = RadioSettingValueList(options, options[_mic.fhm1]) rs = RadioSetting("micset.fhm1", "Home Slot 1", rx) rs.set_apply_callback(self._setQA, _mic, "fhm1", options) @@ -1843,82 +1860,87 @@ def get_settings(self): x1 = mnu * 2 # _shr index of first byte vx = _shr[x1].shbyt bx = False - if vx != 0xff: bx = True + if vx != 0xff: + bx = True sx = "share1/%d.shbyt" % mnu - rx = RadioSettingValueBoolean(bx) - rs = RadioSetting(sx, menu_items[mnu], rx) + rx = RadioSettingValueBoolean(bx) + rs = RadioSetting(sx, menu_items[mnu], rx) fmenu.append(rs) - rs.set_apply_callback(self._setfunc, _shr, "shbyt", mnu) - # End fmenu settings + rs.set_apply_callback(self._setfunc, _shr, "shbyt", mnu) + # End fmenu settings # Begin microphone settings options = ["Min", "Low", "Normal", "High", "Max"] rx = RadioSettingValueList(options, options[_mic.micgain]) rs = RadioSetting("micset.micgain", "Microphone Gain", rx) mic.append(rs) - + options = ["ARTS", "SCAN On", "HOME Recall", "Repeater Duplex", "Repeater Reverse", "Transmit Power", "Squelch Off", "T-Call", "Dual Watch", "Weather Channel"] if self.FTM200: - options = ["Off", "Band Scope", "Scan", "Home", "Rpt Shift", - "Reverse", "TX Power", "SQL Off", "T-Call", "Voice", - "D_X", "WX", "Stn_List", "Msg List", "Reply", + options = ["Off", "Band Scope", "Scan", "Home", "Rpt Shift", + "Reverse", "TX Power", "SQL Off", "T-Call", "Voice", + "D_X", "WX", "Stn_List", "Msg List", "Reply", "M-Edit"] else: # FTM200- P1 is fixed as GM, immutable - vx = _mic.micp1- 0xdd - if vx == 10: vx = 9 # stupid index jump + vx = _mic.micp1 - 0xdd + if vx == 10: + vx = 9 # stupid index jump rx = RadioSettingValueList(options, options[vx]) rs = RadioSetting("micset.micp1", "Microphone Key P1", rx) rs.set_apply_callback(self._micpkey, _mic, "micp1", options) mic.append(rs) - + vx = _mic.micp2 - 0xdd - if vx == 10: vx = 9 - if self.FTM200: - vx = _mic.micp2 - 0xdc + if vx == 10: + vx = 9 + if self.FTM200: + vx = _mic.micp2 - 0xdc rx = RadioSettingValueList(options, options[vx]) rs = RadioSetting("micset.micp2", "Microphone Key P2", rx) rs.set_apply_callback(self._micpkey, _mic, "micp2", options) mic.append(rs) vx = _mic.micp3 - 0xdd - if vx == 10: vx = 9 - if self.FTM200: - vx = _mic.micp3 - 0xdc + if vx == 10: + vx = 9 + if self.FTM200: + vx = _mic.micp3 - 0xdc rx = RadioSettingValueList(options, options[vx]) rs = RadioSetting("micset.micp3", "Microphone Key P3", rx) rs.set_apply_callback(self._micpkey, _mic, "micp3", options) mic.append(rs) vx = _mic.micp4 - 0xdd - if vx == 10: vx = 9 - if self.FTM200: - vx = _mic.micp4 - 0xdc + if vx == 10: + vx = 9 + if self.FTM200: + vx = _mic.micp4 - 0xdc rx = RadioSettingValueList(options, options[vx]) rs = RadioSetting("micset.micp4", "Microphone Key P4", rx) rs.set_apply_callback(self._micpkey, _mic, "micp4", options) mic.append(rs) # End mic settings - + # Begin DTMF settings options = ["Manual", "Auto"] rx = RadioSettingValueList(options, options[_setx.dtmf_auto]) rs = RadioSetting("setts.dtmf_auto", "DTMF Transmit Mode", rx) dtmf.append(rs) - + for kx in range(0, 9): sx = self._unpack_str(_dtm[kx].codes) rx = RadioSettingValueString(0, 16, sx, False) # NOTE the / to indicate indexed array vx = kx + 1 rs = RadioSetting("dtmfcode/%d.codes" % kx, - "DTMF Code %d" % vx, rx) + "DTMF Code %d" % vx, rx) rs.set_apply_callback(self._pack_chars, _dtm, "codes", kx) - dtmf.append(rs) + dtmf.append(rs) # End of dtmf settings - + # Begin Scan settings if self.FTM200: options = ["Busy", "Hold", "1 Second", "3 Seconds", "5 Seconds"] @@ -1929,7 +1951,7 @@ def get_settings(self): rs = RadioSetting("setts.scnrsm2b", "B: Scan Resume Mode", rx) scan.append(rs) - options = ["0.5 seconds","1 sec","2 sec" ,"3 sec", "5 sec", + options = ["0.5 seconds", "1 sec", "2 sec", "3 sec", "5 sec", "7 sec", "10 secs"] rx = RadioSettingValueList(options, options[_setx.scndria]) rs = RadioSetting("setts.scndria", "A: Dual Receive Interval", @@ -1939,61 +1961,62 @@ def get_settings(self): rs = RadioSetting("setts.scndrib", "B: Dual Receive Interval", rx) scan.append(rs) - + rx = RadioSettingValueList(offon, offon[_setx.dwrvt]) rs = RadioSetting("setts.dwrvt", "A: Priority Revert", rx) scan.append(rs) rx = RadioSettingValueList(offon, offon[_setx.dwrvtb]) rs = RadioSetting("setts.dwrvtb", "B: Priority Revert", rx) scan.append(rs) - + options = ["Off", "Priority Scan", "A-B Dual Receive"] # unbelievable 2- byte configuration v0 = _setx.scndrm1 # at 17f62 bit 8 v1 = _setx.scndrm2 # at 17f6b bit 1 - vx =0 + vx = 0 if v0 == 1: vx = 1 - elif v1 == 1: vx =2 + elif v1 == 1: + vx = 2 rx = RadioSettingValueList(options, options[vx]) rs = RadioSetting("setts.scndrm1", "Scan Dual Receive Mode", rx) rs.set_apply_callback(self._scndrm, _setx) scan.append(rs) - + else: options = ["Busy", "Hold", "1 Second", "3 Seconds", "5 Seconds"] rx = RadioSettingValueList(options, options[_setx.scnrsm]) rs = RadioSetting("setts.scnrsm", "Scan Resume Mode", rx) scan.append(rs) - + rx = RadioSettingValueList(offon, offon[_setx.dwrvt]) rs = RadioSetting("setts.dwrvt", "Dual Watch Revert", rx) scan.append(rs) # End of Scan settings - + # Begin Data settings - options = ["4700 bps", "9600 bps", "19200 bps", "38400 bps", - "57600 bps"] + options = ["4700 bps", "9600 bps", "19200 bps", "38400 bps", + "57600 bps"] rx = RadioSettingValueList(options, options[_wierd.comspd]) rs = RadioSetting("wierd.comspd", "COM Port Speed", rx) dat.append(rs) - - options = ["Off", "GPS Out", "Packet", "Waypoint"] + + options = ["Off", "GPS Out", "Packet", "Waypoint"] rx = RadioSettingValueList(options, options[_wierd.comout]) rs = RadioSetting("wierd.comout", "COM Port Output", rx) dat.append(rs) - + options = ["NMEA9", "NMEA8", "NMEA7", "NMEA6"] rx = RadioSettingValueList(options, options[_wierd.comwpf]) rs = RadioSetting("wierd.comwpf", "COM Port Waypoint Format", rx) dat.append(rs) - - options = ["All", "Mobile", "Frequency", "Object/Item", "Digipeater", + + options = ["All", "Mobile", "Frequency", "Object/Item", "Digipeater", "VoIP", "Weather", "Yaesu", "Call Ringer", "Rng Ringer"] rx = RadioSettingValueList(options, options[_wierd.comflt]) rs = RadioSetting("wierd.comflt", "COM Port Waypoint Filter", rx) dat.append(rs) - + options = ["Main Band", "Sub Band", "A-Band Fix", "B-Band Fix"] rx = RadioSettingValueList(options, options[_wierd.dbsela]) rs = RadioSetting("wierd.dbsela", "Data Band Select: APRS", rx) @@ -2001,7 +2024,7 @@ def get_settings(self): rx = RadioSettingValueList(options, options[_wierd.dbseld]) rs = RadioSetting("wierd.dbseld", "Data Band Select: Data", rx) dat.append(rs) - + options = ["1200 bps", "9600 bps"] rx = RadioSettingValueList(options, options[_wierd.dspda]) rs = RadioSetting("wierd.dspda", "Data Speed: APRS", rx) @@ -2009,45 +2032,45 @@ def get_settings(self): rx = RadioSettingValueList(options, options[_wierd.pktspd]) rs = RadioSetting("wierd.pktspd", "Data Speed: Data", rx) dat.append(rs) - + rx = RadioSettingValueList(offon, offon[_wierd.datsql]) rs = RadioSetting("wierd.datsql", "Data Squelch", rx) - dat.append(rs) + dat.append(rs) # End of Data Settings - + # Begin Options settings if self.FTM200: options = ["FREE 5 min", "LAST 30 sec"] rx = RadioSettingValueList(options, options[_setx.fvsrec]) rs = RadioSetting("setts.fvsrec", "FVS-2: Play/Record", rx) opts.append(rs) - + options = ["Off", "Manual", "Auto"] rx = RadioSettingValueList(options, options[_setx.fvsanc]) rs = RadioSetting("setts.fvsanc", "FVS-2: Announce Mode", rx) opts.append(rs) - + options = ["English", "Japanese"] rx = RadioSettingValueList(options, options[_setx.fvslan]) rs = RadioSetting("setts.fvslan", "FVS-2: Language", rx) opts.append(rs) - + options = ["Low", "Mid", "High"] rx = RadioSettingValueList(options, options[_setx.fvsvol]) rs = RadioSetting("setts.fvsvol", "FVS-2: Volume", rx) - opts.append(rs) - + opts.append(rs) + # Yaesu split the FTM-200 BEEP 0/1/2 into 2 byte locations!! # and assigned this bit to the upper Beep of the FTM-6000!! rx = RadioSettingValueList(onoff, onoff[_setx.fvsrxm]) rs = RadioSetting("setts.fvsrxm", "FVS-2: RX Mute", rx) - opts.append(rs) + opts.append(rs) - # Common Options - BLUETOOTH + # Common Options - BLUETOOTH rx = RadioSettingValueList(offon, offon[_setx.bton]) rs = RadioSetting("setts.bton", "Bluetooth: Enabled", rx) opts.append(rs) - + rx = RadioSettingValueList(offon, offon[_setx.btsave]) rs = RadioSetting("setts.btsave", "Bluetooth: Save", rx) opts.append(rs) @@ -2056,44 +2079,45 @@ def get_settings(self): rx = RadioSettingValueList(options, options[_setx.btaud]) rs = RadioSetting("setts.btaud", "Bluetooth: Audio", rx) opts.append(rs) - + if self.FTM200: options = ["320 x 240", "160 x 120"] rx = RadioSettingValueList(options, options[_mic.usbcamsz]) rs = RadioSetting("micset.usbcamsz", "USB Camera: Image Size", rx) opts.append(rs) - + options = ["Low", "Normal", "High"] rx = RadioSettingValueList(options, options[_mic.usbcamql]) - rs = RadioSetting("micset.usbcamql", "USB Camera: Image Quality", rx) + rs = RadioSetting("micset.usbcamql", "USB Camera: Image Quality", + rx) opts.append(rs) - + # End of Options settings - + # Begin Other settings - + if self.FTM200: options = ["A", "B", "A+B"] rx = RadioSettingValueList(options, options[_setx.audrec - 1]) rs = RadioSetting("setts.audrec", "Audio Recording Band", rx) rs.set_apply_callback(self._adjlist, _setx, "audrec", options, - 1) + 1) other.append(rs) - + rx = RadioSettingValueList(offon, offon[_setx.audmic]) rs = RadioSetting("setts.audmic", "Microphone", rx) other.append(rs) - + options = ["Off", "Low", "High"] rx = RadioSettingValueList(options, options[_setx.voxsen]) rs = RadioSetting("setts.voxsen", "VOX Sensitivity", rx) other.append(rs) - options = ["0.5 seconds", "1 sec", "1.5 sec", "2.0 sec", + options = ["0.5 seconds", "1 sec", "1.5 sec", "2.0 sec", "2.5sec", "3 sec"] rx = RadioSettingValueList(options, options[_setx.voxdly]) rs = RadioSetting("setts.voxdly", "VOX Delay", rx) other.append(rs) - + rx = RadioSettingValueList(offon, offon[_setx.bskpa1]) rs = RadioSetting("setts.bskpa1", "A: Air Band Enabled", rx) other.append(rs) @@ -2121,7 +2145,7 @@ def get_settings(self): rs = RadioSetting("setts.bskpb3", "B: Other Band Enabled", rx) rs.set_apply_callback(self._skp_other, _setx, "B", options) other.append(rs) - + else: options = ["1200 bps", "9600 bps"] rx = RadioSettingValueList(options, options[_wierd.pktspd]) @@ -2132,19 +2156,19 @@ def get_settings(self): rx = RadioSettingValueList(offon, offon[_setx.airb]) rs = RadioSetting("setts.airb", "Air Band Enabled", rx) other.append(rs) - + rx = RadioSettingValueList(offon, offon[_setx.vhfb]) rs = RadioSetting("setts.vhfb", "VHF Band Enabled", rx) other.append(rs) - + rx = RadioSettingValueList(offon, offon[_setx.uhfb]) rs = RadioSetting("setts.uhfb", "UHF Band Enabled", rx) other.append(rs) - + rx = RadioSettingValueList(offon, offon[_setx.otrb]) rs = RadioSetting("setts.otrb", "Other Band Enabled", rx) other.append(rs) - # End of Other Settings + # End of Other Settings # Start FTM200 Unique settings if self.FTM200: @@ -2157,10 +2181,11 @@ def get_settings(self): sx = getattr(_wrx, atr) tx = "" for cx in sx: - if cx == 0xff: break + if cx == 0xff: + break tx += xmap[cx] tx = tx.strip() - rx = RadioSettingValueString(0,128, tx, False) + rx = RadioSettingValueString(0, 128, tx, False) atr = "wrxmsg.msg%02d" % ix rs = RadioSetting(atr, "Message M%02d" % ix, rx) rs.set_apply_callback(self._xmsg, _wrx, ix, xmap) @@ -2169,41 +2194,41 @@ def get_settings(self): rx = RadioSettingValueList(offon, offon[_setx.wrxrng]) rs = RadioSetting("setts.wrxrng", "Range Ringer", rx) wires.append(rs) - + options = ["Auto", "TX FM Fixed", "TX DN Fixed"] rx = RadioSettingValueList(options, options[_setx.wrxams]) rs = RadioSetting("setts.wrxams", "AMS TX Mode", rx) wires.append(rs) - - options = ["Off", "2 seconds", "4 sec", "6 sec", "8 sec", + + options = ["Off", "2 seconds", "4 sec", "6 sec", "8 sec", "10 sec", "20 sec", "30 sec", "60 sec", "Continuous"] rx = RadioSettingValueList(options, options[_mic.wrxpop]) rs = RadioSetting("micset.wrxpop", "Digital Popup", rx) wires.append(rs) - + rx = RadioSettingValueList(offon, offon[_setx.wrxloc]) rs = RadioSetting("setts.wrxloc", "Location Service", rx) wires.append(rs) - + rx = RadioSettingValueList(onoff, onoff[_setx.wrxstb]) rs = RadioSetting("setts.wrxstb", "Standby Beep", rx) wires.append(rs) - + rx = RadioSettingValueList(offon, offon[_setx.wrxdvw]) rs = RadioSetting("setts.wrxdvw", "Digital VW Enable", rx) wires.append(rs) - + options = ["Manual", "Preset"] rx = RadioSettingValueList(options, options[_setx.wrxrwf]) rs = RadioSetting("setts.wrxrwf", "RPT/WIRES Frequency Mode", rx) wires.append(rs) - + options = ["VHF Preset", "UHF Preset"] rx = RadioSettingValueList(options, options[_mic.wrxbsel]) rs = RadioSetting("micset.wrxbsel", "RPT/WIRES Preset Band Select", rx) wires.append(rs) - + vx = self._freqdcode(_mic.wrxvfrq) / 1000000 rx = RadioSettingValueFloat(144.0, 149.0, vx, 0.001, 3) rs = RadioSetting("micset.wrxvfrq", "RPT/WIRES VHF Preset Freq", @@ -2217,82 +2242,83 @@ def get_settings(self): rx) rs.set_apply_callback(self._wrxfrq, _mic, "wrxufrq") wires.append(rs) - + options = ["History", "Activity"] rx = RadioSettingValueList(options, options[_setx.wrxsrch]) rs = RadioSetting("setts.wrxsrch", "RPT/WIRES Search Setup", rx) wires.append(rs) - + options = ["Auto"] - for vx in range(1,100): + for vx in range(1, 100): options.append("%02d" % vx) rx = RadioSettingValueList(options, options[_mic.wrxdid]) rs = RadioSetting("micset.wrxdid", "RPT/WIRES Radio Digital ID", rx) wires.append(rs) - + _wrxc = self._memobj.wrxcat for ix in range(1, 6): atr = "c%d" % ix sx = getattr(_wrxc, atr) tx = "" for cx in sx: - if cx == 0xca: break + if cx == 0xca: + break tx += xmap[cx] tx = tx.strip() - rx = RadioSettingValueString(0,16, tx, False) + rx = RadioSettingValueString(0, 16, tx, False) atr = "wrxcat.c%d" % ix rs = RadioSetting(atr, "Category Text C%d" % ix, rx) rs.set_apply_callback(self._xmsg, _wrxc, ix, xmap, 1) wires.append(rs) - + rx = RadioSettingValueList(offon, offon[_wierd.aprson]) rs = RadioSetting("wierd.aprson", "APRS Enabled", rx) aprscom.append(rs) - + rx = RadioSettingValueList(offon, offon[_wierd.aprmut]) rs = RadioSetting("wierd.aprmut", "Mute", rx) aprscom.append(rs) - + options = ["100ms", "150ms", "200ms", "250ms", "300ms", "400ms", "500ms", "750ms", "1000ms"] rx = RadioSettingValueList(options, options[_wierd.aprtxd]) rs = RadioSetting("wierd.aprtxd", "TX Delay", rx) aprscom.append(rs) - + options = ["Off", "1 digit", "2 digits", "3 digits", "4 digits"] rx = RadioSettingValueList(options, options[_wierd.aprbamb]) rs = RadioSetting("wierd.aprbamb", "Beacon Ambiguity", rx) aprscom.append(rs) - + rx = RadioSettingValueList(offon, offon[_wierd.aprspdc]) rs = RadioSetting("wierd.aprspdc", "Beacon Speed/Course", rx) aprscom.append(rs) - + rx = RadioSettingValueList(offon, offon[_wierd.aprsalt]) rs = RadioSetting("wierd.aprsalt", "Beacon Altitude", rx) aprscom.append(rs) - + options = ["Off", "On", "Smart"] rx = RadioSettingValueList(options, options[_wierd.aprbaut]) rs = RadioSetting("wierd.aprbaut", "Beacon TX Mode", rx) aprscom.append(rs) - + options = ["30 sec", "1 minute", "2 mins", "3 mins", "5 mins", "10 mins", "15 mins", "20 mins", "30 mins", "60 mins"] rx = RadioSettingValueList(options, options[_wierd.aprstxi]) rs = RadioSetting("wierd.aprstxi", "Beacon TX Interval", rx) aprscom.append(rs) - + rx = RadioSettingValueList(offon, offon[_wierd.aprspro]) rs = RadioSetting("wierd.aprspro", "Beacon TX Proportional", rx) aprscom.append(rs) - + rx = RadioSettingValueList(offon, offon[_wierd.aprsdcy]) rs = RadioSetting("wierd.aprsdcy", "Beacon TX Decay", rx) aprscom.append(rs) - - #Lets try using integer values instead of list; just for kicks + + # Lets try using integer values instead of list; just for kicks rx = RadioSettingValueInteger(1, 99, _wierd.aprslow) rs = RadioSetting("wierd.aprslow", "TX Low Speed (mph)", rx) aprscom.append(rs) @@ -2300,152 +2326,161 @@ def get_settings(self): rx = RadioSettingValueInteger(5, 180, _wierd.aprsrate) rs = RadioSetting("wierd.aprsrate", "TX Rate Limit (secs)", rx) aprscom.append(rs) - + sx = self._b2s(_wierd.aprcsgn, 0xca) rx = RadioSettingValueString(0, 6, sx, False) rs = RadioSetting("wierd.aprcsgn", "APRS Callsign", rx) rs.set_apply_callback(self._s2b, _wierd, "aprcsgn", 6, 0xca) - aprscom.append(rs) - + aprscom.append(rs) + options = [""] for i in range(1, 16): options.append("-%d" % i) vx = _wierd.aprcsfx - if vx == 0xca: vx = 0 + if vx == 0xca: + vx = 0 rx = RadioSettingValueList(options, options[vx]) rs = RadioSetting("wierd.aprcsfx", "Call Sign SSID ", rx) rs.set_apply_callback(self._aprsfx, _wierd, "aprcsfx", 0xca) - aprscom.append(rs) - - options = ["Off Duty", "En Route", "In Service", "Returning", - "Committed", "Special", "Priority", "Sustom 0", - "Custom 1", "Custom 2", "Custom 3","Custom 4", + aprscom.append(rs) + + options = ["Off Duty", "En Route", "In Service", "Returning", + "Committed", "Special", "Priority", "Sustom 0", + "Custom 1", "Custom 2", "Custom 3", "Custom 4", "Custom 5", "Custom 6", "EMERGENCY!"] rx = RadioSettingValueList(options, options[_wierd.aprcmt]) rs = RadioSetting("wierd.aprcmt", "Position Comment", rx) aprscom.append(rs) - + options = ["Off", "3 secs", " 5 secs", "10 secs", "HOLD"] vx = _wierd.aprpopb # hex encoded decimal plus ff= hold v1 = 0 - if vx == 3: v1 = 1 - if vx == 5: v1 = 2 - if vx == 10: v1 = 3 - if vx == 0xff: v1 = 4 + if vx == 3: + v1 = 1 + if vx == 5: + v1 = 2 + if vx == 10: + v1 = 3 + if vx == 0xff: + v1 = 4 rx = RadioSettingValueList(options, options[v1]) rs = RadioSetting("wierd.aprpopb", "Beacon Popup Display Time", rx) rs.set_apply_callback(self._aprspop, _wierd, "aprpopb") aprscom.append(rs) - + vx = _wierd.aprpopm v1 = 0 - if vx == 3: v1 = 1 - if vx == 5: v1 = 2 - if vx == 10: v1 = 3 - if vx == 0xff: v1 = 4 + if vx == 3: + v1 = 1 + if vx == 5: + v1 = 2 + if vx == 10: + v1 = 3 + if vx == 0xff: + v1 = 4 rx = RadioSettingValueList(options, options[v1]) - rs = RadioSetting("wierd.aprpopm", + rs = RadioSetting("wierd.aprpopm", "Message Popup Display Time", rx) rs.set_apply_callback(self._aprspop, _wierd, "aprpopm") aprscom.append(rs) - + rx = RadioSettingValueList(offon, offon[_wierd.aprmpkt]) rs = RadioSetting("wierd.aprmpkt", "My Packet", rx) aprscom.append(rs) - + options = ["Time", "Call Sign", "Distance"] rx = RadioSettingValueList(options, options[_wierd.aprsfs]) rs = RadioSetting("wierd.aprsfs", "Sort Filter: Sort By", rx) - aprscom.append(rs) - - options = ["All", "Mobile", "Frequency", "Object/Item", - "Digipeater", "VoIP", "Weather", "Yaesu", - "Other Packet", " Call Ringer", "Range Ringer", + aprscom.append(rs) + + options = ["All", "Mobile", "Frequency", "Object/Item", + "Digipeater", "VoIP", "Weather", "Yaesu", + "Other Packet", " Call Ringer", "Range Ringer", "1200 bps", "9600 bps"] rx = RadioSettingValueList(options, options[_wierd.aprsff]) rs = RadioSetting("wierd.aprsff", "Sort Filter: Filter Type", rx) aprscom.append(rs) - + options = ["Normal", "Tone-SQL", "DCS", "Rx-TSQL", "Rx-DCS"] rx = RadioSettingValueList(options, options[_wierd.aprvlrt]) rs = RadioSetting("wierd.aprvlrt", "Voice Alert: Mode", rx) aprscom.append(rs) - + options = [] for vx in chirp_common.TONES: options.append("%.1f" % vx) rx = RadioSettingValueList(options, options[_wierd.aprtsql]) rs = RadioSetting("wierd.aprtsql", "Voice Alert: TSQL Tone", rx) aprscom.append(rs) - + options = [] for vx in chirp_common.DTCS_CODES: options.append("%03d" % vx) rx = RadioSettingValueList(options, options[_wierd.aprvdcs]) rs = RadioSetting("wierd.aprvdcs", "Voice Alert: DCS Code", rx) aprscom.append(rs) - + options = ["GPS", "Manual"] rx = RadioSettingValueList(options, options[_wierd.aprmpos]) rs = RadioSetting("wierd.aprmpos", "My Position Mode", rx) aprscom.append(rs) - + optns = ["North", "South"] rx = RadioSettingValueList(optns, optns[_wierd.aprltns]) - rs = RadioSetting("wierd.aprltns", + rs = RadioSetting("wierd.aprltns", "My Position Manual Lat N/S", rx) aprscom.append(rs) - + v0 = int("%X" % _wierd.aprlad) # Hex coded Decimal rx = RadioSettingValueInteger(0, 90, v0) - rs = RadioSetting("wierd.aprlad", + rs = RadioSetting("wierd.aprlad", "My Position Manual Lat Degrees", rx) rs.set_apply_callback(self._enchcd, _wierd, "aprlad") - aprscom.append(rs) - + aprscom.append(rs) + v0 = int("%X" % _wierd.aprlam) # Whole Minutes, HCD v1 = _wierd.aprlas v1 = v1 / 1000 vx = v0 + v1 rx = RadioSettingValueFloat(0, 59.99, vx, 0.01, 2) - rs = RadioSetting("wierd.aprlas", + rs = RadioSetting("wierd.aprlas", "My Position Manual Lat Minutes", rx) rs.set_apply_callback(self._mdot, _wierd, "aprlam", "aprlas") aprscom.append(rs) - + optns = ["East", "West"] rx = RadioSettingValueList(optns, optns[_wierd.aprlgew]) - rs = RadioSetting("wierd.aprlgew", + rs = RadioSetting("wierd.aprlgew", "My Position Manual Long N/S", rx) aprscom.append(rs) - - v0 = int("%X" % _wierd.aprlgd) + + v0 = int("%X" % _wierd.aprlgd) rx = RadioSettingValueInteger(0, 180, v0) - rs = RadioSetting("wierd.aprlgd", + rs = RadioSetting("wierd.aprlgd", "My Position Manual Long Degrees", rx) rs.set_apply_callback(self._enchcd, _wierd, "aprlgd") - aprscom.append(rs) - - v0 = int("%X" % _wierd.aprlgm) + aprscom.append(rs) + + v0 = int("%X" % _wierd.aprlgm) v1 = _wierd.aprlgs v1 = v1 / 1000 vx = v0 + v1 rx = RadioSettingValueFloat(0, 59.99, vx, 0.01, 2) - rs = RadioSetting("wierd.aprlgs", + rs = RadioSetting("wierd.aprlgs", "My Position Manual Long Minutes", rx) rs.set_apply_callback(self._mdot, _wierd, "aprlgm", "aprlgs") - aprscom.append(rs) - + aprscom.append(rs) + # APRS Digipeater Settings - - options = ["Off", "Wide 1-1", "Wide 1-1, 1-2", "Path 1", + + options = ["Off", "Wide 1-1", "Wide 1-1, 1-2", "Path 1", "Path 2", "Path 3", "Path 4", "Full 1", "Full2"] rx = RadioSettingValueList(options, options[_wierd.aprdig]) rs = RadioSetting("wierd.aprdig", "Digipeater Route Selection", rx) aprsdgp.append(rs) - + # Using shared memory 'share1'; extracting Digipath data _shr = self._memobj.share1 optsfx = [""] # List for path suffix @@ -2459,7 +2494,7 @@ def get_settings(self): tx = "Path-%d First Route Callsign" % (px + 1) rs = RadioSetting("share1/%d.shbyte" % pz, tx, rx) rs.set_apply_callback(self._putdgpname, py) - aprsdgp.append(rs) + aprsdgp.append(rs) pz += 1 rx = RadioSettingValueList(optsfx, optsfx[sfx]) tx = "Path-%d First Route SSID" % (px + 1) @@ -2470,26 +2505,26 @@ def get_settings(self): pz += 1 sx, sfx = self._getdgpath(py) rx = RadioSettingValueString(0, 6, sx, False) - tx ="Path-%d Second Route Callsign" % (px + 1) + tx = "Path-%d Second Route Callsign" % (px + 1) rs = RadioSetting("share1/%d.shbyte" % pz, tx, rx) rs.set_apply_callback(self._putdgpname, py) aprsdgp.append(rs) pz += 1 rx = RadioSettingValueList(optsfx, optsfx[sfx]) tx = "Path-%d Second Route SSID" % (px + 1) - rs = RadioSetting("share1/%d.shbyte" % pz,tx, rx) + rs = RadioSetting("share1/%d.shbyte" % pz, tx, rx) rs.set_apply_callback(self._putdgpsfx, py) aprsdgp.append(rs) py += 1 pz += 1 # Now 8 routes for 'Full1' - for px in range(0, 8): + for px in range(0, 8): sx, sfx = self._getdgpath(py) rx = RadioSettingValueString(0, 6, sx, False) tx = "Full-1 Route %d Callsign" % (px + 1) rs = RadioSetting("share1/%d.shbyte" % pz, tx, rx) rs.set_apply_callback(self._putdgpname, py) - aprsdgp.append(rs) + aprsdgp.append(rs) pz += 1 rx = RadioSettingValueList(optsfx, optsfx[sfx]) tx = "Full-1 Route %d SSID" % (px + 1) @@ -2499,13 +2534,13 @@ def get_settings(self): py += 1 pz += 1 # and 8 more for 'Full2' - for px in range(0, 8): + for px in range(0, 8): sx, sfx = self._getdgpath(py) rx = RadioSettingValueString(0, 6, sx, False) tx = "Full-2 Route %d Callsign" % (px + 1) rs = RadioSetting("share1/%d.shbyte" % pz, tx, rx) rs.set_apply_callback(self._putdgpname, py) - aprsdgp.append(rs) + aprsdgp.append(rs) pz += 1 rx = RadioSettingValueList(optsfx, optsfx[sfx]) tx = "Full-2 Route %d SSID" % (px + 1) @@ -2513,10 +2548,10 @@ def get_settings(self): rs.set_apply_callback(self._putdgpsfx, py) aprsdgp.append(rs) py += 1 - pz += 1 - + pz += 1 + # --- APRS Messages ===== - + _apmsg = self._memobj.aprsmsg for vx in range(1, 7): tx = "grp%d" % vx @@ -2526,8 +2561,8 @@ def get_settings(self): rx = RadioSettingValueString(0, 9, sx, False) rs = RadioSetting(qx, "Message Group %d Text" % vx, rx) rs.set_apply_callback(self._s2b, _apmsg, tx, 9, 0xca) - aprsmsg.append(rs) - + aprsmsg.append(rs) + for vx in range(1, 4): tx = "blt%d" % vx bx = getattr(_apmsg, tx) @@ -2536,8 +2571,8 @@ def get_settings(self): rx = RadioSettingValueString(0, 9, sx, False) rs = RadioSetting(qx, "Message Bulletin %d Text" % vx, rx) rs.set_apply_callback(self._s2b, _apmsg, tx, 9, 0xca) - aprsmsg.append(rs) - + aprsmsg.append(rs) + _aptxt = self._memobj.aprstxt for vx in range(1, 9): tx = "txt%d" % vx @@ -2550,7 +2585,8 @@ def get_settings(self): aprsmsg.append(rs) options = [] - for i in range(1, 9): options.append("%d" % i) + for i in range(1, 9): + options.append("%d" % i) rx = RadioSettingValueList(options, options[_wierd.aprstxn]) rs = RadioSetting("wierd.aprstxn", "Message # Selected", rx) aprsmsg.append(rs) @@ -2563,34 +2599,35 @@ def get_settings(self): rx = RadioSettingValueString(0, 6, sx, False) rs = RadioSetting("wierd.aprrcsn", "Message Reply Callsign", rx) rs.set_apply_callback(self._s2b, _wierd, "aprrcsn", 6, 0x2a) - aprsmsg.append(rs) - + aprsmsg.append(rs) + options = [" "] for i in range(1, 16): options.append("-%d" % i) options.append("-**") # index 16 vx = _wierd.aprrcfx - if vx == 0x2a: vx = 16 + if vx == 0x2a: + vx = 16 rx = RadioSettingValueList(options, options[vx]) rs = RadioSetting("wierd.aprrcfx", "Reply Call Sign SSID", rx) rs.set_apply_callback(self._aprsfx, _wierd, "aprrcfx", 0x2a) aprsmsg.append(rs) - + sx = self._b2s(_wierd.aprrtxt, 0xca) rx = RadioSettingValueString(0, 64, sx, False) rs = RadioSetting("wierd.aprrtxt", "Message Reply Text", rx) rs.set_apply_callback(self._s2b, _wierd, "aprrtxt", 64, 0xca) aprsmsg.append(rs) - options = ["/#", "/&", "/'", "/-", "/.", "/0", "/:", "/;", "/<", - "/=", "/>", "/C", "/E", "/I", "/K", "/O", "/P", "/R", - "/T", "/U", "/V", "/W", "/X", "Y", "/[", "/\\", "/^", - "/_", "/a", "/b", "/f", "/g", "/j", "/k", "/m", "/r", - "/s", "/u", "/v", "/y", "\\#", "\\&", "\\-", "\\.", - "\\0", "E0", "IO", "W0", "\\;", "\\>", "\\A", "\\K", - "\\W", "\\Y", "KY", "YY", "\\^", "\\_", "\\m", "\\n", + options = ["/#", "/&", "/'", "/-", "/.", "/0", "/:", "/;", "/<", + "/=", "/>", "/C", "/E", "/I", "/K", "/O", "/P", "/R", + "/T", "/U", "/V", "/W", "/X", "Y", "/[", "/\\", "/^", + "/_", "/a", "/b", "/f", "/g", "/j", "/k", "/m", "/r", + "/s", "/u", "/v", "/y", "\\#", "\\&", "\\-", "\\.", + "\\0", "E0", "IO", "W0", "\\;", "\\>", "\\A", "\\K", + "\\W", "\\Y", "KY", "YY", "\\^", "\\_", "\\m", "\\n", "\\s", "\\u", "\\v", "\\x"] - for i in range(1,4): + for i in range(1, 4): tx = "aprsym%d" % i bx = getattr(_wierd, tx) sx = self._b2s(bx, 0) # 2-byte char string @@ -2601,20 +2638,25 @@ def get_settings(self): aprsmsg.append(rs) options = ["/"] - for i in range(48, 58): options.append(chr(i)) # numerals - for i in range(65, 91): options.append(chr(i)) # Cap letters + for i in range(48, 58): + options.append(chr(i)) # numerals + for i in range(65, 91): + options.append(chr(i)) # Cap letters options.append("\\") sx = chr(_wierd.aprsym4a) rx = RadioSettingValueList(options, sx) - rs = RadioSetting("wierd.aprsym4a", "My Symbol #4 First Value", rx) + rs = RadioSetting("wierd.aprsym4a", "My Symbol #4 First Value", + rx) rs.set_apply_callback(self._c2u8, _wierd, "aprsym4a") aprsmsg.append(rs) - + options = [] - for i in range(33, 127): options.append(chr(i)) # full ascii + for i in range(33, 127): + options.append(chr(i)) # full ascii sx = chr(_wierd.aprsym4b) rx = RadioSettingValueList(options, sx) - rs = RadioSetting("wierd.aprsym4b", "My Symbol #4 Second Value", rx) + rs = RadioSetting("wierd.aprsym4b", "My Symbol #4 Second Value", + rx) rs.set_apply_callback(self._c2u8, _wierd, "aprsym4b") aprsmsg.append(rs) @@ -2622,36 +2664,36 @@ def get_settings(self): rx = RadioSettingValueList(options, options[_wierd.aprsym]) rs = RadioSetting("wierd.aprsym", "My Symbol Selected", rx) aprsmsg.append(rs) - + # --- APRS Beacon Settings ----- rx = RadioSettingValueList(offon, offon[_wierd.aprbfme]) rs = RadioSetting("wierd.aprbfme", "Filter: MIC-E", rx) bcnfltr.append(rs) - + rx = RadioSettingValueList(offon, offon[_wierd.aprbfpo]) rs = RadioSetting("wierd.aprbfpo", "Filter: Position", rx) bcnfltr.append(rs) - + rx = RadioSettingValueList(offon, offon[_wierd.aprbfwx]) rs = RadioSetting("wierd.aprbfwx", "Filter: Weather", rx) bcnfltr.append(rs) - + rx = RadioSettingValueList(offon, offon[_wierd.aprbfob]) rs = RadioSetting("wierd.aprbfob", "Filter: Object", rx) bcnfltr.append(rs) - + rx = RadioSettingValueList(offon, offon[_wierd.aprbfit]) rs = RadioSetting("wierd.aprbfit", "Filter: Item", rx) bcnfltr.append(rs) - + rx = RadioSettingValueList(offon, offon[_wierd.aprbfst]) rs = RadioSetting("wierd.aprbfst", "Filter: Status", rx) bcnfltr.append(rs) - + rx = RadioSettingValueList(offon, offon[_wierd.aprbfot]) rs = RadioSetting("wierd.aprbfot", "Filter: Other", rx) bcnfltr.append(rs) - + options = ["Off", "1", "10", "100", "1000", "3000"] v0 = int(_wierd.aprbfrl) # u16 int: 0,1,10,100,1000,3000 if v0 == 0: @@ -2659,7 +2701,7 @@ def get_settings(self): else: vx = options.index(str(v0)) rx = RadioSettingValueList(options, options[vx]) - rs = RadioSetting("wierd.aprbfrl", + rs = RadioSetting("wierd.aprbfrl", "Filter: Range Limit (km:miles)", rx) rs.set_apply_callback(self._rnglmt, _wierd, "aprbfrl") bcnfltr.append(rs) @@ -2667,17 +2709,17 @@ def get_settings(self): rx = RadioSettingValueList(offon, offon[_wierd.aprbfan]) rs = RadioSetting("wierd.aprbfan", "Filter: AltNet", rx) bcnfltr.append(rs) - + options = ["dd mm ss", "dd mm.mm"] rx = RadioSettingValueList(options, options[_wierd.aprbupo]) rs = RadioSetting("wierd.aprbupo", "Units: Position Format", rx) bcnunit.append(rs) - + options = ["kilometers", "miles"] rx = RadioSettingValueList(options, options[_wierd.aprbudi]) rs = RadioSetting("wierd.aprbudi", "Units: Distance", rx) bcnunit.append(rs) - + options = ["km/h", "mph", "knots"] rx = RadioSettingValueList(options, options[_wierd.aprbusp]) rs = RadioSetting("wierd.aprbusp", "Units: Speed", rx) @@ -2687,10 +2729,10 @@ def get_settings(self): rx = RadioSettingValueList(options, options[_wierd.aprbual]) rs = RadioSetting("wierd.aprbual", "Units: Altitude", rx) bcnunit.append(rs) - + options = ["hPa", "mb", "mmHg", "inHg"] rx = RadioSettingValueList(options, options[_wierd.aprbubo]) - rs = RadioSetting("wierd.aprbubo", "Units: Barometric Pressure", + rs = RadioSetting("wierd.aprbubo", "Units: Barometric Pressure", rx) bcnunit.append(rs) @@ -2698,12 +2740,12 @@ def get_settings(self): rx = RadioSettingValueList(options, options[_wierd.aprbutp]) rs = RadioSetting("wierd.aprbutp", "Units: Temperature", rx) bcnunit.append(rs) - + options = ["mm", "inch"] rx = RadioSettingValueList(options, options[_wierd.aprburn]) rs = RadioSetting("wierd.aprburn", "Units: Rain", rx) bcnunit.append(rs) - + options = ["m/s", "mph", "knots"] rx = RadioSettingValueList(options, options[_wierd.aprbuwd]) rs = RadioSetting("wierd.aprbuwd", "Units: Wind Speed", rx) @@ -2712,15 +2754,15 @@ def get_settings(self): rx = RadioSettingValueList(offon, offon[_wierd.aprbrtb]) rs = RadioSetting("wierd.aprbrtb", "Ringer: TX Beacon", rx) bcnrngr.append(rs) - + rx = RadioSettingValueList(offon, offon[_wierd.aprbrtm]) rs = RadioSetting("wierd.aprbrtm", "Ringer: TX Message", rx) bcnrngr.append(rs) - + rx = RadioSettingValueList(offon, offon[_wierd.aprbrrb]) rs = RadioSetting("wierd.aprbrrb", "Ringer: RX Beacon", rx) bcnrngr.append(rs) - + rx = RadioSettingValueList(offon, offon[_wierd.aprbrrm]) rs = RadioSetting("wierd.aprbrrm", "Ringer: RX Message", rx) bcnrngr.append(rs) @@ -2728,11 +2770,11 @@ def get_settings(self): rx = RadioSettingValueList(offon, offon[_wierd.aprbrmp]) rs = RadioSetting("wierd.aprbrmp", "Ringer: My Packet", rx) bcnrngr.append(rs) - + rx = RadioSettingValueList(offon, offon[_wierd.aprbrcr]) rs = RadioSetting("wierd.aprbrcr", "Ringer: Call Ringer", rx) bcnrngr.append(rs) - + options = ["Off", "1", "5", "10", "50", "100"] v0 = int(_wierd.aprbrrr) # u8 int: 0,1,5,10,50,100 if v0 == 0: @@ -2757,7 +2799,7 @@ def get_settings(self): tx = "Ringer Callsign %d" % (px + 1) rs = RadioSetting("share1/%d.shbyte" % pz, tx, rx) rs.set_apply_callback(self._putdgpname, py) - bcnrngr.append(rs) + bcnrngr.append(rs) pz += 1 rx = RadioSettingValueList(optsfx, optsfx[sfx]) tx = "Ringer Callsign %d SSID" % (px + 1) @@ -2766,57 +2808,57 @@ def get_settings(self): bcnrngr.append(rs) py += 1 pz += 1 - + # --- Beacon Status Text ---- - _bstat = self._memobj.bcntxt - options = ["Off", "Text 1", "Text 2", "Text 3", "Text 4", + _bstat = self._memobj.bcntxt + options = ["Off", "Text 1", "Text 2", "Text 3", "Text 4", "Text 5"] rx = RadioSettingValueList(options, options[_wierd.bcnstat]) rs = RadioSetting("wierd.bcnstat", "APRS Beacon Text Select", rx) bcnstat.append(rs) - + options = ["1/1", "1/2", "1/3", "1/4", "1/5", "1/6", "1/7", "1/8", "1/2(Freq)", "1/3(Freq)", "1/4(Freq)", "1/5(Freq)", "1/6(Freq)", "1/7(Freq)", "1/8(Freq)"] rx = RadioSettingValueList(options, options[_wierd.bcntxra]) rs = RadioSetting("wierd.bcntxra", "Beacon Text Rate", rx) bcnstat.append(rs) - + options = ["None", "Frequency", "Freq & SQL & Shift"] - + for i in range(0, 5): vx = i + 1 sx = self._b2s(_bstat[i].msg, 0xca) rx = RadioSettingValueString(0, 60, sx) - rs = RadioSetting("bcntxt/%d.msg" %i, + rs = RadioSetting("bcntxt/%d.msg" % i, "Status Text %d" % vx, rx) rs.set_apply_callback(self._s2b, _bstat[i], "msg", 60, 0xca) bcnstat.append(rs) - + rx = RadioSettingValueList(options, options[_bstat[i].mode]) - rs = RadioSetting("bcntxt/%d.mode" % i, + rs = RadioSetting("bcntxt/%d.mode" % i, "Status Text %d Mode" % vx, rx) bcnstat.append(rs) - + # --- Smart Beaconing - + options = ["Off", "Type 1", "Type 2", "Type 3"] rx = RadioSettingValueList(options, options[_wierd.bcnsmart]) rs = RadioSetting("wierd.bcnsmart", "Smart Beaconing Status", rx) bcnsmrt.append(rs) - - labls = ["Low Speed (2-30)", "High Speed (3-90)", - "Slow Rate (1-100 min)", "Fast Rate (10-180 sec)", - "Turn Angle (5-90 deg)", "Turn Slope (1-255)", + + labls = ["Low Speed (2-30)", "High Speed (3-90)", + "Slow Rate (1-100 min)", "Fast Rate (10-180 sec)", + "Turn Angle (5-90 deg)", "Turn Slope (1-255)", "Turn Time (5-180 sec)"] minvals = [2, 3, 1, 10, 5, 1, 5] maxvals = [30, 90, 100, 180, 90, 255, 180] - for v0 in range(1,4): # Type + for v0 in range(1, 4): # Type sx = "Type %d" % v0 for v1 in range(0, 7): # Parameters v2 = getattr(_wierd, "typ%dval%d" % (v0, v1)) - rx =RadioSettingValueInteger(minvals[v1], maxvals[v1], v2) - rs = RadioSetting("wierd.typ%dval%d" % (v0, v1), + rx = RadioSettingValueInteger(minvals[v1], maxvals[v1], v2) + rs = RadioSetting("wierd.typ%dval%d" % (v0, v1), "%s %s" % (sx, labls[v1]), rx) bcnsmrt.append(rs) # End If FTM-200 Unique settings @@ -2824,8 +2866,6 @@ def get_settings(self): def set_settings(self, settings): _setx = self._memobj.setts - _mic = self._memobj.micset - _mem = self._memobj for element in settings: if not isinstance(element, RadioSetting): self.set_settings(element) @@ -2862,16 +2902,15 @@ def set_settings(self, settings): class Ftm200dAlias(chirp_common.Alias): VENDOR = "Yaesu" MODEL = "FTM-200D" - + @directory.register class FTM200radio(FTM6000Radio): """Yaesu FTM-200""" - FTM200= True + FTM200 = True MODEL = "FTM-200" NAME_LEN = 16 # Valid name length ALIASES = [Ftm200dAlias] CHARSET = list(chirp_common.CHARSET_ASCII) MODES = ["AM", "FM", "NFM", "DN"] # TESTME = False - \ No newline at end of file From 2193034058d9305fb299eafa311ad6b272dc0035 Mon Sep 17 00:00:00 2001 From: Old-Phart Date: Wed, 24 Apr 2024 06:31:35 -0700 Subject: [PATCH 07/11] Tox pep corrections, get_settings logice fixes --- chirp/drivers/ftm6000.py | 113 ++++++++++++++++++++------------------- 1 file changed, 57 insertions(+), 56 deletions(-) diff --git a/chirp/drivers/ftm6000.py b/chirp/drivers/ftm6000.py index a725f7a8f..276e0e309 100644 --- a/chirp/drivers/ftm6000.py +++ b/chirp/drivers/ftm6000.py @@ -53,7 +53,7 @@ class FTM6000Radio(yaesu_clone.YaesuCloneModeRadio): MODES = ["FM", "AM", "NFM"] TMODES = ["", "Tone", "TSQL", "TSQL-R", "DTCS", "Cross"] CROSS_MODES = ["->DTCS", "Tone->DTCS", "DTCS->Tone"] - DUPLEX = ["", "n/a", "-", "+", "split"] + DUPLEX = ["", "off", "-", "+", "split"] T_STEPS = [2.5, 5.0, 6.25, 10.0, 12.5, 15.0, 20.0, 25.0, 50.0, 100.0] VALID_BANDS = [(108000000, 137000000), (137000000, 174000000), @@ -1471,29 +1471,29 @@ def get_settings(self): fmenu = RadioSettingGroup("fmnu", "Quick Functions") mic = RadioSettingGroup("mic", "Microphone") sig = RadioSettingGroup("sig", "Signalling") - dat = RadioSettingGroup("dat", "Data") opts = RadioSettingGroup("opts", "Options") dtmf = RadioSettingGroup("dtmf", "DTMF") scan = RadioSettingGroup("scan", "Scanning") - wires = RadioSettingGroup("wires", "GM/WIRES-X") - aprscom = RadioSettingGroup("aprscom", "APRS Settings") - aprsdgp = RadioSettingGroup("aprsdgp", "APRS Digipeater") - aprsmsg = RadioSettingGroup("aprsmsg", "APRS Messages") - bcnfltr = RadioSettingGroup("bcnfltr", "APRS Beacon Filter") - bcnunit = RadioSettingGroup("bcnunit", "APRS Beacon Units") - bcnrngr = RadioSettingGroup("bcnrngr", "APRS Beacon Ringer") - bcnstat = RadioSettingGroup("bcnstat", "APRS Beacon Status") - bcnsmrt = RadioSettingGroup("bcnsmrt", "APRS Smart Beaconing") other = RadioSettingGroup("other", "Other") if self.FTM200: + dat = RadioSettingGroup("dat", "Data") + wires = RadioSettingGroup("wires", "GM/WIRES-X") + aprscom = RadioSettingGroup("aprscom", "APRS Settings") + aprsdgp = RadioSettingGroup("aprsdgp", "APRS Digipeater") + aprsmsg = RadioSettingGroup("aprsmsg", "APRS Messages") + bcnfltr = RadioSettingGroup("bcnfltr", "APRS Beacon Filter") + bcnunit = RadioSettingGroup("bcnunit", "APRS Beacon Units") + bcnrngr = RadioSettingGroup("bcnrngr", "APRS Beacon Ringer") + bcnstat = RadioSettingGroup("bcnstat", "APRS Beacon Status") + bcnsmrt = RadioSettingGroup("bcnsmrt", "APRS Smart Beaconing") group = RadioSettings(cfg, dsp, fmenu, mic, sig, opts, dtmf, scan, dat, wires, aprscom, aprsmsg, aprsdgp, bcnfltr, bcnunit, bcnrngr, bcnstat, bcnsmrt, other) else: group = RadioSettings(cfg, dsp, fmenu, mic, sig, opts, dtmf, - scan) + scan, other) menu_items = ["01: Auto Power Off (APO)", "02: ARTS Mode", "03: ARTS Interval", "04: Busy Channel Lockout (BCLO)", @@ -1514,7 +1514,6 @@ def get_settings(self): # Begin Config settings if self.FTM200: - sx = self._b2s(_mic.csign, 0xff) rx = RadioSettingValueString(0, 10, sx, False) rs = RadioSetting("micset.csign", "Call Sign Label", rx) @@ -1995,47 +1994,48 @@ def get_settings(self): # End of Scan settings # Begin Data settings - options = ["4700 bps", "9600 bps", "19200 bps", "38400 bps", - "57600 bps"] - rx = RadioSettingValueList(options, options[_wierd.comspd]) - rs = RadioSetting("wierd.comspd", "COM Port Speed", rx) - dat.append(rs) - - options = ["Off", "GPS Out", "Packet", "Waypoint"] - rx = RadioSettingValueList(options, options[_wierd.comout]) - rs = RadioSetting("wierd.comout", "COM Port Output", rx) - dat.append(rs) - - options = ["NMEA9", "NMEA8", "NMEA7", "NMEA6"] - rx = RadioSettingValueList(options, options[_wierd.comwpf]) - rs = RadioSetting("wierd.comwpf", "COM Port Waypoint Format", rx) - dat.append(rs) - - options = ["All", "Mobile", "Frequency", "Object/Item", "Digipeater", - "VoIP", "Weather", "Yaesu", "Call Ringer", "Rng Ringer"] - rx = RadioSettingValueList(options, options[_wierd.comflt]) - rs = RadioSetting("wierd.comflt", "COM Port Waypoint Filter", rx) - dat.append(rs) - - options = ["Main Band", "Sub Band", "A-Band Fix", "B-Band Fix"] - rx = RadioSettingValueList(options, options[_wierd.dbsela]) - rs = RadioSetting("wierd.dbsela", "Data Band Select: APRS", rx) - dat.append(rs) - rx = RadioSettingValueList(options, options[_wierd.dbseld]) - rs = RadioSetting("wierd.dbseld", "Data Band Select: Data", rx) - dat.append(rs) - - options = ["1200 bps", "9600 bps"] - rx = RadioSettingValueList(options, options[_wierd.dspda]) - rs = RadioSetting("wierd.dspda", "Data Speed: APRS", rx) - dat.append(rs) - rx = RadioSettingValueList(options, options[_wierd.pktspd]) - rs = RadioSetting("wierd.pktspd", "Data Speed: Data", rx) - dat.append(rs) - - rx = RadioSettingValueList(offon, offon[_wierd.datsql]) - rs = RadioSetting("wierd.datsql", "Data Squelch", rx) - dat.append(rs) + if self.FTM200: + options = ["4700 bps", "9600 bps", "19200 bps", "38400 bps", + "57600 bps"] + rx = RadioSettingValueList(options, options[_wierd.comspd]) + rs = RadioSetting("wierd.comspd", "COM Port Speed", rx) + dat.append(rs) + + options = ["Off", "GPS Out", "Packet", "Waypoint"] + rx = RadioSettingValueList(options, options[_wierd.comout]) + rs = RadioSetting("wierd.comout", "COM Port Output", rx) + dat.append(rs) + + options = ["NMEA9", "NMEA8", "NMEA7", "NMEA6"] + rx = RadioSettingValueList(options, options[_wierd.comwpf]) + rs = RadioSetting("wierd.comwpf", "COM Port Waypoint Format", rx) + dat.append(rs) + + options = ["All", "Mobile", "Frequency", "Object/Item", "Digipeater", + "VoIP", "Weather", "Yaesu", "Call Ringer", "Rng Ringer"] + rx = RadioSettingValueList(options, options[_wierd.comflt]) + rs = RadioSetting("wierd.comflt", "COM Port Waypoint Filter", rx) + dat.append(rs) + + options = ["Main Band", "Sub Band", "A-Band Fix", "B-Band Fix"] + rx = RadioSettingValueList(options, options[_wierd.dbsela]) + rs = RadioSetting("wierd.dbsela", "Data Band Select: APRS", rx) + dat.append(rs) + rx = RadioSettingValueList(options, options[_wierd.dbseld]) + rs = RadioSetting("wierd.dbseld", "Data Band Select: Data", rx) + dat.append(rs) + + options = ["1200 bps", "9600 bps"] + rx = RadioSettingValueList(options, options[_wierd.dspda]) + rs = RadioSetting("wierd.dspda", "Data Speed: APRS", rx) + dat.append(rs) + rx = RadioSettingValueList(options, options[_wierd.pktspd]) + rs = RadioSetting("wierd.pktspd", "Data Speed: Data", rx) + dat.append(rs) + + rx = RadioSettingValueList(offon, offon[_wierd.datsql]) + rs = RadioSetting("wierd.datsql", "Data Squelch", rx) + dat.append(rs) # End of Data Settings # Begin Options settings @@ -2865,7 +2865,7 @@ def get_settings(self): return group # End get_settings() def set_settings(self, settings): - _setx = self._memobj.setts + # _setx = self._memobj.setts for element in settings: if not isinstance(element, RadioSetting): self.set_settings(element) @@ -2885,7 +2885,8 @@ def set_settings(self, settings): obj = getattr(obj, bit) setting = bits[-1] else: - obj = _setx + # obj = _setx + obj = self._memobj setting = element.get_name() if element.has_apply_callback(): From 29a1abbf5f5f012d9612b25fcf024c0d7ebce90e Mon Sep 17 00:00:00 2001 From: Old-Phart Date: Thu, 25 Apr 2024 08:44:27 -0700 Subject: [PATCH 08/11] Style Scrubbed. TESTME enabled --- chirp/drivers/ftm6000.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/chirp/drivers/ftm6000.py b/chirp/drivers/ftm6000.py index 276e0e309..7f064ebfc 100644 --- a/chirp/drivers/ftm6000.py +++ b/chirp/drivers/ftm6000.py @@ -42,11 +42,11 @@ class Ftm6000RAlias(chirp_common.Alias): class FTM6000Radio(yaesu_clone.YaesuCloneModeRadio): """Yaesu FTM-6000""" FTM200 = False - # TESTME = False + TESTME = False BAUD_RATE = 38400 - COM_BITS = 8 # number of data bitsTMODEW - COM_PRTY = 'N' # parity checking - COM_STOP = 1 # stop bits + COM_BITS = 8 + COM_PRTY = 'N' + COM_STOP = 1 MODEL = "FTM-6000" NAME_LEN = 6 # Valid Name Length ALIASES = [Ftm6000RAlias] @@ -2914,4 +2914,4 @@ class FTM200radio(FTM6000Radio): ALIASES = [Ftm200dAlias] CHARSET = list(chirp_common.CHARSET_ASCII) MODES = ["AM", "FM", "NFM", "DN"] - # TESTME = False + TESTME = False From 27c9cfad95e0be3b61845b5ed7c409f1888bb5b9 Mon Sep 17 00:00:00 2001 From: Old-Phart Date: Fri, 26 Apr 2024 05:19:38 -0700 Subject: [PATCH 09/11] More style fixes. Added 'Needs_Compat_Serial=False' --- chirp/drivers/ftm6000.py | 34 +++++++++++++++++++--------------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/chirp/drivers/ftm6000.py b/chirp/drivers/ftm6000.py index 7f064ebfc..9491c4fc0 100644 --- a/chirp/drivers/ftm6000.py +++ b/chirp/drivers/ftm6000.py @@ -33,6 +33,7 @@ LOG = logging.getLogger(__name__) CMD_ACK = b'\x06' + class Ftm6000RAlias(chirp_common.Alias): Vendor = "Yaesu" MODEL = "FTM-6000R" @@ -43,6 +44,7 @@ class FTM6000Radio(yaesu_clone.YaesuCloneModeRadio): """Yaesu FTM-6000""" FTM200 = False TESTME = False + NEEDS_COMPAT_SERIAL = False BAUD_RATE = 38400 COM_BITS = 8 COM_PRTY = 'N' @@ -61,8 +63,8 @@ class FTM6000Radio(yaesu_clone.YaesuCloneModeRadio): (400000000, 480000000), (480000000, 999999999)] POWER_LEVELS = [chirp_common.PowerLevel("Hi", watts=50), - chirp_common.PowerLevel("Mid", watts=20), - chirp_common.PowerLevel("Low", watts=5)] + chirp_common.PowerLevel("Mid", watts=20), + chirp_common.PowerLevel("Low", watts=5)] SKIPS = ["", "S"] # No lowercase,{} or ~ CHARSET = [chr(x) for x in list(range(ord(" "), ord("_") + 1)) + @@ -668,7 +670,7 @@ def _read(self, blck, blsz): break time.sleep(0.5) if len(data) == blsz: - LOG.debug("Received block %s, sub %s" % (hex(data[0]), + LOG.debug("Received block %s, sub %s" % (hex(data[0]), hex(data[1]))) checksum = data[blsz - 1] cs = 0 @@ -1486,7 +1488,7 @@ def get_settings(self): bcnunit = RadioSettingGroup("bcnunit", "APRS Beacon Units") bcnrngr = RadioSettingGroup("bcnrngr", "APRS Beacon Ringer") bcnstat = RadioSettingGroup("bcnstat", "APRS Beacon Status") - bcnsmrt = RadioSettingGroup("bcnsmrt", "APRS Smart Beaconing") + bcnsmrt = RadioSettingGroup("bcnsmrt", "APRS Smart Beaconing") group = RadioSettings(cfg, dsp, fmenu, mic, sig, opts, dtmf, scan, dat, wires, aprscom, aprsmsg, aprsdgp, bcnfltr, bcnunit, bcnrngr, @@ -1497,9 +1499,9 @@ def get_settings(self): menu_items = ["01: Auto Power Off (APO)", "02: ARTS Mode", "03: ARTS Interval", "04: Busy Channel Lockout (BCLO)", - "05: Beep", "06: Bell", "07: Clock Type", - "08: LCD Dimmer", "09: DTMF Manual/Auto", - "10: DTMF TX", "11:DTMF Codes", "12: Home", + "05: Beep", "06: Bell", "07: Clock Type", + "08: LCD Dimmer", "09: DTMF Manual/Auto", + "10: DTMF TX", "11:DTMF Codes", "12: Home", "13: Microphone Gain", "14: Microphone P Keys", "15: Pager TX/RX", "16: Packet Speed", "17:RX Mode", "18: Band Select", "19: Repeater Reverse", @@ -1507,7 +1509,7 @@ def get_settings(self): "23: Scan Type", "24: Squelch Type", "25:Squelch Code", "26: Squelch Expansion", "27: Step", "28: Radio Temperature", "29: Time Out Timer (TOT)", - "30: TX Power", "31: Version", "32: Voltage", + "30: TX Power", "31: Version", "32: Voltage", "33: Width", "34: Weather Alert", "35: Bluetooth"] offon = ["Off", "On"] onoff = ["On", "Off"] # Inverted logic @@ -1560,7 +1562,7 @@ def get_settings(self): options = ["Off", "0.5 Hours", "1 Hours", "1.5 Hours", "2 Hours", "3 Hours", "4 Hours", "5 Hours", "6 Hours", "7 Hours", - "8 Hours", "9 Hours", "10 Hours", "11 Hours", + "8 Hours", "9 Hours", "10 Hours", "11 Hours", "12 Hours"] v0 = _setx.apo # Hours BCD v1 = _setx.apo1 # 0.5 hours yes/no @@ -1994,7 +1996,7 @@ def get_settings(self): # End of Scan settings # Begin Data settings - if self.FTM200: + if self.FTM200: options = ["4700 bps", "9600 bps", "19200 bps", "38400 bps", "57600 bps"] rx = RadioSettingValueList(options, options[_wierd.comspd]) @@ -2011,8 +2013,9 @@ def get_settings(self): rs = RadioSetting("wierd.comwpf", "COM Port Waypoint Format", rx) dat.append(rs) - options = ["All", "Mobile", "Frequency", "Object/Item", "Digipeater", - "VoIP", "Weather", "Yaesu", "Call Ringer", "Rng Ringer"] + options = ["All", "Mobile", "Frequency", "Object/Item", + "Digipeater", "VoIP", "Weather", "Yaesu", + "Call Ringer", "Rng Ringer"] rx = RadioSettingValueList(options, options[_wierd.comflt]) rs = RadioSetting("wierd.comflt", "COM Port Waypoint Filter", rx) dat.append(rs) @@ -2088,7 +2091,7 @@ def get_settings(self): options = ["Low", "Normal", "High"] rx = RadioSettingValueList(options, options[_mic.usbcamql]) - rs = RadioSetting("micset.usbcamql", "USB Camera: Image Quality", + rs = RadioSetting("micset.usbcamql", "USB Camera: Image Quality", rx) opts.append(rs) @@ -2645,7 +2648,7 @@ def get_settings(self): options.append("\\") sx = chr(_wierd.aprsym4a) rx = RadioSettingValueList(options, sx) - rs = RadioSetting("wierd.aprsym4a", "My Symbol #4 First Value", + rs = RadioSetting("wierd.aprsym4a", "My Symbol #4 First Value", rx) rs.set_apply_callback(self._c2u8, _wierd, "aprsym4a") aprsmsg.append(rs) @@ -2655,7 +2658,7 @@ def get_settings(self): options.append(chr(i)) # full ascii sx = chr(_wierd.aprsym4b) rx = RadioSettingValueList(options, sx) - rs = RadioSetting("wierd.aprsym4b", "My Symbol #4 Second Value", + rs = RadioSetting("wierd.aprsym4b", "My Symbol #4 Second Value", rx) rs.set_apply_callback(self._c2u8, _wierd, "aprsym4b") aprsmsg.append(rs) @@ -2914,4 +2917,5 @@ class FTM200radio(FTM6000Radio): ALIASES = [Ftm200dAlias] CHARSET = list(chirp_common.CHARSET_ASCII) MODES = ["AM", "FM", "NFM", "DN"] + NEEDS_COMPAT_SERIAL = False TESTME = False From 109c9496a2893f3631beff6324213c4d5245e37f Mon Sep 17 00:00:00 2001 From: Old-Phart Date: Fri, 26 Apr 2024 05:32:11 -0700 Subject: [PATCH 10/11] Added FTM-200, included in FTM-6000 --- tests/py3_driver_testers.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/py3_driver_testers.txt b/tests/py3_driver_testers.txt index f54a2b93c..4f41c0e36 100644 --- a/tests/py3_driver_testers.txt +++ b/tests/py3_driver_testers.txt @@ -366,6 +366,7 @@ Yaesu_FT-818ND_US,+Yaesu_FT-817,14-Feb-2019 Yaesu_FT-857_897,+Yaesu_FT-817,14-Feb-2019 Yaesu_FT-857_897_US,+Yaesu_FT-817,14-Feb-2019 Yaesu_FT-90,#10386,22-Feb-2023 +Yaesu_FTM-200,@Old-Phart,16-Apr-2024 Yaesu_FTM-350,@kk7ds,4-Dec-2022 Yaesu_FTM-6000,@Old-Phart,16-Apr-2024 Yaesu_VX-2,@thomasrussellmurphy,20-Jan-2023 From 4eca53b37b5637f413bb12b7c5b2a01a5e1c38fc Mon Sep 17 00:00:00 2001 From: Old-Phart Date: Fri, 26 Apr 2024 05:34:11 -0700 Subject: [PATCH 11/11] Re-gen after py3_driver_testers added FTM-200 --- tests/Python3_Driver_Testing.md | 43 ++++++++++++++++++++++++++++----- 1 file changed, 37 insertions(+), 6 deletions(-) diff --git a/tests/Python3_Driver_Testing.md b/tests/Python3_Driver_Testing.md index 44eb45029..d742804b7 100644 --- a/tests/Python3_Driver_Testing.md +++ b/tests/Python3_Driver_Testing.md @@ -5,6 +5,7 @@ | Abbree_AR-518 | [@KC9HI](https://github.com/KC9HI) | 16-Dec-2022 | Yes | 0.24% | | Abbree_AR-63 | [@KC9HI](https://github.com/KC9HI) | 30-Nov-2022 | Yes | 0.03% | | Abbree_AR-730 | [@KC9HI](https://github.com/KC9HI) | 17-Aug-2023 | Yes | | +| Abbree_AR-869 | | | Yes | 0.01% | | Abbree_AR-F5 | [@KC9HI](https://github.com/KC9HI) | 09-Aug-2023 | Yes | | | Alinco_DJ-G7EG | [@HB9UF](https://github.com/HB9UF) | 09-Dec-2022 | Yes | 0.44% | | Alinco_DJ-G7T | [Reported working](https://chirp.danplanet.com/issues/10567) | 09-May-2023 | Yes | | @@ -15,6 +16,7 @@ | Alinco_DR135T | [Implied by Alinco_DR235T](#user-content-Alinco_DR235T) | 12-Dec-2022 | Yes | 0.04% | | Alinco_DR235T | [@kk7ds](https://github.com/kk7ds) | 12-Dec-2022 | Yes | 0.02% | | Alinco_DR435T | [Implied by Alinco_DR235T](#user-content-Alinco_DR235T) | 12-Dec-2022 | Yes | 0.02% | +| Alinco_DR735T | | | Yes | | | AnyTone_5888UV | [@kk7ds](https://github.com/kk7ds) | 9-Dec-2022 | Yes | 0.14% | | AnyTone_5888UVIII | [@bschuler42](https://github.com/bschuler42) | 9-Jan-2023 | Yes | 0.04% | | AnyTone_778UV | [Implied by Retevis_RT95](#user-content-Retevis_RT95) | 13-Nov-2022 | Yes | 0.17% | @@ -44,6 +46,8 @@ | BTECH_UV-50X2_G2 | [@KC9HI](https://github.com/KC9HI) | 30-Nov-2022 | Yes | 0.00% | | BTECH_UV-50X3 | [@KC9HI](https://github.com/KC9HI) | 10-Dec-2022 | Yes | 0.06% | | BTECH_UV-5X3 | [@KC9HI](https://github.com/KC9HI) | 9-Dec-2022 | Yes | 0.43% | +| Baofeng_5RM | | | Yes | | +| Baofeng_5RX | | | Yes | | | Baofeng_BF-1901 | [@cetinajero](https://github.com/cetinajero) | 3-Jul-2023 | Yes | | | Baofeng_BF-1904 | [@cetinajero](https://github.com/cetinajero) | 3-Jul-2023 | Yes | | | Baofeng_BF-888 | [@kk7ds](https://github.com/kk7ds) | 13-Feb-2019 | Yes | **15.53%** | @@ -52,11 +56,19 @@ | Baofeng_BF-F8HP | [@KC9HI](https://github.com/KC9HI) | 18-Nov-2022 | Yes | **6.33%** | | Baofeng_BF-M4 | [@cetinajero](https://github.com/cetinajero) | 8-May-2023 | Yes | | | Baofeng_BF-T1 | [@KC9HI](https://github.com/KC9HI) | 10-Dec-2022 | Yes | 0.76% | +| Baofeng_BF-T20 | | | Yes | | +| Baofeng_BF-T20FRS | | | Yes | | | Baofeng_BF-T8 | [@KC9HI](https://github.com/KC9HI) | 30-Nov-2022 | Yes | 0.42% | | Baofeng_BF-V8A | [@KC9HI](https://github.com/KC9HI) | 28-Nov-2022 | Yes | 0.03% | | Baofeng_F-11 | [Implied by Baofeng_UV-5R](#user-content-Baofeng_UV-5R) | 18-Nov-2022 | Yes | 0.12% | +| Baofeng_GM-5RH | | | Yes | | | Baofeng_GT-3WP | [@KC9HI](https://github.com/KC9HI) | 3-Dec-2022 | Yes | 0.43% | | Baofeng_GT-5R | [@KC9HI](https://github.com/KC9HI) | 18-Nov-2022 | Yes | 0.68% | +| Baofeng_K5-Plus | | | Yes | | +| Baofeng_UV-13Pro | | | Yes | | +| Baofeng_UV-17 | | | Yes | | +| Baofeng_UV-17Pro | | | Yes | | +| Baofeng_UV-17ProGPS | | | Yes | | | Baofeng_UV-3R | [@yarda](https://github.com/yarda) | 26-Sep-2022 | Yes | 0.45% | | Baofeng_UV-5R | [@lekv](https://github.com/lekv) | 23-Oct-2022 | Yes | **28.81%** | | Baofeng_UV-6 | [Implied by Baofeng_UV-5R](#user-content-Baofeng_UV-5R) | 18-Nov-2022 | Yes | 0.46% | @@ -71,9 +83,10 @@ | Baofeng_W31E | [@KC9HI](https://github.com/KC9HI) | 14-Aug-2023 | Yes | | | Baojie_BJ-218 | [Implied by LUITON_LT-725UV](#user-content-LUITON_LT-725UV) | 16-Feb-2023 | Yes | 0.29% | | Baojie_BJ-318 | [@KC9HI](https://github.com/KC9HI) | 2-Jan-2023 | Yes | 0.10% | -| Baojie_BJ-9900 | | | | 0.02% | +| Baojie_BJ-9900 | | | Yes | 0.02% | | Baojie_BJ-UV55 | | | Yes | 0.03% | | Boblov_X3Plus | | | | 0.02% | +| Boristone_8RS | | | Yes | 0.00% | | CRT_Micron_UV | [Implied by Retevis_RT95](#user-content-Retevis_RT95) | 13-Nov-2022 | Yes | 0.08% | | CRT_Micron_UV_V2 | [Implied by Retevis_RT95](#user-content-Retevis_RT95) | 13-Nov-2022 | Yes | 0.10% | | Cignus_XTR-5 | [Implied by Radioddity_GS-5B](#user-content-Radioddity_GS-5B) | 17-Mar-2023 | Yes | | @@ -89,6 +102,7 @@ | Feidaxin_FD-460A | | | | 0.01% | | Feidaxin_FD-460UH | | | | 0.01% | | Generic_CSV | [@kk7ds](https://github.com/kk7ds) | 4-Dec-2022 | | | +| HamGeek_HG-590 | | | Yes | 0.00% | | Hiroyasu_HI-8811 | [@KC9HI](https://github.com/KC9HI) | 4-Jun-2023 | Yes | | | HobbyPCB_RS-UV3 | [@kk7ds](https://github.com/kk7ds) | 9-Dec-2022 | Yes | 0.02% | | Icom_IC-208H | [Probably works](https://github.com/kk7ds/chirp/blob/py3/chirp/drivers/icf.py) | 12-Dec-2022 | Yes | 0.05% | @@ -102,6 +116,7 @@ | Icom_IC-7100 | Mike W | 16-Feb-2023 | Yes | 0.06% | | Icom_IC-7200 | [@kk7ds](https://github.com/kk7ds) | 22-Oct-2022 | Yes | | | Icom_IC-7300 | [@kk7ds](https://github.com/kk7ds) | 22-Oct-2022 | Yes | 0.03% | +| Icom_IC-7400 | | | Yes | | | Icom_IC-746 | [Reported working](https://chirp.danplanet.com/issues/10346) | 3-Feb-2023 | Yes | | | Icom_IC-7610 | [@kk7ds](https://github.com/kk7ds) | 24-Oct-2022 | Yes | 0.00% | | Icom_IC-910 | [@mfncooper](https://github.com/mfncooper) | 1-Oct-2021 | Yes | 0.00% | @@ -129,9 +144,11 @@ | Icom_ID-880H | [@kk7ds](https://github.com/kk7ds) | 22-Oct-2022 | Yes | 0.02% | | Intek_HR-2040 | [Implied by AnyTone_5888UV](#user-content-AnyTone_5888UV) | 9-Dec-2022 | Yes | 0.02% | | Intek_KT-980HP | [Implied by Baofeng_BF-F8HP](#user-content-Baofeng_BF-F8HP) | 18-Nov-2022 | Yes | 0.04% | +| JJCC_JC-8629 | | | Yes | | | Jetstream_JT220M | [Implied by Alinco_DR235T](#user-content-Alinco_DR235T) | 12-Dec-2022 | Yes | 0.01% | | Jetstream_JT270M | [Implied by Jetstream_JT270M](#user-content-Jetstream_JT270M) | 13-Dec-2022 | Yes | 0.01% | | Jetstream_JT270MH | [@kk7ds](https://github.com/kk7ds) | 13-Dec-2022 | Yes | 0.01% | +| Jianpai_8800_Plus | | | Yes | 0.01% | | KYD_IP-620 | | | | 0.02% | | KYD_NC-630A | | | | 0.02% | | Kenwood_HMK | [Implied by Generic_CSV](#user-content-Generic_CSV) | 4-Dec-2022 | | 0.00% | @@ -141,6 +158,7 @@ | Kenwood_TH-D72_live_mode | [@kk7ds](https://github.com/kk7ds) | 21-Oct-2022 | Yes | 0.00% | | Kenwood_TH-D74_clone_mode | [@kk7ds](https://github.com/kk7ds) | 30-Nov-2022 | Yes | 0.00% | | Kenwood_TH-D74_live_mode | [@kk7ds](https://github.com/kk7ds) | 20-Oct-2022 | Yes | 0.00% | +| Kenwood_TH-D75 | | | Yes | | | Kenwood_TH-D7G | [Probably works](https://github.com/kk7ds/chirp/blob/py3/chirp/drivers/kenwood_live.py) | 12-Dec-2022 | Yes | 0.00% | | Kenwood_TH-F6 | [@KC9HI](https://github.com/KC9HI) | 30-Nov-2022 | Yes | 0.03% | | Kenwood_TH-F7 | [@sv1](https://github.com/sv1) | 19-Oct-2022 | Yes | 0.03% | @@ -218,8 +236,12 @@ | LUITON_LT-588UV | [@KC9HI](https://github.com/KC9HI) | 11-Nov-2022 | Yes | 0.01% | | LUITON_LT-725UV | [@KC9HI](https://github.com/KC9HI) | 11-Dec-2022 | Yes | 0.02% | | Lanchonlh_HG-UV98 | | | Yes | 0.00% | -| Leixen_VV-898 | [Implied by Jetstream_JT270MH](#user-content-Jetstream_JT270MH) | 13-Dec-2022 | Yes | 0.18% | -| Leixen_VV-898S | [@READ10](https://github.com/READ10) | 19-Dec-2022 | Yes | 0.10% | +| Leixen_VV-898 | [Implied by Jetstream_JT270MH](#user-content-Jetstream_JT270MH) | 13-Dec-2022 | Yes | 0.16% | +| Leixen_VV-898E | | | Yes | 0.02% | +| Leixen_VV-898E_Dual_Bank | | | Yes | | +| Leixen_VV-898S | [@READ10](https://github.com/READ10) | 19-Dec-2022 | Yes | 0.08% | +| Leixen_VV-898S_Dual_Bank | | | Yes | | +| MMLradio_JC-8629 | | | Yes | 0.01% | | MTC_UV-5R-3 | [Implied by BTECH_UV-5X3](#user-content-BTECH_UV-5X3) | 9-Dec-2022 | Yes | 0.02% | | Maverick_RA-100 | [@cetinajero](https://github.com/cetinajero) | 7-Jul-2023 | Yes | | | Maverick_RA-425 | [@cetinajero](https://github.com/cetinajero) | 7-Jul-2023 | Yes | | @@ -242,6 +264,7 @@ | QYT_KT980PLUS | [Implied by BTECH_UV-25X2](#user-content-BTECH_UV-25X2) | 11-Nov-2022 | Yes | 0.09% | | Quansheng_TG-UV2+ | [Reported working](https://chirp.danplanet.com/issues/10398) | 26-Feb-2023 | Yes | 0.05% | | Quansheng_UV-K5 | [@sq5bpf](https://github.com/sq5bpf) | 29-May-2023 | Yes | | +| Quansheng_UV-K5_egzumer | | | Yes | | | RT_Systems_CSV | | | | | | Radioddity_DB25-G | [@KC9HI](https://github.com/KC9HI) | 11-Nov-2022 | Yes | 0.17% | | Radioddity_GA-2S | [@KC9HI](https://github.com/KC9HI) | 4-Dec-2022 | Yes | 0.19% | @@ -254,12 +277,14 @@ | Radtel_RT-470 | [@KC9HI](https://github.com/KC9HI) | 2-Apr-2023 | Yes | 0.00% | | Radtel_RT-470L | [@KC9HI](https://github.com/KC9HI) | 5-May-2023 | Yes | | | Radtel_RT-470X | [@KC9HI](https://github.com/KC9HI) | 10-Aug-2023 | Yes | | +| Radtel_RT-490 | | | Yes | 0.08% | | Radtel_T18 | [@KC9HI](https://github.com/KC9HI) | 28-Nov-2022 | Yes | 0.07% | | Retevis_H777S | [@KC9HI](https://github.com/KC9HI) | 22-Dec-2022 | Yes | | | Retevis_H777_Plus | [@KC9HI](https://github.com/KC9HI) | 4-Dec-2022 | Yes | 0.06% | | Retevis_RA685 | [@KC9HI](https://github.com/KC9HI) | 19-Nov-2022 | Yes | 0.25% | | Retevis_RA79 | [@KC9HI](https://github.com/KC9HI) | 27-Oct-2023 | Yes | | | Retevis_RA85 | [@KC9HI](https://github.com/KC9HI) | 19-Nov-2022 | Yes | 0.05% | +| Retevis_RA89 | | | Yes | | | Retevis_RB15 | [@KC9HI](https://github.com/KC9HI) | 18-Dec-2022 | Yes | 0.01% | | Retevis_RB17 | [@KC9HI](https://github.com/KC9HI) | 28-Nov-2022 | Yes | 0.02% | | Retevis_RB17A | [@KC9HI](https://github.com/KC9HI) | 30-Nov-2022 | Yes | 0.01% | @@ -328,7 +353,12 @@ | Ruyage_UV58Plus | [@KC9HI](https://github.com/KC9HI) | 18-Mar-2023 | Yes | | | Sainsonic_AP510 | | | | 0.00% | | SenhaiX_8800 | [Implied by Radioddity_GS-5B](#user-content-Radioddity_GS-5B) | 17-Mar-2023 | Yes | | +| Socotran_FB-8629 | | | Yes | 0.00% | +| Socotran_JC-8629 | | | Yes | | | TDXone_TD-Q8A | [@KC9HI](https://github.com/KC9HI) | 18-Dec-2022 | | 0.02% | +| TIDRADIO_TD-H3 | | | Yes | | +| TIDRADIO_TD-H3-GMRS | | | Yes | | +| TIDRADIO_TD-H3-HAM | | | Yes | | | TIDRADIO_TD-H6 | [@kk7ds](https://github.com/kk7ds) | 21-Oct-2022 | Yes | 0.43% | | TIDRADIO_TD-H8 | [@Sandmann34](https://github.com/Sandmann34) | 7-Feb-2023 | Yes | | | TIDRADIO_TD-H8-GMRS | [@Sandmann34](https://github.com/Sandmann34) | 7-Feb-2023 | Yes | | @@ -350,6 +380,7 @@ | TYT_TH9000_220 | [Implied by Retevis_RT9000D_220-260](#user-content-Retevis_RT9000D_220-260) | 8-Dec-2022 | Yes | 0.04% | | TYT_TH9000_440 | [Implied by Retevis_RT9000D_400-490](#user-content-Retevis_RT9000D_400-490) | 8-Dec-2022 | Yes | 0.04% | | Talkpod_A36plus | [@KC9HI](https://github.com/KC9HI) | 12-Jun-2023 | Yes | | +| Talkpod_A36plus_8w | | | Yes | | | Vertex_Standard_FTL-1011 | | | | 0.02% | | Vertex_Standard_FTL-2011 | | | | 0.05% | | Vertex_Standard_FTL-7011 | | | | 0.03% | @@ -427,11 +458,11 @@ | Zastone_ZT-X6 | [Implied by Retevis_RT22](#user-content-Retevis_RT22) | 9-Dec-2022 | Yes | 0.11% | ## Stats -**Drivers:** 424 +**Drivers:** 455 -**Tested:** 87% (370/54) (93% of usage stats) +**Tested:** 81% (371/84) (93% of usage stats) -**Byte clean:** 90% (384/40) +**Byte clean:** 91% (416/39) ## Meaning of this testing