Project

General

Profile

New Model #7223 » kguv980p b2.0.py

KG-UV980P Beta 2.0 Driver - Mel Terechenok, 10/19/2022 11:16 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
MEM_VALID = 0x00
45

    
46
CHARSET_NUMERIC = "0123456789"
47
CHARSET = "0123456789" + \
48
          ":;<=>?@" + \
49
          "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + \
50
          "[\]^_`" + \
51
          "abcdefghijklmnopqrstuvwxyz" + \
52
          "{|}~\x4E" + \
53
          " !\"#$%&'()*+,-./"
54

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

    
134

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

    
138
_MEM_FORMAT = """
139
    #seekto 0x004c;
140
    struct {
141
        u24 mode_psw;
142
        u8  xunk04F;
143
        u8  display_name[8];
144
    } oem;
145

    
146
    #seekto 0x0060;
147
    struct {
148
        u16    limit_144M_ChA_rx_start;
149
        u16    limit_144M_ChA_rx_stop;    
150
        u16    limit_70cm_rx_start;
151
        u16    limit_70cm_rx_stop;    
152
        u16    limit_10m_rx_start;
153
        u16    limit_10m_rx_stop;    
154
        u16    limit_6m_rx_start;
155
        u16    limit_6m_rx_stop;    
156
        u16    limit_350M_rx_start;
157
        u16    limit_350M_rx_stop;    
158
        u16    limit_850M_rx_start;
159
        u16    limit_850M_rx_stop;    
160
        u16    limit_144M_ChA_tx_start;
161
        u16    limit_144M_ChA_tx_stop;    
162
        u16    limit_70cm_tx_start;
163
        u16    limit_70cm_tx_stop;    
164
        u16    limit_10m_tx_start;
165
        u16    limit_10m_tx_stop;    
166
        u16    limit_6m_tx_start;
167
        u16    limit_6m_tx_stop;    
168
        u16    limit_144M_ChB_rx_start;
169
        u16    limit_144M_ChB_rx_stop;
170
    } bandlimits;
171

    
172

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

    
534

    
535
    #seekto 0x09f0;
536
    struct {
537
        u32     rxfreq;
538
        u32     txfreq;
539
        u16     txtone;
540
        u16     rxtone;
541
        u8      unknown1:3,
542
                mute_mode:2,
543
                unknown2:3;
544
        u8      named:1,
545
                scan_add:1,
546
                extra_power_bit:1,
547
                power:2,
548
                am_mode:1,
549
                unknownbit2:1,
550
                isnarrow:1;
551
        u8      unknown3:6,
552
                Unknown4_shft_dir:2;
553
        u8      unknown5:3,
554
                compander:1
555
                scrambler:4;
556
    } memory[1000];
557

    
558
    #seekto 0x48f8;
559
    struct {
560
        u8    name[8];
561
    } names[1000];
562

    
563
    #seekto 0x6fff;
564
    u8          valid[1000];
565
    """
566

    
567
def _freq_decode(in_freq, bytes=4):
568
    out_freq = 0
569
    for i in range(bytes*2):
570
        out_freq += (in_freq & 0xF) * (10 ** i)
571
        in_freq = in_freq >> 4
572
    if bytes == 4:
573
        return out_freq * 10
574
    elif bytes == 2:
575
        return out_freq * 100000
576

    
577

    
578
def _freq_encode(in_freq, bytes=4):
579
    if bytes == 4:
580
        return int('%08d' % (in_freq / 10), 16)
581
    elif bytes == 2:
582
        return int('%04d' % (in_freq / 100000), 16)
583

    
584
def _oem_str_decode(in_str):
585
    out_str = ''
586
    stopchar = FALSE
587
    for c in in_str:
588
        if c !=0x50 and stopchar==FALSE:
589
            if chr(c+48) in chirp_common.CHARSET_ASCII:
590
                out_str+= chr(c+48)
591
        else:
592
            out_str+=''
593
            stopchar = TRUE
594
    return out_str
595

    
596
def _oem_str_encode(in_str):
597
    out_str = ''
598
    LOG.debug("OEM Input String = %s", in_str)
599
    for c in in_str:
600
        try:
601
            out_str += chr(int(ord(c))-48)
602
        except ValueError:
603
            pass
604
    while len(out_str) < 8:
605
        out_str += chr(0x50)
606
    LOG.debug("OEM Ouput String = %s", out_str)
607
    return out_str
608

    
609

    
610
def _str_decode(in_str):
611
    out_str = ''
612
    stopchar = FALSE
613
    for c in in_str:
614
        if c !=0x00 and stopchar==FALSE:
615
            if chr(c) in chirp_common.CHARSET_ASCII:
616
                out_str+= chr(c)
617
        else:
618
            out_str+=''
619
            stopchar = TRUE
620
    return out_str
621

    
622

    
623
def _str_encode(in_str):
624
    out_str = ''
625
    for c in in_str:
626
        try:
627
            out_str += chr(ord(c))
628
        except ValueError:
629
            pass
630
    while len(out_str) < 8:
631
        out_str += chr(0x00)
632
    return out_str
633

    
634
def _chnum_decode(in_ch):
635
    return int(('%04x' % in_ch)[0:3])
636

    
637

    
638
def _chnum_encode(in_ch):
639
    return int('%03d0' % in_ch, 16)
640

    
641
# Support for the Wouxun KG-UV980P radio
642
# Serial coms are at 19200 baud
643
# The data is passed in variable length records
644
# Record structure:
645
#  Offset   Usage
646
#    0      start of record (\x7c)
647
#    1      Command (\x80 Identify \x81 End/Reboot \x82 Read \x83 Write)
648
#    2      direction (\xff PC-> Radio, \x00 Radio -> PC)
649
#    3      length of payload (excluding header/checksum) (n)
650
#    4      payload (n bytes)
651
#    4+n+1  checksum - only lower 4 bits of byte sum (% 256) of bytes 1 -> 4+n
652
#
653
# Memory Read Records:
654
# the payload is 3 bytes, first 2 are offset (big endian),
655
# 3rd is number of bytes to read
656
# Memory Write Records:
657
# the maximum payload size (from the Wouxun software) seems to be 66 bytes
658
#  (2 bytes location + 64 bytes data).
659

    
660

    
661

    
662
class KGUV8TRadio(chirp_common.Alias):
663
    VENDOR = "Wouxun"
664
    MODEL = "KG-UV980P"
665

    
666

    
667
@directory.register
668
class KG980GRadio(chirp_common.CloneModeRadio,
669
                  chirp_common.ExperimentalRadio):
670

    
671
    """Wouxun KG-UV980P"""
672
    VENDOR = "Wouxun"
673
    MODEL = "KG-UV980P"
674
    _model = "KG-UV950R2"
675
    _file_ident = "980P"
676
    BAUD_RATE = 19200
677

    
678
    POWER_LEVELS = [chirp_common.PowerLevel("L", watts=1.0), 
679
                    chirp_common.PowerLevel("M", watts=20.0), 
680
                    chirp_common.PowerLevel("H", watts=50.0)]
681
    _mmap = ""
682
    ALIASES = [KGUV8TRadio, ]
683

    
684
    def _checksum(self, data):
685
        cs = 0
686
        for byte in data:
687
            cs += ord(byte)
688
        return chr(cs % 256)
689

    
690
    # def _write_record_id(self):
691
	# _header = '\xda\x80\xff\x00\x58'
692
    #     LOG.error("Sent:\n%s" % util.hexprint(_header))
693
	# self.pipe.write(_header)
694

    
695
    def _write_record(self, cmd, payload=None):
696
        # build the packet
697
        _header = '\xda' + chr(cmd) + '\xff'
698

    
699
        _length = 0
700
        if payload:
701
            _length = len(payload)
702

    
703
        # update the length field
704
        _header += chr(_length)
705

    
706
        if payload:
707
            # calculate checksum then add it with the payload
708
            # to the packet and encrypt
709
            crc = self._checksum(_header[1:] + payload)
710
            # Checksum is only the lower 4 bits
711
            crc = chr(ord(crc) & 0xf)
712
            payload += crc
713
            _header += self.encrypt(payload)
714
        else:
715
            # calculate and add encrypted checksum to the packet
716
            crc = self._checksum(_header[1:])
717
            # Checksum is only the lower 4 bits
718
            crc = chr(ord(crc) & 0xf)
719
            _header += self.strxor(crc, '\x57')
720

    
721
        try:
722
            LOG.debug("Sent:\n%s" % util.hexprint(_header))
723
            self.pipe.write(_header)
724
        except Exception, e:
725
            raise errors.RadioError("Failed to communicate with radio: %s" % e)
726

    
727
    def _read_record(self):
728
        # read 4 chars for the header
729
        _header = self.pipe.read(4)
730
        #LOG.debug("header = " % util.hexprint(_header))
731
        if len(_header) != 4:
732
            raise errors.RadioError('Radio did not respond- header length')
733
        _length = ord(_header[3])
734
        _packet = self.pipe.read(_length)
735
        _rcs_xor = _packet[-1]
736
        _packet = self.decrypt(_packet)
737
        _cs = ord(self._checksum(_header[1:] + _packet))
738
        # It appears the checksum is only 4bits
739
        _cs = _cs & 0xf
740
        # read the checksum and decrypt it 
741
        _rcs = ord(self.strxor(self.pipe.read(1), _rcs_xor))
742
        _rcs = _rcs & 0xf
743
        return (_rcs != _cs, _packet)
744

    
745
    def decrypt(self, data):
746
        result = ''
747
        for i in range(len(data)-1, 0, -1):
748
            result += self.strxor(data[i], data[i - 1])
749
        result += self.strxor(data[0], '\x57')
750
        return result[::-1]
