Project

General

Profile

New Model #7223 » kguv980p beta 2.4.py

KG-UV980P CHIRP Driver Beta 2.4 - Release Candidate - Mel Terechenok, 11/29/2022 10:24 PM

 
1
# melvin.terechenok@gmail.com
2
# modify for KG-UV980P using KG-935G, KG-UV8H, KG-UV920P drivers as resources
3

    
4
# Copyright 2019 Pavel Milanes CO7WT <pavelmc@gmail.com>
5
#
6
# Based on the work of Krystian Struzik <toner_82@tlen.pl>
7
# who figured out the crypt used and made possible the
8
# Wuoxun KG-UV8D Plus driver, in which this work is based.
9
#
10
# This program is free software: you can redistribute it and/or modify
11
# it under the terms of the GNU General Public License as published by
12
# the Free Software Foundation, either version 3 of the License, or
13
# (at your option) any later version.
14
#
15
# This program is distributed in the hope that it will be useful,
16
# but WITHOUT ANY WARRANTY; without even the implied warranty of
17
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18
# GNU General Public License for more details.
19
#
20
# You should have received a copy of the GNU General Public License
21
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
22

    
23
"""Wouxun KG-UV980P radio management module"""
24

    
25
from pickle import FALSE, TRUE
26
import time
27
import os
28
import logging
29

    
30
from chirp import util, chirp_common, bitwise, memmap, errors, directory
31
from chirp.settings import RadioSetting, RadioSettingGroup, \
32
    RadioSettingValueBoolean, RadioSettingValueList, \
33
    RadioSettingValueInteger, RadioSettingValueString, \
34
    RadioSettingValueFloat, RadioSettingValueMap, RadioSettings
35

    
36

    
37
LOG = logging.getLogger(__name__)
38

    
39
CMD_ID = 128    # \x80
40
CMD_END = 129   # \x81
41
CMD_RD = 130    # \x82
42
CMD_WR = 131    # \x83
43

    
44
# This is used to write the configuration of the radio base on info
45
# gleaned from the downloaded app. There are empty spaces and we honor
46
# them because we don't know what they are (yet) although we read the
47
# whole of memory.
48

    
49
config_map = (          # map address, write size, write count
50
    (0x4c,  12, 1),    # Mode PSW --  Display name
51
    (0x60,  44, 1),    # Freq Limits
52
    (0x740,  40, 1),    # FM chan 1-20
53
    (0x830,  16, 13),    # General settings
54
    (0x900, 8, 1),       # General settings
55
    (0x940,  64, 2),    # Scan groups and names
56
    (0xa00,  64, 249),  # Memory Channels 1-996
57
    (0x4840, 48, 1),    # Memory Channels 997-999
58
    (0x4900, 64, 124),  # Memory Names    1-992
59
    (0x6800, 8, 7),    # Memory Names    997-999
60
    (0x7000, 64, 15),    # mem valid 1 -960
61
    (0x73c0, 39, 1),    # mem valid 961 - 999
62
    )
63

    
64

    
65
MEM_VALID = 0x00
66
TX_BLANK = 0x40
67
RX_BLANK = 0x80
68

    
69
CHARSET_NUMERIC = "0123456789"
70
CHARSET = "0123456789" + \
71
          ":;<=>?@" + \
72
          "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + \
73
          "[\]^_`" + \
74
          "abcdefghijklmnopqrstuvwxyz" + \
75
          "{|}~\x4E" + \
76
          " !\"#$%&'()*+,-./"
77

    
78
SCANNAME_CHARSET = "0123456789" + \
79
          ":;<=>?@" + \
80
          "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + \
81
          "[\]^_`" + \
82
          "abcdefghijklmnopqrstuvwxyz" + \
83
          "{|}~\x4E" + \
84
          " !\"#$%&'()*+,-./"
85

    
86
MUTE_MODE_MAP = [('QT',      0b01),
87
                 ('QT*DTMF', 0b10),
88
                 ('QT+DTMF', 0b11)]
89
STEPS = [2.5, 5.0, 6.25, 10.0, 12.5, 20.0, 25.0, 30.0, 50.0, 100.0]
90
STEP_LIST = [str(x) for x in STEPS]
91
SQL_LIST = [int(i) for i in range(0, 10)]
92
M_POWER_MAP = [('1 = 20W', 1),
93
               ('2 = 10W', 2)]
94
ROGER_LIST = ["Off", "BOT", "EOT", "Both"]
95
VOICE_LIST = ["Off", "Chinese", "English"]
96
SC_REV_MAP = [('Timeout (TO)',  1),
97
              ('Carrier (CO)',  2),
98
              ('Stop (SE)',     3)]
99
TOT_MAP = [('%d min' % i, int('%02d' % i, 10)) for i in range(1, 61)]
100
TOA_LIST = ["Off", "1s", "2s", "3s", "4s", "5s", "6s", "7s", "8s", "9s", "10s"]
101
RING_LIST = ["Off", "1s", "2s", "3s", "4s", "5s", "6s", "7s",
102
             "8s", "9s", "10s"]
103
DTMF_ST_LIST = ["Off", "DT-ST", "ANI-ST", "DT+ANI"]
104
PTT_ID_LIST = ["BOT", "EOT", "Both"]
105
PTT_ID_MAP = [('BOT',  1),
106
              ('EOT',  2),
107
              ('Both', 3)]
108
BACKLIGHT_LIST = ["Off", "Red", "Orange", "Green"]
109
SPEAKER_MAP = [('SPK_1',   1),
110
               ('SPK_2',   2),
111
               ('SPK_1+2', 3)]
112
RPT_MODE_LIST = ["Radio", "X-DIRPT", "X-TWRPT", "RPT-RX", "T-W RPT"]
113
APO_TIME_LIST = ["Off", "30", "60", "90", "120", "150"]
114
ALERT_MAP = [('1750', 1),
115
             ('2100', 2),
116
             ('1000', 3),
117
             ('1450', 4)]
118
FAN_MODE_LIST = ["TX", "Hi-Temp/TX", "Always"]
119
SCAN_GROUP_LIST = ["All"] + ["%s" % x for x in range(1, 11)]
120
WORKMODE_MAP = [('VFO',             1),
121
                ('Ch. No.',         2),
122
                ('Ch. No.+Freq.',   3),
123
                ('Ch. No.+Name',    4)]
124
VFOBAND_MAP = [("150M", 0),
125
               ("450M", 1),
126
               ("20M", 2),
127
               ("50M", 3),
128
               ("350M", 4),
129
               ("850M", 5)]
130
AB_LIST = ["A", "B"]
131
POWER_MAP = [('Low', 0),
132
             ('Med', 1),
133
             ('Med2', 2),
134
             ('High', 3)]
135
BANDWIDTH_MAP = [('Narrow', 1),
136
                 ('Wide',  0)]
137
SCRAMBLER_LIST = ["Off", "1", "2", "3", "4", "5", "6", "7", "8"]
138
ANS_LIST = ["Off", "Normal", "Strong"]
139
DTMF_TIMES = [str(x) for x in range(80, 501, 20)]
140
DTMF_INTERVALS = [str(x) for x in range(60, 501, 20)]
141
ROGER_TIMES = [str(x) for x in range(20, 1001, 20)]
142
PTT_ID_DELAY_MAP = [(str(x), x/100) for x in range(100, 1001, 100)]
143
ROGER_INTERVALS = ROGER_TIMES
144
TONE_MAP = [('Off', 0x0000)] + \
145
           [('%.1f' % tone, int(tone * 10)) for tone in chirp_common.TONES] + \
146
           [('DN%d' % tone, int(0x8000 + tone))
147
               for tone in chirp_common.DTCS_CODES] + \
148
           [('DI%d' % tone, int(0xC000 + tone))
149
               for tone in chirp_common.DTCS_CODES]
150
DUPLEX_LIST = ["Off", "Plus", "Minus"]
151
SC_QT_MAP = [("Decoder - Rx QT/DT MEM", 1), ("Encoder- Tx QT/DT MEM", 2),
152
             ("All- RxTx QT/DT MEM", 3)]
153
HOLD_TIMES = ["Off"] + ["%s" % x for x in range(100, 5001, 100)]
154
PF1_SETTINGS = ["Off", "Stun", "Kill", "Monitor", "Inspection"]
155
ABR_LIST = ["Always", "1", "2", "3", "4", "5", "6", "7", "8",
156
            "9", "10", "11", "12", "13", "14", "15", "16", "17",
157
            "18", "19", "20", "Off"]
158
KEY_LIST = ["Off", "B/SW", "MENCH", "H-M-L", "VFO/MR", "SET-D", "TDR",
159
            "SQL", "SCAN", "FM-Radio", "Scan CTCSS", "Scan DCS"]
