|
# 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
|
|
# 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 <http://www.gnu.org/licenses/>.
|
|
|
|
"""FTM-6000 Yaesu Radio Driver"""
|
|
|
|
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 math
|
|
import sys
|
|
|
|
LOG = logging.getLogger(__name__)
|
|
CMD_ACK = b'\x06'
|
|
|
|
|
|
class Ftm6000RAlias(chirp_common.Alias):
|
|
Vendor = "Yaesu"
|
|
MODEL = "FTM-6000R"
|
|
|
|
|
|
@directory.register
|
|
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'
|
|
COM_STOP = 1
|
|
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 = ["", "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),
|
|
(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
|
|
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
|
|
|
|
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 %i" %
|
|
(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.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 is 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 is 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 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)
|
|
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 is 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 = 3
|
|
if sx == "Mid":
|
|
v0 = 1
|
|
if sx == "Full":
|
|
v0 = 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 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
|
|
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
|
|
|
|
cfg = RadioSettingGroup("cfg", "Config")
|
|
dsp = RadioSettingGroup("dsp", "Display")
|
|
fmenu = RadioSettingGroup("fmnu", "Quick Functions")
|
|
mic = RadioSettingGroup("mic", "Microphone")
|
|
sig = RadioSettingGroup("sig", "Signalling")
|
|
opts = RadioSettingGroup("opts", "Options")
|
|
dtmf = RadioSettingGroup("dtmf", "DTMF")
|
|
scan = RadioSettingGroup("scan", "Scanning")
|
|
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, other)
|
|
|
|
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 = ["Dim", "Mid", "Full"]
|
|
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
|
|
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
|
|
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
|
|
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
|
|
obj = self._memobj
|
|
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"]
|
|
NEEDS_COMPAT_SERIAL = False
|
|
TESTME = False
|