Project

General

Profile

New Model #7223 » kguv980p beta 2.3.py

KG-UV980P Beta 2.3 Driver - Mel Terechenok, 11/03/2022 07:48 PM

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

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

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

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

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

    
36

    
37
LOG = logging.getLogger(__name__)
38

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

    
44
MEM_VALID = 0x00
45
TX_BLANK = 0x40
46
RX_BLANK = 0x80
47

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

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

    
65
MUTE_MODE_MAP = [('QT',      0b01),
66
                 ('QT*DTMF', 0b10),
67
                 ('QT+DTMF', 0b11)]
68
STEPS = [2.5, 5.0, 6.25, 10.0, 12.5, 20.0, 25.0, 30.0, 50.0, 100.0]
69
STEP_LIST = [str(x) for x in STEPS]
70
SQL_LIST = [int(i) for i in range(0, 10)]
71
M_POWER_MAP = [('1 = 20W', 1),
72
               ('2 = 10W', 2)]
73
ROGER_LIST = ["Off", "BOT", "EOT", "Both"]
74
VOICE_LIST = ["Off", "Chinese", "English"]
75
SC_REV_MAP = [('Timeout (TO)',  1),
76
              ('Carrier (CO)',  2),
77
              ('Stop (SE)',     3)]
78
TOT_MAP = [('%d min' % i, int('%02d' % i, 10)) for i in range(1, 61)]
79
TOA_LIST = ["Off", "1s", "2s", "3s", "4s", "5s", "6s", "7s", "8s", "9s", "10s"]
80
RING_LIST = ["Off", "1s", "2s", "3s", "4s", "5s", "6s", "7s", "8s", "9s", "10s"]
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
        u16  FM_radio_cur_freq;
425
        u8  x902;
426
        u8  scan_det;
427
        u8  x904;
428
        u8  thr_vol_tx;
429
        u16  thr_vol_lvl;
430
        u8  x908;
431
        u8  x909;
432
        u8  x90A;
433
        u8  x90B;
434
        u8  x90C;
435
        u8  x90D;
436
        u8  x90E;
437
        u8  x90F;
438
        u8  x910pad[48];
439
        u16  scanlower1; // x940
440
        u16  scanupper1;
441
        u16  scanlower2;
442
        u16  scanupper2;
443
        u16  scanlower3;
444
        u16  scanupper3;
445
        u16  scanlower4;
446
        u16  scanupper4;
447
        u16  scanlower5;
448
        u16  scanupper5;
449
        u16  scanlower6;
450
        u16  scanupper6;
451
        u16  scanlower7;
452
        u16  scanupper7;
453
        u16  scanlower8;
454
        u16  scanupper8;
455
        u16  scanlower9;
456
        u16  scanupper9;
457
        u16  scanlower10;
458
        u16  scanupper10;
459
        char  scanname0[8]; // x968
460
        char  scanname1[8];
461
        char  scanname2[8];
462
        char  scanname3[8];
463
        char  scanname4[8];
464
        char  scanname5[8];
465
        char  scanname6[8];
466
        char  scanname7[8];
467
        char  scanname8[8];
468
        char  scanname9[8];
469
        char  scanname10[8];
470
     } settings;
471

    
472

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

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

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

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

    
515

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

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

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

    
547

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

    
560

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

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

    
577

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

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

    
600

    
601

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

    
606

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1001

    
1002
        self._get_tone(_mem, mem)
1003

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

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

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

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

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

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

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

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

    
1047
        return mem
1048

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

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

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

    
1085
        _mem.rxtone = rxtone
1086
        _mem.txtone = txtone
1087

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

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

    
1099
        # if mem.empty:
1100
        #     _mem.set_raw("\x00" * (_mem.size() / 8))
1101
        #     self._memobj.valid[number] = 0
1102
        #     self._memobj.names[number].set_raw("\x00" * (_nam.size() / 8))
1103
        #     return
1104

    
1105
        if mem.empty:
1106
            LOG.debug("Mem %s is Empty", number)
1107
            self._memobj.valid[number] = 0xFF
1108
            LOG.debug("Set Mem %s Not Valid", number)
1109
            _mem.rxfreq = 0xFFFFFFFF
1110
            LOG.debug("Set Rx Freq = FFFFFFF")
1111
            _mem.txfreq = 0xFFFFFFFF
1112
            LOG.debug("Set Tx Freq = FFFFFFF")
1113
            self._memobj.names[number].set_raw("\xFF" * (_nam.size() / 8))
1114
            LOG.debug("Name %s Cleared", number)
1115
            # The following line is a hack to make CPS happy and not 
1116
            # show memory entries that were deleted with CHIRP
1117
            # _mem=0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
1118
            # LOG.debug("Set _mem = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF")
1119
        else:
1120
            LOG.debug("Mem %s is NOT Empty", number)
1121
            if len(mem.name) > 0:
1122
                LOG.debug("new name = %s", (mem.name))
1123
                _mem.named = True
1124
                name_encoded = _str_encode(mem.name)
1125
                LOG.debug("name endcoded = %s", (name_encoded))
1126
                LOG.debug("number = %s", (number))
1127
                for i in range(0, 8):
1128
                    _nam.name[i] = ord(name_encoded[i])
1129
            else:
1130
                _mem.named = False
1131

    
1132

    
1133
            _mem.rxfreq = _freq_encode(mem.freq)
1134
            if mem.duplex == "off":
1135
                _mem.txfreq = 0xFFFFFFFF
1136
            elif mem.duplex == "split":
1137
                _mem.txfreq = _freq_encode(mem.offset)
1138
            elif mem.duplex == "+":
1139
                _mem.txfreq = _freq_encode(mem.freq + mem.offset)
1140
            elif mem.duplex == "-":
1141
                _mem.txfreq = _freq_encode(mem.freq - mem.offset)
1142
            else:
1143
                _mem.txfreq = _freq_encode(mem.freq)
1144

    
1145
            _mem.scan_add = int(mem.skip != "S")
1146

    
1147
            if mem.mode == "AM":
1148
                _mem.am_mode = True
1149
                _mem.isnarrow = False
1150
            elif mem.mode == "NAM":
1151
                _mem.am_mode = True
1152
                _mem.isnarrow = True
1153
            else:
1154
                _mem.am_mode = False
1155
                if mem.mode =="NFM":
1156
                    _mem.isnarrow = True
1157
                else:
1158
                    _mem.isnarrow = False
1159

    
1160
            # set the tone
1161
            self._set_tone(mem, _mem)
1162
            # MRT set the scrambler and compander to off by default
1163
            # MRT This changes them in the channel memory
1164
            _mem.scrambler = 0
1165
            _mem.compander = 0
1166
            # set the power
1167
            if mem.power:
1168
                _mem.power = self.POWER_LEVELS.index(mem.power)
1169
            else:
1170
                _mem.power = True
1171
            LOG.debug("Set mem.power = %s" % mem.power)
1172
            # pwr_index= mem.power
1173
            # LOG.debug("pwr index = " + str(pwr_index))
1174
            if str(mem.power) == "None":mem.power = 1
1175
            index = self.POWER_LEVELS.index(mem.power)
1176
            LOG.debug("index = %i", (index))
1177
            if index == 2:
1178
                _mem.power = 0b11 #self.POWER_LEVELS.index(mem.power)
1179
            else:
1180
                _mem.power = self.POWER_LEVELS.index(mem.power)
1181
            # Not sure what this bit does yet but it causes the radio to display
1182
            # MED power when the CPS shows Low Power. Forcing it to 0 to keep them 
1183
            # consistent
1184
            _mem.extra_power_bit = 0
1185
            # Set other unknowns to 0 to match default CPS values
1186
            _mem.unknown1 = 0
1187
            _mem.unknown2 = 0
1188
            _mem.unknownbit2 = 0
1189
            _mem.unknown3 = 0
1190
            _mem.Unknown4_shft_dir = 0
1191
            _mem.unknown5 = 0
1192
            
1193
            # if mem.power:
1194
            #     _mem.power = self.POWER_LEVELS.index[mem.power]
1195
            # else:
1196
            #     _mem.power = True
1197

    
1198
            # MRT set to mute mode to QT (not QT+DTMF or QT*DTMF) by default
1199
            # MRT This changes them in the channel memory
