Project

General

Profile

New Model #7223 » kguv980p b2.2.py

KG-UV980P Beta 2.2 Driver - Mel Terechenok, 10/21/2022 12:26 PM

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

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

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

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

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

    
36

    
37
LOG = logging.getLogger(__name__)
38

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

    
44
MEM_VALID = 0x00
45

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

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

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

    
142

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

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

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

    
180

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

    
473

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

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

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

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

    
516

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

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

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

    
548

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

    
561

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

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

    
578

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

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

    
601

    
602

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

    
607

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1002

    
1003
        self._get_tone(_mem, mem)
1004

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

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

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

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

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

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

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

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

    
1048
        return mem
1049

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

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

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

    
1086
        _mem.rxtone = rxtone
1087
        _mem.txtone = txtone
1088

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

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

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

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

    
1117
        if mem.empty:
1118
            self._memobj.valid[number] = 0xff
1119
            _mem.rxfreq = 0xFFFFFFFF
1120
            _mem.txfreq = 0xFFFFFFFF
1121
        if mem.rxfreq == 0x00 & mem.txfreq == 0x00:
1122
            _mem.rxfreq = 0xFFFFFFFF
1123
            _mem.txfreq = 0xFFFFFFFF
1124
            _mem.valid = 0xFF
1125

    
1126
        _mem.rxfreq = _freq_encode(mem.freq)
1127
        if mem.duplex == "off":
1128
            _mem.txfreq = 0xFFFFFFFF
1129
        elif mem.duplex == "split":
1130
            _mem.txfreq = _freq_encode(mem.offset)
1131
        elif mem.duplex == "+":
1132
            _mem.txfreq = _freq_encode(mem.freq + mem.offset)
1133
        elif mem.duplex == "-":
1134
            _mem.txfreq = _freq_encode(mem.freq - mem.offset)
1135
        else:
1136
            _mem.txfreq = _freq_encode(mem.freq)
1137

    
1138
        _mem.scan_add = int(mem.skip != "S")
1139

    
1140
        if mem.mode == "AM":
1141
            _mem.am_mode = True
1142
            _mem.isnarrow = False
1143
        elif mem.mode == "NAM":
1144
            _mem.am_mode = True
1145
            _mem.isnarrow = True
1146
        else:
1147
            _mem.am_mode = False
1148
            if mem.mode =="NFM":
1149
                _mem.isnarrow = True
1150
            else:
1151
                _mem.isnarrow = False
1152

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

    
1190
        # MRT set to mute mode to QT (not QT+DTMF or QT*DTMF) by default
1191
        # MRT This changes them in the channel memory
1192
        _mem.mute_mode = 1
1193

    
1194
    def _get_settings(self):
1195
        _settings = self._memobj.settings
1196
        _limits = self._memobj.bandlimits
1197
        _oem = self._memobj.oem
1198
#        _vfoa = self._memobj.vfoa
1199
#        _vfob = self._memobj.vfob
1200
#        _scan = self._memobj.scan_groups
1201
#        _call = self._memobj.call_groups
1202
#        _callname = self._memobj.call_names
1203
#        _fmpreset = self._memobj.fm_preset
1204

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

    
1256
# Memory extras
1257
        # rs = RadioSetting("_mem.mute_mode", "Mute Mode"+str(number),
1258
        #                   RadioSettingValueBoolean(_mem.mute_mode))
1259
        # memxtras_grp.append(rs)
1260

    
1261
# Configuration Settings
1262

    
1263
        rs = RadioSetting("roger", "Roger Beep",
1264
                          RadioSettingValueList(ROGER_LIST,
1265
                                                ROGER_LIST[_settings.
1266
                                                           roger]))
1267
        cfg1_grp.append(rs)
1268

    
1269
        rs = RadioSetting("beep", "Keypad Beep",
1270
                          RadioSettingValueBoolean(_settings.beep))
1271
        cfg1_grp.append(rs)
1272

    
1273
        rs = RadioSetting("voice", "Voice Guide",
1274
                          RadioSettingValueBoolean(_settings.voice))
1275
        cfg1_grp.append(rs)
1276

    
1277
        rs = RadioSetting("bcl_a", "Busy Channel Lock-out A",
1278
                          RadioSettingValueBoolean(_settings.bcl_a))
1279
        cfg1_grp.append(rs)
1280

    
1281
        rs = RadioSetting("bcl_b", "Busy Channel Lock-out B",
1282
                          RadioSettingValueBoolean(_settings.bcl_b))
1283
        cfg1_grp.append(rs)
1284

    
1285
        rs = RadioSetting("sc_rev", "Scan Mode",
1286
                          RadioSettingValueMap(SC_REV_MAP, _settings.sc_rev))
1287
        cfg1_grp.append(rs)
1288
        rs = RadioSetting("tot", "Timeout Timer (TOT)",
1289
                          RadioSettingValueMap(
1290
                              TOT_MAP, _settings.tot))
1291
        cfg1_grp.append(rs)
1292

    
1293
        rs = RadioSetting("toa", "Timeout Alarm (TOA)",
1294
                          RadioSettingValueMap(
1295
                              TOA_MAP, _settings.toa))
1296
        cfg1_grp.append(rs)
1297

    
1298
        rs = RadioSetting("ani_sw", "Caller ID Tx - ANI-SW",
1299
                          RadioSettingValueBoolean(_settings.ani_sw))
1300
        cfg1_grp.append(rs)
1301

    
1302
        rs = RadioSetting("ring", "Ring Time (Sec)",
1303
                          RadioSettingValueMap(RING_MAP, _settings.ring))
1304
        cfg1_grp.append(rs)
1305

    
1306

    
1307
        rs = RadioSetting("dtmfsf", "DTMF Sidetone",
1308
                          RadioSettingValueList(
1309
                              DTMF_ST_LIST,
1310
                              DTMF_ST_LIST[_settings.dtmfsf]))
