Project

General

Profile

New Model #7223 » kguv980p b2.1.py

KG-UV980P Beta 2.1 Driver - Mel Terechenok, 10/21/2022 04:10 AM

 
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
SCANNAME_CHARSET = "0123456789" + \
56
          ":;<=>?@" + \
57
          "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + \
58
          "[\]^_`" + \
59
          "abcdefghijklmnopqrstuvwxyz" + \
60
          "{|}~\x4E\x00" + \
61
          " !\"#$%&'()*+,-./"
62

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

    
142

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

    
146
_MEM_FORMAT = """
147
    #seekto 0x004c;
148
    struct {
149
        u24 mode_psw;
150
        u8  xunk04F;
151
        u8  display_name[8];
152
    } oem;
153

    
154
    #seekto 0x0060;
155
    struct {
156
        u16    limit_144M_ChA_rx_start;
157
        u16    limit_144M_ChA_rx_stop;    
158
        u16    limit_70cm_rx_start;
159
        u16    limit_70cm_rx_stop;    
160
        u16    limit_10m_rx_start;
161
        u16    limit_10m_rx_stop;    
162
        u16    limit_6m_rx_start;
163
        u16    limit_6m_rx_stop;    
164
        u16    limit_350M_rx_start;
165
        u16    limit_350M_rx_stop;    
166
        u16    limit_850M_rx_start;
167
        u16    limit_850M_rx_stop;    
168
        u16    limit_144M_ChA_tx_start;
169
        u16    limit_144M_ChA_tx_stop;    
170
        u16    limit_70cm_tx_start;
171
        u16    limit_70cm_tx_stop;    
172
        u16    limit_10m_tx_start;
173
        u16    limit_10m_tx_stop;    
174
        u16    limit_6m_tx_start;
175
        u16    limit_6m_tx_stop;    
176
        u16    limit_144M_ChB_rx_start;
177
        u16    limit_144M_ChB_rx_stop;
178
    } bandlimits;
179

    
180

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

    
473

    
474
    #seekto 0x09f0;
475
    struct {
476
        u32     rxfreq;
477
        u32     txfreq;
478
        u16     txtone;
479
        u16     rxtone;
480
        u8      unknown1:3,
481
                mute_mode:2,
482
                unknown2:3;
483
        u8      named:1,
484
                scan_add:1,
485
                extra_power_bit:1,
486
                power:2,
487
                am_mode:1,
488
                unknownbit2:1,
489
                isnarrow:1;
490
        u8      unknown3:6,
491
                Unknown4_shft_dir:2;
492
        u8      unknown5:3,
493
                compander:1
494
                scrambler:4;
495
    } memory[1000];
496

    
497
    #seekto 0x48f8;
498
    struct {
499
        u8    name[8];
500
    } names[1000];
501

    
502
    #seekto 0x6fff;
503
    u8          valid[1000];
504
    """
505

    
506
def _freq_decode(in_freq, bytes=4):
507
    out_freq = 0
508
    for i in range(bytes*2):
509
        out_freq += (in_freq & 0xF) * (10 ** i)
510
        in_freq = in_freq >> 4
511
    if bytes == 4:
512
        return out_freq * 10
513
    elif bytes == 2:
514
        return out_freq * 100000
515

    
516

    
517
def _freq_encode(in_freq, bytes=4):
518
    if bytes == 4:
519
        return int('%08d' % (in_freq / 10), 16)
520
    elif bytes == 2:
521
        return int('%04d' % (in_freq / 100000), 16)
522

    
523
def _oem_str_decode(in_str):
524
    out_str = ''
525
    stopchar = FALSE
526
    for c in in_str:
527
        if c !=0x50 and stopchar==FALSE:
528
            if chr(c+48) in chirp_common.CHARSET_ASCII:
529
                out_str+= chr(c+48)
530
        else:
531
            out_str+=''
532
            stopchar = TRUE
533
    return out_str
534

    
535
def _oem_str_encode(in_str):
536
    out_str = ''
537
    LOG.debug("OEM Input String = %s", in_str)
538
    for c in in_str:
539
        try:
540
            out_str += chr(int(ord(c))-48)
541
        except ValueError:
542
            pass
543
    while len(out_str) < 8:
544
        out_str += chr(0x50)
545
    LOG.debug("OEM Ouput String = %s", out_str)
546
    return out_str
547

    
548

    
549
def _str_decode(in_str):
550
    out_str = ''
551
    stopchar = FALSE
552
    for c in in_str:
553
        if c !=0x00 and stopchar==FALSE:
554
            if chr(c) in chirp_common.CHARSET_ASCII:
555
                out_str+= chr(c)
556
        else:
557
            out_str+=''
558
            stopchar = TRUE
559
    return out_str
560

    
561

    
562
def _str_encode(in_str):
563
    out_str = ''
564
    for c in in_str:
565
        try:
566
            out_str += chr(ord(c))
567
        except ValueError:
568
            pass
569
    while len(out_str) < 8:
570
        out_str += chr(0x00)
571
    if out_str == "        " or out_str == "":
572
        out_str = "\x00\x00\x00\x00\x00\x00\x00\x00"
573
    return out_str
574

    
575
def _chnum_decode(in_ch):
576
    return int(('%04x' % in_ch)[0:3])
577

    
578

    
579
def _chnum_encode(in_ch):
580
    return int('%03d0' % in_ch, 16)
581

    
582
# Support for the Wouxun KG-UV980P radio
583
# Serial coms are at 19200 baud
584
# The data is passed in variable length records
585
# Record structure:
586
#  Offset   Usage
587
#    0      start of record (\x7c)
588
#    1      Command (\x80 Identify \x81 End/Reboot \x82 Read \x83 Write)
589
#    2      direction (\xff PC-> Radio, \x00 Radio -> PC)
590
#    3      length of payload (excluding header/checksum) (n)
591
#    4      payload (n bytes)
592
#    4+n+1  checksum - only lower 4 bits of byte sum (% 256) of bytes 1 -> 4+n
593
#
594
# Memory Read Records:
595
# the payload is 3 bytes, first 2 are offset (big endian),
596
# 3rd is number of bytes to read
597
# Memory Write Records:
598
# the maximum payload size (from the Wouxun software) seems to be 66 bytes
599
#  (2 bytes location + 64 bytes data).
600

    
601

    
602

    
603
class KGUV8TRadio(chirp_common.Alias):
604
    VENDOR = "Wouxun"
605
    MODEL = "KG-UV980P"
606

    
607

    
608
@directory.register
609
class KG980GRadio(chirp_common.CloneModeRadio,
610
                  chirp_common.ExperimentalRadio):
611

    
612
    """Wouxun KG-UV980P"""
613
    VENDOR = "Wouxun"
614
    MODEL = "KG-UV980P"
615
    _model = "KG-UV950R2"
616
    _file_ident = "980P"
617
    BAUD_RATE = 19200
618

    
619
    POWER_LEVELS = [chirp_common.PowerLevel("L", watts=1.0), 
620
                    chirp_common.PowerLevel("M", watts=20.0), 
621
                    chirp_common.PowerLevel("H", watts=50.0)]
622
    _mmap = ""
623
    ALIASES = [KGUV8TRadio, ]
624

    
625
    def _checksum(self, data):
626
        cs = 0
627
        for byte in data:
628
            cs += ord(byte)
629
        return chr(cs % 256)
630

    
631
    # def _write_record_id(self):
632
	# _header = '\xda\x80\xff\x00\x58'
633
    #     LOG.error("Sent:\n%s" % util.hexprint(_header))
634
	# self.pipe.write(_header)
635

    
636
    def _write_record(self, cmd, payload=None):
637
        # build the packet
638
        _header = '\xda' + chr(cmd) + '\xff'
639

    
640
        _length = 0
641
        if payload:
642
            _length = len(payload)
643

    
644
        # update the length field
645
        _header += chr(_length)
646

    
647
        if payload:
648
            # calculate checksum then add it with the payload
649
            # to the packet and encrypt
650
            crc = self._checksum(_header[1:] + payload)
651
            # Checksum is only the lower 4 bits
652
            crc = chr(ord(crc) & 0xf)
653
            payload += crc
654
            _header += self.encrypt(payload)
655
        else:
656
            # calculate and add encrypted checksum to the packet
657
            crc = self._checksum(_header[1:])
658
            # Checksum is only the lower 4 bits
659
            crc = chr(ord(crc) & 0xf)
660
            _header += self.strxor(crc, '\x57')
661

    
662
        try:
663
            LOG.debug("Sent:\n%s" % util.hexprint(_header))
664
            self.pipe.write(_header)
665
        except Exception, e:
666
            raise errors.RadioError("Failed to communicate with radio: %s" % e)
667

    
668
    def _read_record(self):
669
        # read 4 chars for the header
670
        _header = self.pipe.read(4)
671
        #LOG.debug("header = " % util.hexprint(_header))
672
        if len(_header) != 4:
673
            raise errors.RadioError('Radio did not respond- header length')
674
        _length = ord(_header[3])
675
        _packet = self.pipe.read(_length)
676
        _rcs_xor = _packet[-1]
677
        _packet = self.decrypt(_packet)
678
        _cs = ord(self._checksum(_header[1:] + _packet))
679
        # It appears the checksum is only 4bits
680
        _cs = _cs & 0xf
681
        # read the checksum and decrypt it 
682
        _rcs = ord(self.strxor(self.pipe.read(1), _rcs_xor))
683
        _rcs = _rcs & 0xf
684
        return (_rcs != _cs, _packet)
685

    
686
    def decrypt(self, data):
687
        result = ''
688
        for i in range(len(data)-1, 0, -1):
689
            result += self.strxor(data[i], data[i - 1])
690
        result += self.strxor(data[0], '\x57')
691
        return result[::-1]
692

    
693
    def encrypt(self, data):
694
        result = self.strxor('\x57', data[0])
695
        for i in range(1, len(data), 1):
696
            result += self.strxor(result[i - 1], data[i])
697
        return result
698

    
699
    def strxor(self, xora, xorb):
700
        return chr(ord(xora) ^ ord(xorb))
701

    
702
    # Identify the radio
703
    #
704
    # A Gotcha: the first identify packet returns a bad checksum, subsequent
705
    # attempts return the correct checksum... (well it does on my radio!)
706
    #
707
    # The ID record returned by the radio also includes the
708
    # current frequency range
709
    # as 4 bytes big-endian in 10Hz increments
710
    #
711
    # Offset
712
    #  0:10     Model, zero padded 
713

    
714
    @classmethod
715
    def match_model(cls, filedata, filename):
716
        id = cls._file_ident
717
        return cls._file_ident in filedata[0x426:0x430]
718

    
719
    def _identify(self):
720
        """Do the identification dance"""
721
        for _i in range(0, 3):
722
            LOG.debug("ID try #"+str(_i))
723
            self._write_record(CMD_ID)
724
            _chksum_err, _resp = self._read_record()
725
            if len(_resp) == 0:
726
                raise Exception("Radio not responding")
727
            else:
728
                LOG.debug("Got:\n%s" % util.hexprint(_resp))
729
                LOG.debug("Model received is %s" % _resp[0:10])
730
                LOG.debug("Model expected is %s" % self._model)
731
                if _chksum_err:
732
                    LOG.error("Checksum error: retrying ident...")