751

    
752
    def encrypt(self, data):
753
        result = self.strxor('\x57', data[0])
754
        for i in range(1, len(data), 1):
755
            result += self.strxor(result[i - 1], data[i])
756
        return result
757

    
758
    def strxor(self, xora, xorb):
759
        return chr(ord(xora) ^ ord(xorb))
760

    
761
    # Identify the radio
762
    #
763
    # A Gotcha: the first identify packet returns a bad checksum, subsequent
764
    # attempts return the correct checksum... (well it does on my radio!)
765
    #
766
    # The ID record returned by the radio also includes the
767
    # current frequency range
768
    # as 4 bytes big-endian in 10Hz increments
769
    #
770
    # Offset
771
    #  0:10     Model, zero padded 
772

    
773
    @classmethod
774
    def match_model(cls, filedata, filename):
775
        id = cls._file_ident
776
        return cls._file_ident in filedata[0x426:0x430]
777

    
778
    def _identify(self):
779
        """Do the identification dance"""
780
        for _i in range(0, 3):
781
            LOG.debug("ID try #"+str(_i))
782
            self._write_record(CMD_ID)
783
            _chksum_err, _resp = self._read_record()
784
            if len(_resp) == 0:
785
                raise Exception("Radio not responding")
786
            else:
787
                LOG.debug("Got:\n%s" % util.hexprint(_resp))
788
                LOG.debug("Model received is %s" % _resp[0:10])
789
                LOG.debug("Model expected is %s" % self._model)
790
                if _chksum_err:
791
                    LOG.error("Checksum error: retrying ident...")
792
                    time.sleep(0.100)
793
                    continue
794
                else:
795
                    LOG.debug("checksum passed")
796
                    if _resp[0:8] == self._model[0:8]:
797
                        LOG.debug("Passed identify")
798
                        break
799
                    else:
800
                        LOG.debug("FAILED to identify") 
801
                  
802

    
803
    def _finish(self):
804
        self._write_record(CMD_END)
805

    
806
    def process_mmap(self):
807
        self._memobj = bitwise.parse(_MEM_FORMAT, self._mmap)
808

    
809
    def sync_in(self):
810
        try:
811
            self._mmap = self._download()
812
        except errors.RadioError:
813
            raise
814
        except Exception, e:
815
            raise errors.RadioError("Failed to communicate with radio: %s" % e)
816
        self.process_mmap()
817

    
818
    def sync_out(self):
819
        self._upload()
820

    
821
    # TODO: Load all memory.
822
    # It would be smarter to only load the active areas and none of
823
    # the padding/unused areas. Padding still need to be investigated.
824
    def _download(self):
825
        """Talk to a wouxun KG-UV980P and do a download"""
826
        try:
827
            self._identify()
828
            return self._do_download(0, 32768, 64)
829
        except errors.RadioError:
830
            raise
831
        except Exception, e:
832
            LOG.exception('Unknown error during download process')
833
            raise errors.RadioError("Failed to communicate with radio: %s" % e)
834

    
835
    def _do_download(self, start, end, blocksize):
836
        # allocate & fill memory
837
        LOG.debug("Start Download")
838
        image = ""
839
        for i in range(start, end, blocksize):
840
            req = chr(i / 256) + chr(i % 256) + chr(blocksize)
841
            self._write_record(CMD_RD, req)
842
            cs_error, resp = self._read_record()
843
            LOG.debug("Got:\n%s" % util.hexprint(resp))
844

    
845
            if cs_error:
846
                LOG.debug(util.hexprint(resp))
847
                raise Exception("Checksum error on read")
848
            # LOG.debug("Got:\n%s" % util.hexprint(resp))
849
            image += resp[2:]
850
            if self.status_fn:
851
                status = chirp_common.Status()
852
                status.cur = i
853
                status.max = end
854
                status.msg = "Cloning from radio"
855
                self.status_fn(status)
856
        self._finish()
857
        return memmap.MemoryMap(''.join(image))
858

    
859
    def _upload(self):
860
        """Talk to a wouxun KG-UV980P and do a upload"""
861
        try:
862
            self._identify()
863
            LOG.debug("Done with Upload Identify")
864
            # self._do_upload(0, 1856, 16)
865
            # LOG.debug("Done with Limits Upload")
866
            # self._do_upload(1856, 32768, 64)
867
            self._do_upload(0, 32768, 64)
868
            LOG.debug("Done with Mem and Settings Upload")
869
            self._finish()
870
        except errors.RadioError:
871
            raise
872
        except Exception, e:
873
            raise errors.RadioError("Failed to communicate with radio: %s" % e)
874
        return
875

    
876
    def _do_upload(self, start, end, blocksize):
877
        LOG.debug("Start of _do_upload")
878
        ptr = start
879
        LOG.debug("ptr = " + str(ptr))
880
        for i in range(start, end, blocksize):
881
            LOG.debug("Start of loop in _do_upload index = "+str(i))
882
            LOG.debug("Start %i End %i Size %i" % (start, end, blocksize))
883
            req = chr(i/ 256) + chr(i % 256)
884
            LOG.debug("REQ")
885
            chunk = self.get_mmap()[ptr:ptr + blocksize]
886
            LOG.debug("CHUNK")
887
            self._write_record(CMD_WR, req + chunk)
888
#            LOG.debug("Upload-- SENT : " % util.hexprint(_sent))
889
            cserr, ack = self._read_record()
890
            LOG.debug("Upload-- CSUM ERROR : " + str(cserr))
891
            LOG.debug("Upload-- RCVD :\n%s " % util.hexprint(ack))
892
            
893
            j = ord(ack[0]) * 256 + ord(ack[1])
894
            if cserr or j != ptr:
895
                raise Exception("Radio did not ack block %i" % ptr)
896
            ptr += blocksize
897
            if self.status_fn:
898
                status = chirp_common.Status()
899
                status.cur = i
900
                status.max = end
901
                status.msg = "Cloning to radio"
902
                self.status_fn(status)
903
        # self._finish()
904

    
905
    def get_features(self):
906
        rf = chirp_common.RadioFeatures()
907
        rf.has_settings = True
908
        rf.has_ctone = True
909
        rf.has_rx_dtcs = True
910
        rf.has_cross = True
911
        rf.has_tuning_step = False
912
        rf.has_bank = False
913
        rf.can_odd_split = True
914
        rf.valid_skips = ["", "S"]
915
        rf.valid_tmodes = ["", "Tone", "TSQL", "DTCS", "Cross"]
916
        rf.valid_cross_modes = [
917
            "Tone->Tone",
918
            "Tone->DTCS",
919
            "DTCS->Tone",
920
            "DTCS->",
921
            "->Tone",
922
            "->DTCS",
923
            "DTCS->DTCS",
924
        ]
925
        rf.valid_modes = ["FM", "NFM", "AM", "NAM"]
926
        rf.valid_power_levels = self.POWER_LEVELS
927
        rf.valid_name_length = 8
928
        rf.valid_duplexes = ["", "-", "+", "split", "off"]
929
#   MRT - Open up channel memory freq range to support RxFreq limit expansion
930
        rf.valid_bands = [(26000000, 299999999),  # supports VHF
931
                          (300000000, 999999999)]  # supports UHF
932

    
933
        rf.valid_characters = chirp_common.CHARSET_ASCII
934
        rf.memory_bounds = (1, 999)  # 999 memories
935
        rf.valid_tuning_steps = STEPS
936
        return rf
937

    
938
    @classmethod
939
    def get_prompts(cls):
940
        rp = chirp_common.RadioPrompts()
941
        rp.experimental = \
942
            ('This driver is experimental and may contain bugs. \n'
943
              'USE AT YOUR OWN RISK  - '
944
              ' SAVE A COPY OF DOWNLOAD FROM YOUR RADIO BEFORE MAKING CHANGES\n'
945
              '\nAll known CPS settings are implemented \n'
946
              '\n Additional settings found only on radio are also included'
947
              '\nMute, Compander and Scrambler are defaulted to '
948
              'QT, OFF , OFF for all channel memories\n'
949
              '\n'
950
              'Modification of Freq Limit Interfaces is done AT YOUR OWN RISK and '
951
              'may affect radio performance and may violate rules, regulations '
952
              'or laws in your jurisdiction.\n'
953
             )
954
        return rp
955

    
956
    def get_raw_memory(self, number):
957
        return repr(self._memobj.memory[number])
958
# MRT - corrected the Polarity decoding to match 980P implementation
959
# use 0x4000 bit mask for R
960
# MRT - 0x4000 appears to be the bit mask for Inverted DCS tones
961
# MRT - n DCS Tone will be 0x8xxx values - i DCS Tones will
962
# be 0xCxxx values.
963
# MRT - Chirp Uses N for n DCS Tones and R for i DCS Tones
964
# MRT - 980P encodes DCS tone # in decimal -  NOT OCTAL
965

    
966
    def _get_tone(self, _mem, mem):
967
        def _get_dcs(val):
968
            code = int("%03d" % (val & 0x07FF))
969
            pol = (val & 0x4000) and "R" or "N"
970
            return code, pol
971
# MRT - Modified the function below to bitwise AND with 0x4000
972
# to check for 980P DCS Tone decoding
973
# MRT 0x8000 appears to be the bit mask for DCS tones
974
        tpol = False
975
# MRT Beta 1.1 - Fix the txtone compare to 0x8000 - was rxtone.
976
        if _mem.txtone != 0xFFFF and (_mem.txtone & 0x8000) == 0x8000:
977
            tcode, tpol = _get_dcs(_mem.txtone)
978
            mem.dtcs = tcode
979
            txmode = "DTCS"
980
        elif _mem.txtone != 0xFFFF and _mem.txtone != 0x0:
981
            mem.rtone = (_mem.txtone & 0x7fff) / 10.0
982
            txmode = "Tone"
983
        else:
984
            txmode = ""
985
# MRT - Modified the function below to bitwise AND with 0x4000
986
# to check for 980P DCS Tone decoding
987
        rpol = False
988
        if _mem.rxtone != 0xFFFF and (_mem.rxtone & 0x8000) == 0x8000:
989
            rcode, rpol = _get_dcs(_mem.rxtone)
990
            mem.rx_dtcs = rcode
991
            rxmode = "DTCS"
992
        elif _mem.rxtone != 0xFFFF and _mem.rxtone != 0x0:
993
            mem.ctone = (_mem.rxtone & 0x7fff) / 10.0
994
            rxmode = "Tone"
995
        else:
996
            rxmode = ""
997

    
998
        if txmode == "Tone" and not rxmode:
999
            mem.tmode = "Tone"
1000
        elif txmode == rxmode and txmode == "Tone" and mem.rtone == mem.ctone:
1001
            mem.tmode = "TSQL"
1002
        elif txmode == rxmode and txmode == "DTCS" and mem.dtcs == mem.rx_dtcs:
1003
            mem.tmode = "DTCS"
1004
        elif rxmode or txmode:
1005
            mem.tmode = "Cross"
1006
            mem.cross_mode = "%s->%s" % (txmode, rxmode)
1007

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

    
1011
        LOG.debug("Got TX %s (%i) RX %s (%i)" %
1012
                  (txmode, _mem.txtone, rxmode, _mem.rxtone))
1013

    
1014
    def get_memory(self, number):
1015
        _mem = self._memobj.memory[number]
1016
        _nam = self._memobj.names[number]
1017

    
1018
        mem = chirp_common.Memory()
1019
        mem.number = number
1020
        _valid = self._memobj.valid[mem.number]
1021

    
1022
        LOG.debug("Mem %d valid is %s", number, _valid == MEM_VALID)
1023
        LOG.debug("Rx Freq %s", _mem.rxfreq)
1024
        if (_valid != MEM_VALID) & (_mem.rxfreq == 0xFFFFFFFF):
1025
            mem.empty = True
1026
            return mem
1027
        elif (_valid != MEM_VALID) & ((_mem.rxfreq != 0xFFFFFFFF)
1028
              or (_mem.rxfreq != 0x00000000)):
1029
            LOG.debug("Changed chan %d %s", number, "to valid")
1030
            _valid = MEM_VALID
1031
            mem.empty = False
1032
        else:
1033
            _valid = MEM_VALID
1034
            mem.empty = False
1035
        mem.freq = int(_mem.rxfreq) * 10
1036
        _rxfreq = _freq_decode(_mem.rxfreq)
1037
        _txfreq = _freq_decode(_mem.txfreq)
1038
        mem.freq = _rxfreq
1039
        LOG.debug("Tx Freq is "+ str(_mem.txfreq))
1040
        if  _mem.txfreq == 0xFFFFFFFF:
1041
            # TX freq not set
1042
            mem.duplex = "off"
1043
            mem.offset = 0
1044
        elif int(_rxfreq) == int(_txfreq):
1045
            mem.duplex = ""
1046
            mem.offset = 0
1047
        elif abs(_rxfreq - _txfreq) > 70000000:
1048
            mem.duplex = "split"
1049
            mem.offset = _txfreq
1050
        else:
1051
            mem.duplex = _rxfreq > _txfreq and "-" or "+"
1052
            mem.offset = abs(_rxfreq - _txfreq)
1053

    
1054
        if _mem.named:
1055
            mem.name = _str_decode(self._memobj.names[number].name)
1056
        else:
1057
            mem.name = ''
1058

    
1059

    
1060
        self._get_tone(_mem, mem)
1061

    
1062
        mem.skip = "" if bool(_mem.scan_add) else "S"
1063

    
1064
        LOG.debug("Mem Power " + str(_mem.power))
1065
        pwr_index= _mem.power
1066
        if _mem.power == 3:
1067
            pwr_index = 2
1068
            LOG.debug("Force Mem Power to" + str(pwr_index))
1069
        if _mem.power:
1070
            mem.power = self.POWER_LEVELS[pwr_index]
1071
        else: 
1072
            mem.power = self.POWER_LEVELS[0]
1073
        
1074
        # mem.am_mode = _mem.power & 0x2
1075

    
1076
        # LOG.debug("Mem Power Index " + str(_mem.power))
1077
#        mem.power = self.POWER_LEVELS[_mem.power]
1078

    
1079
        if _mem.am_mode:
1080
            if _mem.isnarrow:
1081
                mem.mode = "NAM"
1082
            else:
1083
                mem.mode = "AM"
1084
        else:
1085
            mem.mode = _mem.isnarrow and "NFM" or "FM"
1086

    
1087
        mem.extra = RadioSettingGroup("Extra", "extra")
1088

    
1089
        _scram = _mem.scrambler
1090
        if _mem.scrambler > 8:
1091
            _scram = 0
1092
        # rs = RadioSetting("scrambler", "Scrambler",
1093
        #                   RadioSettingValueList(SCRAMBLER_LIST,
1094
        #                                         SCRAMBLER_LIST[_scram]))
1095
        # mem.extra.append(rs)
1096

    
1097
        # rs = RadioSetting("compander", "Compander",
1098
        #                   RadioSettingValueBoolean(_mem.compander))
1099
        # mem.extra.append(rs)
1100

    
1101
        # rs = RadioSetting("mute_mode", "Mute",
1102
        #                   RadioSettingValueMap(MUTE_MODE_MAP, _mem.mute_mode))
1103
        # mem.extra.append(rs)
1104

    
1105
        return mem
1106

    
1107
    def _set_tone(self, mem, _mem):
1108
        def _set_dcs(code, pol):
1109
            # MRT Change to 0x8000 to
1110
            # set the bit for DCS- code is a decimal version of the code # - NOT OCTAL
1111
            val = int("%i" % code, 10) | 0x8000
1112
            if pol == "R":
1113
                # MRT Change to 0x4000 to set the bit for
1114
                # i/R polarity
1115
                val += 0x4000
1116
            return val
1117

    
1118
        rx_mode = tx_mode = None
1119
        rxtone = txtone = 0x0000
1120

    
1121
        if mem.tmode == "Tone":
1122
            tx_mode = "Tone"
1123
            rx_mode = None
1124
            txtone = int(mem.rtone * 10) 
1125
        elif mem.tmode == "TSQL":
1126
            rx_mode = tx_mode = "Tone"
1127
            rxtone = txtone = int(mem.ctone * 10) 
1128
        elif mem.tmode == "DTCS":
1129
            tx_mode = rx_mode = "DTCS"
1130
            txtone = _set_dcs(mem.dtcs, mem.dtcs_polarity[0])
1131
            rxtone = _set_dcs(mem.dtcs, mem.dtcs_polarity[1])
1132
        elif mem.tmode == "Cross":
1133
            tx_mode, rx_mode = mem.cross_mode.split("->")
1134
            if tx_mode == "DTCS":
1135
                txtone = _set_dcs(mem.dtcs, mem.dtcs_polarity[0])
1136
            elif tx_mode == "Tone":
1137
                txtone = int(mem.rtone * 10) 
1138
            if rx_mode == "DTCS":
1139
                rxtone = _set_dcs(mem.rx_dtcs, mem.dtcs_polarity[1])
1140
            elif rx_mode == "Tone":
1141
                rxtone = int(mem.ctone * 10) 
1142

    
1143
        _mem.rxtone = rxtone
1144
        _mem.txtone = txtone
1145

    
1146
        LOG.debug("Set TX %s (%i) RX %s (%i)" %
1147
                  (tx_mode, _mem.txtone, rx_mode, _mem.rxtone))
1148

    
1149
    def set_memory(self, mem):
1150
#   _mem = Stored Memory value 
1151
#    mem = New value from user entry
1152
        number = mem.number
1153
        _mem = self._memobj.memory[number]
1154
        _nam = self._memobj.names[number]
1155

    
1156
        if len(mem.name) > 0:
1157
            LOG.debug("new name = %s", (mem.name))
1158
            _mem.named = True
1159
            name_encoded = _str_encode(mem.name)
1160
            LOG.debug("name endcoded = %s", (name_encoded))
1161
            LOG.debug("number = %s", (number))
1162
            for i in range(0, 8):
1163
                _nam.name[i] = ord(name_encoded[i])
1164
        else:
1165
            _mem.named = False
1166

    
1167
        # if mem.empty:
1168
        #     _mem.set_raw("\x00" * (_mem.size() / 8))
1169
        #     self._memobj.valid[number] = 0
1170
        #     self._memobj.names[number].set_raw("\x00" * (_nam.size() / 8))
1171
        #     return
1172

    
1173
        _mem.rxfreq = _freq_encode(mem.freq)
1174
        if mem.duplex == "off":
1175
            _mem.txfreq = 0xFFFFFFFF
1176
        elif mem.duplex == "split":
1177
            _mem.txfreq = _freq_encode(mem.offset)
1178
        elif mem.duplex == "+":
1179
            _mem.txfreq = _freq_encode(mem.freq + mem.offset)
1180
        elif mem.duplex == "-":
1181
            _mem.txfreq = _freq_encode(mem.freq - mem.offset)
1182
        else:
1183
            _mem.txfreq = _freq_encode(mem.freq)
1184

    
1185
        _mem.scan_add = int(mem.skip != "S")
1186

    
1187
        if mem.mode == "AM":
1188
            _mem.am_mode = True
1189
            _mem.isnarrow = False
1190
        elif mem.mode == "NAM":