1200
            _mem.mute_mode = 1
1201

    
1202
    def _get_settings(self):
1203
        _settings = self._memobj.settings
1204
        _limits = self._memobj.bandlimits
1205
        _oem = self._memobj.oem
1206
#        _vfoa = self._memobj.vfoa
1207
#        _vfob = self._memobj.vfob
1208
#        _scan = self._memobj.scan_groups
1209
#        _call = self._memobj.call_groups
1210
#        _callname = self._memobj.call_names
1211
#        _fmpreset = self._memobj.fm_preset
1212

    
1213
        cfg_grp = RadioSettingGroup("cfg_grp", "Config Settings")
1214
        cfg1_grp = RadioSettingGroup("cfg1_grp", "Config Settings 1")
1215
        cfg2_grp = RadioSettingGroup("cfg2_grp", "Config Settings 2")
1216
        vfoa_grp = RadioSettingGroup("vfoa_grp", "VFO A Settings")
1217
        vfo150_grp = RadioSettingGroup("vfo150_grp", "150M Settings")
1218
        vfo450_grp = RadioSettingGroup("vfo450_grp", "450M Settings")
1219
        vfo20_grp = RadioSettingGroup("vfo20_grp", "20M Settings")
1220
        vfo50_grp = RadioSettingGroup("vfo50_grp", "50M Settings")
1221
        vfo350_grp = RadioSettingGroup("vfo350_grp", "350M Settings")
1222
        vfo850_grp = RadioSettingGroup("vfo850_grp", "850M Settings")
1223
        vfoabands_grp = RadioSettingGroup("vfoabands_grp", "VFO A Band Settings")
1224
        vfob_grp = RadioSettingGroup("vfob_grp", "VFO B Settings")
1225
        key_grp = RadioSettingGroup("key_grp", "Key Settings")
1226
        fmradio_grp = RadioSettingGroup("fmradio_grp", "FM Broadcast Memory")
1227
        lmt_grp = RadioSettingGroup("lmt_grp", "Frequency Limits")
1228
        lmwrn_grp = RadioSettingGroup("lmwrn_grp", "USE AT YOUR OWN RISK")
1229
        rxlim_grp = RadioSettingGroup("rxlim_grp", "Rx Limits")
1230
        txlim_grp = RadioSettingGroup("txlim_grp", "Tx Limits")
1231
        uhf_lmt_grp = RadioSettingGroup("uhf_lmt_grp", "UHF")
1232
        vhf_lmt_grp = RadioSettingGroup("vhf_lmt_grp", "VHF")
1233
        oem_grp = RadioSettingGroup("oem_grp", "OEM Info")
1234
        scan_grp = RadioSettingGroup("scan_grp", "Scan Group")
1235
        scanname_grp = RadioSettingGroup("scanname_grp", "Scan Names")
1236
        call_grp = RadioSettingGroup("call_grp", "Call Settings")
1237
        remote_grp = RadioSettingGroup("remote_grp", "Remote Settings")
1238
        extra_grp = RadioSettingGroup("extra_grp",
1239
                                      "Extra Settings"
1240
                                      "\nNOT Changed by RESET or CPS")
1241
        vfo_grp = RadioSettingGroup("vfo_grp",
1242
                                    "VFO Settings")
1243
        memxtras_grp = RadioSettingGroup("memxtras_grp", "Memory Extras")
1244
        extra_grp.append(oem_grp)
1245
        cfg_grp.append(cfg1_grp)
1246
        cfg_grp.append(cfg2_grp)
1247
        lmt_grp.append(lmwrn_grp)
1248
        lmt_grp.append(rxlim_grp)
1249
        lmt_grp.append(txlim_grp)
1250
        extra_grp.append(lmt_grp)
1251
        vfo_grp.append(vfoa_grp)
1252
        vfo_grp.append(vfob_grp)
1253
        vfoa_grp.append(vfo150_grp)
1254
        vfoa_grp.append(vfo450_grp) 
1255
        vfoa_grp.append(vfo20_grp) 
1256
        vfoa_grp.append(vfo50_grp)
1257
        vfoa_grp.append(vfo350_grp) 
1258
        vfoa_grp.append(vfo850_grp)
1259
        scan_grp.append(scanname_grp)
1260
        
1261
        group = RadioSettings(cfg_grp, vfo_grp, fmradio_grp, 
1262
                        remote_grp, scan_grp, extra_grp)
1263

    
1264
# Memory extras
1265
        # rs = RadioSetting("_mem.mute_mode", "Mute Mode"+str(number),
1266
        #                   RadioSettingValueBoolean(_mem.mute_mode))
1267
        # memxtras_grp.append(rs)
1268

    
1269
# Configuration Settings
1270

    
1271
        rs = RadioSetting("roger", "Roger Beep",
1272
                          RadioSettingValueList(ROGER_LIST,
1273
                                                ROGER_LIST[_settings.
1274
                                                           roger]))
1275
        cfg1_grp.append(rs)
1276

    
1277
        rs = RadioSetting("beep", "Keypad Beep",
1278
                          RadioSettingValueBoolean(_settings.beep))
1279
        cfg1_grp.append(rs)
1280

    
1281
        rs = RadioSetting("voice", "Voice Guide",
1282
                          RadioSettingValueBoolean(_settings.voice))
1283
        cfg1_grp.append(rs)
1284

    
1285
        rs = RadioSetting("bcl_a", "Busy Channel Lock-out A",
1286
                          RadioSettingValueBoolean(_settings.bcl_a))
1287
        cfg1_grp.append(rs)
1288

    
1289
        rs = RadioSetting("bcl_b", "Busy Channel Lock-out B",
1290
                          RadioSettingValueBoolean(_settings.bcl_b))
1291
        cfg1_grp.append(rs)
1292

    
1293
        rs = RadioSetting("sc_rev", "Scan Mode",
1294
                          RadioSettingValueMap(SC_REV_MAP, _settings.sc_rev))
1295
        cfg1_grp.append(rs)
1296
        rs = RadioSetting("tot", "Timeout Timer (TOT)",
1297
                          RadioSettingValueMap(
1298
                              TOT_MAP, _settings.tot))
1299
        cfg1_grp.append(rs)
1300

    
1301
        rs = RadioSetting("toa", "Timeout Alarm (TOA)",
1302
                          RadioSettingValueList(
1303
                              TOA_LIST, TOA_LIST[_settings.toa]))
1304
        cfg1_grp.append(rs)
1305

    
1306
        rs = RadioSetting("ani_sw", "Caller ID Tx - ANI-SW",
1307
                          RadioSettingValueBoolean(_settings.ani_sw))
1308
        cfg1_grp.append(rs)
1309

    
1310
        rs = RadioSetting("ring", "Ring Time (Sec)",
1311
                          RadioSettingValueList(RING_LIST,
1312
                           RING_LIST[_settings.ring]))
1313
        cfg1_grp.append(rs)
1314

    
1315

    
1316
        rs = RadioSetting("dtmfsf", "DTMF Sidetone",
1317
                          RadioSettingValueList(
1318
                              DTMF_ST_LIST,
1319
                              DTMF_ST_LIST[_settings.dtmfsf]))
1320
        cfg1_grp.append(rs)
1321

    
1322

    
1323
        rs = RadioSetting("ptt_id", "Caller ID Tx Mode (PTT_ID)",
1324
                          RadioSettingValueMap(PTT_ID_MAP, _settings.ptt_id))
1325
        cfg1_grp.append(rs)
1326

    
1327

    
1328
        rs = RadioSetting("wt_led", "Standby / WT LED",
1329
                          RadioSettingValueList(
1330
                              BACKLIGHT_LIST,
1331
                              BACKLIGHT_LIST[_settings.wt_led]))
1332
        cfg1_grp.append(rs)
1333

    
1334
        rs = RadioSetting("tx_led", "TX LED",
1335
                          RadioSettingValueList(
1336
                              BACKLIGHT_LIST,
1337
                              BACKLIGHT_LIST[_settings.tx_led]))
1338
        cfg1_grp.append(rs)
1339

    
1340
        rs = RadioSetting("rx_led", "Rx LED",
1341
                          RadioSettingValueList(
1342
                              BACKLIGHT_LIST,
1343
                              BACKLIGHT_LIST[_settings.rx_led]))