160
RC_POWER_LIST = ["RC Stop", "RC Open"]
161
ACTIVE_AREA_LIST = ["Area A - Left", "Area B - Right"]
162
TDR_LIST = ["TDR ON", "TDR OFF"]
163

    
164

    
165
# memory slot 0 is not used, start at 1 (so need 1000 slots, not 999)
166
# structure elements whose name starts with x are currently unidentified
167

    
168
_MEM_FORMAT = """
169
    #seekto 0x004c;
170
    struct {
171
        u24 mode_psw;
172
        u8  xunk04F;
173
        u8  display_name[8];
174
    } oem;
175

    
176
    #seekto 0x0060;
177
    struct {
178
        u16    limit_144M_ChA_rx_start;
179
        u16    limit_144M_ChA_rx_stop;
180
        u16    limit_70cm_rx_start;
181
        u16    limit_70cm_rx_stop;
182
        u16    limit_10m_rx_start;
183
        u16    limit_10m_rx_stop;
184
        u16    limit_6m_rx_start;
185
        u16    limit_6m_rx_stop;
186
        u16    limit_350M_rx_start;
187
        u16    limit_350M_rx_stop;
188
        u16    limit_850M_rx_start;
189
        u16    limit_850M_rx_stop;
190
        u16    limit_144M_ChA_tx_start;
191
        u16    limit_144M_ChA_tx_stop;
192
        u16    limit_70cm_tx_start;
193
        u16    limit_70cm_tx_stop;
194
        u16    limit_10m_tx_start;
195
        u16    limit_10m_tx_stop;
196
        u16    limit_6m_tx_start;
197
        u16    limit_6m_tx_stop;
198
        u16    limit_144M_ChB_rx_start;
199
        u16    limit_144M_ChB_rx_stop;
200
    } bandlimits;
201

    
202

    
203
    #seekto 0x0740;
204
    struct {
205
        u16    FM_radio1;
206
        u16    FM_radio2;
207
        u16    FM_radio3;
208
        u16    FM_radio4;
209
        u16    FM_radio5;
210
        u16    FM_radio6;
211
        u16    FM_radio7;
212
        u16    FM_radio8;
213
        u16    FM_radio9;
214
        u16    FM_radio10;
215
        u16    FM_radio11;
216
        u16    FM_radio12;
217
        u16    FM_radio13;
218
        u16    FM_radio14;
219
        u16    FM_radio15;
220
        u16    FM_radio16;
221
        u16    FM_radio17;
222
        u16    FM_radio18;
223
        u16    FM_radio19;
224
        u16    FM_radio20;
225
        u16    FM_radio21;
226
        u16    FM_radio22;
227
        u8  x76c_pad[196];
228
        u32  vfofreq1;     // 0x0830
229
        u32  vfoofst1;
230
        u16  txtone1;
231
        u16  rxtone1;
232
        u8  xunk83C_1:3,
233
            mute1:2,
234
            xunk83C_2:3;
235
        u8  xunk83d_1:1,
236
            xunk83d_2:1,
237
            xunk83d_3:1,
238
            power1:2,
239
            am_mode1:1,
240
            xunk83d_7:1,
241
            narrow1:1;
242
        u8  xunk83e:6,
243
            shft_dir1:2;
244
        u8  xunk83F:3,
245
            compander1:1,
246
            scrambler1:4;
247
        u32  vfofreq2;
248
        u32  vfoofst2;
249
        u16  txtone2;
250
        u16  rxtone2;
251
        u8  xunk84C_1:3,
252
            mute2:2,
253
            xunk84C_2:3;
254
        u8  xunk84d_1:1,
255
            xunk84d_2:1,
256
            xunk84d_3:1,
257
            power2:2,
258
            am_mode2:1,
259
            xunk84d_7:1,
260
            narrow2:1;
261
        u8  xunk84e:6,
262
            shft_dir2:2;
263
        u8  xunk84F:3,
264
            compander2:1,
265
            scrambler2:4;
266
        u32  vfofreq3;
267
        u32  vfoofst3;
268
        u16  txtone3;
269
        u16  rxtone3;
270
        u8  xunk85C_1:3,
271
            mute3:2,
272
            xunk85C_2:3;
273
        u8  xunk85d_1:1,
274
            xunk85d_2:1,
275
            xunk85d_3:1,
276
            power3:2,
277
            am_mode3:1,
278
            xunk85d_7:1,
279
            narrow3:1;
280
        u8  xunk85e:6,
281
            shft_dir3:2;
282
        u8  xunk85F:3,
283
            compander3:1,
284
            scrambler3:4;
285
        u32  vfofreq4;
286
        u32  vfoofst4;
287
        u16  txtone4;
288
        u16  rxtone4;
289
        u8  xunk86C_1:3,
290
            mute4:2,
291
            xunk86C_2:3;
292
        u8  xunk86d_1:1,
293
            xunk86d_2:1,
294
            xunk86d_3:1,
295
            power4:2,
296
            am_mode4:1,
297
            xunk86d_7:1,
298
            narrow4:1;
299
        u8  xunk86e:6,
300
            shft_dir4:2;
301
        u8  xunk86F:3,
302
            compander4:1,
303
            scrambler4:4;
304
        u32  vfofreq5;
305
        u32  vfoofst5;
306
        u16  txtone5;
307
        u16  rxtone5;
308
        u8  xunk87C_1:3,
309
            mute5:2,
310
            xunk87C_2:3;
311
        u8  xunk87d_1:1,
312
            xunk87d_2:1,
313
            xunk87d_3:1,
314
            power5:2,
315
            am_mode5:1,
316
            xunk87d_7:1,
317
            narrow5:1;
318
        u8  xunk87e:6,
319
            shft_dir5:2;
320
        u8  xunk87F:3,
321
            compander5:1,
322
            scrambler5:4;
323
        u32  vfofreq6;
324
        u32  vfoofst6;
325
        u16  txtone6;
326
        u16  rxtone6;
327
        u8  xunk88C_1:3,
328
            mute6:2,
329
            xunk88C_2:3;
330
        u8  xunk88d_1:1,
331
            xunk88d_2:1,
332
            xunk88d_3:1,
333
            power6:2,
334
            am_mode6:1,
335
            xunk88d_7:1,
336
            narrow6:1;
337
        u8  xunk88e:6,
338
            shft_dir6:2;
339
        u8  xunk8F:3,
340
            compander6:1,
341
            scrambler6:4;
342
        u32  vfofreq7;
343
        u32  vfoofst7;
344
        u16  txtone7;
345
        u16  rxtone7;
346
        u8  xunk89C_1:3,
347
            mute7:2,
348
            xunk89C_2:3;
349
        u8  xunk89d_1:1,
350
            xunk89d_2:1,
351
            xunk89d_3:1,
352
            power7:2,
353
            am_mode7:1,
354
            xunk89d_7:1,
355
            narrow7:1;
356
        u8  xunk89e:6,
357
            shft_dir7:2;
358
        u8  xunk89F:3,
359
            compander7:1,
360
            scrambler7:4;
361
        u8  x8a0;
362
        u16  vfochan_a;
363
        u8  x8a3;
364
        u16  vfochan_b;
365
        u16  pri_ch;
366
        u8  x8a8;
367
        u8  x8a9;
368
        u8  scan_a_act;
369
        u8  scan_b_act;
370
        u8  m_pwr;
371
        u8  hold_time_rpt;
372
        u8  spk_cont;
373
        u8  x8af;
374
        u8  rc_power;
375
        u8  voice;
376
        u8  tot;
377
        u8  toa;
378
        u8  roger;
379
        u8  sc_rev;
380
        u8  dtmfsf;
381
        u8  ptt_id;
382
        u8  ring;
383
        u8  ani_sw;
384
        u8  rc_sw;
385
        u8  alert;
386
        u8  bcl_a;
387
        u8  prich_sw;
388
        u8  x8bE;
389
        u8  ptt_id_dly;
390
        u8  menu;
391
        u8  x8c1;
392
        u8  beep;
393
        u8  x8c3;
394
        u8  x8c4;
395
        u8  tx_led;
396
        u8  wt_led;
397
        u8  rx_led;
398
        u8  act_area;
399
        u8  vfomode_a;
400
        u8  vfomode_b;
401
        u8  vfosquelch_a;
402
        u8  vfosquelch_b;
403
        u8  vfostep_a;
404
        u8  vfostep_b;
405
        u8  tdr_off;
406
        u8  rpt_spk;
407
        u8  rpt_ptt;
408
        u8  autolock;
409
        u8  apo_time;
410
        u8  low_v;
411
        u8  fan;
412
        u8  rpt_set_model;
413
        u8  pf1_set;
414
        u8  auto_am;
415
        u8  dtmf_time;
416
        u8  dtmf_int;
417
        u8  bcl_b;
418
        u8  rpt_tone;
419
        u8  sc_qt;
420
        u8  vfoband_a;
421
        u8  x8dF;
422
        u24  ani_edit;
423
        u8  x8e3;
424
        u24  mcc_edit;
425
        u8  x8e7;
426
        u24  scc_edit;
427
        u8  x8eB;
428
        u24  ctrl_edit;
429
        u8  x8eF;
430
        u8  KeyA;
431
        u8  KeyB;
432
        u8  KeyC;
433
        u8  ABR;
434
        u8  x8f4;
435
        u8  x8f5;
436
        u8  x8f6;
437
        u8  x8f7;
438
        u8  x8f8;
439
        u8  x8f9;
440
        u8  x8fA;
441
        u8  x8fB;
442
        u8  x8fC;
443
        u8  x8fD;
444
        u8  x8fE;
445
        u8  x8fF;
446
        u16  FM_radio_cur_freq;
447
        u8  x902;
448
        u8  scan_det;
449
        u8  x904;
450
        u8  thr_vol_tx;
451
        u16  thr_vol_lvl;
452
        u8  x908;
453
        u8  x909;
454
        u8  x90A;
455
        u8  x90B;
456
        u8  x90C;
457
        u8  x90D;
458
        u8  x90E;
459
        u8  x90F;
460
        u8  x910pad[48];
461
        u16  scanlower1; // x940
462
        u16  scanupper1;
463
        u16  scanlower2;
464
        u16  scanupper2;
465
        u16  scanlower3;
466
        u16  scanupper3;
467
        u16  scanlower4;
468
        u16  scanupper4;
469
        u16  scanlower5;
470
        u16  scanupper5;
471
        u16  scanlower6;
472
        u16  scanupper6;
473
        u16  scanlower7;
474
        u16  scanupper7;
475
        u16  scanlower8;
476
        u16  scanupper8;
477
        u16  scanlower9;
478
        u16  scanupper9;
479
        u16  scanlower10;
480
        u16  scanupper10;
481
        char  scanname0[8]; // x968
482
        char  scanname1[8];
483
        char  scanname2[8];
484
        char  scanname3[8];
485
        char  scanname4[8];
486
        char  scanname5[8];
487
        char  scanname6[8];
488
        char  scanname7[8];
489
        char  scanname8[8];
490
        char  scanname9[8];
491
        char  scanname10[8];
492
     } settings;
493

    
494

    
495
    #seekto 0x09f0;
496
    struct {
497
        u32     rxfreq;
498
        u32     txfreq;
499
        u16     txtone;
500
        u16     rxtone;
501
        u8      unknown1:3,
502
                mute_mode:2,
503
                unknown2:3;
504
        u8      named:1,
505
                scan_add:1,
506
                extra_power_bit:1,
507
                power:2,
508
                am_mode:1,
509
                unknownbit2:1,
510
                isnarrow:1;
511
        u8      unknown3:6,
512
                Unknown4_shft_dir:2;
513
        u8      unknown5:3,
514
                compander:1
515
                scrambler:4;
516
    } memory[1000];
517

    
518
    #seekto 0x48f8;
519
    struct {
520
        u8    name[8];
521
    } names[1000];
522

    
523
    #seekto 0x6fff;
524
    u8          valid[1000];
525
    """
526

    
527

    
528
def _freq_decode(in_freq, bytes=4):
529
    out_freq = 0
530
    for i in range(bytes*2):
531
        out_freq += (in_freq & 0xF) * (10 ** i)
532
        in_freq = in_freq >> 4
533
    if bytes == 4:
534
        return out_freq * 10
535
    elif bytes == 2:
536
        return out_freq * 100000
537

    
538

    
539
def _freq_encode(in_freq, bytes=4):
540
    if bytes == 4:
541
        return int('%08d' % (in_freq / 10), 16)
542
    elif bytes == 2:
543
        return int('%04d' % (in_freq / 100000), 16)
544

    
545

    
546
def _oem_str_decode(in_str):
547
    out_str = ''
548
    stopchar = FALSE
549
    for c in in_str:
550
        if c != 0x50 and stopchar == FALSE:
551
            if chr(c+48) in chirp_common.CHARSET_ASCII:
552
                out_str += chr(c+48)
553
        else:
554
            out_str += ''
555
            stopchar = TRUE
556
    return out_str
557

    
558

    
559
def _oem_str_encode(in_str):
560
    out_str = ''
561
    LOG.debug("OEM Input String = %s", in_str)
562
    for c in in_str:
563
        try:
564
            out_str += chr(int(ord(c))-48)
565
        except ValueError:
566
            pass
567
    while len(out_str) < 8:
568
        out_str += chr(0x50)
569
    LOG.debug("OEM Ouput String = %s", out_str)
570
    return out_str
571

    
572

    
573
def _str_decode(in_str):
574
    out_str = ''
575
    stopchar = FALSE
576
    for c in in_str:
577
        if c != 0x00 and stopchar == FALSE:
578
            if chr(c) in chirp_common.CHARSET_ASCII:
579
                out_str += chr(c)
580
        else:
581
            out_str += ''
582
            stopchar = TRUE
583
    return out_str
584

    
585

    
586
def _str_encode(in_str):
587
    out_str = ''
588
    for c in in_str:
589
        try:
590
            out_str += chr(ord(c))
591
        except ValueError:
592
            pass
593
    while len(out_str) < 8:
594
        out_str += chr(0x00)
595
    if out_str == "        " or out_str == "":
596
        out_str = "\x00\x00\x00\x00\x00\x00\x00\x00"
597
    return out_str
598

    
599

    
600
def _chnum_decode(in_ch):
601
    return int(('%04x' % in_ch)[0:3])
602

    
603

    
604
def _chnum_encode(in_ch):
605
    return int('%03d0' % in_ch, 16)
606

    
607
# Support for the Wouxun KG-UV980P radio
608
# Serial coms are at 19200 baud
609
# The data is passed in variable length records
610
# Record structure:
611
#  Offset   Usage
612
#    0      start of record (\x7c)
613
#    1      Command (\x80 Identify \x81 End/Reboot \x82 Read \x83 Write)
614
#    2      direction (\xff PC-> Radio, \x00 Radio -> PC)
615
#    3      length of payload (excluding header/checksum) (n)
616
#    4      payload (n bytes)
617
#    4+n+1  checksum - only lower 4 bits of byte sum (% 256) of bytes 1 -> 4+n
618
#
619
# Memory Read Records:
620
# the payload is 3 bytes, first 2 are offset (big endian),
621
# 3rd is number of bytes to read
622
# Memory Write Records:
623
# the maximum payload size (from the Wouxun software) seems to be 66 bytes
624
#  (2 bytes location + 64 bytes data).
625

    
626

    
627
class KGUV8TRadio(chirp_common.Alias):
628
    VENDOR = "Wouxun"
629
    MODEL = "KG-UV980P"
630

    
631

    
632
@directory.register
633
class KG980GRadio(chirp_common.CloneModeRadio,
634
                  chirp_common.ExperimentalRadio):
635

    
636
    """Wouxun KG-UV980P"""
637
    VENDOR = "Wouxun"
638
    MODEL = "KG-UV980P"
639
    _model = "KG-UV950R2"
640
    _file_ident = "980P"
641
    BAUD_RATE = 19200
642

    
643
    POWER_LEVELS = [chirp_common.PowerLevel("L", watts=1.0),
644
                    chirp_common.PowerLevel("M", watts=20.0),
645
                    chirp_common.PowerLevel("H", watts=50.0)]
646
    _mmap = ""
647
    ALIASES = [KGUV8TRadio, ]
648

    
649
    def _checksum(self, data):
650
        cs = 0
651
        for byte in data:
652
            cs += ord(byte)
653
        return chr(cs % 256)
654

    
655
    # def _write_record_id(self):
656
    # _header = '\xda\x80\xff\x00\x58'
657
    #     LOG.error("Sent:\n%s" % util.hexprint(_header))
658
    # self.pipe.write(_header)
659

    
660
    def _write_record(self, cmd, payload=None):
661
        # build the packet
662
        _header = '\xda' + chr(cmd) + '\xff'
663

    
664
        _length = 0
665
        if payload:
666
            _length = len(payload)
667

    
668
        # update the length field
669
        _header += chr(_length)
670

    
671
        if payload:
672
            # calculate checksum then add it with the payload
673
            # to the packet and encrypt
674
            crc = self._checksum(_header[1:] + payload)
675
            # Checksum is only the lower 4 bits
676
            crc = chr(ord(crc) & 0xf)
677
            payload += crc
678
            _header += self.encrypt(payload)
679
        else:
680
            # calculate and add encrypted checksum to the packet
681
            crc = self._checksum(_header[1:])
682
            # Checksum is only the lower 4 bits
683
            crc = chr(ord(crc) & 0xf)
684
            _header += self.strxor(crc, '\x57')
685

    
686
        try:
687
            LOG.debug("Sent:\n%s" % util.hexprint(_header))
688
            self.pipe.write(_header)
689
        except Exception, e:
690
            raise errors.RadioError("Failed to communicate with radio: %s" % e)
691

    
692
    def _read_record(self):
693
        # read 4 chars for the header
694
        _header = self.pipe.read(4)
695
        # LOG.debug("header = " % util.hexprint(_header))
696
        if len(_header) != 4:
697
            raise errors.RadioError('Radio did not respond- header length')
698
        _length = ord(_header[3])
699
        _packet = self.pipe.read(_length)
700
        _rcs_xor = _packet[-1]
701
        _packet = self.decrypt(_packet)
702
        _cs = ord(self._checksum(_header[1:] + _packet))
703
        # It appears the checksum is only 4bits
704
        _cs = _cs & 0xf
705
        # read the checksum and decrypt it
706
        _rcs = ord(self.strxor(self.pipe.read(1), _rcs_xor))
707
        _rcs = _rcs & 0xf
708
        return (_rcs != _cs, _packet)
709

    
710
    def decrypt(self, data):
711
        result = ''
712
        for i in range(len(data)-1, 0, -1):
713
            result += self.strxor(data[i], data[i - 1])
714
        result += self.strxor(data[0], '\x57')
715
        return result[::-1]
716

    
717
    def encrypt(self, data):
718
        result = self.strxor('\x57', data[0])
719
        for i in range(1, len(data), 1):
720
            result += self.strxor(result[i - 1], data[i])
721
        return result
722

    
723
    def strxor(self, xora, xorb):
724
        return chr(ord(xora) ^ ord(xorb))
725

    
726
    # Identify the radio
727
    #
728
    # A Gotcha: the first identify packet returns a bad checksum, subsequent
729
    # attempts return the correct checksum... (well it does on my radio!)
730
    #
731
    # The ID record returned by the radio also includes the
732
    # current frequency range
733
    # as 4 bytes big-endian in 10Hz increments
734
    #
735
    # Offset
736
    #  0:10     Model, zero padded
737

    
738
    @classmethod
739
    def match_model(cls, filedata, filename):
740
        id = cls._file_ident
741
        return cls._file_ident in filedata[0x426:0x430]
742

    
743
    def _identify(self):
744
        """Do the identification dance"""
745
        for _i in range(0, 3):
746
            LOG.debug("ID try #"+str(_i))
747
            self._write_record(CMD_ID)
748
            _chksum_err, _resp = self._read_record()
749
            if len(_resp) == 0:
750
                raise Exception("Radio not responding")
751
            else:
752
                LOG.debug("Got:\n%s" % util.hexprint(_resp))
753
                LOG.debug("Model received is %s" % _resp[0:10])
754
                LOG.debug("Model expected is %s" % self._model)
755
                if _chksum_err:
756
                    LOG.error("Checksum error: retrying ident...")
757
                    time.sleep(0.100)
758
                    continue
759
                else:
760
                    LOG.debug("checksum passed")
761
                    if _resp[0:8] == self._model[0:8]:
762
                        LOG.debug("Passed identify")
763
                        break
764
                    else:
765
                        LOG.debug("FAILED to identify")
766

    
767
    def _finish(self):
768
        self._write_record(CMD_END)
769

    
770
    def process_mmap(self):
771
        self._memobj = bitwise.parse(_MEM_FORMAT, self._mmap)
772

    
773
    def sync_in(self):
774
        try:
775
            self._mmap = self._download()
776
        except errors.RadioError:
777
            raise
778
        except Exception, e:
779
            raise errors.RadioError("Failed to communicate with radio: %s" % e)
780
        self.process_mmap()
781

    
782
    def sync_out(self):
783
        self._upload()
784

    
785
    # TODO: Load all memory.
786
    # It would be smarter to only load the active areas and none of
787
    # the padding/unused areas. Padding still need to be investigated.
788
    def _download(self):
789
        """Talk to a wouxun KG-UV980P and do a download"""
790
        try:
791
            self._identify()
792
            return self._do_download(0, 32768, 64)
793
        except errors.RadioError:
794
            raise
795
        except Exception, e:
796
            LOG.exception('Unknown error during download process')
797
            raise errors.RadioError("Failed to communicate with radio: %s" % e)
798

    
799
    def _do_download(self, start, end, blocksize):
800
        # allocate & fill memory
801
        LOG.debug("Start Download")
802
        image = ""
803
        for i in range(start, end, blocksize):
804
            req = chr(i / 256) + chr(i % 256) + chr(blocksize)
805
            self._write_record(CMD_RD, req)
806
            cs_error, resp = self._read_record()
807
            LOG.debug("Got:\n%s" % util.hexprint(resp))
808

    
809
            if cs_error:
810
                LOG.debug(util.hexprint(resp))
811
                raise Exception("Checksum error on read")
812
            # LOG.debug("Got:\n%s" % util.hexprint(resp))
813
            image += resp[2:]
814
            if self.status_fn:
815
                status = chirp_common.Status()
816
                status.cur = i
817
                status.max = end
818
                status.msg = "Cloning from radio"
819
                self.status_fn(status)
820
        self._finish()
821
        return memmap.MemoryMap(''.join(image))
822

    
823
    def _upload(self):
824
        """Talk to a wouxun KG-UV980P and do a upload"""
825
        try:
826
            self._identify()
827
            LOG.debug("Done with Upload Identify")
828
            # self._do_upload(0, 1856, 16)
829
            # LOG.debug("Done with Limits Upload")
830
            # self._do_upload(1856, 32768, 64)
831
            self._do_upload()
832
            LOG.debug("Done with Mem and Settings Upload")
833
            self._finish()
834
        except errors.RadioError:
835
            raise
836
        except Exception, e:
837
            raise errors.RadioError("Failed to communicate with radio: %s" % e)
838
        return
839

    
840
    def _do_upload(self):
841
        LOG.debug("Start of _do_upload")
842
        for ar, size, count in config_map:
843
            for addr in range(ar, ar + (size*count), size):
844
                start = ar
845
                ptr = start
846
                LOG.debug("ptr = " + str(ptr))
847
                end = ar + (size*count)
848
                blocksize = size
849
                LOG.debug("Start of loop in _do_upload index = "+str(addr))
850
                LOG.debug("Start %i End %i Size %i" % (start, end, blocksize))
851
                req = chr(addr / 256) + chr(addr % 256)
852
                LOG.debug("REQ")
853
                chunk = self.get_mmap()[addr:addr + blocksize]
854
                LOG.debug("CHUNK")
855
                self._write_record(CMD_WR, req + chunk)
856
    #            LOG.debug("Upload-- SENT : " % util.hexprint(_sent))
857
                cserr, ack = self._read_record()
858
                LOG.debug("Upload-- CSUM ERROR : " + str(cserr))
859
                LOG.debug("Upload-- RCVD :\n%s " % util.hexprint(ack))
860

    
861
                j = ord(ack[0]) * 256 + ord(ack[1])
862
                LOG.debug("j = " + str(j))
863
                LOG.debug("addr= " + str(addr))
864

    
865
                if cserr or j != addr:
866
                    raise Exception("Radio did not ack block %i" % addr)
867
                # ptr += blocksize
868
                if self.status_fn:
869
                    status = chirp_common.Status()
870
                    status.cur = addr
871
                    status.max = 0x73e7
872
                    status.msg = "Cloning to radio"
873
                    self.status_fn(status)
874
        # self._finish()
875

    
876
    def get_features(self):
877
        rf = chirp_common.RadioFeatures()
878
        rf.has_settings = True
879
        rf.has_ctone = True
880
        rf.has_rx_dtcs = True
881
        rf.has_cross = True
882
        rf.has_tuning_step = False
883
        rf.has_bank = False
884
        rf.can_odd_split = True
885
        rf.valid_skips = ["", "S"]
886
        rf.valid_tmodes = ["", "Tone", "TSQL", "DTCS", "Cross"]
887
        rf.valid_cross_modes = [
888
            "Tone->Tone",
889
            "Tone->DTCS",
890
            "DTCS->Tone",
891
            "DTCS->",
892
            "->Tone",
893
            "->DTCS",
894
            "DTCS->DTCS",
895
        ]
896
        rf.valid_modes = ["FM", "NFM", "AM", "NAM"]
897
        rf.valid_power_levels = self.POWER_LEVELS
898
        rf.valid_name_length = 8
899
        rf.valid_duplexes = ["", "-", "+", "split", "off"]
900
#   MRT - Open up channel memory freq range to support RxFreq limit expansion
901
        rf.valid_bands = [(26000000, 299999990),  # supports VHF
902
                          (300000000, 999999990)]  # supports UHF
903

    
904
        rf.valid_characters = chirp_common.CHARSET_ASCII
905
        rf.memory_bounds = (1, 999)  # 999 memories
906
        rf.valid_tuning_steps = STEPS
907
        return rf
908

    
909
    @classmethod
910
    def get_prompts(cls):
911
        rp = chirp_common.RadioPrompts()
912
        rp.experimental = \
913
            ('This driver is experimental and may contain bugs. \n'
914
             'USE AT YOUR OWN RISK  - '
915
             'SAVE A COPY OF DOWNLOAD FROM YOUR RADIO BEFORE MAKING CHANGES\n'
916
             '\nAll known CPS settings are implemented \n'
917
             '\n Additional settings found only on radio are also included'
918
             '\nMute, Compander and Scrambler are defaulted to '
919
             'QT, OFF , OFF for all channel memories\n'
920
             '\n'
921
             'Modification of Freq Limit Interfaces is done '
922
             'AT YOUR OWN RISK and '
923
             'may affect radio performance and may violate rules, '
924
             'regulations '
925
             'or laws in your jurisdiction.\n'
926
             )
927
        return rp
928

    
929
    def get_raw_memory(self, number):
930
        return repr(self._memobj.memory[number])
931
# MRT - corrected the Polarity decoding to match 980P implementation
932
# use 0x4000 bit mask for R
933
# MRT - 0x4000 appears to be the bit mask for Inverted DCS tones
934
# MRT - n DCS Tone will be 0x8xxx values - i DCS Tones will
935
# be 0xCxxx values.
936
# MRT - Chirp Uses N for n DCS Tones and R for i DCS Tones
937
# MRT - 980P encodes DCS tone # in decimal -  NOT OCTAL
938

    
939
    def _get_tone(self, _mem, mem):
940
        def _get_dcs(val):
941
            code = int("%03d" % (val & 0x07FF))
942
            pol = (val & 0x4000) and "R" or "N"
943
            return code, pol
944
# MRT - Modified the function below to bitwise AND with 0x4000
945
# to check for 980P DCS Tone decoding
946
# MRT 0x8000 appears to be the bit mask for DCS tones
947
        tpol = False
948
# MRT Beta 1.1 - Fix the txtone compare to 0x8000 - was rxtone.
949
        if _mem.txtone != 0xFFFF and (_mem.txtone & 0x8000) == 0x8000:
950
            tcode, tpol = _get_dcs(_mem.txtone)
951
            mem.dtcs = tcode
952
            txmode = "DTCS"
953
        elif _mem.txtone != 0xFFFF and _mem.txtone != 0x0:
954
            mem.rtone = (_mem.txtone & 0x7fff) / 10.0
955
            txmode = "Tone"
956
        else:
957
            txmode = ""
958
# MRT - Modified the function below to bitwise AND with 0x4000
959
# to check for 980P DCS Tone decoding
960
        rpol = False
961
        if _mem.rxtone != 0xFFFF and (_mem.rxtone & 0x8000) == 0x8000:
962
            rcode, rpol = _get_dcs(_mem.rxtone)
963
            mem.rx_dtcs = rcode
964
            rxmode = "DTCS"
965
        elif _mem.rxtone != 0xFFFF and _mem.rxtone != 0x0:
966
            mem.ctone = (_mem.rxtone & 0x7fff) / 10.0
967
            rxmode = "Tone"
968
        else:
969
            rxmode = ""
970

    
971
        if txmode == "Tone" and not rxmode:
972
            mem.tmode = "Tone"
973
        elif txmode == rxmode and txmode == "Tone" and mem.rtone == mem.ctone:
974
            mem.tmode = "TSQL"
975
        elif txmode == rxmode and txmode == "DTCS" and mem.dtcs == mem.rx_dtcs:
976
            mem.tmode = "DTCS"
977
        elif rxmode or txmode:
978
            mem.tmode = "Cross"
979
            mem.cross_mode = "%s->%s" % (txmode, rxmode)
980

    
981
        # always set it even if no dtcs is used
982
        mem.dtcs_polarity = "%s%s" % (tpol or "N", rpol or "N")
983

    
984
        LOG.debug("Got TX %s (%i) RX %s (%i)" %
985
                  (txmode, _mem.txtone, rxmode, _mem.rxtone))
986

    
987
    def get_memory(self, number):
988
        _mem = self._memobj.memory[number]
989
        _nam = self._memobj.names[number]
990

    
991
        mem = chirp_common.Memory()
992
        mem.number = number
993
        _valid = self._memobj.valid[mem.number]
994

    
995
        LOG.debug("Mem %d valid is %s", number, _valid == MEM_VALID)
996
        LOG.debug("Rx Freq %s", _mem.rxfreq)
997
        if (_valid != MEM_VALID) & ((_mem.rxfreq == 0xFFFFFFFF) or
998
                                    _mem.rxfreq == 0x00000000):
999
            mem.empty = True
1000
            _valid = 0xFF
1001
            return mem
1002
        elif (_valid != MEM_VALID) & ((_mem.rxfreq != 0xFFFFFFFF) and
1003
                                      (_mem.rxfreq != 0x00000000)):
1004
            LOG.debug("Changed chan %d %s", number, "to valid")
1005
            _valid = MEM_VALID
1006
            mem.empty = False
1007
        else:
1008
            _valid = MEM_VALID
1009
            mem.empty = False
1010
        mem.freq = int(_mem.rxfreq) * 10
1011
        _rxfreq = _freq_decode(_mem.rxfreq)
1012
        _txfreq = _freq_decode(_mem.txfreq)
1013
        mem.freq = _rxfreq
1014
        LOG.debug("Tx Freq is " + str(_mem.txfreq))
1015
        if _mem.txfreq == 0xFFFFFFFF:
1016
            # TX freq not set
1017
            mem.duplex = "off"
1018
            mem.offset = 0
1019
        elif int(_rxfreq) == int(_txfreq):
1020
            mem.duplex = ""
1021
            mem.offset = 0
1022
        elif abs(_rxfreq - _txfreq) > 70000000:
1023
            mem.duplex = "split"
1024
            mem.offset = _txfreq
1025
        else:
1026
            mem.duplex = _rxfreq > _txfreq and "-" or "+"
1027
            mem.offset = abs(_rxfreq - _txfreq)
1028

    
1029
        if _mem.named:
1030
            mem.name = _str_decode(self._memobj.names[number].name)
1031
        else:
1032
            mem.name = ''
1033

    
1034
        self._get_tone(_mem, mem)
1035

    
1036
        mem.skip = "" if bool(_mem.scan_add) else "S"
1037

    
1038
        LOG.debug("Mem Power " + str(_mem.power))
1039
        pwr_index = _mem.power
1040
        if _mem.power == 3:
1041
            pwr_index = 2
1042
            LOG.debug("Force Mem Power to" + str(pwr_index))
1043
        if _mem.power:
1044
            mem.power = self.POWER_LEVELS[pwr_index]
1045
        else:
1046
            mem.power = self.POWER_LEVELS[0]
1047

    
1048
        # mem.am_mode = _mem.power & 0x2
1049

    
1050
        # LOG.debug("Mem Power Index " + str(_mem.power))
1051
#        mem.power = self.POWER_LEVELS[_mem.power]
1052

    
1053
        if _mem.am_mode:
1054
            if _mem.isnarrow:
1055
                mem.mode = "NAM"
1056
            else:
1057
                mem.mode = "AM"
1058
        else:
1059
            mem.mode = _mem.isnarrow and "NFM" or "FM"
1060

    
1061
        mem.extra = RadioSettingGroup("Extra", "extra")
1062

    
1063
        _scram = _mem.scrambler
1064
        if _mem.scrambler > 8:
1065
            _scram = 0
1066
        # rs = RadioSetting("scrambler", "Scrambler",
1067
        #                   RadioSettingValueList(SCRAMBLER_LIST,
1068
        #                                         SCRAMBLER_LIST[_scram]))
1069
        # mem.extra.append(rs)
1070

    
1071
        # rs = RadioSetting("compander", "Compander",
1072
        #                   RadioSettingValueBoolean(_mem.compander))
1073
        # mem.extra.append(rs)
1074

    
1075
        # rs = RadioSetting("mute_mode", "Mute",
1076
        #                   RadioSettingValueMap(MUTE_MODE_MAP,
1077
        #                   _mem.mute_mode))
1078
        # mem.extra.append(rs)
1079

    
1080
        return mem
1081

    
1082
    def _set_tone(self, mem, _mem):
1083
        def _set_dcs(code, pol):
1084
            # MRT Change to 0x8000 to
1085
            # set the bit for DCS- code is a decimal version
1086
            # of the code # - NOT OCTAL
1087
            val = int("%i" % code, 10) | 0x8000
1088
            if pol == "R":
1089
                # MRT Change to 0x4000 to set the bit for
1090
                # i/R polarity
1091
                val += 0x4000
1092
            return val
1093

    
1094
        rx_mode = tx_mode = None
1095
        rxtone = txtone = 0x0000
1096

    
1097
        if mem.tmode == "Tone":