1191
            _mem.am_mode = True
1192
            _mem.isnarrow = True
1193
        else:
1194
            _mem.am_mode = False
1195
            if mem.mode =="NFM":
1196
                _mem.isnarrow = True
1197
            else:
1198
                _mem.isnarrow = False
1199

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

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

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

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

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

    
1308
# Configuration Settings
1309

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

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

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

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

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

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

    
1340
        rs = RadioSetting("toa", "Timeout Alarm (TOA)",
1341
                          RadioSettingValueMap(
1342
                              TOA_MAP, _settings.toa))
1343
        cfg1_grp.append(rs)
1344

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

    
1349
        rs = RadioSetting("ring", "Ring Time (Sec)",
1350
                          RadioSettingValueMap(RING_MAP, _settings.ring))
1351
        cfg1_grp.append(rs)
1352

    
1353

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

    
1360

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

    
1365

    
1366
        rs = RadioSetting("wt_led", "Standby / WT LED",
1367
                          RadioSettingValueList(
1368
                              BACKLIGHT_LIST,
1369
                              BACKLIGHT_LIST[_settings.wt_led]))
1370
        cfg1_grp.append(rs)
1371

    
1372
        rs = RadioSetting("tx_led", "TX LED",
1373
                          RadioSettingValueList(
1374
                              BACKLIGHT_LIST,
1375
                              BACKLIGHT_LIST[_settings.tx_led]))
1376
        cfg1_grp.append(rs)
1377

    
1378
        rs = RadioSetting("rx_led", "Rx LED",
1379
                          RadioSettingValueList(
1380
                              BACKLIGHT_LIST,
1381
                              BACKLIGHT_LIST[_settings.rx_led]))
1382
        cfg1_grp.append(rs)
1383

    
1384
        rs = RadioSetting("prich_sw", "Priority Channel Scan",
1385
                          RadioSettingValueBoolean(_settings.prich_sw))
1386
        cfg1_grp.append(rs)
1387

    
1388
        rs = RadioSetting("spk_cont", "Speaker Control",
1389
                          RadioSettingValueMap(
1390
                              SPEAKER_MAP,
1391
                              _settings.spk_cont))
1392
        cfg1_grp.append(rs)
1393

    
1394
        rs = RadioSetting("autolock", "Autolock",
1395
                          RadioSettingValueBoolean(_settings.autolock))
1396
        cfg1_grp.append(rs)
1397

    
1398
        rs = RadioSetting("low_v", "Low Voltage Shutoff",
1399
                          RadioSettingValueBoolean(_settings.low_v))
1400
        cfg1_grp.append(rs)
1401

    
1402
        rs = RadioSetting("fan", "Fan Mode",
1403
                          RadioSettingValueList(
1404
                              FAN_MODE_LIST,
1405
                              FAN_MODE_LIST[_settings.fan]))
1406
        cfg1_grp.append(rs)
1407

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

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

    
1422
        rs = RadioSetting("rpt_set_model", "Model (RPT-SET)",
1423
                          RadioSettingValueList(
1424
                              RPT_MODE_LIST,
1425
                              RPT_MODE_LIST[_settings.rpt_set_model]))
1426
        cfg2_grp.append(rs)
1427

    
1428
        rs = RadioSetting("rpt_spk", "Repeater Speaker Switch (RPT-SPK)",
1429
                          RadioSettingValueBoolean(_settings.rpt_spk))
1430
        cfg2_grp.append(rs)
1431

    
1432
        rs = RadioSetting("rpt_ptt", "Repeater PTT (RPT-PTT)",
1433
                          RadioSettingValueBoolean(_settings.rpt_ptt))
1434
        cfg2_grp.append(rs)
1435

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

    
1447
        rs = RadioSetting("sc_qt", "CTCSS/DCS Scan",
1448
                          RadioSettingValueMap(
1449
                              SC_QT_MAP,_settings.sc_qt))
1450
        cfg2_grp.append(rs)
1451

    
1452
        rs = RadioSetting("pri_ch", "Priority Channel",
1453
                          RadioSettingValueInteger(
1454
                              1, 999, _chnum_decode(_settings.pri_ch)))
1455
        cfg2_grp.append(rs)
1456

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

    
1462
        rs = RadioSetting("rc_sw", "Remote Control RC-SW",
1463
                          RadioSettingValueBoolean(_settings.rc_sw))
1464
        cfg2_grp.append(rs)
1465

    
1466
        rs = RadioSetting("scan_det", "Scan DET",
1467
                          RadioSettingValueBoolean(_settings.scan_det))
1468
        cfg2_grp.append(rs)
1469

    
1470
        rs = RadioSetting("menu", "Menu Available",
1471
                          RadioSettingValueBoolean(_settings.menu))
1472
        cfg2_grp.append(rs)
1473

    
1474
        rs = RadioSetting("thr_vol_tx", "Threshold Voltage Tx",
1475
                          RadioSettingValueBoolean(_settings.thr_vol_tx))
1476
        cfg2_grp.append(rs)
1477

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

    
1484
        rs = RadioSetting("auto_am", "Auto AM",
1485
                          RadioSettingValueBoolean(_settings.auto_am))
1486
        cfg2_grp.append(rs)
1487

    
1488
        rs = RadioSetting("rpt_tone", "Repeat Tone",
1489
                          RadioSettingValueBoolean(_settings.rpt_tone))
1490
        cfg2_grp.append(rs)
1491

    
1492
        rs = RadioSetting("pf1_set", "PF1 setting",
1493
                          RadioSettingValueList(
1494
                              PF1_SETTINGS,
1495
                              PF1_SETTINGS[_settings.pf1_set]))
1496
        cfg2_grp.append(rs)
1497

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

    
1503
        dtmfchars = "0123456789"
1504
        _code =''
1505
        test = int(_oem.mode_psw)
1506
        _codeobj = '0x{0:0{1}X}'.format(test,6)
1507
        LOG.debug("codeobj = %s" % _codeobj)
1508
        _psw = str(_codeobj)
1509
        for i in range(2,8):
1510
            LOG.debug("psw[i] = %s" % _psw[i])
1511
            if _psw[i] in dtmfchars:
1512
                _code += _psw[i]
1513
        val_psw = int(_code)
1514
        LOG.debug("psw = %s" % val_psw)
1515
        val_psw = RadioSettingValueString(6, 6, _code, False)
1516
        val_psw.set_charset(dtmfchars)
1517
        rs = RadioSetting("oem.mode_psw", "MODE PSW", val_psw)
1518
        def apply_psw_id(setting, obj):
1519
            val2 = hex(int(str(val_psw),16))
1520
            LOG.debug("val2= %s" % val2)
1521
            if (int(val2,16) != 0):
1522
               while len(val2) < 8:
1523
                   val2 += '0'
1524
            psw = int(str(val2),16)
1525
            LOG.debug("val3= %s" % psw)
1526
            LOG.debug("val= %s" % val_psw)
1527
            obj.mode_psw = psw
1528
        rs.set_apply_callback(apply_psw_id, _oem)
1529
        cfg2_grp.append(rs)
1530

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

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

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

    
1564
# Freq Limits settings
1565
        
1566
        # Convert Integer back to correct limit HEX value:  limit = hex(int(str(limit*10),16))        
1567
        # # LOG.debug("limit =" % limit)
1568

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

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

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

    
1591
        _temp =str(hex(int("%i" % self._memobj.bandlimits.limit_144M_ChB_rx_stop, 10)))
1592
        _temp = int(int(_temp[2:])/10.0)
1593
        val= RadioSettingValueInteger(0,999, _temp)
1594
        rs = RadioSetting("bandlimits.limit_144M_ChB_rx_stop", "144M ChB Rx Upper Limit (MHz)",
1595
                          RadioSettingValueInteger(0,999,
1596
                              val))
1597
        rxlim_grp.append(rs)
1598

    
1599
        _temp =str(hex(int("%i" % self._memobj.bandlimits.limit_70cm_rx_start, 10)))
1600
        _temp = int(int(_temp[2:])/10.0)
1601
        val= RadioSettingValueInteger(0,999, _temp)
1602
        rs = RadioSetting("bandlimits.limit_70cm_rx_start", "450M Rx Lower Limit (MHz)",
1603
                          RadioSettingValueInteger(0,999,
1604
                              val))
1605
        rxlim_grp.append(rs)
1606

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

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

    
1623
        _temp =str(hex(int("%i" % self._memobj.bandlimits.limit_10m_rx_stop, 10)))
1624
        _temp = int(int(_temp[2:])/10.0)
1625
        val= RadioSettingValueInteger(0,999, _temp)
1626
        rs = RadioSetting("bandlimits.limit_10m_rx_stop", "20M Rx Upper Limit (MHz)",
1627
                          RadioSettingValueInteger(0,999,
1628
                              val))
1629
        rxlim_grp.append(rs)
1630

    
1631
        _temp =str(hex(int("%i" % self._memobj.bandlimits.limit_6m_rx_start, 10)))
1632
        _temp = int(int(_temp[2:])/10.0)
1633
        val= RadioSettingValueInteger(0,999, _temp)
1634
        rs = RadioSetting("bandlimits.limit_6m_rx_start", "50M Rx Lower Limit (MHz)",
1635
                          RadioSettingValueInteger(0,999,
1636
                              val))
1637
        rxlim_grp.append(rs)
1638

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

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

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

    
1663
        _temp =str(hex(int("%i" % self._memobj.bandlimits.limit_850M_rx_start, 10)))
1664
        _temp = int(int(_temp[2:])/10.0)
1665
        val= RadioSettingValueInteger(0,999, _temp)