1344
        cfg1_grp.append(rs)
1345

    
1346
        rs = RadioSetting("prich_sw", "Priority Channel Scan",
1347
                          RadioSettingValueBoolean(_settings.prich_sw))
1348
        cfg1_grp.append(rs)
1349

    
1350
        rs = RadioSetting("spk_cont", "Speaker Control",
1351
                          RadioSettingValueMap(
1352
                              SPEAKER_MAP,
1353
                              _settings.spk_cont))
1354
        cfg1_grp.append(rs)
1355

    
1356
        rs = RadioSetting("autolock", "Autolock",
1357
                          RadioSettingValueBoolean(_settings.autolock))
1358
        cfg1_grp.append(rs)
1359

    
1360
        rs = RadioSetting("low_v", "Low Voltage Shutoff",
1361
                          RadioSettingValueBoolean(_settings.low_v))
1362
        cfg1_grp.append(rs)
1363

    
1364
        rs = RadioSetting("fan", "Fan Mode",
1365
                          RadioSettingValueList(
1366
                              FAN_MODE_LIST,
1367
                              FAN_MODE_LIST[_settings.fan]))
1368
        cfg1_grp.append(rs)
1369

    
1370
        rs = RadioSetting("apo_time", "Auto Power-Off (Min)",
1371
                          RadioSettingValueList(
1372
                              APO_TIME_LIST,
1373
                              APO_TIME_LIST[_settings.apo_time]))
1374
        cfg1_grp.append(rs)
1375

    
1376
        rs = RadioSetting("alert", "Alert Pulse (Hz)",
1377
                          RadioSettingValueMap(ALERT_MAP, _settings.alert))
1378
        cfg1_grp.append(rs)
1379
        rs = RadioSetting("m_pwr", "Medium Power Level (W)",
1380
                          RadioSettingValueMap(M_POWER_MAP,
1381
                                               _settings.m_pwr))
1382
        cfg1_grp.append(rs)
1383

    
1384
        rs = RadioSetting("rpt_set_model", "Model (RPT-SET)",
1385
                          RadioSettingValueList(
1386
                              RPT_MODE_LIST,
1387
                              RPT_MODE_LIST[_settings.rpt_set_model]))
1388
        cfg2_grp.append(rs)
1389

    
1390
        rs = RadioSetting("rpt_spk", "Repeater Speaker Switch (RPT-SPK)",
1391
                          RadioSettingValueBoolean(_settings.rpt_spk))
1392
        cfg2_grp.append(rs)
1393

    
1394
        rs = RadioSetting("rpt_ptt", "Repeater PTT (RPT-PTT)",
1395
                          RadioSettingValueBoolean(_settings.rpt_ptt))
1396
        cfg2_grp.append(rs)
1397

    
1398
        rs = RadioSetting("dtmf_time", "DTMF Tx Duration (ms)",
1399
                          RadioSettingValueList(
1400
                              DTMF_TIMES,
1401
                              DTMF_TIMES[_settings.dtmf_time]))
1402
        cfg2_grp.append(rs)
1403
        rs = RadioSetting("dtmf_int", "DTMF Interval (ms)",
1404
                          RadioSettingValueList(
1405
                              DTMF_INTERVALS,
1406
                              DTMF_INTERVALS[_settings.dtmf_int]))
1407
        cfg2_grp.append(rs)
1408

    
1409
        rs = RadioSetting("sc_qt", "CTCSS/DCS Scan",
1410
                          RadioSettingValueMap(
1411
                              SC_QT_MAP,_settings.sc_qt))
1412
        cfg2_grp.append(rs)
1413

    
1414
        rs = RadioSetting("pri_ch", "Priority Channel",
1415
                          RadioSettingValueInteger(
1416
                              1, 999, _chnum_decode(_settings.pri_ch)))
1417
        cfg2_grp.append(rs)
1418

    
1419
        rs = RadioSetting("ptt_id_dly", "Caller ID Tx Delay PTT-ID-DLY (ms)",
1420
                          RadioSettingValueMap(PTT_ID_DELAY_MAP,
1421
                                               _settings.ptt_id_dly))
1422
        cfg2_grp.append(rs)
1423

    
1424
        rs = RadioSetting("rc_sw", "Remote Control RC-SW",
1425
                          RadioSettingValueBoolean(_settings.rc_sw))
1426
        cfg2_grp.append(rs)
1427

    
1428
        rs = RadioSetting("scan_det", "Scan DET",
1429
                          RadioSettingValueBoolean(_settings.scan_det))
1430
        cfg2_grp.append(rs)
1431

    
1432
        rs = RadioSetting("menu", "Menu Available",
1433
                          RadioSettingValueBoolean(_settings.menu))
1434
        cfg2_grp.append(rs)
1435

    
1436
        rs = RadioSetting("thr_vol_tx", "Threshold Voltage Tx",
1437
                          RadioSettingValueBoolean(_settings.thr_vol_tx))
1438
        cfg2_grp.append(rs)
1439

    
1440
        rs = RadioSetting("hold_time_rpt", "Hold Time of Repeat (ms)",
1441
                          RadioSettingValueList(
1442
                              HOLD_TIMES,
1443
                              HOLD_TIMES[_settings.hold_time_rpt]))
1444
        cfg2_grp.append(rs)
1445

    
1446
        rs = RadioSetting("auto_am", "Auto AM",
1447
                          RadioSettingValueBoolean(_settings.auto_am))
1448
        cfg2_grp.append(rs)
1449

    
1450
        rs = RadioSetting("rpt_tone", "Repeat Tone",
1451
                          RadioSettingValueBoolean(_settings.rpt_tone))
1452
        cfg2_grp.append(rs)
1453

    
1454
        rs = RadioSetting("pf1_set", "PF1 setting",
1455
                          RadioSettingValueList(
1456
                              PF1_SETTINGS,
1457
                              PF1_SETTINGS[_settings.pf1_set]))
1458
        cfg2_grp.append(rs)
1459

    
1460
        rs = RadioSetting("settings.thr_vol_lvl", "Threshold Voltage Level",
1461
                          RadioSettingValueFloat(
1462
                              9.5, 10.5, _settings.thr_vol_lvl / 100.0 , 0.1, 1))
1463
        cfg2_grp.append(rs)
1464

    
1465
        dtmfchars = "0123456789"
1466
        _code =''
1467
        test = int(_oem.mode_psw)
1468
        _codeobj = '0x{0:0{1}X}'.format(test,6)
1469
        LOG.debug("codeobj = %s" % _codeobj)
1470
        _psw = str(_codeobj)
1471
        for i in range(2,8):
1472
            LOG.debug("psw[i] = %s" % _psw[i])
1473
            if _psw[i] in dtmfchars:
1474
                _code += _psw[i]
1475
        val_psw = int(_code)
1476
        LOG.debug("psw = %s" % val_psw)
1477
        val_psw = RadioSettingValueString(6, 6, _code, False)
1478
        val_psw.set_charset(dtmfchars)
1479
        rs = RadioSetting("oem.mode_psw", "MODE PSW", val_psw)
1480
        def apply_psw_id(setting, obj):
1481
            val2 = hex(int(str(val_psw),16))
1482
            LOG.debug("val2= %s" % val2)
1483
            if (int(val2,16) != 0):
1484
               while len(val2) < 8:
1485
                   val2 += '0'
1486
            psw = int(str(val2),16)
1487
            LOG.debug("val3= %s" % psw)
1488
            LOG.debug("val= %s" % val_psw)
1489
            obj.mode_psw = psw
1490
        rs.set_apply_callback(apply_psw_id, _oem)
1491
        cfg2_grp.append(rs)
1492

    
1493
        rs = RadioSetting("ABR", "ABR (Backlight On Time)",
1494
                          RadioSettingValueList(
1495
                              ABR_LIST,
1496
                              ABR_LIST[_settings.ABR]))
1497
        cfg2_grp.append(rs)
1498

    
1499
        rs = RadioSetting("KeyA", "Key A",
1500
                          RadioSettingValueList(
1501
                              KEY_LIST,
1502
                              KEY_LIST[_settings.KeyA]))
1503
        cfg2_grp.append(rs)