733
                    time.sleep(0.100)
734
                    continue
735
                else:
736
                    LOG.debug("checksum passed")
737
                    if _resp[0:8] == self._model[0:8]:
738
                        LOG.debug("Passed identify")
739
                        break
740
                    else:
741
                        LOG.debug("FAILED to identify") 
742
                  
743

    
744
    def _finish(self):
745
        self._write_record(CMD_END)
746

    
747
    def process_mmap(self):
748
        self._memobj = bitwise.parse(_MEM_FORMAT, self._mmap)
749

    
750
    def sync_in(self):
751
        try:
752
            self._mmap = self._download()
753
        except errors.RadioError:
754
            raise
755
        except Exception, e:
756
            raise errors.RadioError("Failed to communicate with radio: %s" % e)
757
        self.process_mmap()
758

    
759
    def sync_out(self):
760
        self._upload()
761

    
762
    # TODO: Load all memory.
763
    # It would be smarter to only load the active areas and none of
764
    # the padding/unused areas. Padding still need to be investigated.
765
    def _download(self):
766
        """Talk to a wouxun KG-UV980P and do a download"""
767
        try:
768
            self._identify()
769
            return self._do_download(0, 32768, 64)
770
        except errors.RadioError:
771
            raise
772
        except Exception, e:
773
            LOG.exception('Unknown error during download process')
774
            raise errors.RadioError("Failed to communicate with radio: %s" % e)
775

    
776
    def _do_download(self, start, end, blocksize):
777
        # allocate & fill memory
778
        LOG.debug("Start Download")
779
        image = ""
780
        for i in range(start, end, blocksize):
781
            req = chr(i / 256) + chr(i % 256) + chr(blocksize)
782
            self._write_record(CMD_RD, req)
783
            cs_error, resp = self._read_record()
784
            LOG.debug("Got:\n%s" % util.hexprint(resp))
785

    
786
            if cs_error:
787
                LOG.debug(util.hexprint(resp))
788
                raise Exception("Checksum error on read")
789
            # LOG.debug("Got:\n%s" % util.hexprint(resp))
790
            image += resp[2:]
791
            if self.status_fn:
792
                status = chirp_common.Status()
793
                status.cur = i
794
                status.max = end
795
                status.msg = "Cloning from radio"
796
                self.status_fn(status)
797
        self._finish()
798
        return memmap.MemoryMap(''.join(image))
799

    
800
    def _upload(self):
801
        """Talk to a wouxun KG-UV980P and do a upload"""
802
        try:
803
            self._identify()
804
            LOG.debug("Done with Upload Identify")
805
            # self._do_upload(0, 1856, 16)
806
            # LOG.debug("Done with Limits Upload")
807
            # self._do_upload(1856, 32768, 64)
808
            self._do_upload(0, 32768, 64)
809
            LOG.debug("Done with Mem and Settings Upload")
810
            self._finish()
811
        except errors.RadioError:
812
            raise
813
        except Exception, e:
814
            raise errors.RadioError("Failed to communicate with radio: %s" % e)
815
        return
816

    
817
    def _do_upload(self, start, end, blocksize):
818
        LOG.debug("Start of _do_upload")
819
        ptr = start
820
        LOG.debug("ptr = " + str(ptr))
821
        for i in range(start, end, blocksize):
822
            LOG.debug("Start of loop in _do_upload index = "+str(i))
823
            LOG.debug("Start %i End %i Size %i" % (start, end, blocksize))
824
            req = chr(i/ 256) + chr(i % 256)
825
            LOG.debug("REQ")
826
            chunk = self.get_mmap()[ptr:ptr + blocksize]
827
            LOG.debug("CHUNK")
828
            self._write_record(CMD_WR, req + chunk)
829
#            LOG.debug("Upload-- SENT : " % util.hexprint(_sent))
830
            cserr, ack = self._read_record()
831
            LOG.debug("Upload-- CSUM ERROR : " + str(cserr))
832
            LOG.debug("Upload-- RCVD :\n%s " % util.hexprint(ack))
833
            
834
            j = ord(ack[0]) * 256 + ord(ack[1])
835
            if cserr or j != ptr:
836
                raise Exception("Radio did not ack block %i" % ptr)
837
            ptr += blocksize
838
            if self.status_fn:
839
                status = chirp_common.Status()
840
                status.cur = i
841
                status.max = end
842
                status.msg = "Cloning to radio"
843
                self.status_fn(status)
844
        # self._finish()
845

    
846
    def get_features(self):
847
        rf = chirp_common.RadioFeatures()
848
        rf.has_settings = True
849
        rf.has_ctone = True
850
        rf.has_rx_dtcs = True
851
        rf.has_cross = True
852
        rf.has_tuning_step = False
853
        rf.has_bank = False
854
        rf.can_odd_split = True
855
        rf.valid_skips = ["", "S"]
856
        rf.valid_tmodes = ["", "Tone", "TSQL", "DTCS", "Cross"]
857
        rf.valid_cross_modes = [
858
            "Tone->Tone",
859
            "Tone->DTCS",
860
            "DTCS->Tone",
861
            "DTCS->",
862
            "->Tone",
863
            "->DTCS",
864
            "DTCS->DTCS",
865
        ]
866
        rf.valid_modes = ["FM", "NFM", "AM", "NAM"]
867
        rf.valid_power_levels = self.POWER_LEVELS
868
        rf.valid_name_length = 8
869
        rf.valid_duplexes = ["", "-", "+", "split", "off"]
870
#   MRT - Open up channel memory freq range to support RxFreq limit expansion
871
        rf.valid_bands = [(26000000, 299999999),  # supports VHF
872
                          (300000000, 999999999)]  # supports UHF
873

    
874
        rf.valid_characters = chirp_common.CHARSET_ASCII
875
        rf.memory_bounds = (1, 999)  # 999 memories
876
        rf.valid_tuning_steps = STEPS
877
        return rf
878

    
879
    @classmethod
880
    def get_prompts(cls):
881
        rp = chirp_common.RadioPrompts()
882
        rp.experimental = \
883
            ('This driver is experimental and may contain bugs. \n'
884
              'USE AT YOUR OWN RISK  - '
885
              ' SAVE A COPY OF DOWNLOAD FROM YOUR RADIO BEFORE MAKING CHANGES\n'
886
              '\nAll known CPS settings are implemented \n'
887
              '\n Additional settings found only on radio are also included'
888
              '\nMute, Compander and Scrambler are defaulted to '
889
              'QT, OFF , OFF for all channel memories\n'
890
              '\n'
891
              'Modification of Freq Limit Interfaces is done AT YOUR OWN RISK and '
892
              'may affect radio performance and may violate rules, regulations '
893
              'or laws in your jurisdiction.\n'
894
             )
895
        return rp
896

    
897
    def get_raw_memory(self, number):
898
        return repr(self._memobj.memory[number])
899
# MRT - corrected the Polarity decoding to match 980P implementation
900
# use 0x4000 bit mask for R
901
# MRT - 0x4000 appears to be the bit mask for Inverted DCS tones
902
# MRT - n DCS Tone will be 0x8xxx values - i DCS Tones will
903
# be 0xCxxx values.
904
# MRT - Chirp Uses N for n DCS Tones and R for i DCS Tones
905
# MRT - 980P encodes DCS tone # in decimal -  NOT OCTAL
906

    
907
    def _get_tone(self, _mem, mem):
908
        def _get_dcs(val):
909
            code = int("%03d" % (val & 0x07FF))
910
            pol = (val & 0x4000) and "R" or "N"
911
            return code, pol
912
# MRT - Modified the function below to bitwise AND with 0x4000
913
# to check for 980P DCS Tone decoding
914
# MRT 0x8000 appears to be the bit mask for DCS tones
915
        tpol = False
916
# MRT Beta 1.1 - Fix the txtone compare to 0x8000 - was rxtone.
917
        if _mem.txtone != 0xFFFF and (_mem.txtone & 0x8000) == 0x8000:
918
            tcode, tpol = _get_dcs(_mem.txtone)
919
            mem.dtcs = tcode
920
            txmode = "DTCS"
921
        elif _mem.txtone != 0xFFFF and _mem.txtone != 0x0:
922
            mem.rtone = (_mem.txtone & 0x7fff) / 10.0
923
            txmode = "Tone"
924
        else:
925
            txmode = ""
926
# MRT - Modified the function below to bitwise AND with 0x4000
927
# to check for 980P DCS Tone decoding
928
        rpol = False
929
        if _mem.rxtone != 0xFFFF and (_mem.rxtone & 0x8000) == 0x8000:
930
            rcode, rpol = _get_dcs(_mem.rxtone)
931
            mem.rx_dtcs = rcode
932
            rxmode = "DTCS"
933
        elif _mem.rxtone != 0xFFFF and _mem.rxtone != 0x0:
934
            mem.ctone = (_mem.rxtone & 0x7fff) / 10.0
935
            rxmode = "Tone"
936
        else:
937
            rxmode = ""
938

    
939
        if txmode == "Tone" and not rxmode:
940
            mem.tmode = "Tone"
941
        elif txmode == rxmode and txmode == "Tone" and mem.rtone == mem.ctone:
942
            mem.tmode = "TSQL"
943
        elif txmode == rxmode and txmode == "DTCS" and mem.dtcs == mem.rx_dtcs:
944
            mem.tmode = "DTCS"
945
        elif rxmode or txmode:
946
            mem.tmode = "Cross"
947
            mem.cross_mode = "%s->%s" % (txmode, rxmode)
948

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

    
952
        LOG.debug("Got TX %s (%i) RX %s (%i)" %
953
                  (txmode, _mem.txtone, rxmode, _mem.rxtone))
954

    
955
    def get_memory(self, number):
956
        _mem = self._memobj.memory[number]
957
        _nam = self._memobj.names[number]
958

    
959
        mem = chirp_common.Memory()
960
        mem.number = number
961
        _valid = self._memobj.valid[mem.number]
962

    
963
        LOG.debug("Mem %d valid is %s", number, _valid == MEM_VALID)
964
        LOG.debug("Rx Freq %s", _mem.rxfreq)
965
        if (_valid != MEM_VALID) & (_mem.rxfreq == 0xFFFFFFFF):
966
            mem.empty = True
967
            return mem
968
        elif (_valid != MEM_VALID) & ((_mem.rxfreq != 0xFFFFFFFF)
969
              or (_mem.rxfreq != 0x00000000)):
970
            LOG.debug("Changed chan %d %s", number, "to valid")
971
            _valid = MEM_VALID
972
            mem.empty = False
973
        else:
974
            _valid = MEM_VALID
975
            mem.empty = False
976
        mem.freq = int(_mem.rxfreq) * 10
977
        _rxfreq = _freq_decode(_mem.rxfreq)
978
        _txfreq = _freq_decode(_mem.txfreq)
979
        mem.freq = _rxfreq
980
        LOG.debug("Tx Freq is "+ str(_mem.txfreq))
981
        if  _mem.txfreq == 0xFFFFFFFF:
982
            # TX freq not set
983
            mem.duplex = "off"
984
            mem.offset = 0
985
        elif int(_rxfreq) == int(_txfreq):
986
            mem.duplex = ""
987
            mem.offset = 0
988
        elif abs(_rxfreq - _txfreq) > 70000000:
989
            mem.duplex = "split"
990
            mem.offset = _txfreq
991
        else:
992
            mem.duplex = _rxfreq > _txfreq and "-" or "+"
993
            mem.offset = abs(_rxfreq - _txfreq)
994

    
995
        if _mem.named:
996
            mem.name = _str_decode(self._memobj.names[number].name)
997
        else:
998
            mem.name = ''
999

    
1000

    
1001
        self._get_tone(_mem, mem)
1002

    
1003
        mem.skip = "" if bool(_mem.scan_add) else "S"
1004

    
1005
        LOG.debug("Mem Power " + str(_mem.power))
1006
        pwr_index= _mem.power
1007
        if _mem.power == 3:
1008
            pwr_index = 2
1009
            LOG.debug("Force Mem Power to" + str(pwr_index))
1010
        if _mem.power:
1011
            mem.power = self.POWER_LEVELS[pwr_index]
1012
        else: 
1013
            mem.power = self.POWER_LEVELS[0]
1014
        
1015
        # mem.am_mode = _mem.power & 0x2
1016

    
1017
        # LOG.debug("Mem Power Index " + str(_mem.power))
1018
#        mem.power = self.POWER_LEVELS[_mem.power]
1019

    
1020
        if _mem.am_mode:
1021
            if _mem.isnarrow:
1022
                mem.mode = "NAM"
1023
            else:
1024
                mem.mode = "AM"
1025
        else:
1026
            mem.mode = _mem.isnarrow and "NFM" or "FM"
1027

    
1028
        mem.extra = RadioSettingGroup("Extra", "extra")
1029

    
1030
        _scram = _mem.scrambler
1031
        if _mem.scrambler > 8:
1032
            _scram = 0
1033
        # rs = RadioSetting("scrambler", "Scrambler",
1034
        #                   RadioSettingValueList(SCRAMBLER_LIST,
1035
        #                                         SCRAMBLER_LIST[_scram]))
1036
        # mem.extra.append(rs)
1037

    
1038
        # rs = RadioSetting("compander", "Compander",
1039
        #                   RadioSettingValueBoolean(_mem.compander))
1040
        # mem.extra.append(rs)
1041

    
1042
        # rs = RadioSetting("mute_mode", "Mute",
1043
        #                   RadioSettingValueMap(MUTE_MODE_MAP, _mem.mute_mode))
1044
        # mem.extra.append(rs)
1045

    
1046
        return mem
1047

    
1048
    def _set_tone(self, mem, _mem):
1049
        def _set_dcs(code, pol):
1050
            # MRT Change to 0x8000 to
1051
            # set the bit for DCS- code is a decimal version of the code # - NOT OCTAL
1052
            val = int("%i" % code, 10) | 0x8000
1053
            if pol == "R":
1054
                # MRT Change to 0x4000 to set the bit for
1055
                # i/R polarity
1056
                val += 0x4000
1057
            return val
1058

    
1059
        rx_mode = tx_mode = None
1060
        rxtone = txtone = 0x0000
1061

    
1062
        if mem.tmode == "Tone":
1063
            tx_mode = "Tone"
1064
            rx_mode = None
1065
            txtone = int(mem.rtone * 10) 
1066
        elif mem.tmode == "TSQL":
1067
            rx_mode = tx_mode = "Tone"
1068
            rxtone = txtone = int(mem.ctone * 10) 
1069
        elif mem.tmode == "DTCS":
1070
            tx_mode = rx_mode = "DTCS"
1071
            txtone = _set_dcs(mem.dtcs, mem.dtcs_polarity[0])
1072
            rxtone = _set_dcs(mem.dtcs, mem.dtcs_polarity[1])
1073
        elif mem.tmode == "Cross":
1074
            tx_mode, rx_mode = mem.cross_mode.split("->")
1075
            if tx_mode == "DTCS":
1076
                txtone = _set_dcs(mem.dtcs, mem.dtcs_polarity[0])
1077
            elif tx_mode == "Tone":
1078
                txtone = int(mem.rtone * 10) 
1079
            if rx_mode == "DTCS":
1080
                rxtone = _set_dcs(mem.rx_dtcs, mem.dtcs_polarity[1])
1081
            elif rx_mode == "Tone":
1082
                rxtone = int(mem.ctone * 10) 
1083

    
1084
        _mem.rxtone = rxtone
1085
        _mem.txtone = txtone
1086

    
1087
        LOG.debug("Set TX %s (%i) RX %s (%i)" %
1088
                  (tx_mode, _mem.txtone, rx_mode, _mem.rxtone))
1089

    
1090
    def set_memory(self, mem):
1091
#   _mem = Stored Memory value 
1092
#    mem = New value from user entry
1093
        number = mem.number
1094
        _mem = self._memobj.memory[number]
1095
        _nam = self._memobj.names[number]
1096

    
1097
        if len(mem.name) > 0:
1098
            LOG.debug("new name = %s", (mem.name))
1099
            _mem.named = True
1100
            name_encoded = _str_encode(mem.name)
1101
            LOG.debug("name endcoded = %s", (name_encoded))
1102
            LOG.debug("number = %s", (number))
1103
            for i in range(0, 8):
1104
                _nam.name[i] = ord(name_encoded[i])
1105
        else:
1106
            _mem.named = False
1107

    
1108
        # if mem.empty:
1109
        #     _mem.set_raw("\x00" * (_mem.size() / 8))
1110
        #     self._memobj.valid[number] = 0
1111
        #     self._memobj.names[number].set_raw("\x00" * (_nam.size() / 8))
1112
        #     return
1113

    
1114
        _mem.rxfreq = _freq_encode(mem.freq)
1115
        if mem.duplex == "off":
1116
            _mem.txfreq = 0xFFFFFFFF
1117
        elif mem.duplex == "split":
1118
            _mem.txfreq = _freq_encode(mem.offset)
1119
        elif mem.duplex == "+":
1120
            _mem.txfreq = _freq_encode(mem.freq + mem.offset)
1121
        elif mem.duplex == "-":
1122
            _mem.txfreq = _freq_encode(mem.freq - mem.offset)
1123
        else:
1124
            _mem.txfreq = _freq_encode(mem.freq)
1125

    
1126
        _mem.scan_add = int(mem.skip != "S")
1127

    
1128
        if mem.mode == "AM":
1129
            _mem.am_mode = True
1130
            _mem.isnarrow = False
1131
        elif mem.mode == "NAM":
1132
            _mem.am_mode = True
1133
            _mem.isnarrow = True
1134
        else:
1135
            _mem.am_mode = False
1136
            if mem.mode =="NFM":
1137
                _mem.isnarrow = True
1138
            else:
1139
                _mem.isnarrow = False
1140

    
1141
        # set the tone
1142
        self._set_tone(mem, _mem)
1143
        # MRT set the scrambler and compander to off by default
1144
        # MRT This changes them in the channel memory
1145
        _mem.scrambler = 0
1146
        _mem.compander = 0
1147
        # set the power
1148
        # if mem.power:
1149
        #     _mem.power = self.POWER_LEVELS.index(mem.power)
1150
        # else:
1151
        #     _mem.power = True
1152
        LOG.debug("Set mem.power = %s" % mem.power)
1153
        # pwr_index= mem.power
1154
        # LOG.debug("pwr index = " + str(pwr_index))
1155
        index = self.POWER_LEVELS.index(mem.power)
1156
        LOG.debug("index = %i", (index))
1157
        if index == 2:
1158
            _mem.power = 0b11 #self.POWER_LEVELS.index(mem.power)
1159
        else:
1160
            _mem.power = self.POWER_LEVELS.index(mem.power)
1161
        # Not sure what this bit does yet but it causes the radio to display
1162
        # MED power when the CPS shows Low Power. Forcing it to 0 to keep them 
1163
        # consistent
1164
        _mem.extra_power_bit = 0
1165
        # Set other unknowns to 0 to match default CPS values
1166
        _mem.unknown1 = 0
1167
        _mem.unknown2 = 0
1168
        _mem.unknownbit2 = 0
1169
        _mem.unknown3 = 0
1170
        _mem.Unknown4_shft_dir = 0
1171
        _mem.unknown5 = 0
1172
        
1173
        # if mem.power:
1174
        #     _mem.power = self.POWER_LEVELS.index[mem.power]
1175
        # else:
1176
        #     _mem.power = True
1177

    
1178
        # MRT set to mute mode to QT (not QT+DTMF or QT*DTMF) by default
1179
        # MRT This changes them in the channel memory
1180
        _mem.mute_mode = 1
1181

    
1182
    def _get_settings(self):
1183
        _settings = self._memobj.settings
1184
        _limits = self._memobj.bandlimits
1185
        _oem = self._memobj.oem
1186
#        _vfoa = self._memobj.vfoa
1187
#        _vfob = self._memobj.vfob
1188
#        _scan = self._memobj.scan_groups
1189
#        _call = self._memobj.call_groups
1190
#        _callname = self._memobj.call_names
1191
#        _fmpreset = self._memobj.fm_preset
1192

    
1193
        cfg_grp = RadioSettingGroup("cfg_grp", "Config Settings")
1194
        cfg1_grp = RadioSettingGroup("cfg1_grp", "Config Settings 1")
1195
        cfg2_grp = RadioSettingGroup("cfg2_grp", "Config Settings 2")
1196
        vfoa_grp = RadioSettingGroup("vfoa_grp", "VFO A Settings")
1197
        vfo150_grp = RadioSettingGroup("vfo150_grp", "150M Settings")
1198
        vfo450_grp = RadioSettingGroup("vfo450_grp", "450M Settings")
1199
        vfo20_grp = RadioSettingGroup("vfo20_grp", "20M Settings")
1200
        vfo50_grp = RadioSettingGroup("vfo50_grp", "50M Settings")
1201
        vfo350_grp = RadioSettingGroup("vfo350_grp", "350M Settings")
1202
        vfo850_grp = RadioSettingGroup("vfo850_grp", "850M Settings")
1203
        vfoabands_grp = RadioSettingGroup("vfoabands_grp", "VFO A Band Settings")
1204
        vfob_grp = RadioSettingGroup("vfob_grp", "VFO B Settings")
1205
        key_grp = RadioSettingGroup("key_grp", "Key Settings")
1206
        fmradio_grp = RadioSettingGroup("fmradio_grp", "FM Broadcast Memory")
1207
        lmt_grp = RadioSettingGroup("lmt_grp", "Frequency Limits")
1208
        lmwrn_grp = RadioSettingGroup("lmwrn_grp", "USE AT YOUR OWN RISK")
1209
        rxlim_grp = RadioSettingGroup("rxlim_grp", "Rx Limits")
1210
        txlim_grp = RadioSettingGroup("txlim_grp", "Tx Limits")
1211
        uhf_lmt_grp = RadioSettingGroup("uhf_lmt_grp", "UHF")
1212
        vhf_lmt_grp = RadioSettingGroup("vhf_lmt_grp", "VHF")
1213
        oem_grp = RadioSettingGroup("oem_grp", "OEM Info")
1214
        scan_grp = RadioSettingGroup("scan_grp", "Scan Group")
1215
        scanname_grp = RadioSettingGroup("scanname_grp", "Scan Names")
1216
        call_grp = RadioSettingGroup("call_grp", "Call Settings")