1311
        cfg1_grp.append(rs)
1312

    
1313

    
1314
        rs = RadioSetting("ptt_id", "Caller ID Tx Mode (PTT_ID)",
1315
                          RadioSettingValueMap(PTT_ID_MAP, _settings.ptt_id))
1316
        cfg1_grp.append(rs)
1317

    
1318

    
1319
        rs = RadioSetting("wt_led", "Standby / WT LED",
1320
                          RadioSettingValueList(
1321
                              BACKLIGHT_LIST,
1322
                              BACKLIGHT_LIST[_settings.wt_led]))
1323
        cfg1_grp.append(rs)
1324

    
1325
        rs = RadioSetting("tx_led", "TX LED",
1326
                          RadioSettingValueList(
1327
                              BACKLIGHT_LIST,
1328
                              BACKLIGHT_LIST[_settings.tx_led]))
1329
        cfg1_grp.append(rs)
1330

    
1331
        rs = RadioSetting("rx_led", "Rx LED",
1332
                          RadioSettingValueList(
1333
                              BACKLIGHT_LIST,
1334
                              BACKLIGHT_LIST[_settings.rx_led]))
1335
        cfg1_grp.append(rs)
1336

    
1337
        rs = RadioSetting("prich_sw", "Priority Channel Scan",
1338
                          RadioSettingValueBoolean(_settings.prich_sw))
1339
        cfg1_grp.append(rs)
1340

    
1341
        rs = RadioSetting("spk_cont", "Speaker Control",
1342
                          RadioSettingValueMap(
1343
                              SPEAKER_MAP,
1344
                              _settings.spk_cont))
1345
        cfg1_grp.append(rs)
1346

    
1347
        rs = RadioSetting("autolock", "Autolock",
1348
                          RadioSettingValueBoolean(_settings.autolock))
1349
        cfg1_grp.append(rs)
1350

    
1351
        rs = RadioSetting("low_v", "Low Voltage Shutoff",
1352
                          RadioSettingValueBoolean(_settings.low_v))
1353
        cfg1_grp.append(rs)
1354

    
1355
        rs = RadioSetting("fan", "Fan Mode",
1356
                          RadioSettingValueList(
1357
                              FAN_MODE_LIST,
1358
                              FAN_MODE_LIST[_settings.fan]))
1359
        cfg1_grp.append(rs)
1360

    
1361
        rs = RadioSetting("apo_time", "Auto Power-Off (Min)",
1362
                          RadioSettingValueList(
1363
                              APO_TIME_LIST,
1364
                              APO_TIME_LIST[_settings.apo_time]))
1365
        cfg1_grp.append(rs)
1366

    
1367
        rs = RadioSetting("alert", "Alert Pulse (Hz)",
1368
                          RadioSettingValueMap(ALERT_MAP, _settings.alert))
1369
        cfg1_grp.append(rs)
1370
        rs = RadioSetting("m_pwr", "Medium Power Level (W)",
1371
                          RadioSettingValueMap(M_POWER_MAP,
1372
                                               _settings.m_pwr))
1373
        cfg1_grp.append(rs)
1374

    
1375
        rs = RadioSetting("rpt_set_model", "Model (RPT-SET)",
1376
                          RadioSettingValueList(
1377
                              RPT_MODE_LIST,
1378
                              RPT_MODE_LIST[_settings.rpt_set_model]))
1379
        cfg2_grp.append(rs)
1380

    
1381
        rs = RadioSetting("rpt_spk", "Repeater Speaker Switch (RPT-SPK)",
1382
                          RadioSettingValueBoolean(_settings.rpt_spk))
1383
        cfg2_grp.append(rs)
1384

    
1385
        rs = RadioSetting("rpt_ptt", "Repeater PTT (RPT-PTT)",
1386
                          RadioSettingValueBoolean(_settings.rpt_ptt))
1387
        cfg2_grp.append(rs)
1388

    
1389
        rs = RadioSetting("dtmf_time", "DTMF Tx Duration (ms)",
1390
                          RadioSettingValueList(
1391
                              DTMF_TIMES,
1392
                              DTMF_TIMES[_settings.dtmf_time]))
1393
        cfg2_grp.append(rs)
1394
        rs = RadioSetting("dtmf_int", "DTMF Interval (ms)",
1395
                          RadioSettingValueList(
1396
                              DTMF_INTERVALS,
1397
                              DTMF_INTERVALS[_settings.dtmf_int]))
1398
        cfg2_grp.append(rs)
1399

    
1400
        rs = RadioSetting("sc_qt", "CTCSS/DCS Scan",
1401
                          RadioSettingValueMap(
1402
                              SC_QT_MAP,_settings.sc_qt))
1403
        cfg2_grp.append(rs)
1404

    
1405
        rs = RadioSetting("pri_ch", "Priority Channel",
1406
                          RadioSettingValueInteger(
1407
                              1, 999, _chnum_decode(_settings.pri_ch)))
1408
        cfg2_grp.append(rs)
1409

    
1410
        rs = RadioSetting("ptt_id_dly", "Caller ID Tx Delay PTT-ID-DLY (ms)",
1411
                          RadioSettingValueMap(PTT_ID_DELAY_MAP,
1412
                                               _settings.ptt_id_dly))
1413
        cfg2_grp.append(rs)
1414

    
1415
        rs = RadioSetting("rc_sw", "Remote Control RC-SW",
1416
                          RadioSettingValueBoolean(_settings.rc_sw))
1417
        cfg2_grp.append(rs)
1418

    
1419
        rs = RadioSetting("scan_det", "Scan DET",
1420
                          RadioSettingValueBoolean(_settings.scan_det))
1421
        cfg2_grp.append(rs)
1422

    
1423
        rs = RadioSetting("menu", "Menu Available",
1424
                          RadioSettingValueBoolean(_settings.menu))