1504
        rs = RadioSetting("KeyB", "Key B",
1505
                          RadioSettingValueList(
1506
                              KEY_LIST,
1507
                              KEY_LIST[_settings.KeyB]))
1508
        cfg2_grp.append(rs)
1509
        rs = RadioSetting("KeyC", "Key C",
1510
                          RadioSettingValueList(
1511
                              KEY_LIST,
1512
                              KEY_LIST[_settings.KeyC]))
1513
        cfg2_grp.append(rs)
1514

    
1515
        rs = RadioSetting("act_area", "Active Area (BAND)",
1516
                          RadioSettingValueList(
1517
                              ACTIVE_AREA_LIST,
1518
                              ACTIVE_AREA_LIST[_settings.act_area]))
1519
        cfg2_grp.append(rs)
1520
        rs = RadioSetting("tdr_off", "TDR",
1521
                          RadioSettingValueList(
1522
                              TDR_LIST,
1523
                              TDR_LIST[_settings.tdr_off]))
1524
        cfg2_grp.append(rs)
1525

    
1526
# Freq Limits settings
1527
        
1528
        # Convert Integer back to correct limit HEX value:  limit = hex(int(str(limit*10),16))        
1529
        # # LOG.debug("limit =" % limit)
1530

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

    
1538
        _temp =str(hex(int("%i" % self._memobj.bandlimits.limit_144M_ChA_rx_stop, 10)))
1539
        _temp = int(int(_temp[2:])/10.0)
1540
        val= RadioSettingValueInteger(0,999, _temp)
1541
        rs = RadioSetting("bandlimits.limit_144M_ChA_rx_stop", "144M ChA Rx Upper Limit (MHz)",
1542
                          RadioSettingValueInteger(0,999,
1543
                              val))
1544
        rxlim_grp.append(rs)
1545

    
1546
        _temp =str(hex(int("%i" % self._memobj.bandlimits.limit_144M_ChB_rx_start, 10)))
1547
        _temp = int(int(_temp[2:])/10.0)
1548
        val= RadioSettingValueInteger(0,999, _temp)
1549
        rs = RadioSetting("bandlimits.limit_144M_ChB_rx_start", "144M ChB Rx Lower Limit (MHz)",
1550
                          val)
1551
        rxlim_grp.append(rs)
1552

    
1553
        _temp =str(hex(int("%i" % self._memobj.bandlimits.limit_144M_ChB_rx_stop, 10)))
1554
        _temp = int(int(_temp[2:])/10.0)
1555
        val= RadioSettingValueInteger(0,999, _temp)
1556
        rs = RadioSetting("bandlimits.limit_144M_ChB_rx_stop", "144M ChB Rx Upper Limit (MHz)",
1557
                          RadioSettingValueInteger(0,999,
1558
                              val))
1559
        rxlim_grp.append(rs)
1560

    
1561
        _temp =str(hex(int("%i" % self._memobj.bandlimits.limit_70cm_rx_start, 10)))
1562
        _temp = int(int(_temp[2:])/10.0)
1563
        val= RadioSettingValueInteger(0,999, _temp)
1564
        rs = RadioSetting("bandlimits.limit_70cm_rx_start", "450M Rx Lower Limit (MHz)",
1565
                          RadioSettingValueInteger(0,999,
1566
                              val))
1567
        rxlim_grp.append(rs)
1568

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

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

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

    
1593
        _temp =str(hex(int("%i" % self._memobj.bandlimits.limit_6m_rx_start, 10)))
1594
        _temp = int(int(_temp[2:])/10.0)
1595
        val= RadioSettingValueInteger(0,999, _temp)
1596
        rs = RadioSetting("bandlimits.limit_6m_rx_start", "50M Rx Lower Limit (MHz)",
1597
                          RadioSettingValueInteger(0,999,
1598
                              val))
1599
        rxlim_grp.append(rs)
1600

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

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

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

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

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

    
1641

    
1642
        _temp =str(hex(int("%i" % self._memobj.bandlimits.limit_144M_ChA_tx_start, 10)))
1643
        _temp = int(int(_temp[2:])/10.0)
1644
        val= RadioSettingValueInteger(0,999, _temp)
1645
        rs = RadioSetting("bandlimits.limit_144M_ChA_tx_start", "144M ChA Tx Lower Limit (MHz)",
1646
                          RadioSettingValueInteger(0,999,
1647
                              val))
1648
        txlim_grp.append(rs)
1649

    
1650
        _temp =str(hex(int("%i" % self._memobj.bandlimits.limit_144M_ChA_tx_stop, 10)))
1651
        _temp = int(int(_temp[2:])/10.0)
1652
        val= RadioSettingValueInteger(0,999, _temp)
1653
        rs = RadioSetting("bandlimits.limit_144M_ChA_tx_stop", "144M ChA Tx Upper Limit (MHz)",
1654
                          RadioSettingValueInteger(0,999,
1655
                              val))
1656
        txlim_grp.append(rs)
1657

    
1658
        _temp =str(hex(int("%i" % self._memobj.bandlimits.limit_70cm_tx_start, 10)))
1659
        _temp = int(int(_temp[2:])/10.0)
1660
        val= RadioSettingValueInteger(0,999, _temp)
1661
        rs = RadioSetting("bandlimits.limit_70cm_tx_start", "450M Tx Lower Limit (MHz)",
1662
                          RadioSettingValueInteger(0,999,
1663
                              val))
1664
        txlim_grp.append(rs)
1665

    
1666
        _temp =str(hex(int("%i" % self._memobj.bandlimits.limit_70cm_tx_stop, 10)))
1667
        _temp = int(int(_temp[2:])/10.0)
1668
        val= RadioSettingValueInteger(0,999, _temp)
1669
        rs = RadioSetting("bandlimits.limit_70cm_tx_stop", "450M tx Upper Limit (MHz)",
1670
                          RadioSettingValueInteger(0,999,
1671
                              val))
1672
        txlim_grp.append(rs)
1673

    
1674
        _temp =str(hex(int("%i" % self._memobj.bandlimits.limit_10m_tx_start, 10)))
1675
        _temp = int(int(_temp[2:])/10.0)
1676
        val= RadioSettingValueInteger(0,999, _temp)
1677
        rs = RadioSetting("bandlimits.limit_10m_tx_start", "20M tx Lower Limit (MHz)",
1678
                          RadioSettingValueInteger(0,999,
1679
                              val))
1680
        txlim_grp.append(rs)
1681

    
1682
        _temp =str(hex(int("%i" % self._memobj.bandlimits.limit_10m_tx_stop, 10)))
1683
        _temp = int(int(_temp[2:])/10.0)
1684
        val= RadioSettingValueInteger(0,999, _temp)
1685
        rs = RadioSetting("bandlimits.limit_10m_tx_stop", "20M tx Upper Limit (MHz)",
1686
                          RadioSettingValueInteger(0,999,
1687
                              val))
1688
        txlim_grp.append(rs)
1689

    
1690
        _temp =str(hex(int("%i" % self._memobj.bandlimits.limit_6m_tx_start, 10)))
1691
        _temp = int(int(_temp[2:])/10.0)
1692
        val= RadioSettingValueInteger(0,999, _temp)
1693
        rs = RadioSetting("bandlimits.limit_6m_tx_start", "50M tx Lower Limit (MHz)",
1694
                          RadioSettingValueInteger(0,999,
1695
                              val))
1696
        txlim_grp.append(rs)
1697

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

    
1706
# VFO Settings
1707
        rs = RadioSetting("vfomode_a", "VFO A Working Mode",
1708
                          RadioSettingValueMap(WORKMODE_MAP,
1709
                                               _settings.vfomode_a))
1710
        vfoa_grp.append(rs)
1711

    
1712
        rs = RadioSetting("vfoband_a", "VFO A Current Band",
1713
                          RadioSettingValueMap(VFOBAND_MAP,
1714
                                               _settings.vfoband_a))
1715
        vfoa_grp.append(rs)
1716

    
1717
        rs = RadioSetting("vfochan_a", "VFO A Channel",
1718
                          RadioSettingValueInteger(1, 999,
1719
                              _chnum_decode(_settings.vfochan_a)))
1720
        vfoa_grp.append(rs)
1721

    
1722
        rs = RadioSetting("vfosquelch_a", "VFO A Squelch",
1723
                          RadioSettingValueInteger(0, 9,
1724
                              _settings.vfosquelch_a))