1217
        remote_grp = RadioSettingGroup("remote_grp", "Remote Settings")
1218
        extra_grp = RadioSettingGroup("extra_grp",
1219
                                      "Extra Settings"
1220
                                      "\nNOT Changed by RESET or CPS")
1221
        vfo_grp = RadioSettingGroup("vfo_grp",
1222
                                    "VFO Settings")
1223
        memxtras_grp = RadioSettingGroup("memxtras_grp", "Memory Extras")
1224
        extra_grp.append(oem_grp)
1225
        cfg_grp.append(cfg1_grp)
1226
        cfg_grp.append(cfg2_grp)
1227
        lmt_grp.append(lmwrn_grp)
1228
        lmt_grp.append(rxlim_grp)
1229
        lmt_grp.append(txlim_grp)
1230
        extra_grp.append(lmt_grp)
1231
        vfo_grp.append(vfoa_grp)
1232
        vfo_grp.append(vfob_grp)
1233
        vfoa_grp.append(vfo150_grp)
1234
        vfoa_grp.append(vfo450_grp) 
1235
        vfoa_grp.append(vfo20_grp) 
1236
        vfoa_grp.append(vfo50_grp)
1237
        vfoa_grp.append(vfo350_grp) 
1238
        vfoa_grp.append(vfo850_grp)
1239
        scan_grp.append(scanname_grp)
1240
        
1241
        group = RadioSettings(cfg_grp, vfo_grp, fmradio_grp, 
1242
                        remote_grp, scan_grp, extra_grp)
1243

    
1244
# Memory extras
1245
        # rs = RadioSetting("_mem.mute_mode", "Mute Mode"+str(number),
1246
        #                   RadioSettingValueBoolean(_mem.mute_mode))
1247
        # memxtras_grp.append(rs)
1248

    
1249
# Configuration Settings
1250

    
1251
        rs = RadioSetting("roger", "Roger Beep",
1252
                          RadioSettingValueList(ROGER_LIST,
1253
                                                ROGER_LIST[_settings.
1254
                                                           roger]))
1255
        cfg1_grp.append(rs)
1256

    
1257
        rs = RadioSetting("beep", "Keypad Beep",
1258
                          RadioSettingValueBoolean(_settings.beep))
1259
        cfg1_grp.append(rs)
1260

    
1261
        rs = RadioSetting("voice", "Voice Guide",
1262
                          RadioSettingValueBoolean(_settings.voice))
1263
        cfg1_grp.append(rs)
1264

    
1265
        rs = RadioSetting("bcl_a", "Busy Channel Lock-out A",
1266
                          RadioSettingValueBoolean(_settings.bcl_a))
1267
        cfg1_grp.append(rs)
1268

    
1269
        rs = RadioSetting("bcl_b", "Busy Channel Lock-out B",
1270
                          RadioSettingValueBoolean(_settings.bcl_b))
1271
        cfg1_grp.append(rs)
1272

    
1273
        rs = RadioSetting("sc_rev", "Scan Mode",
1274
                          RadioSettingValueMap(SC_REV_MAP, _settings.sc_rev))
1275
        cfg1_grp.append(rs)
1276
        rs = RadioSetting("tot", "Timeout Timer (TOT)",
1277
                          RadioSettingValueMap(
1278
                              TOT_MAP, _settings.tot))
1279
        cfg1_grp.append(rs)
1280

    
1281
        rs = RadioSetting("toa", "Timeout Alarm (TOA)",
1282
                          RadioSettingValueMap(
1283
                              TOA_MAP, _settings.toa))
1284
        cfg1_grp.append(rs)
1285

    
1286
        rs = RadioSetting("ani_sw", "Caller ID Tx - ANI-SW",
1287
                          RadioSettingValueBoolean(_settings.ani_sw))
1288
        cfg1_grp.append(rs)
1289

    
1290
        rs = RadioSetting("ring", "Ring Time (Sec)",
1291
                          RadioSettingValueMap(RING_MAP, _settings.ring))
1292
        cfg1_grp.append(rs)
1293

    
1294

    
1295
        rs = RadioSetting("dtmfsf", "DTMF Sidetone",
1296
                          RadioSettingValueList(
1297
                              DTMF_ST_LIST,
1298
                              DTMF_ST_LIST[_settings.dtmfsf]))
1299
        cfg1_grp.append(rs)
1300

    
1301

    
1302
        rs = RadioSetting("ptt_id", "Caller ID Tx Mode (PTT_ID)",
1303
                          RadioSettingValueMap(PTT_ID_MAP, _settings.ptt_id))
1304
        cfg1_grp.append(rs)
1305

    
1306

    
1307
        rs = RadioSetting("wt_led", "Standby / WT LED",
1308
                          RadioSettingValueList(
1309
                              BACKLIGHT_LIST,
1310
                              BACKLIGHT_LIST[_settings.wt_led]))
1311
        cfg1_grp.append(rs)
1312

    
1313
        rs = RadioSetting("tx_led", "TX LED",
1314
                          RadioSettingValueList(
1315
                              BACKLIGHT_LIST,
1316
                              BACKLIGHT_LIST[_settings.tx_led]))
1317
        cfg1_grp.append(rs)
1318

    
1319
        rs = RadioSetting("rx_led", "Rx LED",
1320
                          RadioSettingValueList(
1321
                              BACKLIGHT_LIST,
1322
                              BACKLIGHT_LIST[_settings.rx_led]))
1323
        cfg1_grp.append(rs)
1324

    
1325
        rs = RadioSetting("prich_sw", "Priority Channel Scan",
1326
                          RadioSettingValueBoolean(_settings.prich_sw))
1327
        cfg1_grp.append(rs)
1328

    
1329
        rs = RadioSetting("spk_cont", "Speaker Control",
1330
                          RadioSettingValueMap(
1331
                              SPEAKER_MAP,
1332
                              _settings.spk_cont))
1333
        cfg1_grp.append(rs)
1334

    
1335
        rs = RadioSetting("autolock", "Autolock",
1336
                          RadioSettingValueBoolean(_settings.autolock))
1337
        cfg1_grp.append(rs)
1338

    
1339
        rs = RadioSetting("low_v", "Low Voltage Shutoff",
1340
                          RadioSettingValueBoolean(_settings.low_v))
1341
        cfg1_grp.append(rs)
1342

    
1343
        rs = RadioSetting("fan", "Fan Mode",
1344
                          RadioSettingValueList(
1345
                              FAN_MODE_LIST,
1346
                              FAN_MODE_LIST[_settings.fan]))
1347
        cfg1_grp.append(rs)
1348

    
1349
        rs = RadioSetting("apo_time", "Auto Power-Off (Min)",
1350
                          RadioSettingValueList(
1351
                              APO_TIME_LIST,
1352
                              APO_TIME_LIST[_settings.apo_time]))
1353
        cfg1_grp.append(rs)
1354

    
1355
        rs = RadioSetting("alert", "Alert Pulse (Hz)",
1356
                          RadioSettingValueMap(ALERT_MAP, _settings.alert))
1357
        cfg1_grp.append(rs)
1358
        rs = RadioSetting("m_pwr", "Medium Power Level (W)",
1359
                          RadioSettingValueMap(M_POWER_MAP,
1360
                                               _settings.m_pwr))
1361
        cfg1_grp.append(rs)
1362

    
1363
        rs = RadioSetting("rpt_set_model", "Model (RPT-SET)",
1364
                          RadioSettingValueList(
1365
                              RPT_MODE_LIST,
1366
                              RPT_MODE_LIST[_settings.rpt_set_model]))
1367
        cfg2_grp.append(rs)
1368

    
1369
        rs = RadioSetting("rpt_spk", "Repeater Speaker Switch (RPT-SPK)",
1370
                          RadioSettingValueBoolean(_settings.rpt_spk))
1371
        cfg2_grp.append(rs)
1372

    
1373
        rs = RadioSetting("rpt_ptt", "Repeater PTT (RPT-PTT)",
1374
                          RadioSettingValueBoolean(_settings.rpt_ptt))
1375
        cfg2_grp.append(rs)
1376

    
1377
        rs = RadioSetting("dtmf_time", "DTMF Tx Duration (ms)",
1378
                          RadioSettingValueList(
1379
                              DTMF_TIMES,
1380
                              DTMF_TIMES[_settings.dtmf_time]))
1381
        cfg2_grp.append(rs)
1382
        rs = RadioSetting("dtmf_int", "DTMF Interval (ms)",
1383
                          RadioSettingValueList(
1384
                              DTMF_INTERVALS,
1385
                              DTMF_INTERVALS[_settings.dtmf_int]))
1386
        cfg2_grp.append(rs)
1387

    
1388
        rs = RadioSetting("sc_qt", "CTCSS/DCS Scan",
1389
                          RadioSettingValueMap(
1390
                              SC_QT_MAP,_settings.sc_qt))
1391
        cfg2_grp.append(rs)
1392

    
1393
        rs = RadioSetting("pri_ch", "Priority Channel",
1394
                          RadioSettingValueInteger(
1395
                              1, 999, _chnum_decode(_settings.pri_ch)))
1396
        cfg2_grp.append(rs)
1397

    
1398
        rs = RadioSetting("ptt_id_dly", "Caller ID Tx Delay PTT-ID-DLY (ms)",
1399
                          RadioSettingValueMap(PTT_ID_DELAY_MAP,
1400
                                               _settings.ptt_id_dly))
1401
        cfg2_grp.append(rs)
1402

    
1403
        rs = RadioSetting("rc_sw", "Remote Control RC-SW",
1404
                          RadioSettingValueBoolean(_settings.rc_sw))
1405
        cfg2_grp.append(rs)
1406

    
1407
        rs = RadioSetting("scan_det", "Scan DET",
1408
                          RadioSettingValueBoolean(_settings.scan_det))
1409
        cfg2_grp.append(rs)
1410

    
1411
        rs = RadioSetting("menu", "Menu Available",
1412
                          RadioSettingValueBoolean(_settings.menu))
1413
        cfg2_grp.append(rs)
1414

    
1415
        rs = RadioSetting("thr_vol_tx", "Threshold Voltage Tx",
1416
                          RadioSettingValueBoolean(_settings.thr_vol_tx))
1417
        cfg2_grp.append(rs)
1418

    
1419
        rs = RadioSetting("hold_time_rpt", "Hold Time of Repeat (ms)",
1420
                          RadioSettingValueList(
1421
                              HOLD_TIMES,
1422
                              HOLD_TIMES[_settings.hold_time_rpt]))
1423
        cfg2_grp.append(rs)
1424

    
1425
        rs = RadioSetting("auto_am", "Auto AM",
1426
                          RadioSettingValueBoolean(_settings.auto_am))
1427
        cfg2_grp.append(rs)
1428

    
1429
        rs = RadioSetting("rpt_tone", "Repeat Tone",
1430
                          RadioSettingValueBoolean(_settings.rpt_tone))
1431
        cfg2_grp.append(rs)
1432

    
1433
        rs = RadioSetting("pf1_set", "PF1 setting",
1434
                          RadioSettingValueList(
1435
                              PF1_SETTINGS,
1436
                              PF1_SETTINGS[_settings.pf1_set]))
1437
        cfg2_grp.append(rs)