1425
        cfg2_grp.append(rs)
1426

    
1427
        rs = RadioSetting("thr_vol_tx", "Threshold Voltage Tx",
1428
                          RadioSettingValueBoolean(_settings.thr_vol_tx))
1429
        cfg2_grp.append(rs)
1430

    
1431
        rs = RadioSetting("hold_time_rpt", "Hold Time of Repeat (ms)",
1432
                          RadioSettingValueList(
1433
                              HOLD_TIMES,
1434
                              HOLD_TIMES[_settings.hold_time_rpt]))
1435
        cfg2_grp.append(rs)
1436

    
1437
        rs = RadioSetting("auto_am", "Auto AM",
1438
                          RadioSettingValueBoolean(_settings.auto_am))
1439
        cfg2_grp.append(rs)
1440

    
1441
        rs = RadioSetting("rpt_tone", "Repeat Tone",
1442
                          RadioSettingValueBoolean(_settings.rpt_tone))
1443
        cfg2_grp.append(rs)
1444

    
1445
        rs = RadioSetting("pf1_set", "PF1 setting",
1446
                          RadioSettingValueList(
1447
                              PF1_SETTINGS,
1448
                              PF1_SETTINGS[_settings.pf1_set]))
1449
        cfg2_grp.append(rs)
1450

    
1451
        rs = RadioSetting("settings.thr_vol_lvl", "Threshold Voltage Level",
1452
                          RadioSettingValueFloat(
1453
                              9.5, 10.5, _settings.thr_vol_lvl / 100.0 , 0.1, 1))
1454
        cfg2_grp.append(rs)
1455

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

    
1484
        rs = RadioSetting("ABR", "ABR (Backlight On Time)",
1485
                          RadioSettingValueList(
1486
                              ABR_LIST,
1487
                              ABR_LIST[_settings.ABR]))
1488
        cfg2_grp.append(rs)
1489

    
1490
        rs = RadioSetting("KeyA", "Key A",
1491
                          RadioSettingValueList(
1492
                              KEY_LIST,
1493
                              KEY_LIST[_settings.KeyA]))
1494
        cfg2_grp.append(rs)
1495
        rs = RadioSetting("KeyB", "Key B",
1496
                          RadioSettingValueList(
1497
                              KEY_LIST,
1498
                              KEY_LIST[_settings.KeyB]))
1499
        cfg2_grp.append(rs)
1500
        rs = RadioSetting("KeyC", "Key C",
1501
                          RadioSettingValueList(
1502
                              KEY_LIST,
1503
                              KEY_LIST[_settings.KeyC]))
1504
        cfg2_grp.append(rs)
1505

    
1506
        rs = RadioSetting("act_area", "Active Area (BAND)",
1507
                          RadioSettingValueList(
1508
                              ACTIVE_AREA_LIST,
1509
                              ACTIVE_AREA_LIST[_settings.act_area]))
1510
        cfg2_grp.append(rs)
1511
        rs = RadioSetting("tdr_off", "TDR",
1512
                          RadioSettingValueList(
1513
                              TDR_LIST,
1514
                              TDR_LIST[_settings.tdr_off]))
1515
        cfg2_grp.append(rs)
1516

    
1517
# Freq Limits settings
1518
        
1519
        # Convert Integer back to correct limit HEX value:  limit = hex(int(str(limit*10),16))        
1520
        # # LOG.debug("limit =" % limit)
1521

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1632

    
1633
        _temp =str(hex(int("%i" % self._memobj.bandlimits.limit_144M_ChA_tx_start, 10)))
1634
        _temp = int(int(_temp[2:])/10.0)
1635
        val= RadioSettingValueInteger(0,999, _temp)
1636
        rs = RadioSetting("bandlimits.limit_144M_ChA_tx_start", "144M ChA Tx Lower Limit (MHz)",
1637
                          RadioSettingValueInteger(0,999,
1638
                              val))
1639
        txlim_grp.append(rs)
1640

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

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

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

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

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

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

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

    
1697
# VFO Settings
1698
        rs = RadioSetting("vfomode_a", "VFO A Working Mode",
1699
                          RadioSettingValueMap(WORKMODE_MAP,
1700
                                               _settings.vfomode_a))
1701
        vfoa_grp.append(rs)
1702

    
1703
        rs = RadioSetting("vfoband_a", "VFO A Current Band",
1704
                          RadioSettingValueMap(VFOBAND_MAP,
1705
                                               _settings.vfoband_a))
1706
        vfoa_grp.append(rs)
1707

    
1708
        rs = RadioSetting("vfochan_a", "VFO A Channel",
1709
                          RadioSettingValueInteger(1, 999,
1710
                              _chnum_decode(_settings.vfochan_a)))
1711
        vfoa_grp.append(rs)
1712

    
1713
        rs = RadioSetting("vfosquelch_a", "VFO A Squelch",
1714
                          RadioSettingValueInteger(0, 9,
1715
                              _settings.vfosquelch_a))
1716
        vfoa_grp.append(rs)
1717
        rs = RadioSetting("vfostep_a", "VFO A Step",
1718
                          RadioSettingValueList(
1719
                            STEP_LIST,
1720
                            STEP_LIST[_settings.vfostep_a]))
1721
        vfoa_grp.append(rs)
1722
######################
1723

    
1724
        rs = RadioSetting("vfofreq1", "VFO 150M Freq",
1725
                          RadioSettingValueFloat(
1726
                             0, 999.999999, (_freq_decode
1727
                             (_settings.vfofreq1)/1000000.0) ,0.000001, 6))
1728
        vfo150_grp.append(rs)
1729

    
1730
        rs = RadioSetting("vfoofst1", "VFO 150M Offset",
1731
                          RadioSettingValueFloat(
1732
                              0, 999.999999, (_freq_decode
1733
                              (_settings.vfoofst1)/1000000.0),0.000001, 6))