1098
            tx_mode = "Tone"
1099
            rx_mode = None
1100
            txtone = int(mem.rtone * 10)
1101
        elif mem.tmode == "TSQL":
1102
            rx_mode = tx_mode = "Tone"
1103
            rxtone = txtone = int(mem.ctone * 10)
1104
        elif mem.tmode == "DTCS":
1105
            tx_mode = rx_mode = "DTCS"
1106
            txtone = _set_dcs(mem.dtcs, mem.dtcs_polarity[0])
1107
            rxtone = _set_dcs(mem.dtcs, mem.dtcs_polarity[1])
1108
        elif mem.tmode == "Cross":
1109
            tx_mode, rx_mode = mem.cross_mode.split("->")
1110
            if tx_mode == "DTCS":
1111
                txtone = _set_dcs(mem.dtcs, mem.dtcs_polarity[0])
1112
            elif tx_mode == "Tone":
1113
                txtone = int(mem.rtone * 10)
1114
            if rx_mode == "DTCS":
1115
                rxtone = _set_dcs(mem.rx_dtcs, mem.dtcs_polarity[1])
1116
            elif rx_mode == "Tone":
1117
                rxtone = int(mem.ctone * 10)
1118

    
1119
        _mem.rxtone = rxtone
1120
        _mem.txtone = txtone
1121

    
1122
        LOG.debug("Set TX %s (%i) RX %s (%i)" %
1123
                  (tx_mode, _mem.txtone, rx_mode, _mem.rxtone))
1124

    
1125
    def set_memory(self, mem):
1126
        # _mem = Stored Memory value
1127
        # mem = New value from user entry
1128
        number = mem.number
1129
        _mem = self._memobj.memory[number]
1130
        _nam = self._memobj.names[number]
1131
        _valid = self._memobj.valid[mem.number]
1132

    
1133
        # if mem.empty:
1134
        #     _mem.set_raw("\x00" * (_mem.size() / 8))
1135
        #     self._memobj.valid[number] = 0
1136
        #     self._memobj.names[number].set_raw("\x00" * (_nam.size() / 8))
1137
        #     return
1138

    
1139
        if mem.empty:
1140
            LOG.debug("Mem %s is Empty", number)
1141
            self._memobj.valid[number] = 0xFF
1142
            LOG.debug("Set Mem %s Not Valid", number)
1143
            _mem.rxfreq = 0xFFFFFFFF
1144
            LOG.debug("Set Rx Freq = FFFFFFF")
1145
            _mem.txfreq = 0xFFFFFFFF
1146
            LOG.debug("Set Tx Freq = FFFFFFF")
1147
            self._memobj.names[number].set_raw("\xFF" * (_nam.size() / 8))
1148
            LOG.debug("Name %s Cleared", number)
1149
            # The following line is a hack to make CPS happy and not
1150
            # show memory entries that were deleted with CHIRP
1151
            # _mem=0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
1152
            # LOG.debug("Set _mem = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF")
1153
        else:
1154
            LOG.debug("Mem %s is NOT Empty", number)
1155
            if len(mem.name) > 0:
1156
                LOG.debug("new name = %s", (mem.name))
1157
                _mem.named = True
1158
                name_encoded = _str_encode(mem.name)
1159
                LOG.debug("name endcoded = %s", (name_encoded))
1160
                LOG.debug("number = %s", (number))
1161
                for i in range(0, 8):
1162
                    _nam.name[i] = ord(name_encoded[i])
1163
            else:
1164
                _mem.named = False
1165

    
1166
            _mem.rxfreq = _freq_encode(mem.freq)
1167
            if mem.duplex == "off":
1168
                _mem.txfreq = 0xFFFFFFFF
1169
            elif mem.duplex == "split":
1170
                _mem.txfreq = _freq_encode(mem.offset)
1171
            elif mem.duplex == "+":
1172
                _mem.txfreq = _freq_encode(mem.freq + mem.offset)
1173
            elif mem.duplex == "-":
1174
                _mem.txfreq = _freq_encode(mem.freq - mem.offset)
1175
            else:
1176
                _mem.txfreq = _freq_encode(mem.freq)
1177

    
1178
            _mem.scan_add = int(mem.skip != "S")
1179

    
1180
            if mem.mode == "AM":
1181
                _mem.am_mode = True
1182
                _mem.isnarrow = False
1183
            elif mem.mode == "NAM":
1184
                _mem.am_mode = True
1185
                _mem.isnarrow = True
1186
            else:
1187
                _mem.am_mode = False
1188
                if mem.mode == "NFM":
1189
                    _mem.isnarrow = True
1190
                else:
1191
                    _mem.isnarrow = False
1192

    
1193
            # set the tone
1194
            self._set_tone(mem, _mem)
1195
            # MRT set the scrambler and compander to off by default
1196
            # MRT This changes them in the channel memory
1197
            _mem.scrambler = 0
1198
            _mem.compander = 0
1199
            # set the power
1200
            if mem.power:
1201
                _mem.power = self.POWER_LEVELS.index(mem.power)
1202
            else:
1203
                _mem.power = True
1204
            LOG.debug("Set mem.power = %s" % mem.power)
1205
            # pwr_index= mem.power
1206
            # LOG.debug("pwr index = " + str(pwr_index))
1207
            if str(mem.power) == "None":
1208
                mem.power = self.POWER_LEVELS[1]
1209
            index = self.POWER_LEVELS.index(mem.power)
1210
            LOG.debug("index = %i", (index))
1211
            if index == 2:
1212
                _mem.power = 0b11
1213
            else:
1214
                _mem.power = self.POWER_LEVELS.index(mem.power)
1215
            # Not sure what this bit does yet but it causes
1216
            # the radio to display
1217
            # MED power when the CPS shows Low Power.
1218
            # Forcing it to 0 to keep them
1219
            # consistent
1220
            _mem.extra_power_bit = 0
1221
            # Set other unknowns to 0 to match default CPS values
1222
            _mem.unknown1 = 0
1223
            _mem.unknown2 = 0
1224
            _mem.unknownbit2 = 0
1225
            _mem.unknown3 = 0
1226
            _mem.Unknown4_shft_dir = 0
1227
            _mem.unknown5 = 0
1228

    
1229
            # if mem.power:
1230
            #     _mem.power = self.POWER_LEVELS.index[mem.power]
1231
            # else:
1232
            #     _mem.power = True
1233

    
1234
            # MRT set to mute mode to QT (not QT+DTMF or QT*DTMF) by default
1235
            # MRT This changes them in the channel memory
1236
            _mem.mute_mode = 1
1237

    
1238
    def _get_settings(self):
1239
        _settings = self._memobj.settings
1240
        _limits = self._memobj.bandlimits
1241
        _oem = self._memobj.oem
1242
#        _vfoa = self._memobj.vfoa
1243
#        _vfob = self._memobj.vfob
1244
#        _scan = self._memobj.scan_groups
1245
#        _call = self._memobj.call_groups
1246
#        _callname = self._memobj.call_names
1247
#        _fmpreset = self._memobj.fm_preset
1248

    
1249
        cfg_grp = RadioSettingGroup("cfg_grp", "Config Settings")
1250
        cfg1_grp = RadioSettingGroup("cfg1_grp", "Config Settings 1")
1251
        cfg2_grp = RadioSettingGroup("cfg2_grp", "Config Settings 2")
1252
        vfoa_grp = RadioSettingGroup("vfoa_grp", "VFO A Settings")
1253
        vfo150_grp = RadioSettingGroup("vfo150_grp", "150M Settings")
1254
        vfo450_grp = RadioSettingGroup("vfo450_grp", "450M Settings")
1255
        vfo20_grp = RadioSettingGroup("vfo20_grp", "20M Settings")
1256
        vfo50_grp = RadioSettingGroup("vfo50_grp", "50M Settings")
1257
        vfo350_grp = RadioSettingGroup("vfo350_grp", "350M Settings")
1258
        vfo850_grp = RadioSettingGroup("vfo850_grp", "850M Settings")
1259
        vfoabands_grp = RadioSettingGroup(
1260
                            "vfoabands_grp", "VFO A Band Settings")
1261
        vfob_grp = RadioSettingGroup("vfob_grp", "VFO B Settings")
1262
        key_grp = RadioSettingGroup("key_grp", "Key Settings")
1263
        fmradio_grp = RadioSettingGroup("fmradio_grp", "FM Broadcast Memory")
1264
        lmt_grp = RadioSettingGroup("lmt_grp", "Frequency Limits")
1265
        lmwrn_grp = RadioSettingGroup("lmwrn_grp", "USE AT YOUR OWN RISK")
1266
        rxlim_grp = RadioSettingGroup("rxlim_grp", "Rx Limits")
1267
        txlim_grp = RadioSettingGroup("txlim_grp", "Tx Limits")
1268
        uhf_lmt_grp = RadioSettingGroup("uhf_lmt_grp", "UHF")
1269
        vhf_lmt_grp = RadioSettingGroup("vhf_lmt_grp", "VHF")
1270
        oem_grp = RadioSettingGroup("oem_grp", "OEM Info")
1271
        scan_grp = RadioSettingGroup("scan_grp", "Scan Group")
1272
        scanname_grp = RadioSettingGroup("scanname_grp", "Scan Names")
1273
        call_grp = RadioSettingGroup("call_grp", "Call Settings")
1274
        remote_grp = RadioSettingGroup("remote_grp", "Remote Settings")
1275
        extra_grp = RadioSettingGroup("extra_grp",
1276
                                      "Extra Settings"
1277
                                      "\nNOT Changed by RESET or CPS")
1278
        vfo_grp = RadioSettingGroup("vfo_grp",
1279
                                    "VFO Settings")
1280
        memxtras_grp = RadioSettingGroup("memxtras_grp", "Memory Extras")
1281
        extra_grp.append(oem_grp)
1282
        cfg_grp.append(cfg1_grp)
1283
        cfg_grp.append(cfg2_grp)
1284
        lmt_grp.append(lmwrn_grp)
1285
        lmt_grp.append(rxlim_grp)
1286
        lmt_grp.append(txlim_grp)
1287
        extra_grp.append(lmt_grp)
1288
        vfo_grp.append(vfoa_grp)
1289
        vfo_grp.append(vfob_grp)
1290
        vfoa_grp.append(vfo150_grp)
1291
        vfoa_grp.append(vfo450_grp)
1292
        vfoa_grp.append(vfo20_grp)
1293
        vfoa_grp.append(vfo50_grp)
1294
        vfoa_grp.append(vfo350_grp)
1295
        vfoa_grp.append(vfo850_grp)
1296
        scan_grp.append(scanname_grp)
1297

    
1298
        group = RadioSettings(cfg_grp, vfo_grp, fmradio_grp,
1299
                              remote_grp, scan_grp, extra_grp)
1300

    
1301
# Memory extras
1302
        # rs = RadioSetting("_mem.mute_mode", "Mute Mode"+str(number),
1303
        #                   RadioSettingValueBoolean(_mem.mute_mode))
1304
        # memxtras_grp.append(rs)
1305

    
1306
# Configuration Settings
1307

    
1308
        rs = RadioSetting("roger", "Roger Beep",
1309
                          RadioSettingValueList(ROGER_LIST,
1310
                                                ROGER_LIST[_settings.
1311
                                                           roger]))
1312
        cfg1_grp.append(rs)
1313

    
1314
        rs = RadioSetting("beep", "Keypad Beep",
1315
                          RadioSettingValueBoolean(_settings.beep))
1316
        cfg1_grp.append(rs)
1317

    
1318
        rs = RadioSetting("voice", "Voice Guide",
1319
                          RadioSettingValueBoolean(_settings.voice))
1320
        cfg1_grp.append(rs)
1321

    
1322
        rs = RadioSetting("bcl_a", "Busy Channel Lock-out A",
1323
                          RadioSettingValueBoolean(_settings.bcl_a))
1324
        cfg1_grp.append(rs)
1325

    
1326
        rs = RadioSetting("bcl_b", "Busy Channel Lock-out B",
1327
                          RadioSettingValueBoolean(_settings.bcl_b))
1328
        cfg1_grp.append(rs)
1329

    
1330
        rs = RadioSetting("sc_rev", "Scan Mode",
1331
                          RadioSettingValueMap(SC_REV_MAP, _settings.sc_rev))
1332
        cfg1_grp.append(rs)
1333
        rs = RadioSetting("tot", "Timeout Timer (TOT)",
1334
                          RadioSettingValueMap(
1335
                              TOT_MAP, _settings.tot))
1336
        cfg1_grp.append(rs)
1337

    
1338
        rs = RadioSetting("toa", "Timeout Alarm (TOA)",
1339
                          RadioSettingValueList(
1340
                              TOA_LIST, TOA_LIST[_settings.toa]))
1341
        cfg1_grp.append(rs)
1342

    
1343
        rs = RadioSetting("ani_sw", "Caller ID Tx - ANI-SW",
1344
                          RadioSettingValueBoolean(_settings.ani_sw))
1345
        cfg1_grp.append(rs)
1346

    
1347
        rs = RadioSetting("ring", "Ring Time (Sec)",
1348
                          RadioSettingValueList(
1349
                              RING_LIST,
1350
                              RING_LIST[_settings.ring]))
1351
        cfg1_grp.append(rs)
1352

    
1353
        rs = RadioSetting("dtmfsf", "DTMF Sidetone",
1354
                          RadioSettingValueList(
1355
                              DTMF_ST_LIST,
1356
                              DTMF_ST_LIST[_settings.dtmfsf]))
1357
        cfg1_grp.append(rs)
1358

    
1359
        rs = RadioSetting("ptt_id", "Caller ID Tx Mode (PTT_ID)",
1360
                          RadioSettingValueMap(PTT_ID_MAP, _settings.ptt_id))
1361
        cfg1_grp.append(rs)
1362

    
1363
        rs = RadioSetting("wt_led", "Standby / WT LED",
1364
                          RadioSettingValueList(
1365
                              BACKLIGHT_LIST,
1366
                              BACKLIGHT_LIST[_settings.wt_led]))
1367
        cfg1_grp.append(rs)
1368

    
1369
        rs = RadioSetting("tx_led", "TX LED",
1370
                          RadioSettingValueList(
1371
                              BACKLIGHT_LIST,
1372
                              BACKLIGHT_LIST[_settings.tx_led]))
1373
        cfg1_grp.append(rs)
1374

    
1375
        rs = RadioSetting("rx_led", "Rx LED",
1376
                          RadioSettingValueList(
1377
                              BACKLIGHT_LIST,
1378
                              BACKLIGHT_LIST[_settings.rx_led]))