1725
        vfoa_grp.append(rs)
1726
        rs = RadioSetting("vfostep_a", "VFO A Step",
1727
                          RadioSettingValueList(
1728
                            STEP_LIST,
1729
                            STEP_LIST[_settings.vfostep_a]))
1730
        vfoa_grp.append(rs)
1731
######################
1732

    
1733
        rs = RadioSetting("vfofreq1", "VFO 150M Freq",
1734
                          RadioSettingValueFloat(
1735
                             0, 999.999999, (_freq_decode
1736
                             (_settings.vfofreq1)/1000000.0) ,0.000001, 6))
1737
        vfo150_grp.append(rs)
1738

    
1739
        rs = RadioSetting("vfoofst1", "VFO 150M Offset",
1740
                          RadioSettingValueFloat(
1741
                              0, 999.999999, (_freq_decode
1742
                              (_settings.vfoofst1)/1000000.0),0.000001, 6))
1743
        vfo150_grp.append(rs)
1744

    
1745
        rs = RadioSetting("rxtone1", "VFO 150M Rx tone",
1746
                          RadioSettingValueMap(
1747
                            TONE_MAP, _settings.rxtone1))
1748
        vfo150_grp.append(rs)
1749

    
1750
        rs = RadioSetting("txtone1", "VFO 150M Tx tone",
1751
                          RadioSettingValueMap(
1752
                            TONE_MAP, _settings.txtone1))
1753
        vfo150_grp.append(rs)
1754

    
1755
        rs = RadioSetting("power1", "VFO 150M Power",
1756
                          RadioSettingValueMap(
1757
                            POWER_MAP, _settings.power1))
1758
        vfo150_grp.append(rs)
1759

    
1760
        rs = RadioSetting("narrow1", "VFO 150M Bandwidth",
1761
                          RadioSettingValueMap(
1762
                            BANDWIDTH_MAP, _settings.narrow1))
1763
        vfo150_grp.append(rs)
1764

    
1765
        rs = RadioSetting("mute1", "VFO 150M Mute Mode",
1766
                          RadioSettingValueMap(
1767
                            MUTE_MODE_MAP, _settings.mute1))
1768
        vfo150_grp.append(rs)
1769

    
1770
        rs = RadioSetting("shft_dir1", "VFO 150M Shift Direction",
1771
                          RadioSettingValueList(
1772
                            DUPLEX_LIST,
1773
                            DUPLEX_LIST[_settings.shft_dir1]))
1774
        vfo150_grp.append(rs)
1775

    
1776
        rs = RadioSetting("compander1", "VFO 150M Compander",
1777
                          RadioSettingValueBoolean(
1778
                            _settings.compander1))
1779
        vfo150_grp.append(rs)
1780

    
1781
        rs = RadioSetting("scrambler1", "VFO 150M Scrambler",
1782
                          RadioSettingValueList(
1783
                            SCRAMBLER_LIST,
1784
                            SCRAMBLER_LIST[_settings.scrambler1]))
1785
        vfo150_grp.append(rs)
1786
        rs = RadioSetting("am_mode1", "VFO 150M AM Mode",
1787
                          RadioSettingValueBoolean(
1788
                            _settings.am_mode1))
1789
        vfo150_grp.append(rs)
1790
############################
1791

    
1792
        rs = RadioSetting("vfofreq2", "VFO 450M Freq",
1793
                          RadioSettingValueFloat(
1794
                             0, 999.999999, (_freq_decode
1795
                             (_settings.vfofreq2)/1000000.0) ,0.000001, 6))
1796
        vfo450_grp.append(rs)
1797

    
1798
        rs = RadioSetting("vfoofst2", "VFO 450M Offset",
1799
                          RadioSettingValueFloat(
1800
                              0, 999.999999, (_freq_decode
1801
                              (_settings.vfoofst2)/1000000.0),0.000001, 6))
1802
        vfo450_grp.append(rs)
1803

    
1804
        rs = RadioSetting("rxtone2", "VFO 450M Rx tone",
1805
                          RadioSettingValueMap(
1806
                            TONE_MAP, _settings.rxtone2))
1807
        vfo450_grp.append(rs)
1808

    
1809
        rs = RadioSetting("txtone2", "VFO 450M Tx tone",
1810
                          RadioSettingValueMap(
1811
                            TONE_MAP, _settings.txtone2))
1812
        vfo450_grp.append(rs)
1813
        
1814
        rs = RadioSetting("power2", "VFO 450M Power",
1815
                          RadioSettingValueMap(
1816
                            POWER_MAP, _settings.power2))
1817
        vfo450_grp.append(rs)
1818

    
1819
        rs = RadioSetting("narrow2", "VFO 450M Bandwidth",
1820
                          RadioSettingValueMap(
1821
                            BANDWIDTH_MAP, _settings.narrow2))
1822
        vfo450_grp.append(rs)
1823

    
1824
        rs = RadioSetting("mute2", "VFO 450M Mute Mode",
1825
                          RadioSettingValueMap(
1826
                            MUTE_MODE_MAP, _settings.mute2))
1827
        vfo450_grp.append(rs)
1828

    
1829
        rs = RadioSetting("shft_dir2", "VFO 450M Shift Direction",
1830
                          RadioSettingValueList(
1831
                            DUPLEX_LIST,
1832
                            DUPLEX_LIST[_settings.shft_dir2]))
1833
        vfo450_grp.append(rs)
1834

    
1835
        rs = RadioSetting("compander2", "VFO 450M Compander",
1836
                          RadioSettingValueBoolean(
1837
                            _settings.compander2))
1838
        vfo450_grp.append(rs)
1839

    
1840
        rs = RadioSetting("scrambler2", "VFO 450M Scrambler",
1841
                          RadioSettingValueList(
1842
                            SCRAMBLER_LIST,
1843
                            SCRAMBLER_LIST[_settings.scrambler2]))
1844
        vfo450_grp.append(rs)
1845

    
1846
        rs = RadioSetting("am_mode2", "VFO 450M AM Mode",
1847
                          RadioSettingValueBoolean(
1848
                            _settings.am_mode2))
1849
        vfo450_grp.append(rs)
1850
############################
1851
        rs = RadioSetting("vfofreq3", "VFO 20M Freq",
1852
                          RadioSettingValueFloat(
1853
                             0, 999.999999, (_freq_decode
1854
                             (_settings.vfofreq3)/1000000.0) ,0.000001, 6))
1855
        vfo20_grp.append(rs)
1856

    
1857
        rs = RadioSetting("vfoofst3", "VFO 20M Offset",
1858
                          RadioSettingValueFloat(
1859
                              0, 999.999999, (_freq_decode
1860
                              (_settings.vfoofst3)/1000000.0),0.000001, 6))
1861
        vfo20_grp.append(rs)
1862

    
1863
        rs = RadioSetting("rxtone3", "VFO 20M Rx tone",
1864
                          RadioSettingValueMap(
1865
                            TONE_MAP, _settings.rxtone3))
1866
        vfo20_grp.append(rs)
1867

    
1868
        rs = RadioSetting("txtone3", "VFO 20M Tx tone",
1869
                          RadioSettingValueMap(
1870
                            TONE_MAP, _settings.txtone3))
1871
        vfo20_grp.append(rs)
1872
        
1873
        rs = RadioSetting("power3", "VFO 20M Power",
1874
                          RadioSettingValueMap(
1875
                            POWER_MAP, _settings.power3))
1876
        vfo20_grp.append(rs)
1877

    
1878
        rs = RadioSetting("narrow3", "VFO 20M Bandwidth",
1879
                          RadioSettingValueMap(
1880
                            BANDWIDTH_MAP, _settings.narrow3))
1881
        vfo20_grp.append(rs)
1882

    
1883
        rs = RadioSetting("mute3", "VFO 20M Mute Mode",
1884
                          RadioSettingValueMap(
1885
                            MUTE_MODE_MAP, _settings.mute3))
1886
        vfo20_grp.append(rs)
1887

    
1888
        rs = RadioSetting("shft_dir3", "VFO 20M Shift Direction",
1889
                          RadioSettingValueList(
1890
                            DUPLEX_LIST,
1891
                            DUPLEX_LIST[_settings.shft_dir3]))