1734
        vfo150_grp.append(rs)
1735

    
1736
        rs = RadioSetting("rxtone1", "VFO 150M Rx tone",
1737
                          RadioSettingValueMap(
1738
                            TONE_MAP, _settings.rxtone1))
1739
        vfo150_grp.append(rs)
1740

    
1741
        rs = RadioSetting("txtone1", "VFO 150M Tx tone",
1742
                          RadioSettingValueMap(
1743
                            TONE_MAP, _settings.txtone1))
1744
        vfo150_grp.append(rs)
1745

    
1746
        rs = RadioSetting("power1", "VFO 150M Power",
1747
                          RadioSettingValueMap(
1748
                            POWER_MAP, _settings.power1))
1749
        vfo150_grp.append(rs)
1750

    
1751
        rs = RadioSetting("narrow1", "VFO 150M Bandwidth",
1752
                          RadioSettingValueMap(
1753
                            BANDWIDTH_MAP, _settings.narrow1))
1754
        vfo150_grp.append(rs)
1755

    
1756
        rs = RadioSetting("mute1", "VFO 150M Mute Mode",
1757
                          RadioSettingValueMap(
1758
                            MUTE_MODE_MAP, _settings.mute1))
1759
        vfo150_grp.append(rs)
1760

    
1761
        rs = RadioSetting("shft_dir1", "VFO 150M Shift Direction",
1762
                          RadioSettingValueList(
1763
                            DUPLEX_LIST,
1764
                            DUPLEX_LIST[_settings.shft_dir1]))
1765
        vfo150_grp.append(rs)
1766

    
1767
        rs = RadioSetting("compander1", "VFO 150M Compander",
1768
                          RadioSettingValueBoolean(
1769
                            _settings.compander1))
1770
        vfo150_grp.append(rs)
1771

    
1772
        rs = RadioSetting("scrambler1", "VFO 150M Scrambler",
1773
                          RadioSettingValueList(
1774
                            SCRAMBLER_LIST,
1775
                            SCRAMBLER_LIST[_settings.scrambler1]))
1776
        vfo150_grp.append(rs)
1777
        rs = RadioSetting("am_mode1", "VFO 150M AM Mode",
1778
                          RadioSettingValueBoolean(
1779
                            _settings.am_mode1))
1780
        vfo150_grp.append(rs)
1781
############################
1782

    
1783
        rs = RadioSetting("vfofreq2", "VFO 450M Freq",
1784
                          RadioSettingValueFloat(
1785
                             0, 999.999999, (_freq_decode
1786
                             (_settings.vfofreq2)/1000000.0) ,0.000001, 6))
1787
        vfo450_grp.append(rs)
1788

    
1789
        rs = RadioSetting("vfoofst2", "VFO 450M Offset",
1790
                          RadioSettingValueFloat(
1791
                              0, 999.999999, (_freq_decode
1792
                              (_settings.vfoofst2)/1000000.0),0.000001, 6))
1793
        vfo450_grp.append(rs)
1794

    
1795
        rs = RadioSetting("rxtone2", "VFO 450M Rx tone",
1796
                          RadioSettingValueMap(
1797
                            TONE_MAP, _settings.rxtone2))
1798
        vfo450_grp.append(rs)
1799

    
1800
        rs = RadioSetting("txtone2", "VFO 450M Tx tone",
1801
                          RadioSettingValueMap(
1802
                            TONE_MAP, _settings.txtone2))
1803
        vfo450_grp.append(rs)
1804
        
1805
        rs = RadioSetting("power2", "VFO 450M Power",
1806
                          RadioSettingValueMap(
1807
                            POWER_MAP, _settings.power2))
1808
        vfo450_grp.append(rs)
1809

    
1810
        rs = RadioSetting("narrow2", "VFO 450M Bandwidth",
1811
                          RadioSettingValueMap(
1812
                            BANDWIDTH_MAP, _settings.narrow2))
1813
        vfo450_grp.append(rs)
1814

    
1815
        rs = RadioSetting("mute2", "VFO 450M Mute Mode",
1816
                          RadioSettingValueMap(
1817
                            MUTE_MODE_MAP, _settings.mute2))
1818
        vfo450_grp.append(rs)
1819

    
1820
        rs = RadioSetting("shft_dir2", "VFO 450M Shift Direction",
1821
                          RadioSettingValueList(
1822
                            DUPLEX_LIST,
1823
                            DUPLEX_LIST[_settings.shft_dir2]))
1824
        vfo450_grp.append(rs)
1825

    
1826
        rs = RadioSetting("compander2", "VFO 450M Compander",
1827
                          RadioSettingValueBoolean(
1828
                            _settings.compander2))
1829
        vfo450_grp.append(rs)
1830

    
1831
        rs = RadioSetting("scrambler2", "VFO 450M Scrambler",
1832
                          RadioSettingValueList(
1833
                            SCRAMBLER_LIST,
1834
                            SCRAMBLER_LIST[_settings.scrambler2]))
1835
        vfo450_grp.append(rs)
1836

    
1837
        rs = RadioSetting("am_mode2", "VFO 450M AM Mode",
1838
                          RadioSettingValueBoolean(
1839
                            _settings.am_mode2))
1840
        vfo450_grp.append(rs)
1841
############################
1842
        rs = RadioSetting("vfofreq3", "VFO 20M Freq",
1843
                          RadioSettingValueFloat(
1844
                             0, 999.999999, (_freq_decode
1845
                             (_settings.vfofreq3)/1000000.0) ,0.000001, 6))
1846
        vfo20_grp.append(rs)
1847

    
1848
        rs = RadioSetting("vfoofst3", "VFO 20M Offset",
1849
                          RadioSettingValueFloat(
1850
                              0, 999.999999, (_freq_decode
1851
                              (_settings.vfoofst3)/1000000.0),0.000001, 6))