1379
        cfg1_grp.append(rs)
1380

    
1381
        rs = RadioSetting("prich_sw", "Priority Channel Scan",
1382
                          RadioSettingValueBoolean(_settings.prich_sw))
1383
        cfg1_grp.append(rs)
1384

    
1385
        rs = RadioSetting("spk_cont", "Speaker Control",
1386
                          RadioSettingValueMap(
1387
                              SPEAKER_MAP,
1388
                              _settings.spk_cont))
1389
        cfg1_grp.append(rs)
1390

    
1391
        rs = RadioSetting("autolock", "Autolock",
1392
                          RadioSettingValueBoolean(_settings.autolock))
1393
        cfg1_grp.append(rs)
1394

    
1395
        rs = RadioSetting("low_v", "Low Voltage Shutoff",
1396
                          RadioSettingValueBoolean(_settings.low_v))
1397
        cfg1_grp.append(rs)
1398

    
1399
        rs = RadioSetting("fan", "Fan Mode",
1400
                          RadioSettingValueList(
1401
                              FAN_MODE_LIST,
1402
                              FAN_MODE_LIST[_settings.fan]))
1403
        cfg1_grp.append(rs)
1404

    
1405
        rs = RadioSetting("apo_time", "Auto Power-Off (Min)",
1406
                          RadioSettingValueList(
1407
                              APO_TIME_LIST,
1408
                              APO_TIME_LIST[_settings.apo_time]))
1409
        cfg1_grp.append(rs)
1410

    
1411
        rs = RadioSetting("alert", "Alert Pulse (Hz)",
1412
                          RadioSettingValueMap(ALERT_MAP, _settings.alert))
1413
        cfg1_grp.append(rs)
1414
        rs = RadioSetting("m_pwr", "Medium Power Level (W)",
1415
                          RadioSettingValueMap(M_POWER_MAP,
1416
                                               _settings.m_pwr))
1417
        cfg1_grp.append(rs)
1418

    
1419
        rs = RadioSetting("rpt_set_model", "Model (RPT-SET)",
1420
                          RadioSettingValueList(
1421
                              RPT_MODE_LIST,
1422
                              RPT_MODE_LIST[_settings.rpt_set_model]))
1423
        cfg2_grp.append(rs)
1424

    
1425
        rs = RadioSetting("rpt_spk", "Repeater Speaker Switch (RPT-SPK)",
1426
                          RadioSettingValueBoolean(_settings.rpt_spk))
1427
        cfg2_grp.append(rs)
1428

    
1429
        rs = RadioSetting("rpt_ptt", "Repeater PTT (RPT-PTT)",
1430
                          RadioSettingValueBoolean(_settings.rpt_ptt))
1431
        cfg2_grp.append(rs)
1432

    
1433
        rs = RadioSetting("dtmf_time", "DTMF Tx Duration (ms)",
1434
                          RadioSettingValueList(
1435
                              DTMF_TIMES,
1436
                              DTMF_TIMES[_settings.dtmf_time]))
1437
        cfg2_grp.append(rs)
1438
        rs = RadioSetting("dtmf_int", "DTMF Interval (ms)",
1439
                          RadioSettingValueList(
1440
                              DTMF_INTERVALS,
1441
                              DTMF_INTERVALS[_settings.dtmf_int]))
1442
        cfg2_grp.append(rs)
1443

    
1444
        rs = RadioSetting("sc_qt", "CTCSS/DCS Scan",
1445
                          RadioSettingValueMap(
1446
                              SC_QT_MAP, _settings.sc_qt))
1447
        cfg2_grp.append(rs)
1448

    
1449
        rs = RadioSetting("pri_ch", "Priority Channel",
1450
                          RadioSettingValueInteger(
1451
                              1, 999, _chnum_decode(_settings.pri_ch)))
1452
        cfg2_grp.append(rs)
1453

    
1454
        rs = RadioSetting("ptt_id_dly", "Caller ID Tx Delay PTT-ID-DLY (ms)",
1455
                          RadioSettingValueMap(PTT_ID_DELAY_MAP,
1456
                                               _settings.ptt_id_dly))
1457
        cfg2_grp.append(rs)
1458

    
1459
        rs = RadioSetting("rc_sw", "Remote Control RC-SW",
1460
                          RadioSettingValueBoolean(_settings.rc_sw))
1461
        cfg2_grp.append(rs)
1462

    
1463
        rs = RadioSetting("scan_det", "Scan DET",
1464
                          RadioSettingValueBoolean(_settings.scan_det))
1465
        cfg2_grp.append(rs)
1466

    
1467
        rs = RadioSetting("menu", "Menu Available",
1468
                          RadioSettingValueBoolean(_settings.menu))
1469
        cfg2_grp.append(rs)
1470

    
1471
        rs = RadioSetting("thr_vol_tx", "Threshold Voltage Tx",
1472
                          RadioSettingValueBoolean(_settings.thr_vol_tx))
1473
        cfg2_grp.append(rs)
1474

    
1475
        rs = RadioSetting("hold_time_rpt", "Hold Time of Repeat (ms)",
1476
                          RadioSettingValueList(
1477
                              HOLD_TIMES,
1478
                              HOLD_TIMES[_settings.hold_time_rpt]))
1479
        cfg2_grp.append(rs)
1480

    
1481
        rs = RadioSetting("auto_am", "Auto AM",
1482
                          RadioSettingValueBoolean(_settings.auto_am))
1483
        cfg2_grp.append(rs)
1484

    
1485
        rs = RadioSetting("rpt_tone", "Repeat Tone",
1486
                          RadioSettingValueBoolean(_settings.rpt_tone))
1487
        cfg2_grp.append(rs)
1488

    
1489
        rs = RadioSetting("pf1_set", "PF1 setting",
1490
                          RadioSettingValueList(
1491
                              PF1_SETTINGS,
1492
                              PF1_SETTINGS[_settings.pf1_set]))
1493
        cfg2_grp.append(rs)
1494

    
1495
        rs = RadioSetting("settings.thr_vol_lvl", "Threshold Voltage Level",
1496
                          RadioSettingValueFloat(
1497
                           9.5, 10.5, _settings.thr_vol_lvl / 100.0, 0.1, 1))
1498
        cfg2_grp.append(rs)
1499

    
1500
        dtmfchars = "0123456789"
1501
        _code = ''
1502
        test = int(_oem.mode_psw)
1503
        _codeobj = '0x{0:0{1}X}'.format(test, 6)
1504
        LOG.debug("codeobj = %s" % _codeobj)
1505
        _psw = str(_codeobj)
1506
        for i in range(2, 8):
1507
            LOG.debug("psw[i] = %s" % _psw[i])
1508
            if _psw[i] in dtmfchars:
1509
                _code += _psw[i]
1510
        val_psw = int(_code)
1511
        LOG.debug("psw = %s" % val_psw)
1512
        val_psw = RadioSettingValueString(6, 6, _code, False)
1513
        val_psw.set_charset(dtmfchars)
1514
        rs = RadioSetting("oem.mode_psw", "MODE PSW", val_psw)
1515

    
1516
        def apply_psw_id(setting, obj):
1517
            val2 = hex(int(str(val_psw), 16))
1518
            LOG.debug("val2= %s" % val2)
1519
            if (int(val2, 16) != 0):
1520
                while len(val2) < 8:
1521
                    val2 += '0'
1522
            psw = int(str(val2), 16)
1523
            LOG.debug("val3= %s" % psw)
1524
            LOG.debug("val= %s" % val_psw)
1525
            obj.mode_psw = psw
1526
        rs.set_apply_callback(apply_psw_id, _oem)
1527
        cfg2_grp.append(rs)
1528

    
1529
        rs = RadioSetting("ABR", "ABR (Backlight On Time)",
1530
                          RadioSettingValueList(
1531
                              ABR_LIST,
1532
                              ABR_LIST[_settings.ABR]))
1533
        cfg2_grp.append(rs)
1534

    
1535
        rs = RadioSetting("KeyA", "Key A",
1536
                          RadioSettingValueList(
1537
                              KEY_LIST,
1538
                              KEY_LIST[_settings.KeyA]))
1539
        cfg2_grp.append(rs)
1540
        rs = RadioSetting("KeyB", "Key B",
1541
                          RadioSettingValueList(
1542
                              KEY_LIST,
1543
                              KEY_LIST[_settings.KeyB]))
1544
        cfg2_grp.append(rs)
1545
        rs = RadioSetting("KeyC", "Key C",
1546
                          RadioSettingValueList(
1547
                              KEY_LIST,
1548
                              KEY_LIST[_settings.KeyC]))
1549
        cfg2_grp.append(rs)
1550

    
1551
        rs = RadioSetting("act_area", "Active Area (BAND)",
1552
                          RadioSettingValueList(
1553
                              ACTIVE_AREA_LIST,
1554
                              ACTIVE_AREA_LIST[_settings.act_area]))
1555
        cfg2_grp.append(rs)
1556
        rs = RadioSetting("tdr_off", "TDR",
1557
                          RadioSettingValueList(
1558
                              TDR_LIST,
1559
                              TDR_LIST[_settings.tdr_off]))
1560
        cfg2_grp.append(rs)
1561

    
1562
# Freq Limits settings
1563

    
1564
        # Convert Integer back to correct limit HEX value:
1565

    
1566
        _temp = str(hex(int("%i" %
1567
                    self._memobj.bandlimits.limit_144M_ChA_rx_start, 10)))
1568
        _temp = int(int(_temp[2:])/10.0)
1569
        val = RadioSettingValueInteger(0, 999, _temp)
1570
        rs = RadioSetting("bandlimits.limit_144M_ChA_rx_start",
1571
                          "144M ChA Rx Lower Limit (MHz)",
1572
                          RadioSettingValueInteger(0, 999,
1573
                                                   val))
1574
        rxlim_grp.append(rs)
1575

    
1576
        _temp = str(hex(int("%i" %
1577
                    self._memobj.bandlimits.limit_144M_ChA_rx_stop, 10)))
1578
        _temp = int(int(_temp[2:])/10.0)
1579
        val = RadioSettingValueInteger(0, 999, _temp)
1580
        rs = RadioSetting("bandlimits.limit_144M_ChA_rx_stop",
1581
                          "144M ChA Rx Upper Limit (MHz)",
1582
                          RadioSettingValueInteger(0, 999,
1583
                                                   val))
1584
        rxlim_grp.append(rs)
1585

    
1586
        _temp = str(hex(int("%i" %
1587
                    self._memobj.bandlimits.limit_144M_ChB_rx_start, 10)))
1588
        _temp = int(int(_temp[2:])/10.0)
1589
        val = RadioSettingValueInteger(0, 999, _temp)
1590
        rs = RadioSetting("bandlimits.limit_144M_ChB_rx_start",
1591
                          "144M ChB Rx Lower Limit (MHz)",
1592
                          RadioSettingValueInteger(0, 999,
1593
                                                   val))
1594
        rxlim_grp.append(rs)
1595

    
1596
        _temp = str(hex(int("%i" %
1597
                    self._memobj.bandlimits.limit_144M_ChB_rx_stop, 10)))
1598
        _temp = int(int(_temp[2:])/10.0)
1599
        val = RadioSettingValueInteger(0, 999, _temp)
1600
        rs = RadioSetting("bandlimits.limit_144M_ChB_rx_stop",
1601
                          "144M ChB Rx Upper Limit (MHz)",
1602
                          RadioSettingValueInteger(0, 999,
1603
                                                   val))
1604
        rxlim_grp.append(rs)
1605

    
1606
        _temp = str(hex(int("%i" %
1607
                    self._memobj.bandlimits.limit_70cm_rx_start, 10)))
1608
        _temp = int(int(_temp[2:])/10.0)
1609
        val = RadioSettingValueInteger(0, 999, _temp)
1610
        rs = RadioSetting("bandlimits.limit_70cm_rx_start",
1611
                          "450M Rx Lower Limit (MHz)",
1612
                          RadioSettingValueInteger(0, 999,
1613
                                                   val))
1614
        rxlim_grp.append(rs)
1615

    
1616
        _temp = str(hex(int("%i" %
1617
                    self._memobj.bandlimits.limit_70cm_rx_stop, 10)))
1618
        _temp = int(int(_temp[2:])/10.0)
1619
        val = RadioSettingValueInteger(0, 999, _temp)
1620
        rs = RadioSetting("bandlimits.limit_70cm_rx_stop",
1621
                          "450M Rx Upper Limit (MHz)",
1622
                          RadioSettingValueInteger(0, 999,
1623
                                                   val))
1624
        rxlim_grp.append(rs)
1625

    
1626
        _temp = str(hex(int("%i" %
1627
                    self._memobj.bandlimits.limit_10m_rx_start, 10)))
1628
        _temp = int(int(_temp[2:])/10.0)
1629
        val = RadioSettingValueInteger(0, 999, _temp)
1630
        rs = RadioSetting("bandlimits.limit_10m_rx_start",
1631
                          "20M Rx Lower Limit (MHz)",
1632
                          RadioSettingValueInteger(0, 999,
1633
                                                   val))
1634
        rxlim_grp.append(rs)
1635

    
1636
        _temp = str(hex(int("%i" %
1637
                    self._memobj.bandlimits.limit_10m_rx_stop, 10)))
1638
        _temp = int(int(_temp[2:])/10.0)
1639
        val = RadioSettingValueInteger(0, 999, _temp)
1640
        rs = RadioSetting("bandlimits.limit_10m_rx_stop",
1641
                          "20M Rx Upper Limit (MHz)",
1642
                          RadioSettingValueInteger(0, 999,
1643
                                                   val))
1644
        rxlim_grp.append(rs)
1645

    
1646
        _temp = str(hex(int("%i" %
1647
                    self._memobj.bandlimits.limit_6m_rx_start, 10)))
1648
        _temp = int(int(_temp[2:])/10.0)
1649
        val = RadioSettingValueInteger(0, 999, _temp)
1650
        rs = RadioSetting("bandlimits.limit_6m_rx_start",
1651
                          "50M Rx Lower Limit (MHz)",
1652
                          RadioSettingValueInteger(0, 999,
1653
                                                   val))
1654
        rxlim_grp.append(rs)
1655

    
1656
        _temp = str(hex(int("%i" %
1657
                    self._memobj.bandlimits.limit_6m_rx_stop, 10)))
1658
        _temp = int(int(_temp[2:])/10.0)
1659
        val = RadioSettingValueInteger(0, 999, _temp)
1660
        rs = RadioSetting("bandlimits.limit_6m_rx_stop",
1661
                          "50M Rx Upper Limit (MHz)",
1662
                          RadioSettingValueInteger(0, 999,
1663
                                                   val))