1892
        vfo20_grp.append(rs)
1893

    
1894
        rs = RadioSetting("compander3", "VFO 20M Compander",
1895
                          RadioSettingValueBoolean(
1896
                            _settings.compander3))
1897
        vfo20_grp.append(rs)
1898

    
1899
        rs = RadioSetting("scrambler3", "VFO 20M Scrambler",
1900
                          RadioSettingValueList(
1901
                            SCRAMBLER_LIST,
1902
                            SCRAMBLER_LIST[_settings.scrambler3]))
1903
        vfo20_grp.append(rs)
1904

    
1905
        rs = RadioSetting("am_mode3", "VFO 20M AM Mode",
1906
                          RadioSettingValueBoolean(
1907
                            _settings.am_mode3))
1908
        vfo20_grp.append(rs)
1909
############################
1910
        rs = RadioSetting("vfofreq4", "VFO 50M Freq",
1911
                          RadioSettingValueFloat(
1912
                             0, 999.999999, (_freq_decode
1913
                             (_settings.vfofreq4)/1000000.0) ,0.000001, 6))
1914
        vfo50_grp.append(rs)
1915

    
1916
        rs = RadioSetting("vfoofst4", "VFO 50M Offset",
1917
                          RadioSettingValueFloat(
1918
                              0, 999.999999, (_freq_decode
1919
                              (_settings.vfoofst4)/1000000.0),0.000001, 6))
1920
        vfo50_grp.append(rs)
1921

    
1922
        rs = RadioSetting("rxtone4", "VFO 50M Rx tone",
1923
                          RadioSettingValueMap(
1924
                            TONE_MAP, _settings.rxtone4))
1925
        vfo50_grp.append(rs)
1926

    
1927
        rs = RadioSetting("txtone4", "VFO 50M Tx tone",
1928
                          RadioSettingValueMap(
1929
                            TONE_MAP, _settings.txtone4))
1930
        vfo50_grp.append(rs)
1931
        
1932
        rs = RadioSetting("power4", "VFO 50M Power",
1933
                          RadioSettingValueMap(
1934
                            POWER_MAP, _settings.power4))
1935
        vfo50_grp.append(rs)
1936

    
1937
        rs = RadioSetting("narrow4", "VFO 50M Bandwidth",
1938
                          RadioSettingValueMap(
1939
                            BANDWIDTH_MAP, _settings.narrow4))
1940
        vfo50_grp.append(rs)
1941

    
1942
        rs = RadioSetting("mute4", "VFO 50M Mute Mode",
1943
                          RadioSettingValueMap(
1944
                            MUTE_MODE_MAP, _settings.mute4))
1945
        vfo50_grp.append(rs)
1946

    
1947
        rs = RadioSetting("shft_dir4", "VFO 50M Shift Direction",
1948
                          RadioSettingValueList(
1949
                            DUPLEX_LIST,
1950
                            DUPLEX_LIST[_settings.shft_dir4]))
1951
        vfo50_grp.append(rs)
1952

    
1953
        rs = RadioSetting("compander4", "VFO 50M Compander",
1954
                          RadioSettingValueBoolean(
1955
                            _settings.compander4))
1956
        vfo50_grp.append(rs)
1957

    
1958
        rs = RadioSetting("scrambler4", "VFO 50M Scrambler",
1959
                          RadioSettingValueList(
1960
                            SCRAMBLER_LIST,
1961
                            SCRAMBLER_LIST[_settings.scrambler4]))
1962
        vfo50_grp.append(rs)
1963

    
1964
        rs = RadioSetting("am_mode4", "VFO 50M AM Mode",
1965
                          RadioSettingValueBoolean(
1966
                            _settings.am_mode4))
1967
        vfo50_grp.append(rs)
1968
############################
1969
        rs = RadioSetting("vfofreq5", "VFO 350M Freq",
1970
                          RadioSettingValueFloat(
1971
                             0, 999.999999, (_freq_decode
1972
                             (_settings.vfofreq5)/1000000.0) ,0.000001, 6))
1973
        vfo350_grp.append(rs)
1974

    
1975
        rs = RadioSetting("vfoofst5", "VFO 350M Offset",
1976
                          RadioSettingValueFloat(
1977
                              0, 999.999999, (_freq_decode
1978
                              (_settings.vfoofst5)/1000000.0),0.000001, 6))
1979
        vfo350_grp.append(rs)
1980

    
1981
        rs = RadioSetting("rxtone5", "VFO 350M Rx tone",
1982
                          RadioSettingValueMap(
1983
                            TONE_MAP, _settings.rxtone5))
1984
        vfo350_grp.append(rs)
1985

    
1986
        rs = RadioSetting("txtone5", "VFO 350M Tx tone",
1987
                          RadioSettingValueMap(
1988
                            TONE_MAP, _settings.txtone5))
1989
        vfo350_grp.append(rs)
1990
        
1991
        rs = RadioSetting("power5", "VFO 350M Power",
1992
                          RadioSettingValueMap(
1993
                            POWER_MAP, _settings.power5))
1994
        vfo350_grp.append(rs)
1995

    
1996
        rs = RadioSetting("narrow5", "VFO 350M Bandwidth",
1997
                          RadioSettingValueMap(
1998
                            BANDWIDTH_MAP, _settings.narrow5))
1999
        vfo350_grp.append(rs)
2000

    
2001
        rs = RadioSetting("mute5", "VFO 350M Mute Mode",
2002
                          RadioSettingValueMap(
2003
                            MUTE_MODE_MAP, _settings.mute5))
2004
        vfo350_grp.append(rs)
2005

    
2006
        rs = RadioSetting("shft_dir5", "VFO 350M Shift Direction",
2007
                          RadioSettingValueList(
2008
                            DUPLEX_LIST,
2009
                            DUPLEX_LIST[_settings.shft_dir5]))
2010
        vfo350_grp.append(rs)
2011

    
2012
        rs = RadioSetting("compander5", "VFO 350M Compander",
2013
                          RadioSettingValueBoolean(
2014
                            _settings.compander5))
2015
        vfo350_grp.append(rs)
2016

    
2017
        rs = RadioSetting("scrambler5", "VFO 350M Scrambler",
2018
                          RadioSettingValueList(
2019
                            SCRAMBLER_LIST,
2020
                            SCRAMBLER_LIST[_settings.scrambler5]))
2021
        vfo350_grp.append(rs)
2022

    
2023
        rs = RadioSetting("am_mode5", "VFO 350M AM Mode",
2024
                          RadioSettingValueBoolean(
2025
                            _settings.am_mode5))
2026
        vfo350_grp.append(rs)
2027

    
2028
# ############################
2029
        rs = RadioSetting("vfofreq6", "VFO 850M Freq",
2030
                          RadioSettingValueFloat(
2031
                             0, 999.999999, (_freq_decode
2032
                             (_settings.vfofreq6)/1000000.0) ,0.000001, 6))
2033
        vfo850_grp.append(rs)
2034

    
2035
        rs = RadioSetting("vfoofst6", "VFO 850M Offset",
2036
                          RadioSettingValueFloat(
2037
                              0, 999.999999, (_freq_decode
2038
                              (_settings.vfoofst6)/1000000.0),0.000001, 6))
2039
        vfo850_grp.append(rs)
2040

    
2041
        rs = RadioSetting("rxtone6", "VFO 850M Rx tone",
2042
                          RadioSettingValueMap(
2043
                            TONE_MAP, _settings.rxtone6))
2044
        vfo850_grp.append(rs)
2045

    
2046
        rs = RadioSetting("txtone6", "VFO 850M Tx tone",
2047
                          RadioSettingValueMap(
2048
                            TONE_MAP, _settings.txtone6))
2049
        vfo850_grp.append(rs)
2050
        
2051
        rs = RadioSetting("power6", "VFO 850M Power",
2052
                          RadioSettingValueMap(
2053
                            POWER_MAP, _settings.power6))
2054
        vfo850_grp.append(rs)
2055

    
2056
        rs = RadioSetting("narrow6", "VFO 850M Bandwidth",
2057
                          RadioSettingValueMap(
2058
                            BANDWIDTH_MAP, _settings.narrow6))
2059
        vfo850_grp.append(rs)