1852
        vfo20_grp.append(rs)
1853

    
1854
        rs = RadioSetting("rxtone3", "VFO 20M Rx tone",
1855
                          RadioSettingValueMap(
1856
                            TONE_MAP, _settings.rxtone3))
1857
        vfo20_grp.append(rs)
1858

    
1859
        rs = RadioSetting("txtone3", "VFO 20M Tx tone",
1860
                          RadioSettingValueMap(
1861
                            TONE_MAP, _settings.txtone3))
1862
        vfo20_grp.append(rs)
1863
        
1864
        rs = RadioSetting("power3", "VFO 20M Power",
1865
                          RadioSettingValueMap(
1866
                            POWER_MAP, _settings.power3))
1867
        vfo20_grp.append(rs)
1868

    
1869
        rs = RadioSetting("narrow3", "VFO 20M Bandwidth",
1870
                          RadioSettingValueMap(
1871
                            BANDWIDTH_MAP, _settings.narrow3))
1872
        vfo20_grp.append(rs)
1873

    
1874
        rs = RadioSetting("mute3", "VFO 20M Mute Mode",
1875
                          RadioSettingValueMap(
1876
                            MUTE_MODE_MAP, _settings.mute3))
1877
        vfo20_grp.append(rs)
1878

    
1879
        rs = RadioSetting("shft_dir3", "VFO 20M Shift Direction",
1880
                          RadioSettingValueList(
1881
                            DUPLEX_LIST,
1882
                            DUPLEX_LIST[_settings.shft_dir3]))
1883
        vfo20_grp.append(rs)
1884

    
1885
        rs = RadioSetting("compander3", "VFO 20M Compander",
1886
                          RadioSettingValueBoolean(
1887
                            _settings.compander3))
1888
        vfo20_grp.append(rs)
1889

    
1890
        rs = RadioSetting("scrambler3", "VFO 20M Scrambler",
1891
                          RadioSettingValueList(
1892
                            SCRAMBLER_LIST,
1893
                            SCRAMBLER_LIST[_settings.scrambler3]))
1894
        vfo20_grp.append(rs)
1895

    
1896
        rs = RadioSetting("am_mode3", "VFO 20M AM Mode",
1897
                          RadioSettingValueBoolean(
1898
                            _settings.am_mode3))
1899
        vfo20_grp.append(rs)
1900
############################
1901
        rs = RadioSetting("vfofreq4", "VFO 50M Freq",
1902
                          RadioSettingValueFloat(
1903
                             0, 999.999999, (_freq_decode
1904
                             (_settings.vfofreq4)/1000000.0) ,0.000001, 6))
1905
        vfo50_grp.append(rs)
1906

    
1907
        rs = RadioSetting("vfoofst4", "VFO 50M Offset",
1908
                          RadioSettingValueFloat(
1909
                              0, 999.999999, (_freq_decode
1910
                              (_settings.vfoofst4)/1000000.0),0.000001, 6))
1911
        vfo50_grp.append(rs)
1912

    
1913
        rs = RadioSetting("rxtone4", "VFO 50M Rx tone",
1914
                          RadioSettingValueMap(
1915
                            TONE_MAP, _settings.rxtone4))
1916
        vfo50_grp.append(rs)
1917

    
1918
        rs = RadioSetting("txtone4", "VFO 50M Tx tone",
1919
                          RadioSettingValueMap(
1920
                            TONE_MAP, _settings.txtone4))
1921
        vfo50_grp.append(rs)
1922
        
1923
        rs = RadioSetting("power4", "VFO 50M Power",
1924
                          RadioSettingValueMap(
1925
                            POWER_MAP, _settings.power4))
1926
        vfo50_grp.append(rs)
1927

    
1928
        rs = RadioSetting("narrow4", "VFO 50M Bandwidth",
1929
                          RadioSettingValueMap(
1930
                            BANDWIDTH_MAP, _settings.narrow4))
1931
        vfo50_grp.append(rs)
1932

    
1933
        rs = RadioSetting("mute4", "VFO 50M Mute Mode",
1934
                          RadioSettingValueMap(
1935
                            MUTE_MODE_MAP, _settings.mute4))
1936
        vfo50_grp.append(rs)
1937

    
1938
        rs = RadioSetting("shft_dir4", "VFO 50M Shift Direction",
1939
                          RadioSettingValueList(
1940
                            DUPLEX_LIST,
1941
                            DUPLEX_LIST[_settings.shft_dir4]))
1942
        vfo50_grp.append(rs)
1943

    
1944
        rs = RadioSetting("compander4", "VFO 50M Compander",
1945
                          RadioSettingValueBoolean(
1946
                            _settings.compander4))
1947
        vfo50_grp.append(rs)
1948

    
1949
        rs = RadioSetting("scrambler4", "VFO 50M Scrambler",
1950
                          RadioSettingValueList(
1951
                            SCRAMBLER_LIST,
1952
                            SCRAMBLER_LIST[_settings.scrambler4]))
1953
        vfo50_grp.append(rs)
1954

    
1955
        rs = RadioSetting("am_mode4", "VFO 50M AM Mode",
1956
                          RadioSettingValueBoolean(
1957
                            _settings.am_mode4))
1958
        vfo50_grp.append(rs)
1959
############################
1960
        rs = RadioSetting("vfofreq5", "VFO 350M Freq",
1961
                          RadioSettingValueFloat(
1962
                             0, 999.999999, (_freq_decode
1963
                             (_settings.vfofreq5)/1000000.0) ,0.000001, 6))
1964
        vfo350_grp.append(rs)
1965

    
1966
        rs = RadioSetting("vfoofst5", "VFO 350M Offset",
1967
                          RadioSettingValueFloat(
1968
                              0, 999.999999, (_freq_decode
1969
                              (_settings.vfoofst5)/1000000.0),0.000001, 6))