1666
        rs = RadioSetting("bandlimits.limit_850M_rx_start", "850M Rx Lower Limit (MHz)",
1667
                          RadioSettingValueInteger(0,999,
1668
                              val))
1669
        rxlim_grp.append(rs)
1670

    
1671
        _temp =str(hex(int("%i" % self._memobj.bandlimits.limit_850M_rx_stop, 10)))
1672
        _temp = int(int(_temp[2:])/10.0)
1673
        val= RadioSettingValueInteger(0,999, _temp)
1674
        rs = RadioSetting("bandlimits.limit_850M_rx_stop", "850M Rx Upper Limit (MHz)",
1675
                          RadioSettingValueInteger(0,999,
1676
                              val))
1677
        rxlim_grp.append(rs)
1678

    
1679

    
1680
        _temp =str(hex(int("%i" % self._memobj.bandlimits.limit_144M_ChA_tx_start, 10)))
1681
        _temp = int(int(_temp[2:])/10.0)
1682
        val= RadioSettingValueInteger(0,999, _temp)
1683
        rs = RadioSetting("bandlimits.limit_144M_ChA_tx_start", "144M ChA Tx Lower Limit (MHz)",
1684
                          RadioSettingValueInteger(0,999,
1685
                              val))
1686
        txlim_grp.append(rs)
1687

    
1688
        _temp =str(hex(int("%i" % self._memobj.bandlimits.limit_144M_ChA_tx_stop, 10)))
1689
        _temp = int(int(_temp[2:])/10.0)
1690
        val= RadioSettingValueInteger(0,999, _temp)
1691
        rs = RadioSetting("bandlimits.limit_144M_ChA_tx_stop", "144M ChA Tx Upper Limit (MHz)",
1692
                          RadioSettingValueInteger(0,999,
1693
                              val))
1694
        txlim_grp.append(rs)
1695

    
1696
        _temp =str(hex(int("%i" % self._memobj.bandlimits.limit_70cm_tx_start, 10)))
1697
        _temp = int(int(_temp[2:])/10.0)
1698
        val= RadioSettingValueInteger(0,999, _temp)
1699
        rs = RadioSetting("bandlimits.limit_70cm_tx_start", "450M Tx Lower Limit (MHz)",
1700
                          RadioSettingValueInteger(0,999,
1701
                              val))
1702
        txlim_grp.append(rs)
1703

    
1704
        _temp =str(hex(int("%i" % self._memobj.bandlimits.limit_70cm_tx_stop, 10)))
1705
        _temp = int(int(_temp[2:])/10.0)
1706
        val= RadioSettingValueInteger(0,999, _temp)
1707
        rs = RadioSetting("bandlimits.limit_70cm_tx_stop", "450M tx Upper Limit (MHz)",
1708
                          RadioSettingValueInteger(0,999,
1709
                              val))
1710
        txlim_grp.append(rs)
1711

    
1712
        _temp =str(hex(int("%i" % self._memobj.bandlimits.limit_10m_tx_start, 10)))
1713
        _temp = int(int(_temp[2:])/10.0)
1714
        val= RadioSettingValueInteger(0,999, _temp)
1715
        rs = RadioSetting("bandlimits.limit_10m_tx_start", "20M tx Lower Limit (MHz)",
1716
                          RadioSettingValueInteger(0,999,
1717
                              val))
1718
        txlim_grp.append(rs)
1719

    
1720
        _temp =str(hex(int("%i" % self._memobj.bandlimits.limit_10m_tx_stop, 10)))
1721
        _temp = int(int(_temp[2:])/10.0)
1722
        val= RadioSettingValueInteger(0,999, _temp)
1723
        rs = RadioSetting("bandlimits.limit_10m_tx_stop", "20M tx Upper Limit (MHz)",
1724
                          RadioSettingValueInteger(0,999,
1725
                              val))
1726
        txlim_grp.append(rs)
1727

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

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

    
1744
# VFO Settings
1745
        rs = RadioSetting("vfomode_a", "VFO A Working Mode",
1746
                          RadioSettingValueMap(WORKMODE_MAP,
1747
                                               _settings.vfomode_a))
1748
        vfoa_grp.append(rs)
1749

    
1750
        rs = RadioSetting("vfoband_a", "VFO A Current Band",
1751
                          RadioSettingValueMap(VFOBAND_MAP,
1752
                                               _settings.vfoband_a))
1753
        vfoa_grp.append(rs)
1754

    
1755
        rs = RadioSetting("vfochan_a", "VFO A Channel",
1756
                          RadioSettingValueInteger(1, 999,
1757
                              _chnum_decode(_settings.vfochan_a)))
1758
        vfoa_grp.append(rs)
1759

    
1760
        rs = RadioSetting("vfosquelch_a", "VFO A Squelch",
1761
                          RadioSettingValueInteger(0, 9,
1762
                              _settings.vfosquelch_a))
1763
        vfoa_grp.append(rs)
1764
        rs = RadioSetting("vfostep_a", "VFO A Step",
1765
                          RadioSettingValueList(
1766
                            STEP_LIST,
1767
                            STEP_LIST[_settings.vfostep_a]))
1768
        vfoa_grp.append(rs)
1769
######################
1770

    
1771
        rs = RadioSetting("vfofreq1", "VFO 150M Freq",
1772
                          RadioSettingValueFloat(
1773
                             0, 999.999999, (_freq_decode
1774
                             (_settings.vfofreq1)/1000000.0) ,0.000001, 6))
1775
        vfo150_grp.append(rs)
1776

    
1777
        rs = RadioSetting("vfoofst1", "VFO 150M Offset",
1778
                          RadioSettingValueFloat(
1779
                              0, 999.999999, (_freq_decode
1780
                              (_settings.vfoofst1)/1000000.0),0.000001, 6))
1781
        vfo150_grp.append(rs)
1782

    
1783
        rs = RadioSetting("rxtone1", "VFO 150M Rx tone",
1784
                          RadioSettingValueMap(
1785
                            TONE_MAP, _settings.rxtone1))
1786
        vfo150_grp.append(rs)
1787

    
1788
        rs = RadioSetting("txtone1", "VFO 150M Tx tone",
1789
                          RadioSettingValueMap(
1790
                            TONE_MAP, _settings.txtone1))
1791
        vfo150_grp.append(rs)
1792

    
1793
        rs = RadioSetting("power1", "VFO 150M Power",
1794
                          RadioSettingValueMap(
1795
                            POWER_MAP, _settings.power1))
1796
        vfo150_grp.append(rs)
1797

    
1798
        rs = RadioSetting("narrow1", "VFO 150M Bandwidth",
1799
                          RadioSettingValueMap(
1800
                            BANDWIDTH_MAP, _settings.narrow1))
1801
        vfo150_grp.append(rs)
1802

    
1803
        rs = RadioSetting("mute1", "VFO 150M Mute Mode",
1804
                          RadioSettingValueMap(
1805
                            MUTE_MODE_MAP, _settings.mute1))
1806
        vfo150_grp.append(rs)
1807

    
1808
        rs = RadioSetting("shft_dir1", "VFO 150M Shift Direction",
1809
                          RadioSettingValueList(
1810
                            DUPLEX_LIST,
1811
                            DUPLEX_LIST[_settings.shft_dir1]))
1812
        vfo150_grp.append(rs)
1813

    
1814
        rs = RadioSetting("compander1", "VFO 150M Compander",
1815
                          RadioSettingValueBoolean(
1816
                            _settings.compander1))
1817
        vfo150_grp.append(rs)
1818

    
1819
        rs = RadioSetting("scrambler1", "VFO 150M Scrambler",
1820
                          RadioSettingValueList(
1821
                            SCRAMBLER_LIST,
1822
                            SCRAMBLER_LIST[_settings.scrambler1]))
1823
        vfo150_grp.append(rs)
1824
        rs = RadioSetting("am_mode1", "VFO 150M AM Mode",
1825
                          RadioSettingValueBoolean(
1826
                            _settings.am_mode1))
1827
        vfo150_grp.append(rs)
1828
############################
1829

    
1830
        rs = RadioSetting("vfofreq2", "VFO 450M Freq",
1831
                          RadioSettingValueFloat(
1832
                             0, 999.999999, (_freq_decode
1833
                             (_settings.vfofreq2)/1000000.0) ,0.000001, 6))
1834
        vfo450_grp.append(rs)
1835

    
1836
        rs = RadioSetting("vfoofst2", "VFO 450M Offset",
1837
                          RadioSettingValueFloat(
1838
                              0, 999.999999, (_freq_decode
1839
                              (_settings.vfoofst2)/1000000.0),0.000001, 6))
1840
        vfo450_grp.append(rs)
1841

    
1842
        rs = RadioSetting("rxtone2", "VFO 450M Rx tone",
1843
                          RadioSettingValueMap(
1844
                            TONE_MAP, _settings.rxtone2))
1845
        vfo450_grp.append(rs)
1846

    
1847
        rs = RadioSetting("txtone2", "VFO 450M Tx tone",
1848
                          RadioSettingValueMap(
1849
                            TONE_MAP, _settings.txtone2))
1850
        vfo450_grp.append(rs)
1851
        
1852
        rs = RadioSetting("power2", "VFO 450M Power",
1853
                          RadioSettingValueMap(
1854
                            POWER_MAP, _settings.power2))
1855
        vfo450_grp.append(rs)
1856

    
1857
        rs = RadioSetting("narrow2", "VFO 450M Bandwidth",
1858
                          RadioSettingValueMap(
1859
                            BANDWIDTH_MAP, _settings.narrow2))
1860
        vfo450_grp.append(rs)
1861

    
1862
        rs = RadioSetting("mute2", "VFO 450M Mute Mode",
1863
                          RadioSettingValueMap(
1864
                            MUTE_MODE_MAP, _settings.mute2))