2060

    
2061
        rs = RadioSetting("mute6", "VFO 850M Mute Mode",
2062
                          RadioSettingValueMap(
2063
                            MUTE_MODE_MAP, _settings.mute6))
2064
        vfo850_grp.append(rs)
2065

    
2066
        rs = RadioSetting("shft_dir6", "VFO 850M Shift Direction",
2067
                          RadioSettingValueList(
2068
                            DUPLEX_LIST,
2069
                            DUPLEX_LIST[_settings.shft_dir6]))
2070
        vfo850_grp.append(rs)
2071

    
2072
        rs = RadioSetting("compander6", "VFO 850M Compander",
2073
                          RadioSettingValueBoolean(
2074
                            _settings.compander6))
2075
        vfo850_grp.append(rs)
2076

    
2077
        rs = RadioSetting("scrambler6", "VFO 850M Scrambler",
2078
                          RadioSettingValueList(
2079
                            SCRAMBLER_LIST,
2080
                            SCRAMBLER_LIST[_settings.scrambler6]))
2081
        vfo850_grp.append(rs)
2082

    
2083
        rs = RadioSetting("am_mode6", "VFO 850M AM Mode",
2084
                          RadioSettingValueBoolean(
2085
                            _settings.am_mode6))
2086
        vfo850_grp.append(rs)
2087

    
2088
############################
2089

    
2090
        rs = RadioSetting("vfomode_b", "VFO B Working Mode",
2091
                          RadioSettingValueMap(WORKMODE_MAP,
2092
                                               _settings.vfomode_b))
2093
        vfob_grp.append(rs)
2094

    
2095
        rs = RadioSetting("vfochan_b", "VFO B Work Channel",
2096
                          RadioSettingValueInteger(1, 999,
2097
                              _chnum_decode(_settings.vfochan_b)))
2098
        vfob_grp.append(rs)
2099

    
2100
        rs = RadioSetting("vfofreq7", "VFO B Freq",
2101
                          RadioSettingValueFloat(
2102
                             0, 999.999999, (_freq_decode
2103
                             (_settings.vfofreq7)/1000000.0) ,0.000001, 6))
2104
        vfob_grp.append(rs)
2105

    
2106
        rs = RadioSetting("vfoofst7", "VFO B Offset",
2107
                          RadioSettingValueFloat(
2108
                              0, 999.999999, (_freq_decode
2109
                              (_settings.vfoofst7)/1000000.0),0.000001, 6))
2110
        vfob_grp.append(rs)
2111

    
2112
        rs = RadioSetting("rxtone7", "VFOB Rx tone",
2113
                          RadioSettingValueMap(
2114
                            TONE_MAP, _settings.rxtone7))
2115
        vfob_grp.append(rs)
2116

    
2117
        rs = RadioSetting("txtone7", "VFOB Tx tone",
2118
                          RadioSettingValueMap(
2119
                            TONE_MAP, _settings.txtone7))
2120
        vfob_grp.append(rs)
2121
        rs = RadioSetting("power7", "VFOB Power",
2122
                          RadioSettingValueMap(
2123
                            POWER_MAP, _settings.power7))
2124
        vfob_grp.append(rs)
2125
        rs = RadioSetting("narrow7", "VFOB Bandwidth",
2126
                          RadioSettingValueMap(
2127
                            BANDWIDTH_MAP, _settings.narrow7))
2128
        vfob_grp.append(rs)
2129
        rs = RadioSetting("mute7", "VFOB Mute Mode",
2130
                          RadioSettingValueMap(
2131
                            MUTE_MODE_MAP, _settings.mute7))
2132
        vfob_grp.append(rs)
2133
        rs = RadioSetting("shft_dir7", "VFOB Shift Direction",
2134
                          RadioSettingValueList(
2135
                            DUPLEX_LIST,
2136
                            DUPLEX_LIST[_settings.shft_dir7]))
2137
        vfob_grp.append(rs)
2138
        rs = RadioSetting("compander7", "VFOB Compander",
2139
                          RadioSettingValueBoolean(
2140
                            _settings.compander7))
2141
        vfob_grp.append(rs)
2142

    
2143
        rs = RadioSetting("scrambler7", "VFOB Scrambler",
2144
                          RadioSettingValueList(
2145
                            SCRAMBLER_LIST,
2146
                            SCRAMBLER_LIST[_settings.scrambler7]))
2147
        vfob_grp.append(rs)
2148

    
2149
        rs = RadioSetting("vfosquelch_b", "VFO B Squelch",
2150
                          RadioSettingValueInteger(0, 9,
2151
                              _settings.vfosquelch_b))
2152
        vfob_grp.append(rs)
2153
        rs = RadioSetting("vfostep_b", "VFO B Step",
2154
                          RadioSettingValueList(
2155
                            STEP_LIST,
2156
                            STEP_LIST[_settings.vfostep_b]))
2157
        vfob_grp.append(rs)
2158
        # rs = RadioSetting("am_mode7", "VFOB AM Mode",
2159
        #                   RadioSettingValueBoolean(
2160
        #                     _settings.am_mode7))
2161
        # vfob_grp.append(rs)
2162

    
2163
# Scan Group Settings
2164
        def _decode(lst):
2165
            _str = ''.join([chr(c) for c in lst
2166
                            if chr(c) in SCANNAME_CHARSET])
2167
            return _str
2168

    
2169
        rs = RadioSetting("scan_a_act", "Scan A Active Group",
2170
                        RadioSettingValueList(
2171
                            SCAN_GROUP_LIST,
2172
                            SCAN_GROUP_LIST[_settings.scan_a_act]))
2173
        scan_grp.append(rs)
2174
        rs = RadioSetting("scan_b_act", "Scan B Active Group",
2175
                        RadioSettingValueList(
2176
                             SCAN_GROUP_LIST,
2177
                             SCAN_GROUP_LIST[_settings.scan_b_act]))
2178
        scan_grp.append(rs)
2179
       
2180

    
2181
        for i in range(1,11):
2182
            x=str(i)
2183
            _str = _decode(eval("_settings.scanname"+x))
2184
            LOG.debug("ScanName %s",i)
2185
            LOG.debug("is %s", _str)
2186
            # CPS treats PPPPPP as a blank name as it is the factor reset value"
2187
            # The Radio treats PPPPPPP as a blank name and can display 8 chars"
2188
            # Force Chirp to blank out the scan name if value is PPPPPPP to match the radio"
2189
            # Blank out the name if first 6 are spaces or null and the 7th is a P to handle
2190
            # firmware peculiarities in handling all 8 characters.
2191
            if _str[0:7] == "PPPPPPP":_str=""
2192
            elif _str[0:7] =="\x00\x00\x00\x00\x00\x00P":_str=""
2193
            elif _str[0:7] =="\x20\x20\x20\x20\x20\x20P":_str=""
2194
            rs=RadioSetting("scanname"+x, "Scan Name "+x,
2195
                        RadioSettingValueString(0,8, _str))
2196
            # rs = RadioSetting("scanname"+x, "Scan Name "+x, val)
2197
            scanname_grp.append(rs)
2198

    
2199
            scngrp = str(i)
2200
            rs = RadioSetting("scanlower"+scngrp, "Scan Lower "+scngrp,
2201
                            RadioSettingValueInteger(1, 999,  
2202
                            eval("_settings.scanlower"+scngrp)))
2203
            scan_grp.append(rs)
2204
            rs = RadioSetting("scanupper"+scngrp, "Scan Upper "+scngrp,
2205
                            RadioSettingValueInteger(1, 999,  
2206
                            eval("_settings.scanupper"+scngrp)))
2207
            scan_grp.append(rs)
2208
# remote settings
2209
        rs = RadioSetting("rc_power", "RC Power",
2210
                           RadioSettingValueList(
2211
                                    RC_POWER_LIST,
2212
                                    RC_POWER_LIST[_settings.rc_power]))
2213
        remote_grp.append(rs)
2214

    
2215
        _code =''
2216
        test = int(_settings.ani_edit)
2217
        _codeobj = '0x{0:0{1}X}'.format(test,6)
2218
        LOG.debug("codeobj = %s" % _codeobj)
2219
        _ani = str(_codeobj)
2220
        for i in range(2,8):
2221
            LOG.debug("ani[i] = %s" % _ani[i])