1970
        vfo350_grp.append(rs)
1971

    
1972
        rs = RadioSetting("rxtone5", "VFO 350M Rx tone",
1973
                          RadioSettingValueMap(
1974
                            TONE_MAP, _settings.rxtone5))
1975
        vfo350_grp.append(rs)
1976

    
1977
        rs = RadioSetting("txtone5", "VFO 350M Tx tone",
1978
                          RadioSettingValueMap(
1979
                            TONE_MAP, _settings.txtone5))
1980
        vfo350_grp.append(rs)
1981
        
1982
        rs = RadioSetting("power5", "VFO 350M Power",
1983
                          RadioSettingValueMap(
1984
                            POWER_MAP, _settings.power5))
1985
        vfo350_grp.append(rs)
1986

    
1987
        rs = RadioSetting("narrow5", "VFO 350M Bandwidth",
1988
                          RadioSettingValueMap(
1989
                            BANDWIDTH_MAP, _settings.narrow5))
1990
        vfo350_grp.append(rs)
1991

    
1992
        rs = RadioSetting("mute5", "VFO 350M Mute Mode",
1993
                          RadioSettingValueMap(
1994
                            MUTE_MODE_MAP, _settings.mute5))
1995
        vfo350_grp.append(rs)
1996

    
1997
        rs = RadioSetting("shft_dir5", "VFO 350M Shift Direction",
1998
                          RadioSettingValueList(
1999
                            DUPLEX_LIST,
2000
                            DUPLEX_LIST[_settings.shft_dir5]))
2001
        vfo350_grp.append(rs)
2002

    
2003
        rs = RadioSetting("compander5", "VFO 350M Compander",
2004
                          RadioSettingValueBoolean(
2005
                            _settings.compander5))
2006
        vfo350_grp.append(rs)
2007

    
2008
        rs = RadioSetting("scrambler5", "VFO 350M Scrambler",
2009
                          RadioSettingValueList(
2010
                            SCRAMBLER_LIST,
2011
                            SCRAMBLER_LIST[_settings.scrambler5]))
2012
        vfo350_grp.append(rs)
2013

    
2014
        rs = RadioSetting("am_mode5", "VFO 350M AM Mode",
2015
                          RadioSettingValueBoolean(
2016
                            _settings.am_mode5))
2017
        vfo350_grp.append(rs)
2018

    
2019
# ############################
2020
        rs = RadioSetting("vfofreq6", "VFO 850M Freq",
2021
                          RadioSettingValueFloat(
2022
                             0, 999.999999, (_freq_decode
2023
                             (_settings.vfofreq6)/1000000.0) ,0.000001, 6))
2024
        vfo850_grp.append(rs)
2025

    
2026
        rs = RadioSetting("vfoofst6", "VFO 850M Offset",
2027
                          RadioSettingValueFloat(
2028
                              0, 999.999999, (_freq_decode
2029
                              (_settings.vfoofst6)/1000000.0),0.000001, 6))
2030
        vfo850_grp.append(rs)
2031

    
2032
        rs = RadioSetting("rxtone6", "VFO 850M Rx tone",
2033
                          RadioSettingValueMap(
2034
                            TONE_MAP, _settings.rxtone6))
2035
        vfo850_grp.append(rs)
2036

    
2037
        rs = RadioSetting("txtone6", "VFO 850M Tx tone",
2038
                          RadioSettingValueMap(
2039
                            TONE_MAP, _settings.txtone6))
2040
        vfo850_grp.append(rs)
2041
        
2042
        rs = RadioSetting("power6", "VFO 850M Power",
2043
                          RadioSettingValueMap(
2044
                            POWER_MAP, _settings.power6))
2045
        vfo850_grp.append(rs)
2046

    
2047
        rs = RadioSetting("narrow6", "VFO 850M Bandwidth",
2048
                          RadioSettingValueMap(
2049
                            BANDWIDTH_MAP, _settings.narrow6))
2050
        vfo850_grp.append(rs)
2051

    
2052
        rs = RadioSetting("mute6", "VFO 850M Mute Mode",
2053
                          RadioSettingValueMap(
2054
                            MUTE_MODE_MAP, _settings.mute6))
2055
        vfo850_grp.append(rs)
2056

    
2057
        rs = RadioSetting("shft_dir6", "VFO 850M Shift Direction",
2058
                          RadioSettingValueList(
2059
                            DUPLEX_LIST,
2060
                            DUPLEX_LIST[_settings.shft_dir6]))
2061
        vfo850_grp.append(rs)
2062

    
2063
        rs = RadioSetting("compander6", "VFO 850M Compander",
2064
                          RadioSettingValueBoolean(
2065
                            _settings.compander6))
2066
        vfo850_grp.append(rs)
2067

    
2068
        rs = RadioSetting("scrambler6", "VFO 850M Scrambler",
2069
                          RadioSettingValueList(
2070
                            SCRAMBLER_LIST,
2071
                            SCRAMBLER_LIST[_settings.scrambler6]))
2072
        vfo850_grp.append(rs)
2073

    
2074
        rs = RadioSetting("am_mode6", "VFO 850M AM Mode",
2075
                          RadioSettingValueBoolean(
2076
                            _settings.am_mode6))
2077
        vfo850_grp.append(rs)
2078

    
2079
############################
2080

    
2081
        rs = RadioSetting("vfomode_b", "VFO B Working Mode",
2082
                          RadioSettingValueMap(WORKMODE_MAP,
2083
                                               _settings.vfomode_b))
2084
        vfob_grp.append(rs)
2085

    
2086
        rs = RadioSetting("vfochan_b", "VFO B Work Channel",
2087
                          RadioSettingValueInteger(1, 999,
2088
                              _chnum_decode(_settings.vfochan_b)))