1865
        vfo450_grp.append(rs)
1866

    
1867
        rs = RadioSetting("shft_dir2", "VFO 450M Shift Direction",
1868
                          RadioSettingValueList(
1869
                            DUPLEX_LIST,
1870
                            DUPLEX_LIST[_settings.shft_dir2]))
1871
        vfo450_grp.append(rs)
1872

    
1873
        rs = RadioSetting("compander2", "VFO 450M Compander",
1874
                          RadioSettingValueBoolean(
1875
                            _settings.compander2))
1876
        vfo450_grp.append(rs)
1877

    
1878
        rs = RadioSetting("scrambler2", "VFO 450M Scrambler",
1879
                          RadioSettingValueList(
1880
                            SCRAMBLER_LIST,
1881
                            SCRAMBLER_LIST[_settings.scrambler2]))
1882
        vfo450_grp.append(rs)
1883

    
1884
        rs = RadioSetting("am_mode2", "VFO 450M AM Mode",
1885
                          RadioSettingValueBoolean(
1886
                            _settings.am_mode2))
1887
        vfo450_grp.append(rs)
1888
############################
1889
        rs = RadioSetting("vfofreq3", "VFO 20M Freq",
1890
                          RadioSettingValueFloat(
1891
                             0, 999.999999, (_freq_decode
1892
                             (_settings.vfofreq3)/1000000.0) ,0.000001, 6))
1893
        vfo20_grp.append(rs)
1894

    
1895
        rs = RadioSetting("vfoofst3", "VFO 20M Offset",
1896
                          RadioSettingValueFloat(
1897
                              0, 999.999999, (_freq_decode
1898
                              (_settings.vfoofst3)/1000000.0),0.000001, 6))
1899
        vfo20_grp.append(rs)
1900

    
1901
        rs = RadioSetting("rxtone3", "VFO 20M Rx tone",
1902
                          RadioSettingValueMap(
1903
                            TONE_MAP, _settings.rxtone3))
1904
        vfo20_grp.append(rs)
1905

    
1906
        rs = RadioSetting("txtone3", "VFO 20M Tx tone",
1907
                          RadioSettingValueMap(
1908
                            TONE_MAP, _settings.txtone3))
1909
        vfo20_grp.append(rs)
1910
        
1911
        rs = RadioSetting("power3", "VFO 20M Power",
1912
                          RadioSettingValueMap(
1913
                            POWER_MAP, _settings.power3))
1914
        vfo20_grp.append(rs)
1915

    
1916
        rs = RadioSetting("narrow3", "VFO 20M Bandwidth",
1917
                          RadioSettingValueMap(
1918
                            BANDWIDTH_MAP, _settings.narrow3))
1919
        vfo20_grp.append(rs)
1920

    
1921
        rs = RadioSetting("mute3", "VFO 20M Mute Mode",
1922
                          RadioSettingValueMap(
1923
                            MUTE_MODE_MAP, _settings.mute3))
1924
        vfo20_grp.append(rs)
1925

    
1926
        rs = RadioSetting("shft_dir3", "VFO 20M Shift Direction",
1927
                          RadioSettingValueList(
1928
                            DUPLEX_LIST,
1929
                            DUPLEX_LIST[_settings.shft_dir3]))
1930
        vfo20_grp.append(rs)
1931

    
1932
        rs = RadioSetting("compander3", "VFO 20M Compander",
1933
                          RadioSettingValueBoolean(
1934
                            _settings.compander3))
1935
        vfo20_grp.append(rs)
1936

    
1937
        rs = RadioSetting("scrambler3", "VFO 20M Scrambler",
1938
                          RadioSettingValueList(
1939
                            SCRAMBLER_LIST,
1940
                            SCRAMBLER_LIST[_settings.scrambler3]))
1941
        vfo20_grp.append(rs)
1942

    
1943
        rs = RadioSetting("am_mode3", "VFO 20M AM Mode",
1944
                          RadioSettingValueBoolean(
1945
                            _settings.am_mode3))
1946
        vfo20_grp.append(rs)
1947
############################
1948
        rs = RadioSetting("vfofreq4", "VFO 50M Freq",
1949
                          RadioSettingValueFloat(
1950
                             0, 999.999999, (_freq_decode
1951
                             (_settings.vfofreq4)/1000000.0) ,0.000001, 6))
1952
        vfo50_grp.append(rs)
1953

    
1954
        rs = RadioSetting("vfoofst4", "VFO 50M Offset",
1955
                          RadioSettingValueFloat(
1956
                              0, 999.999999, (_freq_decode
1957
                              (_settings.vfoofst4)/1000000.0),0.000001, 6))
1958
        vfo50_grp.append(rs)
1959

    
1960
        rs = RadioSetting("rxtone4", "VFO 50M Rx tone",
1961
                          RadioSettingValueMap(
1962
                            TONE_MAP, _settings.rxtone4))
1963
        vfo50_grp.append(rs)
1964

    
1965
        rs = RadioSetting("txtone4", "VFO 50M Tx tone",
1966
                          RadioSettingValueMap(
1967
                            TONE_MAP, _settings.txtone4))
1968
        vfo50_grp.append(rs)
1969
        
1970
        rs = RadioSetting("power4", "VFO 50M Power",
1971
                          RadioSettingValueMap(
1972
                            POWER_MAP, _settings.power4))
1973
        vfo50_grp.append(rs)
1974

    
1975
        rs = RadioSetting("narrow4", "VFO 50M Bandwidth",
1976
                          RadioSettingValueMap(
1977
                            BANDWIDTH_MAP, _settings.narrow4))
1978
        vfo50_grp.append(rs)
1979

    
1980
        rs = RadioSetting("mute4", "VFO 50M Mute Mode",
1981
                          RadioSettingValueMap(
1982
                            MUTE_MODE_MAP, _settings.mute4))
1983
        vfo50_grp.append(rs)
1984

    
1985
        rs = RadioSetting("shft_dir4", "VFO 50M Shift Direction",
1986
                          RadioSettingValueList(
1987
                            DUPLEX_LIST,
1988
                            DUPLEX_LIST[_settings.shft_dir4]))
1989
        vfo50_grp.append(rs)
1990

    
1991
        rs = RadioSetting("compander4", "VFO 50M Compander",
1992
                          RadioSettingValueBoolean(
1993
                            _settings.compander4))
1994
        vfo50_grp.append(rs)
1995

    
1996
        rs = RadioSetting("scrambler4", "VFO 50M Scrambler",
1997
                          RadioSettingValueList(
1998
                            SCRAMBLER_LIST,
1999
                            SCRAMBLER_LIST[_settings.scrambler4]))
2000
        vfo50_grp.append(rs)
2001

    
2002
        rs = RadioSetting("am_mode4", "VFO 50M AM Mode",
2003
                          RadioSettingValueBoolean(
2004
                            _settings.am_mode4))
2005
        vfo50_grp.append(rs)
2006
############################
2007
        rs = RadioSetting("vfofreq5", "VFO 350M Freq",
2008
                          RadioSettingValueFloat(
2009
                             0, 999.999999, (_freq_decode
2010
                             (_settings.vfofreq5)/1000000.0) ,0.000001, 6))
2011
        vfo350_grp.append(rs)
2012

    
2013
        rs = RadioSetting("vfoofst5", "VFO 350M Offset",
2014
                          RadioSettingValueFloat(
2015
                              0, 999.999999, (_freq_decode
2016
                              (_settings.vfoofst5)/1000000.0),0.000001, 6))
2017
        vfo350_grp.append(rs)
2018

    
2019
        rs = RadioSetting("rxtone5", "VFO 350M Rx tone",
2020
                          RadioSettingValueMap(
2021
                            TONE_MAP, _settings.rxtone5))
2022
        vfo350_grp.append(rs)
2023

    
2024
        rs = RadioSetting("txtone5", "VFO 350M Tx tone",
2025
                          RadioSettingValueMap(
2026
                            TONE_MAP, _settings.txtone5))
2027
        vfo350_grp.append(rs)
2028
        
2029
        rs = RadioSetting("power5", "VFO 350M Power",
2030
                          RadioSettingValueMap(
2031
                            POWER_MAP, _settings.power5))
2032
        vfo350_grp.append(rs)
2033

    
2034
        rs = RadioSetting("narrow5", "VFO 350M Bandwidth",
2035
                          RadioSettingValueMap(
2036
                            BANDWIDTH_MAP, _settings.narrow5))
2037
        vfo350_grp.append(rs)
2038

    
2039
        rs = RadioSetting("mute5", "VFO 350M Mute Mode",
2040
                          RadioSettingValueMap(
2041
                            MUTE_MODE_MAP, _settings.mute5))
2042
        vfo350_grp.append(rs)
2043

    
2044
        rs = RadioSetting("shft_dir5", "VFO 350M Shift Direction",
2045
                          RadioSettingValueList(
2046
                            DUPLEX_LIST,
2047
                            DUPLEX_LIST[_settings.shft_dir5]))
2048
        vfo350_grp.append(rs)
2049

    
2050
        rs = RadioSetting("compander5", "VFO 350M Compander",
2051
                          RadioSettingValueBoolean(
2052
                            _settings.compander5))
2053
        vfo350_grp.append(rs)
2054

    
2055
        rs = RadioSetting("scrambler5", "VFO 350M Scrambler",
2056
                          RadioSettingValueList(
2057
                            SCRAMBLER_LIST,
2058
                            SCRAMBLER_LIST[_settings.scrambler5]))
2059
        vfo350_grp.append(rs)
2060

    
2061
        rs = RadioSetting("am_mode5", "VFO 350M AM Mode",
2062
                          RadioSettingValueBoolean(
2063
                            _settings.am_mode5))