1664
        rxlim_grp.append(rs)
1665

    
1666
        _temp = str(hex(int("%i" %
1667
                    self._memobj.bandlimits.limit_350M_rx_start, 10)))
1668
        _temp = int(int(_temp[2:])/10.0)
1669
        val = RadioSettingValueInteger(0, 999, _temp)
1670
        rs = RadioSetting("bandlimits.limit_350M_rx_start",
1671
                          "350M Rx Lower Limit (MHz)",
1672
                          RadioSettingValueInteger(0, 999,
1673
                                                   val))
1674
        rxlim_grp.append(rs)
1675

    
1676
        _temp = str(hex(int("%i" %
1677
                    self._memobj.bandlimits.limit_350M_rx_stop, 10)))
1678
        _temp = int(int(_temp[2:])/10.0)
1679
        val = RadioSettingValueInteger(0, 999, _temp)
1680
        rs = RadioSetting("bandlimits.limit_350M_rx_stop",
1681
                          "350M Rx Upper Limit (MHz)",
1682
                          RadioSettingValueInteger(0, 999,
1683
                                                   val))
1684
        rxlim_grp.append(rs)
1685

    
1686
        _temp = str(hex(int("%i" %
1687
                    self._memobj.bandlimits.limit_850M_rx_start, 10)))
1688
        _temp = int(int(_temp[2:])/10.0)
1689
        val = RadioSettingValueInteger(0, 999, _temp)
1690
        rs = RadioSetting("bandlimits.limit_850M_rx_start",
1691
                          "850M Rx Lower Limit (MHz)",
1692
                          RadioSettingValueInteger(0, 999,
1693
                                                   val))
1694
        rxlim_grp.append(rs)
1695

    
1696
        _temp = str(hex(int("%i" %
1697
                    self._memobj.bandlimits.limit_850M_rx_stop, 10)))
1698
        _temp = int(int(_temp[2:])/10.0)
1699
        val = RadioSettingValueInteger(0, 999, _temp)
1700
        rs = RadioSetting("bandlimits.limit_850M_rx_stop",
1701
                          "850M Rx Upper Limit (MHz)",
1702
                          RadioSettingValueInteger(0, 999,
1703
                                                   val))
1704
        rxlim_grp.append(rs)
1705

    
1706
        _temp = str(hex(int("%i" %
1707
                    self._memobj.bandlimits.limit_144M_ChA_tx_start, 10)))
1708
        _temp = int(int(_temp[2:])/10.0)
1709
        val = RadioSettingValueInteger(0, 999, _temp)
1710
        rs = RadioSetting("bandlimits.limit_144M_ChA_tx_start",
1711
                          "144M ChA Tx Lower Limit (MHz)",
1712
                          RadioSettingValueInteger(0, 999,
1713
                                                   val))
1714
        txlim_grp.append(rs)
1715

    
1716
        _temp = str(hex(int("%i" %
1717
                    self._memobj.bandlimits.limit_144M_ChA_tx_stop, 10)))
1718
        _temp = int(int(_temp[2:])/10.0)
1719
        val = RadioSettingValueInteger(0, 999, _temp)
1720
        rs = RadioSetting("bandlimits.limit_144M_ChA_tx_stop",
1721
                          "144M ChA Tx Upper Limit (MHz)",
1722
                          RadioSettingValueInteger(0, 999,
1723
                                                   val))
1724
        txlim_grp.append(rs)
1725

    
1726
        _temp = str(hex(int("%i" %
1727
                    self._memobj.bandlimits.limit_70cm_tx_start, 10)))
1728
        _temp = int(int(_temp[2:])/10.0)
1729
        val = RadioSettingValueInteger(0, 999, _temp)
1730
        rs = RadioSetting("bandlimits.limit_70cm_tx_start",
1731
                          "450M Tx Lower Limit (MHz)",
1732
                          RadioSettingValueInteger(0, 999,
1733
                                                   val))
1734
        txlim_grp.append(rs)
1735

    
1736
        _temp = str(hex(int("%i" %
1737
                    self._memobj.bandlimits.limit_70cm_tx_stop, 10)))
1738
        _temp = int(int(_temp[2:])/10.0)
1739
        val = RadioSettingValueInteger(0, 999, _temp)
1740
        rs = RadioSetting("bandlimits.limit_70cm_tx_stop",
1741
                          "450M tx Upper Limit (MHz)",
1742
                          RadioSettingValueInteger(0, 999,
1743
                                                   val))
1744
        txlim_grp.append(rs)
1745

    
1746
        _temp = str(hex(int("%i" %
1747
                    self._memobj.bandlimits.limit_10m_tx_start, 10)))
1748
        _temp = int(int(_temp[2:])/10.0)
1749
        val = RadioSettingValueInteger(0, 999, _temp)
1750
        rs = RadioSetting("bandlimits.limit_10m_tx_start",
1751
                          "20M tx Lower Limit (MHz)",
1752
                          RadioSettingValueInteger(0, 999,
1753
                                                   val))
1754
        txlim_grp.append(rs)
1755

    
1756
        _temp = str(hex(int("%i" %
1757
                    self._memobj.bandlimits.limit_10m_tx_stop, 10)))
1758
        _temp = int(int(_temp[2:])/10.0)
1759
        val = RadioSettingValueInteger(0, 999, _temp)
1760
        rs = RadioSetting("bandlimits.limit_10m_tx_stop",
1761
                          "20M tx Upper Limit (MHz)",
1762
                          RadioSettingValueInteger(0, 999,
1763
                                                   val))
1764
        txlim_grp.append(rs)
1765

    
1766
        _temp = str(hex(int("%i" %
1767
                    self._memobj.bandlimits.limit_6m_tx_start, 10)))
1768
        _temp = int(int(_temp[2:])/10.0)
1769
        val = RadioSettingValueInteger(0, 999, _temp)
1770
        rs = RadioSetting("bandlimits.limit_6m_tx_start",
1771
                          "50M tx Lower Limit (MHz)",
1772
                          RadioSettingValueInteger(0, 999,
1773
                                                   val))
1774
        txlim_grp.append(rs)
1775

    
1776
        _temp = str(hex(int("%i" %
1777
                    self._memobj.bandlimits.limit_6m_tx_stop, 10)))
1778
        _temp = int(int(_temp[2:])/10.0)
1779
        val = RadioSettingValueInteger(0, 999, _temp)
1780
        rs = RadioSetting("bandlimits.limit_6m_tx_stop",
1781
                          "50M tx Upper Limit (MHz)",
1782
                          RadioSettingValueInteger(0, 999,
1783
                                                   val))
1784
        txlim_grp.append(rs)
1785

    
1786
# VFO Settings
1787
        rs = RadioSetting("vfomode_a", "VFO A Working Mode",
1788
                          RadioSettingValueMap(WORKMODE_MAP,
1789
                                               _settings.vfomode_a))
1790
        vfoa_grp.append(rs)
1791

    
1792
        rs = RadioSetting("vfoband_a", "VFO A Current Band",
1793
                          RadioSettingValueMap(VFOBAND_MAP,
1794
                                               _settings.vfoband_a))
1795
        vfoa_grp.append(rs)
1796

    
1797
        rs = RadioSetting("vfochan_a", "VFO A Channel",
1798
                          RadioSettingValueInteger(1, 999,
1799
                                                   _chnum_decode(
1800
                                                    _settings.vfochan_a)))
1801
        vfoa_grp.append(rs)
1802

    
1803
        rs = RadioSetting("vfosquelch_a", "VFO A Squelch",
1804
                          RadioSettingValueInteger(0, 9,
1805
                                                   _settings.vfosquelch_a))
1806
        vfoa_grp.append(rs)
1807
        rs = RadioSetting("vfostep_a", "VFO A Step",
1808
                          RadioSettingValueList(
1809
                            STEP_LIST,
1810
                            STEP_LIST[_settings.vfostep_a]))
1811
        vfoa_grp.append(rs)
1812

    
1813
######################
1814

    
1815
        rs = RadioSetting("vfofreq1", "VFO 150M Freq",
1816
                          RadioSettingValueFloat(
1817
                             0, 999.999999, (_freq_decode
1818
                                             (_settings.vfofreq1) /
1819
                                             1000000.0), 0.000001, 6))
1820
        vfo150_grp.append(rs)
1821

    
1822
        rs = RadioSetting("vfoofst1", "VFO 150M Offset",
1823
                          RadioSettingValueFloat(
1824
                              0, 999.999999, (_freq_decode
1825
                                              (_settings.vfoofst1) /
1826
                                              1000000.0), 0.000001, 6))
1827
        vfo150_grp.append(rs)
1828

    
1829
        rs = RadioSetting("rxtone1", "VFO 150M Rx tone",
1830
                          RadioSettingValueMap(
1831
                            TONE_MAP, _settings.rxtone1))
1832
        vfo150_grp.append(rs)
1833

    
1834
        rs = RadioSetting("txtone1", "VFO 150M Tx tone",
1835
                          RadioSettingValueMap(
1836
                            TONE_MAP, _settings.txtone1))
1837
        vfo150_grp.append(rs)
1838

    
1839
        rs = RadioSetting("power1", "VFO 150M Power",
1840
                          RadioSettingValueMap(
1841
                            POWER_MAP, _settings.power1))
1842
        vfo150_grp.append(rs)
1843

    
1844
        rs = RadioSetting("narrow1", "VFO 150M Bandwidth",
1845
                          RadioSettingValueMap(
1846
                            BANDWIDTH_MAP, _settings.narrow1))
1847
        vfo150_grp.append(rs)
1848

    
1849
        rs = RadioSetting("mute1", "VFO 150M Mute Mode",
1850
                          RadioSettingValueMap(
1851
                            MUTE_MODE_MAP, _settings.mute1))
1852
        vfo150_grp.append(rs)
1853

    
1854
        rs = RadioSetting("shft_dir1", "VFO 150M Shift Direction",
1855
                          RadioSettingValueList(
1856
                            DUPLEX_LIST,
1857
                            DUPLEX_LIST[_settings.shft_dir1]))
1858
        vfo150_grp.append(rs)
1859

    
1860
        rs = RadioSetting("compander1", "VFO 150M Compander",
1861
                          RadioSettingValueBoolean(
1862
                            _settings.compander1))
1863
        vfo150_grp.append(rs)
1864

    
1865
        rs = RadioSetting("scrambler1", "VFO 150M Scrambler",
1866
                          RadioSettingValueList(
1867
                            SCRAMBLER_LIST,
1868
                            SCRAMBLER_LIST[_settings.scrambler1]))
1869
        vfo150_grp.append(rs)
1870
        rs = RadioSetting("am_mode1", "VFO 150M AM Mode",
1871
                          RadioSettingValueBoolean(
1872
                            _settings.am_mode1))
1873
        vfo150_grp.append(rs)
1874

    
1875
############################
1876

    
1877
        rs = RadioSetting("vfofreq2", "VFO 450M Freq",
1878
                          RadioSettingValueFloat(
1879
                             0, 999.999999, (_freq_decode
1880
                                             (_settings.vfofreq2) /
1881
                                             1000000.0), 0.000001, 6))
1882
        vfo450_grp.append(rs)
1883

    
1884
        rs = RadioSetting("vfoofst2", "VFO 450M Offset",
1885
                          RadioSettingValueFloat(
1886
                              0, 999.999999, (_freq_decode
1887
                                              (_settings.vfoofst2) /
1888
                                              1000000.0), 0.000001, 6))
1889
        vfo450_grp.append(rs)
1890

    
1891
        rs = RadioSetting("rxtone2", "VFO 450M Rx tone",
1892
                          RadioSettingValueMap(
1893
                            TONE_MAP, _settings.rxtone2))
1894
        vfo450_grp.append(rs)
1895

    
1896
        rs = RadioSetting("txtone2", "VFO 450M Tx tone",
1897
                          RadioSettingValueMap(
1898
                            TONE_MAP, _settings.txtone2))
1899
        vfo450_grp.append(rs)
1900

    
1901
        rs = RadioSetting("power2", "VFO 450M Power",
1902
                          RadioSettingValueMap(
1903
                            POWER_MAP, _settings.power2))
1904
        vfo450_grp.append(rs)
1905

    
1906
        rs = RadioSetting("narrow2", "VFO 450M Bandwidth",
1907
                          RadioSettingValueMap(
1908
                            BANDWIDTH_MAP, _settings.narrow2))
1909
        vfo450_grp.append(rs)
1910

    
1911
        rs = RadioSetting("mute2", "VFO 450M Mute Mode",
1912
                          RadioSettingValueMap(
1913
                            MUTE_MODE_MAP, _settings.mute2))
1914
        vfo450_grp.append(rs)
1915

    
1916
        rs = RadioSetting("shft_dir2", "VFO 450M Shift Direction",
1917
                          RadioSettingValueList(
1918
                            DUPLEX_LIST,
1919
                            DUPLEX_LIST[_settings.shft_dir2]))
1920
        vfo450_grp.append(rs)
1921

    
1922
        rs = RadioSetting("compander2", "VFO 450M Compander",
1923
                          RadioSettingValueBoolean(
1924
                            _settings.compander2))
1925
        vfo450_grp.append(rs)
1926

    
1927
        rs = RadioSetting("scrambler2", "VFO 450M Scrambler",
1928
                          RadioSettingValueList(
1929
                            SCRAMBLER_LIST,
1930
                            SCRAMBLER_LIST[_settings.scrambler2]))
1931
        vfo450_grp.append(rs)
1932

    
1933
        rs = RadioSetting("am_mode2", "VFO 450M AM Mode",
1934
                          RadioSettingValueBoolean(
1935
                            _settings.am_mode2))
1936
        vfo450_grp.append(rs)
1937

    
1938
############################
1939

    
1940
        rs = RadioSetting("vfofreq3", "VFO 20M Freq",
1941
                          RadioSettingValueFloat(
1942
                             0, 999.999999, (_freq_decode
1943
                                             (_settings.vfofreq3) /
1944
                                             1000000.0), 0.000001, 6))
1945
        vfo20_grp.append(rs)
1946

    
1947
        rs = RadioSetting("vfoofst3", "VFO 20M Offset",
1948
                          RadioSettingValueFloat(
1949
                              0, 999.999999, (_freq_decode
1950
                                              (_settings.vfoofst3) /
1951
                                              1000000.0), 0.000001, 6))
1952
        vfo20_grp.append(rs)
1953

    
1954
        rs = RadioSetting("rxtone3", "VFO 20M Rx tone",
1955
                          RadioSettingValueMap(
1956
                            TONE_MAP, _settings.rxtone3))