2089
        vfob_grp.append(rs)
2090

    
2091
        rs = RadioSetting("vfofreq7", "VFO B Freq",
2092
                          RadioSettingValueFloat(
2093
                             0, 999.999999, (_freq_decode
2094
                             (_settings.vfofreq7)/1000000.0) ,0.000001, 6))
2095
        vfob_grp.append(rs)
2096

    
2097
        rs = RadioSetting("vfoofst7", "VFO B Offset",
2098
                          RadioSettingValueFloat(
2099
                              0, 999.999999, (_freq_decode
2100
                              (_settings.vfoofst7)/1000000.0),0.000001, 6))
2101
        vfob_grp.append(rs)
2102

    
2103
        rs = RadioSetting("rxtone7", "VFOB Rx tone",
2104
                          RadioSettingValueMap(
2105
                            TONE_MAP, _settings.rxtone7))
2106
        vfob_grp.append(rs)
2107

    
2108
        rs = RadioSetting("txtone7", "VFOB Tx tone",
2109
                          RadioSettingValueMap(
2110
                            TONE_MAP, _settings.txtone7))
2111
        vfob_grp.append(rs)
2112
        rs = RadioSetting("power7", "VFOB Power",
2113
                          RadioSettingValueMap(
2114
                            POWER_MAP, _settings.power7))
2115
        vfob_grp.append(rs)
2116
        rs = RadioSetting("narrow7", "VFOB Bandwidth",
2117
                          RadioSettingValueMap(
2118
                            BANDWIDTH_MAP, _settings.narrow7))
2119
        vfob_grp.append(rs)
2120
        rs = RadioSetting("mute7", "VFOB Mute Mode",
2121
                          RadioSettingValueMap(
2122
                            MUTE_MODE_MAP, _settings.mute7))
2123
        vfob_grp.append(rs)
2124
        rs = RadioSetting("shft_dir7", "VFOB Shift Direction",
2125
                          RadioSettingValueList(
2126
                            DUPLEX_LIST,
2127
                            DUPLEX_LIST[_settings.shft_dir7]))
2128
        vfob_grp.append(rs)
2129
        rs = RadioSetting("compander7", "VFOB Compander",
2130
                          RadioSettingValueBoolean(
2131
                            _settings.compander7))
2132
        vfob_grp.append(rs)
2133

    
2134
        rs = RadioSetting("scrambler7", "VFOB Scrambler",
2135
                          RadioSettingValueList(
2136
                            SCRAMBLER_LIST,
2137
                            SCRAMBLER_LIST[_settings.scrambler7]))
2138
        vfob_grp.append(rs)
2139

    
2140
        rs = RadioSetting("vfosquelch_b", "VFO B Squelch",
2141
                          RadioSettingValueInteger(0, 9,
2142
                              _settings.vfosquelch_b))
2143
        vfob_grp.append(rs)
2144
        rs = RadioSetting("vfostep_b", "VFO B Step",
2145
                          RadioSettingValueList(
2146
                            STEP_LIST,
2147
                            STEP_LIST[_settings.vfostep_b]))
2148
        vfob_grp.append(rs)
2149
        # rs = RadioSetting("am_mode7", "VFOB AM Mode",
2150
        #                   RadioSettingValueBoolean(
2151
        #                     _settings.am_mode7))
2152
        # vfob_grp.append(rs)
2153

    
2154
# Scan Group Settings
2155
        def _decode(lst):
2156
            _str = ''.join([chr(c) for c in lst
2157
                            if chr(c) in SCANNAME_CHARSET])
2158
            return _str
2159

    
2160
        rs = RadioSetting("scan_a_act", "Scan A Active Group",
2161
                        RadioSettingValueList(
2162
                            SCAN_GROUP_LIST,
2163
                            SCAN_GROUP_LIST[_settings.scan_a_act]))
2164
        scan_grp.append(rs)
2165
        rs = RadioSetting("scan_b_act", "Scan B Active Group",
2166
                        RadioSettingValueList(
2167
                             SCAN_GROUP_LIST,
2168
                             SCAN_GROUP_LIST[_settings.scan_b_act]))
2169
        scan_grp.append(rs)
2170
       
2171

    
2172
        for i in range(1,11):
2173
            x=str(i)
2174
            _str = _decode(eval("_settings.scanname"+x))
2175
            # CPS treats PPPPPP as a blank name as it is the factor reset value"
2176
            # The Radio treats PPPPPPP as a blank name and can display 8 chars"
2177
            # Force Chirp to blank out the scan name if value is PPPPPPP to match the radio"
2178
            # Blank out the name if first 6 are spaces or null and the 7th is a P to handle
2179
            # firmware peculiarities in handling all 8 characters.
2180
            if _str[0:7] == "PPPPPPP":_str=""
2181
            if _str[0:7] =="\x00\x00\x00\x00\x00\x00P":_str=""
2182
            if _str[0:7] =="\x20\x20\x20\x20\x20\x20P":_str=""
2183
            if _str[0]== "\x00":_str=""
2184
            rs=RadioSetting("scanname"+x, "Scan Name "+x,
2185
                        RadioSettingValueString(0,8, _str))
2186
            # rs = RadioSetting("scanname"+x, "Scan Name "+x, val)
2187
            scanname_grp.append(rs)
2188

    
2189
            scngrp = str(i)
2190
            rs = RadioSetting("scanlower"+scngrp, "Scan Lower "+scngrp,
2191
                            RadioSettingValueInteger(1, 999,  
2192
                            eval("_settings.scanlower"+scngrp)))
2193
            scan_grp.append(rs)
2194
            rs = RadioSetting("scanupper"+scngrp, "Scan Upper "+scngrp,
2195
                            RadioSettingValueInteger(1, 999,  
2196
                            eval("_settings.scanupper"+scngrp)))
2197
            scan_grp.append(rs)