2064
        vfo350_grp.append(rs)
2065

    
2066
# ############################
2067
        rs = RadioSetting("vfofreq6", "VFO 850M Freq",
2068
                          RadioSettingValueFloat(
2069
                             0, 999.999999, (_freq_decode
2070
                             (_settings.vfofreq6)/1000000.0) ,0.000001, 6))
2071
        vfo850_grp.append(rs)
2072

    
2073
        rs = RadioSetting("vfoofst6", "VFO 850M Offset",
2074
                          RadioSettingValueFloat(
2075
                              0, 999.999999, (_freq_decode
2076
                              (_settings.vfoofst6)/1000000.0),0.000001, 6))
2077
        vfo850_grp.append(rs)
2078

    
2079
        rs = RadioSetting("rxtone6", "VFO 850M Rx tone",
2080
                          RadioSettingValueMap(
2081
                            TONE_MAP, _settings.rxtone6))
2082
        vfo850_grp.append(rs)
2083

    
2084
        rs = RadioSetting("txtone6", "VFO 850M Tx tone",
2085
                          RadioSettingValueMap(
2086
                            TONE_MAP, _settings.txtone6))
2087
        vfo850_grp.append(rs)
2088
        
2089
        rs = RadioSetting("power6", "VFO 850M Power",
2090
                          RadioSettingValueMap(
2091
                            POWER_MAP, _settings.power6))
2092
        vfo850_grp.append(rs)
2093

    
2094
        rs = RadioSetting("narrow6", "VFO 850M Bandwidth",
2095
                          RadioSettingValueMap(
2096
                            BANDWIDTH_MAP, _settings.narrow6))
2097
        vfo850_grp.append(rs)
2098

    
2099
        rs = RadioSetting("mute6", "VFO 850M Mute Mode",
2100
                          RadioSettingValueMap(
2101
                            MUTE_MODE_MAP, _settings.mute6))
2102
        vfo850_grp.append(rs)
2103

    
2104
        rs = RadioSetting("shft_dir6", "VFO 850M Shift Direction",
2105
                          RadioSettingValueList(
2106
                            DUPLEX_LIST,
2107
                            DUPLEX_LIST[_settings.shft_dir6]))
2108
        vfo850_grp.append(rs)
2109

    
2110
        rs = RadioSetting("compander6", "VFO 850M Compander",
2111
                          RadioSettingValueBoolean(
2112
                            _settings.compander6))
2113
        vfo850_grp.append(rs)
2114

    
2115
        rs = RadioSetting("scrambler6", "VFO 850M Scrambler",
2116
                          RadioSettingValueList(
2117
                            SCRAMBLER_LIST,
2118
                            SCRAMBLER_LIST[_settings.scrambler6]))
2119
        vfo850_grp.append(rs)
2120

    
2121
        rs = RadioSetting("am_mode6", "VFO 850M AM Mode",
2122
                          RadioSettingValueBoolean(
2123
                            _settings.am_mode6))
2124
        vfo850_grp.append(rs)
2125

    
2126
############################
2127

    
2128
        rs = RadioSetting("vfomode_b", "VFO B Working Mode",
2129
                          RadioSettingValueMap(WORKMODE_MAP,
2130
                                               _settings.vfomode_b))
2131
        vfob_grp.append(rs)
2132

    
2133
        rs = RadioSetting("vfochan_b", "VFO B Work Channel",
2134
                          RadioSettingValueInteger(1, 999,
2135
                              _chnum_decode(_settings.vfochan_b)))
2136
        vfob_grp.append(rs)
2137

    
2138
        rs = RadioSetting("vfofreq7", "VFO B Freq",
2139
                          RadioSettingValueFloat(
2140
                             0, 999.999999, (_freq_decode
2141
                             (_settings.vfofreq7)/1000000.0) ,0.000001, 6))
2142
        vfob_grp.append(rs)
2143

    
2144
        rs = RadioSetting("vfoofst7", "VFO B Offset",
2145
                          RadioSettingValueFloat(
2146
                              0, 999.999999, (_freq_decode
2147
                              (_settings.vfoofst7)/1000000.0),0.000001, 6))
2148
        vfob_grp.append(rs)
2149

    
2150
        rs = RadioSetting("rxtone7", "VFOB Rx tone",
2151
                          RadioSettingValueMap(
2152
                            TONE_MAP, _settings.rxtone7))
2153
        vfob_grp.append(rs)
2154

    
2155
        rs = RadioSetting("txtone7", "VFOB Tx tone",
2156
                          RadioSettingValueMap(
2157
                            TONE_MAP, _settings.txtone7))
2158
        vfob_grp.append(rs)
2159
        rs = RadioSetting("power7", "VFOB Power",
2160
                          RadioSettingValueMap(
2161
                            POWER_MAP, _settings.power7))
2162
        vfob_grp.append(rs)
2163
        rs = RadioSetting("narrow7", "VFOB Bandwidth",
2164
                          RadioSettingValueMap(
2165
                            BANDWIDTH_MAP, _settings.narrow7))
2166
        vfob_grp.append(rs)
2167
        rs = RadioSetting("mute7", "VFOB Mute Mode",
2168
                          RadioSettingValueMap(
2169
                            MUTE_MODE_MAP, _settings.mute7))
2170
        vfob_grp.append(rs)
2171
        rs = RadioSetting("shft_dir7", "VFOB Shift Direction",
2172
                          RadioSettingValueList(
2173
                            DUPLEX_LIST,
2174
                            DUPLEX_LIST[_settings.shft_dir7]))
2175
        vfob_grp.append(rs)
2176
        rs = RadioSetting("compander7", "VFOB Compander",
2177
                          RadioSettingValueBoolean(
2178
                            _settings.compander7))
2179
        vfob_grp.append(rs)
2180

    
2181
        rs = RadioSetting("scrambler7", "VFOB Scrambler",
2182
                          RadioSettingValueList(
2183
                            SCRAMBLER_LIST,
2184
                            SCRAMBLER_LIST[_settings.scrambler7]))
2185
        vfob_grp.append(rs)
2186

    
2187
        rs = RadioSetting("vfosquelch_b", "VFO B Squelch",
2188
                          RadioSettingValueInteger(0, 9,
2189
                              _settings.vfosquelch_b))
2190
        vfob_grp.append(rs)
2191
        rs = RadioSetting("vfostep_b", "VFO B Step",
2192
                          RadioSettingValueList(
2193
                            STEP_LIST,
2194
                            STEP_LIST[_settings.vfostep_b]))
2195
        vfob_grp.append(rs)
2196
        # rs = RadioSetting("am_mode7", "VFOB AM Mode",
2197
        #                   RadioSettingValueBoolean(
2198
        #                     _settings.am_mode7))
2199
        # vfob_grp.append(rs)
2200

    
2201
# Scan Group Settings
2202
        def _decode(lst):
2203
            _str = ''.join([chr(c) for c in lst
2204
                            if chr(c) in chirp_common.CHARSET_ASCII])
2205
            return _str
2206

    
2207
        rs = RadioSetting("scan_a_act", "Scan A Active Group",
2208
                        RadioSettingValueList(
2209
                            SCAN_GROUP_LIST,
2210
                            SCAN_GROUP_LIST[_settings.scan_a_act]))
2211
        scan_grp.append(rs)
2212
        rs = RadioSetting("scan_b_act", "Scan B Active Group",
2213
                        RadioSettingValueList(
2214
                             SCAN_GROUP_LIST,
2215
                             SCAN_GROUP_LIST[_settings.scan_b_act]))
2216
        scan_grp.append(rs)
2217
       
2218

    
2219
        for i in range(1,11):
2220
            x=str(i)
2221
            _str = _decode(eval("_settings.scanname"+x))
2222
            val = RadioSettingValueString(0, 6, _str)
2223
            val.set_mutable(True)
2224
            rs = RadioSetting("scanname"+x, "Scan Name "+x, val)
2225
            scanname_grp.append(rs)
2226

    
2227
            scngrp = str(i)
2228
            rs = RadioSetting("scanlower"+scngrp, "Scan Lower "+scngrp,
2229
                            RadioSettingValueInteger(1, 999,  
2230
                            eval("_settings.scanlower"+scngrp)))
2231
            scan_grp.append(rs)
2232
            rs = RadioSetting("scanupper"+scngrp, "Scan Upper "+scngrp,
2233
                            RadioSettingValueInteger(1, 999,  
2234
                            eval("_settings.scanupper"+scngrp)))
2235
            scan_grp.append(rs)
2236
# remote settings
2237
        rs = RadioSetting("rc_power", "RC Power",
2238
                           RadioSettingValueList(
2239
                                    RC_POWER_LIST,
2240
                                    RC_POWER_LIST[_settings.rc_power]))
2241
        remote_grp.append(rs)
2242

    
2243
        _code =''
2244
        test = int(_settings.ani_edit)
2245
        _codeobj = '0x{0:0{1}X}'.format(test,6)
2246
        LOG.debug("codeobj = %s" % _codeobj)
2247
        _ani = str(_codeobj)
2248
        for i in range(2,8):
2249
            LOG.debug("ani[i] = %s" % _ani[i])
2250
            if _ani[i] in dtmfchars:
2251
                _code += _ani[i]
2252
        val_ani = int(_code)
2253
        LOG.debug("ani = %s" % val_ani)
2254
        val_ani = RadioSettingValueString(3, 6, _code, False)
2255
        val_ani.set_charset(dtmfchars)
2256
        rs = RadioSetting("settings.ani_edit", "ANI Edit", val_ani)
2257
        def apply_ani_id(setting, obj):
2258
            temp = list()
2259
            LOG.debug("val= %s" % val_ani)