1957
        vfo20_grp.append(rs)
1958

    
1959
        rs = RadioSetting("txtone3", "VFO 20M Tx tone",
1960
                          RadioSettingValueMap(
1961
                            TONE_MAP, _settings.txtone3))
1962
        vfo20_grp.append(rs)
1963

    
1964
        rs = RadioSetting("power3", "VFO 20M Power",
1965
                          RadioSettingValueMap(
1966
                            POWER_MAP, _settings.power3))
1967
        vfo20_grp.append(rs)
1968

    
1969
        rs = RadioSetting("narrow3", "VFO 20M Bandwidth",
1970
                          RadioSettingValueMap(
1971
                            BANDWIDTH_MAP, _settings.narrow3))
1972
        vfo20_grp.append(rs)
1973

    
1974
        rs = RadioSetting("mute3", "VFO 20M Mute Mode",
1975
                          RadioSettingValueMap(
1976
                            MUTE_MODE_MAP, _settings.mute3))
1977
        vfo20_grp.append(rs)
1978

    
1979
        rs = RadioSetting("shft_dir3", "VFO 20M Shift Direction",
1980
                          RadioSettingValueList(
1981
                            DUPLEX_LIST,
1982
                            DUPLEX_LIST[_settings.shft_dir3]))
1983
        vfo20_grp.append(rs)
1984

    
1985
        rs = RadioSetting("compander3", "VFO 20M Compander",
1986
                          RadioSettingValueBoolean(
1987
                            _settings.compander3))
1988
        vfo20_grp.append(rs)
1989

    
1990
        rs = RadioSetting("scrambler3", "VFO 20M Scrambler",
1991
                          RadioSettingValueList(
1992
                            SCRAMBLER_LIST,
1993
                            SCRAMBLER_LIST[_settings.scrambler3]))
1994
        vfo20_grp.append(rs)
1995

    
1996
        rs = RadioSetting("am_mode3", "VFO 20M AM Mode",
1997
                          RadioSettingValueBoolean(
1998
                            _settings.am_mode3))
1999
        vfo20_grp.append(rs)
2000

    
2001
############################
2002

    
2003
        rs = RadioSetting("vfofreq4", "VFO 50M Freq",
2004
                          RadioSettingValueFloat(
2005
                             0, 999.999999, (_freq_decode
2006
                                             (_settings.vfofreq4) /
2007
                                             1000000.0), 0.000001, 6))
2008
        vfo50_grp.append(rs)
2009

    
2010
        rs = RadioSetting("vfoofst4", "VFO 50M Offset",
2011
                          RadioSettingValueFloat(
2012
                              0, 999.999999, (_freq_decode
2013
                                              (_settings.vfoofst4) /
2014
                                              1000000.0), 0.000001, 6))
2015
        vfo50_grp.append(rs)
2016

    
2017
        rs = RadioSetting("rxtone4", "VFO 50M Rx tone",
2018
                          RadioSettingValueMap(
2019
                            TONE_MAP, _settings.rxtone4))
2020
        vfo50_grp.append(rs)
2021

    
2022
        rs = RadioSetting("txtone4", "VFO 50M Tx tone",
2023
                          RadioSettingValueMap(
2024
                            TONE_MAP, _settings.txtone4))
2025
        vfo50_grp.append(rs)
2026

    
2027
        rs = RadioSetting("power4", "VFO 50M Power",
2028
                          RadioSettingValueMap(
2029
                            POWER_MAP, _settings.power4))
2030
        vfo50_grp.append(rs)
2031

    
2032
        rs = RadioSetting("narrow4", "VFO 50M Bandwidth",
2033
                          RadioSettingValueMap(
2034
                            BANDWIDTH_MAP, _settings.narrow4))
2035
        vfo50_grp.append(rs)
2036

    
2037
        rs = RadioSetting("mute4", "VFO 50M Mute Mode",
2038
                          RadioSettingValueMap(
2039
                            MUTE_MODE_MAP, _settings.mute4))
2040
        vfo50_grp.append(rs)
2041

    
2042
        rs = RadioSetting("shft_dir4", "VFO 50M Shift Direction",
2043
                          RadioSettingValueList(
2044
                            DUPLEX_LIST,
2045
                            DUPLEX_LIST[_settings.shft_dir4]))
2046
        vfo50_grp.append(rs)
2047

    
2048
        rs = RadioSetting("compander4", "VFO 50M Compander",
2049
                          RadioSettingValueBoolean(
2050
                            _settings.compander4))
2051
        vfo50_grp.append(rs)
2052

    
2053
        rs = RadioSetting("scrambler4", "VFO 50M Scrambler",
2054
                          RadioSettingValueList(
2055
                            SCRAMBLER_LIST,
2056
                            SCRAMBLER_LIST[_settings.scrambler4]))
2057
        vfo50_grp.append(rs)
2058

    
2059
        rs = RadioSetting("am_mode4", "VFO 50M AM Mode",
2060
                          RadioSettingValueBoolean(
2061
                            _settings.am_mode4))
2062
        vfo50_grp.append(rs)
2063
############################
2064
        rs = RadioSetting("vfofreq5", "VFO 350M Freq",
2065
                          RadioSettingValueFloat(
2066
                             0, 999.999999, (_freq_decode
2067
                                             (_settings.vfofreq5) /
2068
                                             1000000.0), 0.000001, 6))
2069
        vfo350_grp.append(rs)
2070

    
2071
        rs = RadioSetting("vfoofst5", "VFO 350M Offset",
2072
                          RadioSettingValueFloat(
2073
                              0, 999.999999, (_freq_decode
2074
                                              (_settings.vfoofst5) /
2075
                                              1000000.0), 0.000001, 6))
2076
        vfo350_grp.append(rs)
2077

    
2078
        rs = RadioSetting("rxtone5", "VFO 350M Rx tone",
2079
                          RadioSettingValueMap(
2080
                            TONE_MAP, _settings.rxtone5))
2081
        vfo350_grp.append(rs)
2082

    
2083
        rs = RadioSetting("txtone5", "VFO 350M Tx tone",
2084
                          RadioSettingValueMap(
2085
                            TONE_MAP, _settings.txtone5))
2086
        vfo350_grp.append(rs)
2087

    
2088
        rs = RadioSetting("power5", "VFO 350M Power",
2089
                          RadioSettingValueMap(
2090
                            POWER_MAP, _settings.power5))
2091
        vfo350_grp.append(rs)
2092

    
2093
        rs = RadioSetting("narrow5", "VFO 350M Bandwidth",
2094
                          RadioSettingValueMap(
2095
                            BANDWIDTH_MAP, _settings.narrow5))
2096
        vfo350_grp.append(rs)
2097

    
2098
        rs = RadioSetting("mute5", "VFO 350M Mute Mode",
2099
                          RadioSettingValueMap(
2100
                            MUTE_MODE_MAP, _settings.mute5))
2101
        vfo350_grp.append(rs)
2102

    
2103
        rs = RadioSetting("shft_dir5", "VFO 350M Shift Direction",
2104
                          RadioSettingValueList(
2105
                            DUPLEX_LIST,
2106
                            DUPLEX_LIST[_settings.shft_dir5]))
2107
        vfo350_grp.append(rs)
2108

    
2109
        rs = RadioSetting("compander5", "VFO 350M Compander",
2110
                          RadioSettingValueBoolean(
2111
                            _settings.compander5))
2112
        vfo350_grp.append(rs)
2113

    
2114
        rs = RadioSetting("scrambler5", "VFO 350M Scrambler",
2115
                          RadioSettingValueList(
2116
                            SCRAMBLER_LIST,
2117
                            SCRAMBLER_LIST[_settings.scrambler5]))
2118
        vfo350_grp.append(rs)
2119

    
2120
        rs = RadioSetting("am_mode5", "VFO 350M AM Mode",
2121
                          RadioSettingValueBoolean(
2122
                            _settings.am_mode5))
2123
        vfo350_grp.append(rs)
2124

    
2125
# ############################
2126
        rs = RadioSetting("vfofreq6", "VFO 850M Freq",
2127
                          RadioSettingValueFloat(
2128
                             0, 999.999999, (_freq_decode
2129
                                             (_settings.vfofreq6) /
2130
                                             1000000.0), 0.000001, 6))
2131
        vfo850_grp.append(rs)
2132

    
2133
        rs = RadioSetting("vfoofst6", "VFO 850M Offset",
2134
                          RadioSettingValueFloat(
2135
                              0, 999.999999, (_freq_decode
2136
                                              (_settings.vfoofst6) /
2137
                                              1000000.0), 0.000001, 6))
2138
        vfo850_grp.append(rs)
2139

    
2140
        rs = RadioSetting("rxtone6", "VFO 850M Rx tone",
2141
                          RadioSettingValueMap(
2142
                            TONE_MAP, _settings.rxtone6))
2143
        vfo850_grp.append(rs)
2144

    
2145
        rs = RadioSetting("txtone6", "VFO 850M Tx tone",
2146
                          RadioSettingValueMap(
2147
                            TONE_MAP, _settings.txtone6))
2148
        vfo850_grp.append(rs)
2149

    
2150
        rs = RadioSetting("power6", "VFO 850M Power",
2151
                          RadioSettingValueMap(
2152
                            POWER_MAP, _settings.power6))
2153
        vfo850_grp.append(rs)
2154

    
2155
        rs = RadioSetting("narrow6", "VFO 850M Bandwidth",
2156
                          RadioSettingValueMap(
2157
                            BANDWIDTH_MAP, _settings.narrow6))
2158
        vfo850_grp.append(rs)
2159

    
2160
        rs = RadioSetting("mute6", "VFO 850M Mute Mode",
2161
                          RadioSettingValueMap(
2162
                            MUTE_MODE_MAP, _settings.mute6))
2163
        vfo850_grp.append(rs)
2164

    
2165
        rs = RadioSetting("shft_dir6", "VFO 850M Shift Direction",
2166
                          RadioSettingValueList(
2167
                            DUPLEX_LIST,
2168
                            DUPLEX_LIST[_settings.shft_dir6]))
2169
        vfo850_grp.append(rs)
2170

    
2171
        rs = RadioSetting("compander6", "VFO 850M Compander",
2172
                          RadioSettingValueBoolean(
2173
                            _settings.compander6))
2174
        vfo850_grp.append(rs)
2175

    
2176
        rs = RadioSetting("scrambler6", "VFO 850M Scrambler",
2177
                          RadioSettingValueList(
2178
                            SCRAMBLER_LIST,
2179
                            SCRAMBLER_LIST[_settings.scrambler6]))
2180
        vfo850_grp.append(rs)
2181

    
2182
        rs = RadioSetting("am_mode6", "VFO 850M AM Mode",
2183
                          RadioSettingValueBoolean(
2184
                            _settings.am_mode6))
2185
        vfo850_grp.append(rs)
2186

    
2187
############################
2188

    
2189
        rs = RadioSetting("vfomode_b", "VFO B Working Mode",
2190
                          RadioSettingValueMap(WORKMODE_MAP,
2191
                                               _settings.vfomode_b))
2192
        vfob_grp.append(rs)
2193

    
2194
        rs = RadioSetting("vfochan_b", "VFO B Work Channel",
2195
                          RadioSettingValueInteger(1, 999,
2196
                                                   _chnum_decode(
2197
                                                    _settings.vfochan_b)))
2198
        vfob_grp.append(rs)
2199

    
2200
        rs = RadioSetting("vfofreq7", "VFO B Freq",
2201
                          RadioSettingValueFloat(
2202
                             0, 999.999999, (_freq_decode
2203
                                             (_settings.vfofreq7) /
2204
                                             1000000.0), 0.000001, 6))
2205
        vfob_grp.append(rs)
2206

    
2207
        rs = RadioSetting("vfoofst7", "VFO B Offset",
2208
                          RadioSettingValueFloat(
2209
                              0, 999.999999, (_freq_decode
2210
                                              (_settings.vfoofst7) /
2211
                                              1000000.0), 0.000001, 6))
2212
        vfob_grp.append(rs)
2213

    
2214
        rs = RadioSetting("rxtone7", "VFOB Rx tone",
2215
                          RadioSettingValueMap(
2216
                            TONE_MAP, _settings.rxtone7))
2217
        vfob_grp.append(rs)
2218

    
2219
        rs = RadioSetting("txtone7", "VFOB Tx tone",
2220
                          RadioSettingValueMap(
2221
                            TONE_MAP, _settings.txtone7))
2222
        vfob_grp.append(rs)
2223
        rs = RadioSetting("power7", "VFOB Power",
2224
                          RadioSettingValueMap(
2225
                            POWER_MAP, _settings.power7))
2226
        vfob_grp.append(rs)
2227
        rs = RadioSetting("narrow7", "VFOB Bandwidth",
2228
                          RadioSettingValueMap(
2229
                            BANDWIDTH_MAP, _settings.narrow7))
2230
        vfob_grp.append(rs)
2231
        rs = RadioSetting("mute7", "VFOB Mute Mode",
2232
                          RadioSettingValueMap(
2233
                            MUTE_MODE_MAP, _settings.mute7))
2234
        vfob_grp.append(rs)
2235
        rs = RadioSetting("shft_dir7", "VFOB Shift Direction",
2236
                          RadioSettingValueList(
2237
                            DUPLEX_LIST,
2238
                            DUPLEX_LIST[_settings.shft_dir7]))
2239
        vfob_grp.append(rs)
2240
        rs = RadioSetting("compander7", "VFOB Compander",
2241
                          RadioSettingValueBoolean(
2242
                            _settings.compander7))
2243
        vfob_grp.append(rs)
2244

    
2245
        rs = RadioSetting("scrambler7", "VFOB Scrambler",
2246
                          RadioSettingValueList(
2247
                            SCRAMBLER_LIST,
2248
                            SCRAMBLER_LIST[_settings.scrambler7]))
2249
        vfob_grp.append(rs)
2250

    
2251
        rs = RadioSetting("vfosquelch_b", "VFO B Squelch",
2252
                          RadioSettingValueInteger(0, 9,
2253
                                                   _settings.vfosquelch_b))
2254
        vfob_grp.append(rs)
2255
        rs = RadioSetting("vfostep_b", "VFO B Step",
2256
                          RadioSettingValueList(
2257
                            STEP_LIST,
2258
                            STEP_LIST[_settings.vfostep_b]))
2259
        vfob_grp.append(rs)
2260
        # rs = RadioSetting("am_mode7", "VFOB AM Mode",
2261
        #                   RadioSettingValueBoolean(
2262
        #                     _settings.am_mode7))
2263
        # vfob_grp.append(rs)