1438

    
1439
        rs = RadioSetting("settings.thr_vol_lvl", "Threshold Voltage Level",
1440
                          RadioSettingValueFloat(
1441
                              9.5, 10.5, _settings.thr_vol_lvl / 100.0 , 0.1, 1))
1442
        cfg2_grp.append(rs)
1443

    
1444
        dtmfchars = "0123456789"
1445
        _code =''
1446
        test = int(_oem.mode_psw)
1447
        _codeobj = '0x{0:0{1}X}'.format(test,6)
1448
        LOG.debug("codeobj = %s" % _codeobj)
1449
        _psw = str(_codeobj)
1450
        for i in range(2,8):
1451
            LOG.debug("psw[i] = %s" % _psw[i])
1452
            if _psw[i] in dtmfchars:
1453
                _code += _psw[i]
1454
        val_psw = int(_code)
1455
        LOG.debug("psw = %s" % val_psw)
1456
        val_psw = RadioSettingValueString(6, 6, _code, False)
1457
        val_psw.set_charset(dtmfchars)
1458
        rs = RadioSetting("oem.mode_psw", "MODE PSW", val_psw)
1459
        def apply_psw_id(setting, obj):
1460
            val2 = hex(int(str(val_psw),16))
1461
            LOG.debug("val2= %s" % val2)
1462
            if (int(val2,16) != 0):
1463
               while len(val2) < 8:
1464
                   val2 += '0'
1465
            psw = int(str(val2),16)
1466
            LOG.debug("val3= %s" % psw)
1467
            LOG.debug("val= %s" % val_psw)
1468
            obj.mode_psw = psw
1469
        rs.set_apply_callback(apply_psw_id, _oem)
1470
        cfg2_grp.append(rs)
1471

    
1472
        rs = RadioSetting("ABR", "ABR (Backlight On Time)",
1473
                          RadioSettingValueList(
1474
                              ABR_LIST,
1475
                              ABR_LIST[_settings.ABR]))
1476
        cfg2_grp.append(rs)
1477

    
1478
        rs = RadioSetting("KeyA", "Key A",
1479
                          RadioSettingValueList(
1480
                              KEY_LIST,
1481
                              KEY_LIST[_settings.KeyA]))
1482
        cfg2_grp.append(rs)
1483
        rs = RadioSetting("KeyB", "Key B",
1484
                          RadioSettingValueList(
1485
                              KEY_LIST,
1486
                              KEY_LIST[_settings.KeyB]))
1487
        cfg2_grp.append(rs)
1488
        rs = RadioSetting("KeyC", "Key C",
1489
                          RadioSettingValueList(
1490
                              KEY_LIST,
1491
                              KEY_LIST[_settings.KeyC]))
1492
        cfg2_grp.append(rs)
1493

    
1494
        rs = RadioSetting("act_area", "Active Area (BAND)",
1495
                          RadioSettingValueList(
1496
                              ACTIVE_AREA_LIST,
1497
                              ACTIVE_AREA_LIST[_settings.act_area]))
1498
        cfg2_grp.append(rs)
1499
        rs = RadioSetting("tdr_off", "TDR",
1500
                          RadioSettingValueList(
1501
                              TDR_LIST,
1502
                              TDR_LIST[_settings.tdr_off]))
1503
        cfg2_grp.append(rs)
1504

    
1505
# Freq Limits settings
1506
        
1507
        # Convert Integer back to correct limit HEX value:  limit = hex(int(str(limit*10),16))        
1508
        # # LOG.debug("limit =" % limit)
1509

    
1510
        _temp =str(hex(int("%i" % self._memobj.bandlimits.limit_144M_ChA_rx_start, 10)))
1511
        _temp = int(int(_temp[2:])/10.0)
1512
        val= RadioSettingValueInteger(0,999, _temp)
1513
        rs = RadioSetting("bandlimits.limit_144M_ChA_rx_start", "144M ChA Rx Lower Limit (MHz)",
1514
                          val)
1515
        rxlim_grp.append(rs)
1516

    
1517
        _temp =str(hex(int("%i" % self._memobj.bandlimits.limit_144M_ChA_rx_stop, 10)))
1518
        _temp = int(int(_temp[2:])/10.0)
1519
        val= RadioSettingValueInteger(0,999, _temp)
1520
        rs = RadioSetting("bandlimits.limit_144M_ChA_rx_stop", "144M ChA Rx Upper Limit (MHz)",
1521
                          RadioSettingValueInteger(0,999,
1522
                              val))
1523
        rxlim_grp.append(rs)
1524

    
1525
        _temp =str(hex(int("%i" % self._memobj.bandlimits.limit_144M_ChB_rx_start, 10)))
1526
        _temp = int(int(_temp[2:])/10.0)
1527
        val= RadioSettingValueInteger(0,999, _temp)
1528
        rs = RadioSetting("bandlimits.limit_144M_ChB_rx_start", "144M ChB Rx Lower Limit (MHz)",
1529
                          val)
1530
        rxlim_grp.append(rs)
1531

    
1532
        _temp =str(hex(int("%i" % self._memobj.bandlimits.limit_144M_ChB_rx_stop, 10)))
1533
        _temp = int(int(_temp[2:])/10.0)
1534
        val= RadioSettingValueInteger(0,999, _temp)
1535
        rs = RadioSetting("bandlimits.limit_144M_ChB_rx_stop", "144M ChB Rx Upper Limit (MHz)",
1536
                          RadioSettingValueInteger(0,999,
1537
                              val))
1538
        rxlim_grp.append(rs)
1539

    
1540
        _temp =str(hex(int("%i" % self._memobj.bandlimits.limit_70cm_rx_start, 10)))
1541
        _temp = int(int(_temp[2:])/10.0)
1542
        val= RadioSettingValueInteger(0,999, _temp)
1543
        rs = RadioSetting("bandlimits.limit_70cm_rx_start", "450M Rx Lower Limit (MHz)",
1544
                          RadioSettingValueInteger(0,999,
1545
                              val))
1546
        rxlim_grp.append(rs)
1547

    
1548
        _temp =str(hex(int("%i" % self._memobj.bandlimits.limit_70cm_rx_stop, 10)))
1549
        _temp = int(int(_temp[2:])/10.0)
1550
        val= RadioSettingValueInteger(0,999, _temp)
1551
        rs = RadioSetting("bandlimits.limit_70cm_rx_stop", "450M Rx Upper Limit (MHz)",
1552
                          RadioSettingValueInteger(0,999,
1553
                              val))
1554
        rxlim_grp.append(rs)
1555

    
1556
        _temp =str(hex(int("%i" % self._memobj.bandlimits.limit_10m_rx_start, 10)))
1557
        _temp = int(int(_temp[2:])/10.0)
1558
        val= RadioSettingValueInteger(0,999, _temp)
1559
        rs = RadioSetting("bandlimits.limit_10m_rx_start", "20M Rx Lower Limit (MHz)",
1560
                          RadioSettingValueInteger(0,999,
1561
                              val))
1562
        rxlim_grp.append(rs)
1563

    
1564
        _temp =str(hex(int("%i" % self._memobj.bandlimits.limit_10m_rx_stop, 10)))
1565
        _temp = int(int(_temp[2:])/10.0)
1566
        val= RadioSettingValueInteger(0,999, _temp)
1567
        rs = RadioSetting("bandlimits.limit_10m_rx_stop", "20M Rx Upper Limit (MHz)",
1568
                          RadioSettingValueInteger(0,999,
1569
                              val))
1570
        rxlim_grp.append(rs)
1571

    
1572
        _temp =str(hex(int("%i" % self._memobj.bandlimits.limit_6m_rx_start, 10)))
1573
        _temp = int(int(_temp[2:])/10.0)
1574
        val= RadioSettingValueInteger(0,999, _temp)
1575
        rs = RadioSetting("bandlimits.limit_6m_rx_start", "50M Rx Lower Limit (MHz)",
1576
                          RadioSettingValueInteger(0,999,
1577
                              val))
1578
        rxlim_grp.append(rs)
1579

    
1580
        _temp =str(hex(int("%i" % self._memobj.bandlimits.limit_6m_rx_stop, 10)))
1581
        _temp = int(int(_temp[2:])/10.0)
1582
        val= RadioSettingValueInteger(0,999, _temp)
1583
        rs = RadioSetting("bandlimits.limit_6m_rx_stop", "50M Rx Upper Limit (MHz)",
1584
                          RadioSettingValueInteger(0,999,
1585
                              val))
1586
        rxlim_grp.append(rs)
1587

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

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

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

    
1612
        _temp =str(hex(int("%i" % self._memobj.bandlimits.limit_850M_rx_stop, 10)))
1613
        _temp = int(int(_temp[2:])/10.0)
1614
        val= RadioSettingValueInteger(0,999, _temp)
1615
        rs = RadioSetting("bandlimits.limit_850M_rx_stop", "850M Rx Upper Limit (MHz)",
1616
                          RadioSettingValueInteger(0,999,
1617
                              val))
1618
        rxlim_grp.append(rs)
1619

    
1620

    
1621
        _temp =str(hex(int("%i" % self._memobj.bandlimits.limit_144M_ChA_tx_start, 10)))
1622
        _temp = int(int(_temp[2:])/10.0)
1623
        val= RadioSettingValueInteger(0,999, _temp)
1624
        rs = RadioSetting("bandlimits.limit_144M_ChA_tx_start", "144M ChA Tx Lower Limit (MHz)",
1625
                          RadioSettingValueInteger(0,999,
1626
                              val))
1627
        txlim_grp.append(rs)
1628

    
1629
        _temp =str(hex(int("%i" % self._memobj.bandlimits.limit_144M_ChA_tx_stop, 10)))
1630
        _temp = int(int(_temp[2:])/10.0)
1631
        val= RadioSettingValueInteger(0,999, _temp)
1632
        rs = RadioSetting("bandlimits.limit_144M_ChA_tx_stop", "144M ChA Tx Upper Limit (MHz)",
1633
                          RadioSettingValueInteger(0,999,
1634
                              val))
1635
        txlim_grp.append(rs)
1636

    
1637
        _temp =str(hex(int("%i" % self._memobj.bandlimits.limit_70cm_tx_start, 10)))
1638
        _temp = int(int(_temp[2:])/10.0)
1639
        val= RadioSettingValueInteger(0,999, _temp)
1640
        rs = RadioSetting("bandlimits.limit_70cm_tx_start", "450M Tx Lower Limit (MHz)",
1641
                          RadioSettingValueInteger(0,999,
1642
                              val))
1643
        txlim_grp.append(rs)
1644

    
1645
        _temp =str(hex(int("%i" % self._memobj.bandlimits.limit_70cm_tx_stop, 10)))
1646
        _temp = int(int(_temp[2:])/10.0)
1647
        val= RadioSettingValueInteger(0,999, _temp)
1648
        rs = RadioSetting("bandlimits.limit_70cm_tx_stop", "450M tx Upper Limit (MHz)",
1649
                          RadioSettingValueInteger(0,999,
1650
                              val))
1651
        txlim_grp.append(rs)
1652

    
1653
        _temp =str(hex(int("%i" % self._memobj.bandlimits.limit_10m_tx_start, 10)))
1654
        _temp = int(int(_temp[2:])/10.0)
1655
        val= RadioSettingValueInteger(0,999, _temp)