2260
            if str(val_ani)[0] == "0":
2261
                raise errors.RadioError("ANI EDIT must start with Non-Zero Digit")
2262
            val2 = hex(int(str(val_ani),16))
2263
            LOG.debug("val2= %s" % val2)
2264
            if (int(val2,16) != 0):
2265
               while len(val2) < 5:
2266
                   val2 += '0'
2267
               while len(val2) < 8:
2268
                   val2 += 'C'
2269
            ani = int(str(val2),16)
2270
            LOG.debug("ani= %s" % ani)
2271
            LOG.debug("val= %s" % val_ani)
2272
            obj.ani_edit = ani
2273
        rs.set_apply_callback(apply_ani_id, _settings)
2274
        remote_grp.append(rs)
2275

    
2276
        _code =''
2277
        test = int(_settings.mcc_edit)
2278
        _codeobj = '0x{0:0{1}X}'.format(test,6)
2279
        LOG.debug("codeobj = %s" % _codeobj)
2280
        _mcc = str(_codeobj)
2281
        for i in range(2,8):
2282
            LOG.debug("mcc[i] = %s" % _mcc[i])
2283
            if _mcc[i] in dtmfchars:
2284
                _code += _mcc[i]
2285
        val_mcc = int(_code)
2286
        LOG.debug("mcc = %s" % val_mcc)
2287
        val_mcc = RadioSettingValueString(3, 6, _code, False)
2288
        val_mcc.set_charset(dtmfchars)
2289
        rs = RadioSetting("mcc_edit", "MCC Edit", val_mcc)
2290
        def apply_mcc_id(setting, obj):
2291
            val2 = hex(int(str(val_mcc),16))
2292
            LOG.debug("val2= %s" % val2)
2293
            if (int(val2,16) != 0):
2294
               while len(val2) < 5:
2295
                   val2 += '0'
2296
               while len(val2) < 8:
2297
                   val2 += 'C'
2298
            mcc = int(str(val2),16)
2299
            LOG.debug("val3= %s" % mcc)
2300
            LOG.debug("val= %s" % val_mcc)
2301
            obj.mcc_edit = mcc
2302
        rs.set_apply_callback(apply_mcc_id, _settings)
2303
        remote_grp.append(rs)
2304

    
2305
        _code =''
2306
        test = int(_settings.scc_edit)
2307
        _codeobj = '0x{0:0{1}X}'.format(test,6)
2308
        LOG.debug("codeobj = %s" % _codeobj)
2309
        _scc = str(_codeobj)
2310
        for i in range(2,8):
2311
            LOG.debug("scc[i] = %s" % _scc[i])
2312
            if _scc[i] in dtmfchars:
2313
                _code += _scc[i]
2314
        val_scc = int(_code)
2315
        LOG.debug("scc = %s" % val_scc)
2316
        val_scc = RadioSettingValueString(3, 6, _code, False)
2317
        val_scc.set_charset(dtmfchars)
2318
        rs = RadioSetting("scc_edit", "SCC Edit", val_scc)
2319
        def apply_scc_id(setting, obj):
2320
            val2 = hex(int(str(val_scc),16))
2321
            LOG.debug("val2= %s" % val2)
2322
            if (int(val2,16) != 0):
2323
               while len(val2) < 5:
2324
                   val2 += '0'
2325
               while len(val2) < 8:
2326
                   val2 += 'C'
2327
            scc = int(str(val2),16)
2328
            LOG.debug("val3= %s" % scc)
2329
            LOG.debug("val= %s" % val_scc)
2330
            obj.scc_edit = scc
2331
        rs.set_apply_callback(apply_scc_id, _settings)
2332
        remote_grp.append(rs)
2333

    
2334
        _code =''
2335
        test = int(_settings.ctrl_edit)
2336
        _codeobj = '0x{0:0{1}X}'.format(test,6)
2337
        LOG.debug("codeobj = %s" % _codeobj)
2338
        _ctrl = str(_codeobj)
2339
        for i in range(2,8):
2340
            LOG.debug("ctrl[i] = %s" % _ctrl[i])
2341
            if _ctrl[i] in dtmfchars:
2342
                _code += _ctrl[i]
2343
        val_ctrl = int(_code)
2344
        LOG.debug("ctrl = %s" % val_ctrl)
2345
        val_ctrl = RadioSettingValueString(3, 6, _code, False)
2346
        val_ctrl.set_charset(dtmfchars)
2347
        rs = RadioSetting("ctrl_edit", "CTRL Edit", val_ctrl)
2348
        def apply_ctrl_id(setting, obj):
2349
            val2 = hex(int(str(val_ctrl),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
            ctrl = int(str(val2),16)
2357
            LOG.debug("val3= %s" % ctrl)
2358
            LOG.debug("val= %s" % val_ctrl)
2359
            obj.ctrl_edit = ctrl
2360
        rs.set_apply_callback(apply_ctrl_id, _settings)
2361
        remote_grp.append(rs)
2362

    
2363

    
2364

    
2365

    
2366

    
2367
# OEM Settings
2368

    
2369
        _oem_name = _oem_str_decode(self._memobj.oem.display_name)
2370
        rs=RadioSetting("oem.display_name", "Display Banner Text",
2371
                        RadioSettingValueString(1,8, _oem_name))
2372
        oem_grp.append(rs)
2373

    
2374
# FM RADIO PRESETS
2375

    
2376
# memory stores raw integer value like 7600
2377
# radio will divide 7600 by 100 and interpret correctly at 76.0Mhz
2378
        #
2379
        # FM Radio Presets Settings
2380
        #
2381
        for i in range(1, 21):
2382
            chan = str(i)
2383
            rs = RadioSetting("FM_radio" + chan, "FM Preset " + chan,
2384
                              RadioSettingValueFloat(76.0, 108.0,
2385
                                                     eval("_settings.FM_radio" +
2386
                                                          chan)/100.0,
2387
                                                     0.1, 1))
2388
            fmradio_grp.append(rs)
2389
        
2390
        return group
2391

    
2392
    def get_settings(self):
2393
        try:
2394
            return self._get_settings()
2395
        except:
2396
            import traceback
2397
            LOG.error("Failed to parse settings: %s", traceback.format_exc())
2398
            return None
2399

    
2400
    def set_settings(self, settings):
2401
        for element in settings:
2402
            if not isinstance(element, RadioSetting):
2403
                self.set_settings(element)
2404
                continue
2405
            else:
2406
                try:
2407
                    if "." in element.get_name():
2408
                        bits = element.get_name().split(".")
2409
                        obj = self._memobj
2410
                        for bit in bits[:-1]:
2411
                            obj = getattr(obj, bit)
2412
                        setting = bits[-1]
2413
                    else:
2414
                        obj = self._memobj.settings
2415
                        setting = element.get_name()
2416

    
2417
                    if element.has_apply_callback():
2418
                        LOG.debug("Using apply callback")
2419
                        element.run_apply_callback()
2420
                    else:
2421
                        LOG.debug("Setting %s = %s" % (setting, element.value))
2422
                        if self._is_freq(element):
2423
                            # setattr(obj, setting, int(element.value / 10))
2424
                            # MRT rescale freq values to match radio
2425
                            # expected values
2426
                            value = _freq_encode(element[0].get_value()*1000000.0)
2427
                            setattr(obj, setting, value)
2428

    
2429
                        elif self._is_fmradio_or_voltage(element):
2430
                            # MRT rescale FM Radio values to match radio
2431
                            # expected values
2432
                            setattr(obj, setting,
2433
                                    int(element.values()[0]._current * 100.0))
2434

    
2435
                        elif self._is_limit(element):
2436
                            setattr(obj, setting,
2437
                                    int(str(element.values()[0]._current * 10), 16))
2438
                # Special VFO A Settings
2439
                #
2440
                        elif self._is_chan(element):
2441
                            value = _chnum_encode(element[0].get_value())
2442
                            setattr(obj, setting, value)
2443
                            continue
2444
                #
2445
                        elif self._is_display_name(element):
2446
                            string=element[0].get_value()
2447
                            nameenc = _oem_str_encode(string)
2448
                            for i in range(0,8):
2449
                                LOG.debug("nameenc %s" % (nameenc[i]))
2450
                                self._memobj.oem.display_name[i] = ord(nameenc[i])
2451
                                # setattr(obj, setting, int(ord(nameenc[i])))
2452
                        else:
2453
                            setattr(obj, setting, element.value)
2454
                except Exception, e:
2455
                    LOG.debug(element.get_name())
2456
                    raise
2457

    
2458
    def _is_freq(self, element):
2459
        return "rxfreq" in element.get_name() or \
2460
               "txoffset" in element.get_name() or \
2461
               "vfofreq" in element.get_name() or\
2462
               "vfoofst" in element.get_name() 
2463
        #  "rx_start" in element.get_name() or \
2464
        #  "rx_stop" in element.get_name() or \
2465
        #  "tx_start" in element.get_name() or \
2466
        #  "tx_stop" in element.get_name()
2467

    
2468
    def _is_limit(self, element):
2469
        return "limit" in element.get_name()
2470

    
2471
    def _is_fmradio_or_voltage(self, element):
2472
        return "FM_radio" in element.get_name() or\
2473
                "thr_vol_lvl" in element.get_name()
2474

    
2475
    
2476
    def _is_chan(self, element):
2477
        return "vfochan" in element.get_name() or\
2478
               "pri_ch" in element.get_name()
2479

    
2480
    def _is_display_name(self, element):
2481
        return "display_name" in element.get_name() 
2482
   
2483
    # def _is_vfofreq(self, element):
2484
    #     return "vfofreq" in element.get_name() or\
2485
    #            "vfoofst" in element.get_name()
(3-3/8)