2222
            if _ani[i] in dtmfchars:
2223
                _code += _ani[i]
2224
        val_ani = int(_code)
2225
        LOG.debug("ani = %s" % val_ani)
2226
        val_ani = RadioSettingValueString(3, 6, _code, False)
2227
        val_ani.set_charset(dtmfchars)
2228
        rs = RadioSetting("settings.ani_edit", "ANI Edit", val_ani)
2229
        def apply_ani_id(setting, obj):
2230
            temp = list()
2231
            LOG.debug("val= %s" % val_ani)
2232
            if str(val_ani)[0] == "0":
2233
                raise errors.RadioError("ANI EDIT must start with Non-Zero Digit")
2234
            val2 = hex(int(str(val_ani),16))
2235
            LOG.debug("val2= %s" % val2)
2236
            if (int(val2,16) != 0):
2237
               while len(val2) < 5:
2238
                   val2 += '0'
2239
               while len(val2) < 8:
2240
                   val2 += 'C'
2241
            ani = int(str(val2),16)
2242
            LOG.debug("ani= %s" % ani)
2243
            LOG.debug("val= %s" % val_ani)
2244
            obj.ani_edit = ani
2245
        rs.set_apply_callback(apply_ani_id, _settings)
2246
        remote_grp.append(rs)
2247

    
2248
        _code =''
2249
        test = int(_settings.mcc_edit)
2250
        _codeobj = '0x{0:0{1}X}'.format(test,6)
2251
        LOG.debug("codeobj = %s" % _codeobj)
2252
        _mcc = str(_codeobj)
2253
        for i in range(2,8):
2254
            LOG.debug("mcc[i] = %s" % _mcc[i])
2255
            if _mcc[i] in dtmfchars:
2256
                _code += _mcc[i]
2257
        val_mcc = int(_code)
2258
        LOG.debug("mcc = %s" % val_mcc)
2259
        val_mcc = RadioSettingValueString(3, 6, _code, False)
2260
        val_mcc.set_charset(dtmfchars)
2261
        rs = RadioSetting("mcc_edit", "MCC Edit", val_mcc)
2262
        def apply_mcc_id(setting, obj):
2263
            val2 = hex(int(str(val_mcc),16))
2264
            LOG.debug("val2= %s" % val2)
2265
            if (int(val2,16) != 0):
2266
               while len(val2) < 5:
2267
                   val2 += '0'
2268
               while len(val2) < 8:
2269
                   val2 += 'C'
2270
            mcc = int(str(val2),16)
2271
            LOG.debug("val3= %s" % mcc)
2272
            LOG.debug("val= %s" % val_mcc)
2273
            obj.mcc_edit = mcc
2274
        rs.set_apply_callback(apply_mcc_id, _settings)
2275
        remote_grp.append(rs)
2276

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

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

    
2335

    
2336

    
2337

    
2338

    
2339
# OEM Settings
2340

    
2341
        _oem_name = _oem_str_decode(self._memobj.oem.display_name)
2342
        rs=RadioSetting("oem.display_name", "Display Banner Text",
2343
                        RadioSettingValueString(1,8, _oem_name))
2344
        oem_grp.append(rs)
2345

    
2346
# FM RADIO PRESETS
2347

    
2348
# memory stores raw integer value like 7600
2349
# radio will divide 7600 by 100 and interpret correctly at 76.0Mhz
2350
        #
2351
        # FM Radio Presets Settings
2352
        #
2353

    
2354
        for i in range(1, 21):
2355
            chan = str(i)
2356
            rs = RadioSetting("FM_radio" + chan, "FM Preset " + chan,
2357
                              RadioSettingValueFloat(76.0, 108.0,
2358
                                                     eval("_settings.FM_radio" +
2359
                                                          chan)/100.0,
2360
                                                     0.1, 1))
2361
            fmradio_grp.append(rs)
2362

    
2363
        return group
2364

    
2365
    def get_settings(self):
2366
        try:
2367
            return self._get_settings()
2368
        except:
2369
            import traceback
2370
            LOG.error("Failed to parse settings: %s", traceback.format_exc())
2371
            return None
2372

    
2373
    def set_settings(self, settings):
2374
        for element in settings:
2375
            if not isinstance(element, RadioSetting):
2376
                self.set_settings(element)
2377
                continue
2378
            else:
2379
                try:
2380
                    if "." in element.get_name():
2381
                        bits = element.get_name().split(".")
2382
                        obj = self._memobj
2383
                        for bit in bits[:-1]:
2384
                            obj = getattr(obj, bit)
2385
                        setting = bits[-1]
2386
                    else:
2387
                        obj = self._memobj.settings
2388
                        setting = element.get_name()
2389

    
2390
                    if element.has_apply_callback():
2391
                        LOG.debug("Using apply callback")
2392
                        element.run_apply_callback()
2393
                    else:
2394
                        LOG.debug("Setting %s = %s" % (setting, element.value))
2395
                        if self._is_freq(element):
2396
                            # setattr(obj, setting, int(element.value / 10))
2397
                            # MRT rescale freq values to match radio
2398
                            # expected values
2399
                            value = _freq_encode(element[0].get_value()*1000000.0)
2400
                            setattr(obj, setting, value)
2401

    
2402
                        elif self._is_fmradio_or_voltage(element):
2403
                            # MRT rescale FM Radio values to match radio
2404
                            # expected values
2405
                            setattr(obj, setting,
2406
                                    int(element.values()[0]._current * 100.0))
2407

    
2408
                        elif self._is_limit(element):
2409
                            setattr(obj, setting,
2410
                                    int(str(element.values()[0]._current * 10), 16))
2411
                # Special VFO A Settings
2412
                #
2413
                        elif self._is_chan(element):
2414
                            value = _chnum_encode(element[0].get_value())
2415
                            setattr(obj, setting, value)
2416
                            continue
2417
                #
2418
                        elif self._is_display_name(element):
2419
                            string=element[0].get_value()
2420
                            nameenc = _oem_str_encode(string)
2421
                            for i in range(0,8):
2422
                                LOG.debug("nameenc %s" % (nameenc[i]))
2423
                                self._memobj.oem.display_name[i] = ord(nameenc[i])
2424
                                # setattr(obj, setting, int(ord(nameenc[i])))
2425

    
2426
                        elif self._is_scan_name(element):
2427
                            string=element[0].get_value()
2428
                            LOG.debug("string %s" % (string))
2429
                            # scaname=element[0].get_name()
2430
                            # LOG.debug("scanname %s" % (scaname))
2431
                            value = _str_encode(string)
2432
                            LOG.debug("scaname %s" % (value))
2433
                            setattr(obj, setting, value)
2434
                            # self._memobj.eval(scaname)[i] = ord(nameenc[i])
2435
                            # setattr(obj, setting, int(ord(nameenc[i])))
2436
                        else:
2437
                            setattr(obj, setting, element.value)
2438
                except Exception, e:
2439
                    LOG.debug(element.get_name())
2440
                    raise
2441

    
2442
    def _is_freq(self, element):
2443
        return "rxfreq" in element.get_name() or \
2444
               "txoffset" in element.get_name() or \
2445
               "vfofreq" in element.get_name() or\
2446
               "vfoofst" in element.get_name() 
2447
        #  "rx_start" in element.get_name() or \
2448
        #  "rx_stop" in element.get_name() or \
2449
        #  "tx_start" in element.get_name() or \
2450
        #  "tx_stop" in element.get_name()
2451

    
2452
    def _is_limit(self, element):
2453
        return "limit" in element.get_name()
2454

    
2455
    def _is_fmradio_or_voltage(self, element):
2456
        return "FM_radio" in element.get_name() or\
2457
                "thr_vol_lvl" in element.get_name()
2458

    
2459
    
2460
    def _is_chan(self, element):
2461
        return "vfochan" in element.get_name() or\
2462
               "pri_ch" in element.get_name()
2463

    
2464
    def _is_display_name(self, element):
2465
        return "display_name" in element.get_name() 
2466
    
2467
    def _is_scan_name(self, element):
2468
        return "scanname" in element.get_name() 
2469
  
2470
    # def _is_vfofreq(self, element):
2471
    #     return "vfofreq" in element.get_name() or\
2472
    #            "vfoofst" in element.get_name()
(6-6/8)