1656
        rs = RadioSetting("bandlimits.limit_10m_tx_start", "20M tx Lower Limit (MHz)",
1657
                          RadioSettingValueInteger(0,999,
1658
                              val))
1659
        txlim_grp.append(rs)
1660

    
1661
        _temp =str(hex(int("%i" % self._memobj.bandlimits.limit_10m_tx_stop, 10)))
1662
        _temp = int(int(_temp[2:])/10.0)
1663
        val= RadioSettingValueInteger(0,999, _temp)
1664
        rs = RadioSetting("bandlimits.limit_10m_tx_stop", "20M tx Upper Limit (MHz)",
1665
                          RadioSettingValueInteger(0,999,
1666
                              val))
1667
        txlim_grp.append(rs)
1668

    
1669
        _temp =str(hex(int("%i" % self._memobj.bandlimits.limit_6m_tx_start, 10)))
1670
        _temp = int(int(_temp[2:])/10.0)
1671
        val= RadioSettingValueInteger(0,999, _temp)
1672
        rs = RadioSetting("bandlimits.limit_6m_tx_start", "50M tx Lower Limit (MHz)",
1673
                          RadioSettingValueInteger(0,999,
1674
                              val))
1675
        txlim_grp.append(rs)
1676

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

    
1685
# VFO Settings
1686
        rs = RadioSetting("vfomode_a", "VFO A Working Mode",
1687
                          RadioSettingValueMap(WORKMODE_MAP,
1688
                                               _settings.vfomode_a))
1689
        vfoa_grp.append(rs)
1690

    
1691
        rs = RadioSetting("vfoband_a", "VFO A Current Band",
1692
                          RadioSettingValueMap(VFOBAND_MAP,
1693
                                               _settings.vfoband_a))
1694
        vfoa_grp.append(rs)
1695

    
1696
        rs = RadioSetting("vfochan_a", "VFO A Channel",
1697
                          RadioSettingValueInteger(1, 999,
1698
                              _chnum_decode(_settings.vfochan_a)))
1699
        vfoa_grp.append(rs)
1700

    
1701
        rs = RadioSetting("vfosquelch_a", "VFO A Squelch",
1702
                          RadioSettingValueInteger(0, 9,
1703
                              _settings.vfosquelch_a))
1704
        vfoa_grp.append(rs)
1705
        rs = RadioSetting("vfostep_a", "VFO A Step",
1706
                          RadioSettingValueList(
1707
                            STEP_LIST,
1708
                            STEP_LIST[_settings.vfostep_a]))
1709
        vfoa_grp.append(rs)
1710
######################
1711

    
1712
        rs = RadioSetting("vfofreq1", "VFO 150M Freq",
1713
                          RadioSettingValueFloat(
1714
                             0, 999.999999, (_freq_decode
1715
                             (_settings.vfofreq1)/1000000.0) ,0.000001, 6))
1716
        vfo150_grp.append(rs)
1717

    
1718
        rs = RadioSetting("vfoofst1", "VFO 150M Offset",
1719
                          RadioSettingValueFloat(
1720
                              0, 999.999999, (_freq_decode
1721
                              (_settings.vfoofst1)/1000000.0),0.000001, 6))
1722
        vfo150_grp.append(rs)
1723

    
1724
        rs = RadioSetting("rxtone1", "VFO 150M Rx tone",
1725
                          RadioSettingValueMap(
1726
                            TONE_MAP, _settings.rxtone1))
1727
        vfo150_grp.append(rs)
1728

    
1729
        rs = RadioSetting("txtone1", "VFO 150M Tx tone",
1730
                          RadioSettingValueMap(
1731
                            TONE_MAP, _settings.txtone1))
1732
        vfo150_grp.append(rs)
1733

    
1734
        rs = RadioSetting("power1", "VFO 150M Power",
1735
                          RadioSettingValueMap(
1736
                            POWER_MAP, _settings.power1))
1737
        vfo150_grp.append(rs)
1738

    
1739
        rs = RadioSetting("narrow1", "VFO 150M Bandwidth",
1740
                          RadioSettingValueMap(
1741
                            BANDWIDTH_MAP, _settings.narrow1))
1742
        vfo150_grp.append(rs)
1743

    
1744
        rs = RadioSetting("mute1", "VFO 150M Mute Mode",
1745
                          RadioSettingValueMap(
1746
                            MUTE_MODE_MAP, _settings.mute1))
1747
        vfo150_grp.append(rs)
1748

    
1749
        rs = RadioSetting("shft_dir1", "VFO 150M Shift Direction",
1750
                          RadioSettingValueList(
1751
                            DUPLEX_LIST,
1752
                            DUPLEX_LIST[_settings.shft_dir1]))
1753
        vfo150_grp.append(rs)
1754

    
1755
        rs = RadioSetting("compander1", "VFO 150M Compander",
1756
                          RadioSettingValueBoolean(
1757
                            _settings.compander1))
1758
        vfo150_grp.append(rs)
1759

    
1760
        rs = RadioSetting("scrambler1", "VFO 150M Scrambler",
1761
                          RadioSettingValueList(
1762
                            SCRAMBLER_LIST,
1763
                            SCRAMBLER_LIST[_settings.scrambler1]))
1764
        vfo150_grp.append(rs)
1765
        rs = RadioSetting("am_mode1", "VFO 150M AM Mode",
1766
                          RadioSettingValueBoolean(
1767
                            _settings.am_mode1))
1768
        vfo150_grp.append(rs)
1769
############################
1770

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

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

    
1783
        rs = RadioSetting("rxtone2", "VFO 450M Rx tone",
1784
                          RadioSettingValueMap(
1785
                            TONE_MAP, _settings.rxtone2))
1786
        vfo450_grp.append(rs)
1787

    
1788
        rs = RadioSetting("txtone2", "VFO 450M Tx tone",
1789
                          RadioSettingValueMap(
1790
                            TONE_MAP, _settings.txtone2))
1791
        vfo450_grp.append(rs)
1792
        
1793
        rs = RadioSetting("power2", "VFO 450M Power",
1794
                          RadioSettingValueMap(
1795
                            POWER_MAP, _settings.power2))
1796
        vfo450_grp.append(rs)
1797

    
1798
        rs = RadioSetting("narrow2", "VFO 450M Bandwidth",
1799
                          RadioSettingValueMap(
1800
                            BANDWIDTH_MAP, _settings.narrow2))
1801
        vfo450_grp.append(rs)
1802

    
1803
        rs = RadioSetting("mute2", "VFO 450M Mute Mode",
1804
                          RadioSettingValueMap(
1805
                            MUTE_MODE_MAP, _settings.mute2))
1806
        vfo450_grp.append(rs)
1807

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

    
1814
        rs = RadioSetting("compander2", "VFO 450M Compander",
1815
                          RadioSettingValueBoolean(
1816
                            _settings.compander2))
1817
        vfo450_grp.append(rs)
1818

    
1819
        rs = RadioSetting("scrambler2", "VFO 450M Scrambler",
1820
                          RadioSettingValueList(
1821
                            SCRAMBLER_LIST,
1822
                            SCRAMBLER_LIST[_settings.scrambler2]))
1823
        vfo450_grp.append(rs)
1824

    
1825
        rs = RadioSetting("am_mode2", "VFO 450M AM Mode",
1826
                          RadioSettingValueBoolean(
1827
                            _settings.am_mode2))
1828
        vfo450_grp.append(rs)
1829
############################
1830
        rs = RadioSetting("vfofreq3", "VFO 20M Freq",
1831
                          RadioSettingValueFloat(
1832
                             0, 999.999999, (_freq_decode
1833
                             (_settings.vfofreq3)/1000000.0) ,0.000001, 6))
1834
        vfo20_grp.append(rs)
1835

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

    
1842
        rs = RadioSetting("rxtone3", "VFO 20M Rx tone",
1843
                          RadioSettingValueMap(
1844
                            TONE_MAP, _settings.rxtone3))
1845
        vfo20_grp.append(rs)
1846

    
1847
        rs = RadioSetting("txtone3", "VFO 20M Tx tone",
1848
                          RadioSettingValueMap(
1849
                            TONE_MAP, _settings.txtone3))
1850
        vfo20_grp.append(rs)
1851
        
1852
        rs = RadioSetting("power3", "VFO 20M Power",
1853
                          RadioSettingValueMap(
1854
                            POWER_MAP, _settings.power3))
1855
        vfo20_grp.append(rs)
1856

    
1857
        rs = RadioSetting("narrow3", "VFO 20M Bandwidth",
1858
                          RadioSettingValueMap(
1859
                            BANDWIDTH_MAP, _settings.narrow3))
1860
        vfo20_grp.append(rs)
1861

    
1862
        rs = RadioSetting("mute3", "VFO 20M Mute Mode",
1863
                          RadioSettingValueMap(
1864
                            MUTE_MODE_MAP, _settings.mute3))
1865
        vfo20_grp.append(rs)
1866

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

    
1873
        rs = RadioSetting("compander3", "VFO 20M Compander",
1874
                          RadioSettingValueBoolean(
1875
                            _settings.compander3))
1876
        vfo20_grp.append(rs)
1877

    
1878
        rs = RadioSetting("scrambler3", "VFO 20M Scrambler",
1879
                          RadioSettingValueList(
1880
                            SCRAMBLER_LIST,
1881
                            SCRAMBLER_LIST[_settings.scrambler3]))
1882
        vfo20_grp.append(rs)
1883

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

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

    
1901
        rs = RadioSetting("rxtone4", "VFO 50M Rx tone",
1902
                          RadioSettingValueMap(
1903
                            TONE_MAP, _settings.rxtone4))
1904
        vfo50_grp.append(rs)
1905

    
1906
        rs = RadioSetting("txtone4", "VFO 50M Tx tone",
1907
                          RadioSettingValueMap(
1908
                            TONE_MAP, _settings.txtone4))
1909
        vfo50_grp.append(rs)
1910
        
1911
        rs = RadioSetting("power4", "VFO 50M Power",
1912
                          RadioSettingValueMap(
1913
                            POWER_MAP, _settings.power4))
1914
        vfo50_grp.append(rs)
1915

    
1916
        rs = RadioSetting("narrow4", "VFO 50M Bandwidth",
1917
                          RadioSettingValueMap(
1918
                            BANDWIDTH_MAP, _settings.narrow4))
1919
        vfo50_grp.append(rs)
1920

    
1921
        rs = RadioSetting("mute4", "VFO 50M Mute Mode",
1922
                          RadioSettingValueMap(
1923
                            MUTE_MODE_MAP, _settings.mute4))
1924
        vfo50_grp.append(rs)
1925

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

    
1932
        rs = RadioSetting("compander4", "VFO 50M Compander",
1933
                          RadioSettingValueBoolean(
1934
                            _settings.compander4))
1935
        vfo50_grp.append(rs)
1936

    
1937
        rs = RadioSetting("scrambler4", "VFO 50M Scrambler",
1938
                          RadioSettingValueList(
1939
                            SCRAMBLER_LIST,
1940
                            SCRAMBLER_LIST[_settings.scrambler4]))
1941
        vfo50_grp.append(rs)
1942

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

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

    
1960
        rs = RadioSetting("rxtone5", "VFO 350M Rx tone",
1961
                          RadioSettingValueMap(
1962
                            TONE_MAP, _settings.rxtone5))
1963
        vfo350_grp.append(rs)