2264

    
2265
# Scan Group Settings
2266
        def _decode(lst):
2267
            _str = ''.join([chr(c) for c in lst
2268
                            if chr(c) in SCANNAME_CHARSET])
2269
            return _str
2270

    
2271
        rs = RadioSetting("scan_a_act", "Scan A Active Group",
2272
                          RadioSettingValueList(
2273
                            SCAN_GROUP_LIST,
2274
                            SCAN_GROUP_LIST[_settings.scan_a_act]))
2275
        scan_grp.append(rs)
2276
        rs = RadioSetting("scan_b_act", "Scan B Active Group",
2277
                          RadioSettingValueList(
2278
                             SCAN_GROUP_LIST,
2279
                             SCAN_GROUP_LIST[_settings.scan_b_act]))
2280
        scan_grp.append(rs)
2281

    
2282
        for i in range(1, 11):
2283
            x = str(i)
2284
            _str = _decode(eval("_settings.scanname"+x))
2285
            LOG.debug("ScanName %s", i)
2286
            LOG.debug("is %s", _str)
2287
            # CPS treats PPPPPP as a blank name as it is the factory reset
2288
            # value"
2289
            # The Radio treats PPPPPPP as a blank name and can display 8
2290
            # chars"
2291
            # Force Chirp to blank out the scan name if value is PPPPPPP
2292
            # to match the radio"
2293
            # Blank out the name if first 6 are spaces or null and the
2294
            # 7th is a P to handle
2295
            # firmware peculiarities in handling all 8 characters.
2296
            if _str[0:7] == "PPPPPPP":
2297
                _str = ""
2298
            elif _str[0:7] == "\x00\x00\x00\x00\x00\x00P":
2299
                _str = ""
2300
            elif _str[0:7] == "\x20\x20\x20\x20\x20\x20P":
2301
                _str = ""
2302
            rs = RadioSetting("scanname" + x, "Scan Name " + x,
2303
                              RadioSettingValueString(0, 8, _str))
2304
            # rs = RadioSetting("scanname"+x, "Scan Name "+x, val)
2305
            scanname_grp.append(rs)
2306

    
2307
            scngrp = str(i)
2308
            rs = RadioSetting("scanlower"+scngrp, "Scan Lower "+scngrp,
2309
                              RadioSettingValueInteger(1, 999,
2310
                                                       eval(
2311
                                                        "_settings.\
2312
                                                        scanlower" +
2313
                                                        scngrp)))
2314
            scan_grp.append(rs)
2315
            rs = RadioSetting("scanupper"+scngrp, "Scan Upper "+scngrp,
2316
                              RadioSettingValueInteger(1, 999,
2317
                                                       eval(
2318
                                                        "_settings.scanupper" +
2319
                                                        scngrp)))
2320
            scan_grp.append(rs)
2321
# remote settings
2322
        rs = RadioSetting("rc_power", "RC Power",
2323
                          RadioSettingValueList(
2324
                           RC_POWER_LIST,
2325
                           RC_POWER_LIST[_settings.rc_power]))
2326
        remote_grp.append(rs)
2327

    
2328
        _code = ''
2329
        test = int(_settings.ani_edit)
2330
        _codeobj = '0x{0:0{1}X}'.format(test, 6)
2331
        LOG.debug("codeobj = %s" % _codeobj)
2332
        _ani = str(_codeobj)
2333
        for i in range(2, 8):
2334
            LOG.debug("ani[i] = %s" % _ani[i])
2335
            if _ani[i] in dtmfchars:
2336
                _code += _ani[i]
2337
        val_ani = int(_code)
2338
        LOG.debug("ani = %s" % val_ani)
2339
        val_ani = RadioSettingValueString(3, 6, _code, False)
2340
        val_ani.set_charset(dtmfchars)
2341
        rs = RadioSetting("settings.ani_edit", "ANI Edit", val_ani)
2342

    
2343
        def apply_ani_id(setting, obj):
2344
            temp = list()
2345
            LOG.debug("val= %s" % val_ani)
2346
            if str(val_ani)[0] == "0":
2347
                raise errors.RadioError("ANI EDIT must start with \
2348
                                        Non-Zero Digit")
2349
            val2 = hex(int(str(val_ani), 16))
2350
            LOG.debug("val2= %s" % val2)
2351
            if (int(val2, 16) != 0):
2352
                while len(val2) < 5:
2353
                    val2 += '0'
2354
                while len(val2) < 8:
2355
                    val2 += 'C'
2356
            ani = int(str(val2), 16)
2357
            LOG.debug("ani= %s" % ani)
2358
            LOG.debug("val= %s" % val_ani)
2359
            obj.ani_edit = ani
2360
        rs.set_apply_callback(apply_ani_id, _settings)
2361
        remote_grp.append(rs)
2362

    
2363
        _code = ''
2364
        test = int(_settings.mcc_edit)
2365
        _codeobj = '0x{0:0{1}X}'.format(test, 6)
2366
        LOG.debug("codeobj = %s" % _codeobj)
2367
        _mcc = str(_codeobj)
2368
        for i in range(2, 8):
2369
            LOG.debug("mcc[i] = %s" % _mcc[i])
2370
            if _mcc[i] in dtmfchars:
2371
                _code += _mcc[i]
2372
        val_mcc = int(_code)
2373
        LOG.debug("mcc = %s" % val_mcc)
2374
        val_mcc = RadioSettingValueString(3, 6, _code, False)
2375
        val_mcc.set_charset(dtmfchars)
2376
        rs = RadioSetting("mcc_edit", "MCC Edit", val_mcc)
2377

    
2378
        def apply_mcc_id(setting, obj):
2379
            val2 = hex(int(str(val_mcc), 16))
2380
            LOG.debug("val2= %s" % val2)
2381
            if (int(val2, 16) != 0):
2382
                while len(val2) < 5:
2383
                    val2 += '0'
2384
                while len(val2) < 8:
2385
                    val2 += 'C'
2386
            mcc = int(str(val2), 16)
2387
            LOG.debug("val3= %s" % mcc)
2388
            LOG.debug("val= %s" % val_mcc)
2389
            obj.mcc_edit = mcc
2390
        rs.set_apply_callback(apply_mcc_id, _settings)
2391
        remote_grp.append(rs)
2392

    
2393
        _code = ''
2394
        test = int(_settings.scc_edit)
2395
        _codeobj = '0x{0:0{1}X}'.format(test, 6)
2396
        LOG.debug("codeobj = %s" % _codeobj)
2397
        _scc = str(_codeobj)
2398
        for i in range(2, 8):
2399
            LOG.debug("scc[i] = %s" % _scc[i])
2400
            if _scc[i] in dtmfchars:
2401
                _code += _scc[i]
2402
        val_scc = int(_code)
2403
        LOG.debug("scc = %s" % val_scc)
2404
        val_scc = RadioSettingValueString(3, 6, _code, False)
2405
        val_scc.set_charset(dtmfchars)
2406
        rs = RadioSetting("scc_edit", "SCC Edit", val_scc)
2407

    
2408
        def apply_scc_id(setting, obj):
2409
            val2 = hex(int(str(val_scc), 16))
2410
            LOG.debug("val2= %s" % val2)
2411
            if (int(val2, 16) != 0):
2412
                while len(val2) < 5:
2413
                    val2 += '0'
2414
                while len(val2) < 8:
2415
                    val2 += 'C'
2416
            scc = int(str(val2), 16)
2417
            LOG.debug("val3= %s" % scc)
2418
            LOG.debug("val= %s" % val_scc)
2419
            obj.scc_edit = scc
2420
        rs.set_apply_callback(apply_scc_id, _settings)
2421
        remote_grp.append(rs)
2422

    
2423
        _code = ''
2424
        test = int(_settings.ctrl_edit)
2425
        _codeobj = '0x{0:0{1}X}'.format(test, 6)
2426
        LOG.debug("codeobj = %s" % _codeobj)
2427
        _ctrl = str(_codeobj)
2428
        for i in range(2, 8):
2429
            LOG.debug("ctrl[i] = %s" % _ctrl[i])
2430
            if _ctrl[i] in dtmfchars:
2431
                _code += _ctrl[i]
2432
        val_ctrl = int(_code)
2433
        LOG.debug("ctrl = %s" % val_ctrl)
2434
        val_ctrl = RadioSettingValueString(3, 6, _code, False)
2435
        val_ctrl.set_charset(dtmfchars)
2436
        rs = RadioSetting("ctrl_edit", "CTRL Edit", val_ctrl)
2437

    
2438
        def apply_ctrl_id(setting, obj):
2439
            val2 = hex(int(str(val_ctrl), 16))
2440
            LOG.debug("val2= %s" % val2)
2441
            if (int(val2, 16) != 0):
2442
                while len(val2) < 5:
2443
                    val2 += '0'
2444
                while len(val2) < 8:
2445
                    val2 += 'C'
2446
            ctrl = int(str(val2), 16)
2447
            LOG.debug("val3= %s" % ctrl)
2448
            LOG.debug("val= %s" % val_ctrl)
2449
            obj.ctrl_edit = ctrl
2450
        rs.set_apply_callback(apply_ctrl_id, _settings)
2451
        remote_grp.append(rs)
2452

    
2453
# OEM Settings
2454

    
2455
        _oem_name = _oem_str_decode(self._memobj.oem.display_name)
2456
        rs = RadioSetting("oem.display_name", "Display Banner Text",
2457
                          RadioSettingValueString(1, 8, _oem_name))
2458
        oem_grp.append(rs)
2459

    
2460
# FM RADIO PRESETS
2461

    
2462
# memory stores raw integer value like 7600
2463
# radio will divide 7600 by 100 and interpret correctly at 76.0Mhz
2464
        #
2465
        # FM Radio Presets Settings
2466
        #
2467

    
2468
        for i in range(1, 21):
2469
            chan = str(i)
2470
            rs = RadioSetting("FM_radio" + chan, "FM Preset " + chan,
2471
                              RadioSettingValueFloat(76.0, 108.0,
2472
                                                     eval(
2473
                                                        "_settings.FM_radio" +
2474
                                                        chan)/100.0,
2475
                                                     0.1, 1))
2476
            fmradio_grp.append(rs)
2477

    
2478
        return group
2479

    
2480
    def get_settings(self):
2481
        try:
2482
            return self._get_settings()
2483
        except:
2484
            import traceback
2485
            LOG.error("Failed to parse settings: %s", traceback.format_exc())
2486
            return None
2487

    
2488
    def set_settings(self, settings):
2489
        for element in settings:
2490
            if not isinstance(element, RadioSetting):
2491
                self.set_settings(element)
2492
                continue
2493
            else:
2494
                try:
2495
                    if "." in element.get_name():
2496
                        bits = element.get_name().split(".")
2497
                        obj = self._memobj
2498
                        for bit in bits[:-1]:
2499
                            obj = getattr(obj, bit)
2500
                        setting = bits[-1]
2501
                    else:
2502
                        obj = self._memobj.settings
2503
                        setting = element.get_name()
2504

    
2505
                    if element.has_apply_callback():
2506
                        LOG.debug("Using apply callback")
2507
                        element.run_apply_callback()
2508
                    else:
2509
                        LOG.debug("Setting %s = %s" % (setting, element.value))
2510
                        if self._is_freq(element):
2511
                            # setattr(obj, setting, int(element.value / 10))
2512
                            # MRT rescale freq values to match radio
2513
                            # expected values
2514
                            value = _freq_encode(
2515
                                element[0].get_value()*1000000.0)
2516
                            setattr(obj, setting, value)
2517

    
2518
                        elif self._is_fmradio_or_voltage(element):
2519
                            # MRT rescale FM Radio values to match radio
2520
                            # expected values
2521
                            setattr(obj, setting,
2522
                                    int(element.values()[0]._current * 100.0))
2523

    
2524
                        elif self._is_limit(element):
2525
                            setattr(obj, setting,
2526
                                    int(str(element.values()[0].
2527
                                        _current * 10), 16))
2528
                # Special VFO A Settings
2529
                #
2530
                        elif self._is_chan(element):
2531
                            value = _chnum_encode(element[0].get_value())
2532
                            setattr(obj, setting, value)
2533
                            continue
2534
                #
2535
                        elif self._is_display_name(element):
2536
                            string = element[0].get_value()
2537
                            nameenc = _oem_str_encode(string)
2538
                            for i in range(0, 8):
2539
                                LOG.debug("nameenc %s" % (nameenc[i]))
2540
                                self._memobj.oem.display_name[i] = \
2541
                                    ord(nameenc[i])
2542
                                # setattr(obj, setting, int(ord(nameenc[i])))
2543

    
2544
                        elif self._is_scan_name(element):
2545
                            string = element[0].get_value()
2546
                            LOG.debug("string %s" % (string))
2547
                            # scaname=element[0].get_name()
2548
                            # LOG.debug("scanname %s" % (scaname))
2549
                            value = _str_encode(string)
2550
                            LOG.debug("scaname %s" % (value))
2551
                            setattr(obj, setting, value)
2552
                            # self._memobj.eval(scaname)[i] = ord(nameenc[i])
2553
                            # setattr(obj, setting, int(ord(nameenc[i])))
2554
                        else:
2555
                            setattr(obj, setting, element.value)
2556
                except Exception, e:
2557
                    LOG.debug(element.get_name())
2558
                    raise
2559

    
2560
    def _is_freq(self, element):
2561
        return "rxfreq" in element.get_name() or \
2562
               "txoffset" in element.get_name() or \
2563
               "vfofreq" in element.get_name() or\
2564
               "vfoofst" in element.get_name()
2565
        #  "rx_start" in element.get_name() or \
2566
        #  "rx_stop" in element.get_name() or \
2567
        #  "tx_start" in element.get_name() or \
2568
        #  "tx_stop" in element.get_name()
2569

    
2570
    def _is_limit(self, element):
2571
        return "limit" in element.get_name()
2572

    
2573
    def _is_fmradio_or_voltage(self, element):
2574
        return "FM_radio" in element.get_name() or\
2575
                "thr_vol_lvl" in element.get_name()
2576

    
2577
    def _is_chan(self, element):
2578
        return "vfochan" in element.get_name() or\
2579
               "pri_ch" in element.get_name()
2580

    
2581
    def _is_display_name(self, element):
2582
        return "display_name" in element.get_name()
2583

    
2584
    def _is_scan_name(self, element):
2585
        return "scanname" in element.get_name()
2586

    
2587
    # def _is_vfofreq(self, element):
2588
    #     return "vfofreq" in element.get_name() or\
2589
    #            "vfoofst" in element.get_name()
(7-7/8)