2198
# remote settings
2199
        rs = RadioSetting("rc_power", "RC Power",
2200
                           RadioSettingValueList(
2201
                                    RC_POWER_LIST,
2202
                                    RC_POWER_LIST[_settings.rc_power]))
2203
        remote_grp.append(rs)
2204

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

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

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

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

    
2325

    
2326

    
2327

    
2328

    
2329
# OEM Settings
2330

    
2331
        _oem_name = _oem_str_decode(self._memobj.oem.display_name)
2332
        rs=RadioSetting("oem.display_name", "Display Banner Text",
2333
                        RadioSettingValueString(1,8, _oem_name))
2334
        oem_grp.append(rs)
2335

    
2336
# FM RADIO PRESETS
2337

    
2338
# memory stores raw integer value like 7600
2339
# radio will divide 7600 by 100 and interpret correctly at 76.0Mhz
2340
        #
2341
        # FM Radio Presets Settings
2342
        #
2343
        for i in range(1, 21):
2344
            chan = str(i)
2345
            rs = RadioSetting("FM_radio" + chan, "FM Preset " + chan,
2346
                              RadioSettingValueFloat(76.0, 108.0,
2347
                                                     eval("_settings.FM_radio" +
2348
                                                          chan)/100.0,
2349
                                                     0.1, 1))
2350
            fmradio_grp.append(rs)
2351
        
2352
        return group
2353

    
2354
    def get_settings(self):
2355
        try:
2356
            return self._get_settings()
2357
        except:
2358
            import traceback
2359
            LOG.error("Failed to parse settings: %s", traceback.format_exc())
2360
            return None
2361

    
2362
    def set_settings(self, settings):
2363
        for element in settings:
2364
            if not isinstance(element, RadioSetting):
2365
                self.set_settings(element)
2366
                continue
2367
            else:
2368
                try:
2369
                    if "." in element.get_name():
2370
                        bits = element.get_name().split(".")
2371
                        obj = self._memobj
2372
                        for bit in bits[:-1]:
2373
                            obj = getattr(obj, bit)
2374
                        setting = bits[-1]
2375
                    else:
2376
                        obj = self._memobj.settings
2377
                        setting = element.get_name()
2378

    
2379
                    if element.has_apply_callback():
2380
                        LOG.debug("Using apply callback")
2381
                        element.run_apply_callback()
2382
                    else:
2383
                        LOG.debug("Setting %s = %s" % (setting, element.value))
2384
                        if self._is_freq(element):
2385
                            # setattr(obj, setting, int(element.value / 10))
2386
                            # MRT rescale freq values to match radio
2387
                            # expected values
2388
                            value = _freq_encode(element[0].get_value()*1000000.0)
2389
                            setattr(obj, setting, value)
2390

    
2391
                        elif self._is_fmradio_or_voltage(element):
2392
                            # MRT rescale FM Radio values to match radio
2393
                            # expected values
2394
                            setattr(obj, setting,
2395
                                    int(element.values()[0]._current * 100.0))
2396

    
2397
                        elif self._is_limit(element):
2398
                            setattr(obj, setting,
2399
                                    int(str(element.values()[0]._current * 10), 16))
2400
                # Special VFO A Settings
2401
                #
2402
                        elif self._is_chan(element):
2403
                            value = _chnum_encode(element[0].get_value())
2404
                            setattr(obj, setting, value)
2405
                            continue
2406
                #
2407
                        elif self._is_display_name(element):
2408
                            string=element[0].get_value()
2409
                            nameenc = _oem_str_encode(string)
2410
                            for i in range(0,8):
2411
                                LOG.debug("nameenc %s" % (nameenc[i]))
2412
                                self._memobj.oem.display_name[i] = ord(nameenc[i])
2413
                                # setattr(obj, setting, int(ord(nameenc[i])))
2414

    
2415
                        elif self._is_scan_name(element):
2416
                            string=element[0].get_value()
2417
                            LOG.debug("string %s" % (string))
2418
                            # scaname=element[0].get_name()
2419
                            # LOG.debug("scanname %s" % (scaname))
2420
                            value = _str_encode(string)
2421
                            LOG.debug("scaname %s" % (value))
2422
                            setattr(obj, setting, value)
2423
                            # self._memobj.eval(scaname)[i] = ord(nameenc[i])
2424
                            # setattr(obj, setting, int(ord(nameenc[i])))
2425
                        else:
2426
                            setattr(obj, setting, element.value)
2427
                except Exception, e:
2428
                    LOG.debug(element.get_name())
2429
                    raise
2430

    
2431
    def _is_freq(self, element):
2432
        return "rxfreq" in element.get_name() or \
2433
               "txoffset" in element.get_name() or \
2434
               "vfofreq" in element.get_name() or\
2435
               "vfoofst" in element.get_name() 
2436
        #  "rx_start" in element.get_name() or \
2437
        #  "rx_stop" in element.get_name() or \
2438
        #  "tx_start" in element.get_name() or \
2439
        #  "tx_stop" in element.get_name()
2440

    
2441
    def _is_limit(self, element):
2442
        return "limit" in element.get_name()
2443

    
2444
    def _is_fmradio_or_voltage(self, element):
2445
        return "FM_radio" in element.get_name() or\
2446
                "thr_vol_lvl" in element.get_name()
2447

    
2448
    
2449
    def _is_chan(self, element):
2450
        return "vfochan" in element.get_name() or\
2451
               "pri_ch" in element.get_name()
2452

    
2453
    def _is_display_name(self, element):
2454
        return "display_name" in element.get_name() 
2455
    
2456
    def _is_scan_name(self, element):
2457
        return "scanname" in element.get_name() 
2458
  
2459
    # def _is_vfofreq(self, element):
2460
    #     return "vfofreq" in element.get_name() or\
2461
    #            "vfoofst" in element.get_name()
(5-5/8)