1964

    
1965
        rs = RadioSetting("txtone5", "VFO 350M Tx tone",
1966
                          RadioSettingValueMap(
1967
                            TONE_MAP, _settings.txtone5))
1968
        vfo350_grp.append(rs)
1969
        
1970
        rs = RadioSetting("power5", "VFO 350M Power",
1971
                          RadioSettingValueMap(
1972
                            POWER_MAP, _settings.power5))
1973
        vfo350_grp.append(rs)
1974

    
1975
        rs = RadioSetting("narrow5", "VFO 350M Bandwidth",
1976
                          RadioSettingValueMap(
1977
                            BANDWIDTH_MAP, _settings.narrow5))
1978
        vfo350_grp.append(rs)
1979

    
1980
        rs = RadioSetting("mute5", "VFO 350M Mute Mode",
1981
                          RadioSettingValueMap(
1982
                            MUTE_MODE_MAP, _settings.mute5))
1983
        vfo350_grp.append(rs)
1984

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

    
1991
        rs = RadioSetting("compander5", "VFO 350M Compander",
1992
                          RadioSettingValueBoolean(
1993
                            _settings.compander5))
1994
        vfo350_grp.append(rs)
1995

    
1996
        rs = RadioSetting("scrambler5", "VFO 350M Scrambler",
1997
                          RadioSettingValueList(
1998
                            SCRAMBLER_LIST,
1999
                            SCRAMBLER_LIST[_settings.scrambler5]))
2000
        vfo350_grp.append(rs)
2001

    
2002
        rs = RadioSetting("am_mode5", "VFO 350M AM Mode",
2003
                          RadioSettingValueBoolean(
2004
                            _settings.am_mode5))
2005
        vfo350_grp.append(rs)
2006

    
2007
# ############################
2008
        rs = RadioSetting("vfofreq6", "VFO 850M Freq",
2009
                          RadioSettingValueFloat(
2010
                             0, 999.999999, (_freq_decode
2011
                             (_settings.vfofreq6)/1000000.0) ,0.000001, 6))
2012
        vfo850_grp.append(rs)
2013

    
2014
        rs = RadioSetting("vfoofst6", "VFO 850M Offset",
2015
                          RadioSettingValueFloat(
2016
                              0, 999.999999, (_freq_decode
2017
                              (_settings.vfoofst6)/1000000.0),0.000001, 6))
2018
        vfo850_grp.append(rs)
2019

    
2020
        rs = RadioSetting("rxtone6", "VFO 850M Rx tone",
2021
                          RadioSettingValueMap(
2022
                            TONE_MAP, _settings.rxtone6))
2023
        vfo850_grp.append(rs)
2024

    
2025
        rs = RadioSetting("txtone6", "VFO 850M Tx tone",
2026
                          RadioSettingValueMap(
2027
                            TONE_MAP, _settings.txtone6))
2028
        vfo850_grp.append(rs)
2029
        
2030
        rs = RadioSetting("power6", "VFO 850M Power",
2031
                          RadioSettingValueMap(
2032
                            POWER_MAP, _settings.power6))
2033
        vfo850_grp.append(rs)
2034

    
2035
        rs = RadioSetting("narrow6", "VFO 850M Bandwidth",
2036
                          RadioSettingValueMap(
2037
                            BANDWIDTH_MAP, _settings.narrow6))
2038
        vfo850_grp.append(rs)
2039

    
2040
        rs = RadioSetting("mute6", "VFO 850M Mute Mode",
2041
                          RadioSettingValueMap(
2042
                            MUTE_MODE_MAP, _settings.mute6))
2043
        vfo850_grp.append(rs)
2044

    
2045
        rs = RadioSetting("shft_dir6", "VFO 850M Shift Direction",
2046
                          RadioSettingValueList(
2047
                            DUPLEX_LIST,
2048
                            DUPLEX_LIST[_settings.shft_dir6]))
2049
        vfo850_grp.append(rs)
2050

    
2051
        rs = RadioSetting("compander6", "VFO 850M Compander",
2052
                          RadioSettingValueBoolean(
2053
                            _settings.compander6))
2054
        vfo850_grp.append(rs)
2055

    
2056
        rs = RadioSetting("scrambler6", "VFO 850M Scrambler",
2057
                          RadioSettingValueList(
2058
                            SCRAMBLER_LIST,
2059
                            SCRAMBLER_LIST[_settings.scrambler6]))
2060
        vfo850_grp.append(rs)
2061

    
2062
        rs = RadioSetting("am_mode6", "VFO 850M AM Mode",
2063
                          RadioSettingValueBoolean(
2064
                            _settings.am_mode6))
2065
        vfo850_grp.append(rs)
2066

    
2067
############################
2068

    
2069
        rs = RadioSetting("vfomode_b", "VFO B Working Mode",
2070
                          RadioSettingValueMap(WORKMODE_MAP,
2071
                                               _settings.vfomode_b))
2072
        vfob_grp.append(rs)
2073

    
2074
        rs = RadioSetting("vfochan_b", "VFO B Work Channel",
2075
                          RadioSettingValueInteger(1, 999,
2076
                              _chnum_decode(_settings.vfochan_b)))
2077
        vfob_grp.append(rs)
2078

    
2079
        rs = RadioSetting("vfofreq7", "VFO B Freq",
2080
                          RadioSettingValueFloat(
2081
                             0, 999.999999, (_freq_decode
2082
                             (_settings.vfofreq7)/1000000.0) ,0.000001, 6))
2083
        vfob_grp.append(rs)
2084

    
2085
        rs = RadioSetting("vfoofst7", "VFO B Offset",
2086
                          RadioSettingValueFloat(
2087
                              0, 999.999999, (_freq_decode
2088
                              (_settings.vfoofst7)/1000000.0),0.000001, 6))
2089
        vfob_grp.append(rs)
2090

    
2091
        rs = RadioSetting("rxtone7", "VFOB Rx tone",
2092
                          RadioSettingValueMap(
2093
                            TONE_MAP, _settings.rxtone7))
2094
        vfob_grp.append(rs)
2095

    
2096
        rs = RadioSetting("txtone7", "VFOB Tx tone",
2097
                          RadioSettingValueMap(
2098
                            TONE_MAP, _settings.txtone7))
2099
        vfob_grp.append(rs)
2100
        rs = RadioSetting("power7", "VFOB Power",
2101
                          RadioSettingValueMap(
2102
                            POWER_MAP, _settings.power7))
2103
        vfob_grp.append(rs)
2104
        rs = RadioSetting("narrow7", "VFOB Bandwidth",
2105
                          RadioSettingValueMap(
2106
                            BANDWIDTH_MAP, _settings.narrow7))
2107
        vfob_grp.append(rs)
2108
        rs = RadioSetting("mute7", "VFOB Mute Mode",
2109
                          RadioSettingValueMap(
2110
                            MUTE_MODE_MAP, _settings.mute7))
2111
        vfob_grp.append(rs)
2112
        rs = RadioSetting("shft_dir7", "VFOB Shift Direction",
2113
                          RadioSettingValueList(
2114
                            DUPLEX_LIST,
2115
                            DUPLEX_LIST[_settings.shft_dir7]))
2116
        vfob_grp.append(rs)
2117
        rs = RadioSetting("compander7", "VFOB Compander",
2118
                          RadioSettingValueBoolean(
2119
                            _settings.compander7))
2120
        vfob_grp.append(rs)
2121

    
2122
        rs = RadioSetting("scrambler7", "VFOB Scrambler",
2123
                          RadioSettingValueList(
2124
                            SCRAMBLER_LIST,
2125
                            SCRAMBLER_LIST[_settings.scrambler7]))
2126
        vfob_grp.append(rs)
2127

    
2128
        rs = RadioSetting("vfosquelch_b", "VFO B Squelch",
2129
                          RadioSettingValueInteger(0, 9,
2130
                              _settings.vfosquelch_b))
2131
        vfob_grp.append(rs)
2132
        rs = RadioSetting("vfostep_b", "VFO B Step",
2133
                          RadioSettingValueList(
2134
                            STEP_LIST,
2135
                            STEP_LIST[_settings.vfostep_b]))
2136
        vfob_grp.append(rs)
2137
        # rs = RadioSetting("am_mode7", "VFOB AM Mode",
2138
        #                   RadioSettingValueBoolean(
2139
        #                     _settings.am_mode7))
2140
        # vfob_grp.append(rs)
2141

    
2142
# Scan Group Settings
2143
        def _decode(lst):
2144
            _str = ''.join([chr(c) for c in lst
2145
                            if chr(c) in SCANNAME_CHARSET])
2146
            return _str
2147

    
2148
        rs = RadioSetting("scan_a_act", "Scan A Active Group",
2149
                        RadioSettingValueList(
2150
                            SCAN_GROUP_LIST,
2151
                            SCAN_GROUP_LIST[_settings.scan_a_act]))
2152
        scan_grp.append(rs)
2153
        rs = RadioSetting("scan_b_act", "Scan B Active Group",
2154
                        RadioSettingValueList(
2155
                             SCAN_GROUP_LIST,
2156
                             SCAN_GROUP_LIST[_settings.scan_b_act]))
2157
        scan_grp.append(rs)
2158
       
2159

    
2160
        for i in range(1,11):
2161
            x=str(i)
2162
            _str = _decode(eval("_settings.scanname"+x))
2163
            # CPS treats PPPPPP as a blank name as it is the factor reset value"
2164
            # The Radio treats PPPPPPP as a blank name and can display 8 chars"
2165
            # Force Chirp to blank out the scan name if value is PPPPPPP to match the radio"
2166
            # Blank out the name if first 6 are spaces or null and the 7th is a P to handle
2167
            # firmware peculiarities in handling all 8 characters.
2168
            if _str[0:7] == "PPPPPPP":_str=""
2169
            if _str[0:7] =="\x00\x00\x00\x00\x00\x00P":_str=""
2170
            if _str[0:7] =="\x20\x20\x20\x20\x20\x20P":_str=""
2171
            rs=RadioSetting("scanname"+x, "Scan Name "+x,
2172
                        RadioSettingValueString(0,8, _str))
2173
            # rs = RadioSetting("scanname"+x, "Scan Name "+x, val)
2174
            scanname_grp.append(rs)
2175

    
2176
            scngrp = str(i)
2177
            rs = RadioSetting("scanlower"+scngrp, "Scan Lower "+scngrp,
2178
                            RadioSettingValueInteger(1, 999,  
2179
                            eval("_settings.scanlower"+scngrp)))
2180
            scan_grp.append(rs)
2181
            rs = RadioSetting("scanupper"+scngrp, "Scan Upper "+scngrp,
2182
                            RadioSettingValueInteger(1, 999,  
2183
                            eval("_settings.scanupper"+scngrp)))
2184
            scan_grp.append(rs)
2185
# remote settings
2186
        rs = RadioSetting("rc_power", "RC Power",
2187
                           RadioSettingValueList(
2188
                                    RC_POWER_LIST,
2189
                                    RC_POWER_LIST[_settings.rc_power]))
2190
        remote_grp.append(rs)
2191

    
2192
        _code =''
2193
        test = int(_settings.ani_edit)
2194
        _codeobj = '0x{0:0{1}X}'.format(test,6)
2195
        LOG.debug("codeobj = %s" % _codeobj)
2196
        _ani = str(_codeobj)
2197
        for i in range(2,8):
2198
            LOG.debug("ani[i] = %s" % _ani[i])
2199
            if _ani[i] in dtmfchars:
2200
                _code += _ani[i]
2201
        val_ani = int(_code)
2202
        LOG.debug("ani = %s" % val_ani)
2203
        val_ani = RadioSettingValueString(3, 6, _code, False)
2204
        val_ani.set_charset(dtmfchars)
2205
        rs = RadioSetting("settings.ani_edit", "ANI Edit", val_ani)
2206
        def apply_ani_id(setting, obj):
2207
            temp = list()
2208
            LOG.debug("val= %s" % val_ani)
2209
            if str(val_ani)[0] == "0":
2210
                raise errors.RadioError("ANI EDIT must start with Non-Zero Digit")
2211
            val2 = hex(int(str(val_ani),16))
2212
            LOG.debug("val2= %s" % val2)
2213
            if (int(val2,16) != 0):
2214
               while len(val2) < 5:
2215
                   val2 += '0'
2216
               while len(val2) < 8:
2217
                   val2 += 'C'
2218
            ani = int(str(val2),16)
2219
            LOG.debug("ani= %s" % ani)
2220
            LOG.debug("val= %s" % val_ani)
2221
            obj.ani_edit = ani
2222
        rs.set_apply_callback(apply_ani_id, _settings)
2223
        remote_grp.append(rs)
2224

    
2225
        _code =''
2226
        test = int(_settings.mcc_edit)
2227
        _codeobj = '0x{0:0{1}X}'.format(test,6)
2228
        LOG.debug("codeobj = %s" % _codeobj)
2229
        _mcc = str(_codeobj)
2230
        for i in range(2,8):
2231
            LOG.debug("mcc[i] = %s" % _mcc[i])
2232
            if _mcc[i] in dtmfchars:
2233
                _code += _mcc[i]
2234
        val_mcc = int(_code)
2235
        LOG.debug("mcc = %s" % val_mcc)
2236
        val_mcc = RadioSettingValueString(3, 6, _code, False)
2237
        val_mcc.set_charset(dtmfchars)
2238
        rs = RadioSetting("mcc_edit", "MCC Edit", val_mcc)
2239
        def apply_mcc_id(setting, obj):
2240
            val2 = hex(int(str(val_mcc),16))
2241
            LOG.debug("val2= %s" % val2)
2242
            if (int(val2,16) != 0):
2243
               while len(val2) < 5:
2244
                   val2 += '0'
2245
               while len(val2) < 8:
2246
                   val2 += 'C'
2247
            mcc = int(str(val2),16)
2248
            LOG.debug("val3= %s" % mcc)
2249
            LOG.debug("val= %s" % val_mcc)
2250
            obj.mcc_edit = mcc
2251
        rs.set_apply_callback(apply_mcc_id, _settings)
2252
        remote_grp.append(rs)
2253

    
2254
        _code =''
2255
        test = int(_settings.scc_edit)
2256
        _codeobj = '0x{0:0{1}X}'.format(test,6)
2257
        LOG.debug("codeobj = %s" % _codeobj)
2258
        _scc = str(_codeobj)
2259
        for i in range(2,8):
2260
            LOG.debug("scc[i] = %s" % _scc[i])
2261
            if _scc[i] in dtmfchars:
2262
                _code += _scc[i]
2263
        val_scc = int(_code)
2264
        LOG.debug("scc = %s" % val_scc)
2265
        val_scc = RadioSettingValueString(3, 6, _code, False)
2266
        val_scc.set_charset(dtmfchars)
2267
        rs = RadioSetting("scc_edit", "SCC Edit", val_scc)
2268
        def apply_scc_id(setting, obj):
2269
            val2 = hex(int(str(val_scc),16))
2270
            LOG.debug("val2= %s" % val2)
2271
            if (int(val2,16) != 0):
2272
               while len(val2) < 5:
2273
                   val2 += '0'
2274
               while len(val2) < 8:
2275
                   val2 += 'C'
2276
            scc = int(str(val2),16)
2277
            LOG.debug("val3= %s" % scc)
2278
            LOG.debug("val= %s" % val_scc)
2279
            obj.scc_edit = scc
2280
        rs.set_apply_callback(apply_scc_id, _settings)
2281
        remote_grp.append(rs)
2282

    
2283
        _code =''
2284
        test = int(_settings.ctrl_edit)
2285
        _codeobj = '0x{0:0{1}X}'.format(test,6)
2286
        LOG.debug("codeobj = %s" % _codeobj)
2287
        _ctrl = str(_codeobj)
2288
        for i in range(2,8):
2289
            LOG.debug("ctrl[i] = %s" % _ctrl[i])
2290
            if _ctrl[i] in dtmfchars:
2291
                _code += _ctrl[i]
2292
        val_ctrl = int(_code)
2293
        LOG.debug("ctrl = %s" % val_ctrl)
2294
        val_ctrl = RadioSettingValueString(3, 6, _code, False)
2295
        val_ctrl.set_charset(dtmfchars)
2296
        rs = RadioSetting("ctrl_edit", "CTRL Edit", val_ctrl)
2297
        def apply_ctrl_id(setting, obj):
2298
            val2 = hex(int(str(val_ctrl),16))
2299
            LOG.debug("val2= %s" % val2)
2300
            if (int(val2,16) != 0):
2301
               while len(val2) < 5:
2302
                   val2 += '0'
2303
               while len(val2) < 8:
2304
                   val2 += 'C'
2305
            ctrl = int(str(val2),16)
2306
            LOG.debug("val3= %s" % ctrl)
2307
            LOG.debug("val= %s" % val_ctrl)
2308
            obj.ctrl_edit = ctrl
2309
        rs.set_apply_callback(apply_ctrl_id, _settings)
2310
        remote_grp.append(rs)
2311

    
2312

    
2313

    
2314

    
2315

    
2316
# OEM Settings
2317

    
2318
        _oem_name = _oem_str_decode(self._memobj.oem.display_name)
2319
        rs=RadioSetting("oem.display_name", "Display Banner Text",
2320
                        RadioSettingValueString(1,8, _oem_name))
2321
        oem_grp.append(rs)
2322

    
2323
# FM RADIO PRESETS
2324

    
2325
# memory stores raw integer value like 7600
2326
# radio will divide 7600 by 100 and interpret correctly at 76.0Mhz
2327
        #
2328
        # FM Radio Presets Settings
2329
        #
2330
        for i in range(1, 21):
2331
            chan = str(i)
2332
            rs = RadioSetting("FM_radio" + chan, "FM Preset " + chan,
2333
                              RadioSettingValueFloat(76.0, 108.0,
2334
                                                     eval("_settings.FM_radio" +
2335
                                                          chan)/100.0,
2336
                                                     0.1, 1))
2337
            fmradio_grp.append(rs)
2338
        
2339
        return group
2340

    
2341
    def get_settings(self):
2342
        try:
2343
            return self._get_settings()
2344
        except:
2345
            import traceback
2346
            LOG.error("Failed to parse settings: %s", traceback.format_exc())
2347
            return None
2348

    
2349
    def set_settings(self, settings):
2350
        for element in settings:
2351
            if not isinstance(element, RadioSetting):
2352
                self.set_settings(element)
2353
                continue
2354
            else:
2355
                try:
2356
                    if "." in element.get_name():
2357
                        bits = element.get_name().split(".")
2358
                        obj = self._memobj
2359
                        for bit in bits[:-1]:
2360
                            obj = getattr(obj, bit)
2361
                        setting = bits[-1]
2362
                    else:
2363
                        obj = self._memobj.settings
2364
                        setting = element.get_name()
2365

    
2366
                    if element.has_apply_callback():
2367
                        LOG.debug("Using apply callback")
2368
                        element.run_apply_callback()
2369
                    else:
2370
                        LOG.debug("Setting %s = %s" % (setting, element.value))
2371
                        if self._is_freq(element):
2372
                            # setattr(obj, setting, int(element.value / 10))
2373
                            # MRT rescale freq values to match radio
2374
                            # expected values
2375
                            value = _freq_encode(element[0].get_value()*1000000.0)
2376
                            setattr(obj, setting, value)
2377

    
2378
                        elif self._is_fmradio_or_voltage(element):
2379
                            # MRT rescale FM Radio values to match radio
2380
                            # expected values
2381
                            setattr(obj, setting,
2382
                                    int(element.values()[0]._current * 100.0))
2383

    
2384
                        elif self._is_limit(element):
2385
                            setattr(obj, setting,
2386
                                    int(str(element.values()[0]._current * 10), 16))
2387
                # Special VFO A Settings
2388
                #
2389
                        elif self._is_chan(element):
2390
                            value = _chnum_encode(element[0].get_value())
2391
                            setattr(obj, setting, value)
2392
                            continue
2393
                #
2394
                        elif self._is_display_name(element):
2395
                            string=element[0].get_value()
2396
                            nameenc = _oem_str_encode(string)
2397
                            for i in range(0,8):
2398
                                LOG.debug("nameenc %s" % (nameenc[i]))
2399
                                self._memobj.oem.display_name[i] = ord(nameenc[i])
2400
                                # setattr(obj, setting, int(ord(nameenc[i])))
2401

    
2402
                        elif self._is_scan_name(element):
2403
                            string=element[0].get_value()
2404
                            LOG.debug("string %s" % (string))
2405
                            # scaname=element[0].get_name()
2406
                            # LOG.debug("scanname %s" % (scaname))
2407
                            value = _str_encode(string)
2408
                            LOG.debug("scaname %s" % (value))
2409
                            setattr(obj, setting, value)
2410
                            # self._memobj.eval(scaname)[i] = ord(nameenc[i])
2411
                            # setattr(obj, setting, int(ord(nameenc[i])))
2412
                        else:
2413
                            setattr(obj, setting, element.value)
2414
                except Exception, e:
2415
                    LOG.debug(element.get_name())
2416
                    raise
2417

    
2418
    def _is_freq(self, element):
2419
        return "rxfreq" in element.get_name() or \
2420
               "txoffset" in element.get_name() or \
2421
               "vfofreq" in element.get_name() or\
2422
               "vfoofst" in element.get_name() 
2423
        #  "rx_start" in element.get_name() or \
2424
        #  "rx_stop" in element.get_name() or \
2425
        #  "tx_start" in element.get_name() or \
2426
        #  "tx_stop" in element.get_name()
2427

    
2428
    def _is_limit(self, element):
2429
        return "limit" in element.get_name()
2430

    
2431
    def _is_fmradio_or_voltage(self, element):
2432
        return "FM_radio" in element.get_name() or\
2433
                "thr_vol_lvl" in element.get_name()
2434

    
2435
    
2436
    def _is_chan(self, element):
2437
        return "vfochan" in element.get_name() or\
2438
               "pri_ch" in element.get_name()
2439

    
2440
    def _is_display_name(self, element):
2441
        return "display_name" in element.get_name() 
2442
    
2443
    def _is_scan_name(self, element):
2444
        return "scanname" in element.get_name() 
2445
  
2446
    # def _is_vfofreq(self, element):
2447
    #     return "vfofreq" in element.get_name() or\
2448
    #            "vfoofst" in element.get_name()
(4-4/8)