Project

General

Profile

New Model #10109 » kg1000gplus b2.0.py

Wouxun KG-1000G Plus Beta 2.0 Driver - Mel Terechenok, 12/01/2022 03:54 AM

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

    
24
"""Wouxun KG-1000G+ radio management module"""
25

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

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

    
37

    
38
LOG = logging.getLogger(__name__)
39

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

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

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

    
65

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

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

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

    
87
MUTE_MODE_MAP = [('QT',      0b01),
88
                 ('QT*DTMF', 0b10),
89
                 ('QT+DTMF', 0b11)]
90
STEPS = [2.5, 5.0, 6.25, 10.0, 12.5, 20.0, 25.0, 30.0, 50.0, 100.0]
91
STEP_LIST = [str(x) for x in STEPS]
92
SQL_LIST = [int(i) for i in range(0, 10)]
93
M_POWER_MAP = [('1 = 20W', 1),
94
               ('2 = 10W', 2)]
95
ROGER_LIST = ["Off", "BOT", "EOT", "Both"]
96
VOICE_MAP = [('Off', 0),
97
             ('On', 2)]
98
SC_REV_MAP = [('Timeout (TO)',  1),
99
              ('Carrier (CO)',  2),
100
              ('Stop (SE)',     3)]
101
TOT_MAP = [('%d min' % i, int('%02d' % i, 16)) for i in range(1, 61)]
102
TOA_MAP = [('Off', 0)] + \
103
          [('%ds' % i, int('%02d' % i, 16)) for i in range(1, 11)]
104
RING_MAP = [('Off', 0)] + \
105
           [('%ds' % i, int('%02d' % i, 10)) for i in range(1, 11)]
106
DTMF_ST_LIST = ["Off", "DTMF", "ID", "DTMF+ID"]
107
PTT_ID_MAP = [('Off', 0),
108
              ('BOT',  1),
109
              ('EOT',  2),
110
              ('Both', 3)]
111
BACKLIGHT_LIST = ["Off", "Red", "Orange", "Green"]
112
SPEAKER_MAP = [('RADIO',   1),
113
               ('MIC',   2),
114
               ('BOTH', 3)]
115
RPT_MODE_MAP = [("OFF", 0),
116
                ("RPT-RX", 3),
117
                ("RPT-TX", 4)]
118
APO_TIME_LIST = ["Off", "30", "60", "90", "120", "150"]
119
ALERT_MAP = [('1750', 1),
120
             ('2100', 2),
121
             ('1000', 3),
122
             ('1450', 4)]
123
FAN_MODE_LIST = ["TX", "Hi-Temp/TX", "Always"]
124
SCAN_GROUP_LIST = ["All"] + ["%s" % x for x in range(1, 11)]
125
WORKMODE_MAP = [('Freq',      1),
126
                ('Ch-Num',   2),
127
                ('Ch-Freq', 3),
128
                ('Ch-Name',  4)]
129
VFOBAND_MAP = [("150M", 0),
130
               ("450M", 1),
131
               # ("20M",2),
132
               ("50M", 3),
133
               ("350M", 4),
134
               ("850M", 5)]
135
AB_LIST = ["A", "B"]
136
POWER_MAP = [('Low', 0),
137
             ('Med', 1),
138
             ('Med2', 2),
139
             ('High', 3)]
140
BANDWIDTH_MAP = [('Narrow', 1),
141
                 ('Wide',  0)]
142
SCRAMBLER_LIST = ["Off", "1", "2", "3", "4", "5", "6", "7", "8"]
143
ANS_LIST = ["Off", "Normal", "Strong"]
144
DTMF_TIMES = [str(x) for x in range(80, 501, 20)]
145
DTMF_INTERVALS = [str(x) for x in range(60, 501, 20)]
146
ROGER_TIMES = [str(x) for x in range(20, 1001, 20)]
147
PTT_ID_DELAY_MAP = [(str(x), x/100) for x in range(100, 1001, 100)]
148
ROGER_INTERVALS = ROGER_TIMES
149
TONE_MAP = [('Off', 0x0000)] + \
150
           [('%.1f' % tone, int(tone * 10)) for tone in chirp_common.TONES] + \
151
           [('DN%d' % tone, int(0x8000 + tone))
152
               for tone in chirp_common.DTCS_CODES] + \
153
           [('DI%d' % tone, int(0xC000 + tone))
154
               for tone in chirp_common.DTCS_CODES]
155
DUPLEX_LIST = ["Off", "Plus", "Minus"]
156
SC_QT_MAP = [("Rx", 1), ("Tx", 2),
157
             ("Tx/Rx", 3)]
158
HOLD_TIMES = ["Off"] + ["%s" % x for x in range(100, 5001, 100)]
159
PF1_SETTINGS = ["OFF", "Reverse", "Pri-Sel", "Pri-Scan", "Squelch",
160
                "TX PWR", "Scan", "Scan CTCSS",
161
                "Scan DCS", "FM Radio", "Weather", "Ch-Add", "W-N", "TDR",
162
                "WORKMODE",
163
                "Band", "Repeater", "Lock", "Monitor"]
164
ABR_LIST = ["Always", "1", "2", "3", "4", "5", "6", "7", "8",
165
            "9", "10", "11", "12", "13", "14", "15", "16", "17",
166
            "18", "19", "20", "Off"]
167
KEY_LIST = ["OFF", "Reverse", "Pri-Sel", "Pri-Scan", "Squelch", "TX PWR",
168
            "Scan", "Scan CTCSS",
169
            "Scan DCS", "FM Radio", "Weather", "Ch-Add", "W-N", "TDR",
170
            "WORKMODE", "Band", "Repeater", "Lock", "Monitor"]
171
RC_POWER_LIST = ["RC Stop", "RC Open"]
172
ACTIVE_AREA_LIST = ["Area A - Left", "Area B - Right"]
173
TDR_LIST = ["TDR ON", "TDR OFF"]
174
PRI_CH_SCAN_LIST = ["Off", "ON-Stby", "On-Always"]
175

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

    
179
_MEM_FORMAT = """
180
    #seekto 0x004c;
181
    struct {
182
        u24 mode_psw;
183
        u8  xunk04F;
184
        u8  display_name[8];
185
    } oem;
186

    
187
    #seekto 0x0060;
188
    struct {
189
        u16    limit_144M_ChA_rx_start;
190
        u16    limit_144M_ChA_rx_stop;
191
        u16    limit_70cm_rx_start;
192
        u16    limit_70cm_rx_stop;
193
        u16    limit_10m_rx_start;
194
        u16    limit_10m_rx_stop;
195
        u16    limit_6m_rx_start;
196
        u16    limit_6m_rx_stop;
197
        u16    limit_350M_rx_start;
198
        u16    limit_350M_rx_stop;
199
        u16    limit_850M_rx_start;
200
        u16    limit_850M_rx_stop;
201
        u16    limit_144M_ChA_tx_start;
202
        u16    limit_144M_ChA_tx_stop;
203
        u16    limit_70cm_tx_start;
204
        u16    limit_70cm_tx_stop;
205
        u16    limit_10m_tx_start;
206
        u16    limit_10m_tx_stop;
207
        u16    limit_6m_tx_start;
208
        u16    limit_6m_tx_stop;
209
        u16    limit_144M_ChB_rx_start;
210
        u16    limit_144M_ChB_rx_stop;
211
    } bandlimits;
212

    
213

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

    
505

    
506
    #seekto 0x09f0;
507
    struct {
508
        u32     rxfreq;
509
        u32     txfreq;
510
        u16     txtone;
511
        u16     rxtone;
512
        u8      unknown1:3,
513
                mute_mode:2,
514
                unknown2:3;
515
        u8      named:1,
516
                scan_add:1,
517
                extra_power_bit:1,
518
                power:2,
519
                am_mode:1,
520
                unknownbit2:1,
521
                isnarrow:1;
522
        u8      unknown3:6,
523
                Unknown4_shft_dir:2;
524
        u8      unknown5:3,
525
                compander:1
526
                scrambler:4;
527
    } memory[1000];
528

    
529
    #seekto 0x48f8;
530
    struct {
531
        u8    name[8];
532
    } names[1000];
533

    
534
    #seekto 0x6fff;
535
    u8          valid[1000];
536
    """
537

    
538

    
539
def _freq_decode(in_freq, bytes=4):
540
    out_freq = 0
541
    for i in range(bytes*2):
542
        out_freq += (in_freq & 0xF) * (10 ** i)
543
        in_freq = in_freq >> 4
544
    if bytes == 4:
545
        return out_freq * 10
546
    elif bytes == 2:
547
        return out_freq * 100000
548

    
549

    
550
def _freq_encode(in_freq, bytes=4):
551
    if bytes == 4:
552
        return int('%08d' % (in_freq / 10), 16)
553
    elif bytes == 2:
554
        return int('%04d' % (in_freq / 100000), 16)
555

    
556

    
557
def _oem_str_decode(in_str):
558
    LOG.debug("decode OEM Input String = %s", in_str)
559
    out_str = ''
560
    stopchar = FALSE
561
    for c in in_str:
562
        # if c !=0x50 and stopchar==FALSE:
563
        # 1000G+ character mapping starts with P = 32 and O = 127
564
        if 127 >= c >= 80:
565
            LOG.debug(" 127>=c>=80 c = %s", c)
566
            out_str += chr(c - 48)
567
        elif 32 <= c < 80:
568
            LOG.debug(" 32<=c<80 c = %s", c)
569
            out_str += chr(c+48)
570
        # if chr(c-48) in chirp_common.CHARSET_ASCII:
571
        #     out_str+= chr(c-48)
572
        # elif chr(c+48) in chirp_common.CHARSET_ASCII:
573
        #     out_str+= chr(c+48)
574
        else:
575
            out_str += ''
576
            stopchar = TRUE
577
    LOG.debug("decode OEM Ouput String = %s", out_str)
578
    return out_str
579

    
580

    
581
def _oem_str_encode(in_str):
582
    out_str = ''
583
    LOG.debug("encode OEM Input String = %s", in_str)
584
    for c in in_str:
585
        if 32 <= ord(c) < 80:
586
            out_str += chr(int(ord(c)) + 48)
587
        elif 127 >= ord(c) >= 80:
588
            out_str += chr(int(ord(c)) - 48)
589
    while len(out_str) < 8:
590
        out_str += chr(0x50)
591
    LOG.debug("encode OEM Ouput String = %s", out_str)
592
    return out_str
593

    
594

    
595
def _str_decode(in_str):
596
    out_str = ''
597
    stopchar = FALSE
598
    for c in in_str:
599
        if c != 0x00 and stopchar == FALSE:
600
            if chr(c) in chirp_common.CHARSET_ASCII:
601
                out_str += chr(c)
602
        else:
603
            out_str += ''
604
            stopchar = TRUE
605
    return out_str
606

    
607

    
608
def _str_encode(in_str):
609
    out_str = ''
610
    for c in in_str:
611
        try:
612
            out_str += chr(ord(c))
613
        except ValueError:
614
            pass
615
    while len(out_str) < 8:
616
        out_str += chr(0x00)
617
    if out_str == "        " or out_str == "":
618
        out_str = "\x00\x00\x00\x00\x00\x00\x00\x00"
619
    return out_str
620

    
621

    
622
def _chnum_decode(in_ch):
623
    return int(('%04x' % in_ch)[0:3])
624

    
625

    
626
def _chnum_encode(in_ch):
627
    return int('%03d0' % in_ch, 16)
628

    
629
# Support for the Wouxun KG-1000G+ radio
630
# Serial coms are at 19200 baud
631
# The data is passed in variable length records
632
# Record structure:
633
#  Offset   Usage
634
#    0      start of record (\x7c)
635
#    1      Command (\x80 Identify \x81 End/Reboot \x82 Read \x83 Write)
636
#    2      direction (\xff PC-> Radio, \x00 Radio -> PC)
637
#    3      length of payload (excluding header/checksum) (n)
638
#    4      payload (n bytes)
639
#    4+n+1  checksum - only lower 4 bits of byte sum (% 256) of bytes 1 -> 4+n
640
#
641
# Memory Read Records:
642
# the payload is 3 bytes, first 2 are offset (big endian),
643
# 3rd is number of bytes to read
644
# Memory Write Records:
645
# the maximum payload size (from the Wouxun software) seems to be 66 bytes
646
#  (2 bytes location + 64 bytes data).
647

    
648

    
649
class KGUV8TRadio(chirp_common.Alias):
650
    VENDOR = "Wouxun"
651
    MODEL = "KG-1000G Plus"
652

    
653

    
654
@directory.register
655
class KG1000GPlusRadio(chirp_common.CloneModeRadio,
656
                       chirp_common.ExperimentalRadio):
657

    
658
    """Wouxun KG-1000G Plus"""
659
    VENDOR = "Wouxun"
660
    MODEL = "KG-1000G Plus"
661
    _model = "KG-UV950R2"
662
    _file_ident = "1000G Plus"
663
    BAUD_RATE = 19200
664

    
665
    POWER_LEVELS = [chirp_common.PowerLevel("L", watts=1.0),
666
                    chirp_common.PowerLevel("M", watts=20.0),
667
                    chirp_common.PowerLevel("H", watts=50.0)]
668
    _mmap = ""
669
    ALIASES = [KGUV8TRadio, ]
670

    
671
    def _checksum(self, data):
672
        cs = 0
673
        for byte in data:
674
            cs += ord(byte)
675
        return chr(cs % 256)
676

    
677
    def _write_record(self, cmd, payload=None):
678
        # build the packet
679
        _header = '\xda' + chr(cmd) + '\xff'
680

    
681
        _length = 0
682
        if payload:
683
            _length = len(payload)
684

    
685
        # update the length field
686
        _header += chr(_length)
687

    
688
        if payload:
689
            # calculate checksum then add it with the payload
690
            # to the packet and encrypt
691
            crc = self._checksum(_header[1:] + payload)
692
            # Checksum is only the lower 4 bits
693
            crc = chr(ord(crc) & 0xf)
694
            payload += crc
695
            _header += self.encrypt(payload)
696
        else:
697
            # calculate and add encrypted checksum to the packet
698
            crc = self._checksum(_header[1:])
699
            # Checksum is only the lower 4 bits
700
            crc = chr(ord(crc) & 0xf)
701
            _header += self.strxor(crc, '\x57')
702

    
703
        try:
704
            LOG.debug("Sent:\n%s" % util.hexprint(_header))
705
            self.pipe.write(_header)
706
        except Exception, e:
707
            raise errors.RadioError("Failed to communicate with radio: %s" % e)
708

    
709
    def _read_record(self):
710
        # read 4 chars for the header
711
        _header = self.pipe.read(4)
712
        # LOG.debug("header = " % util.hexprint(_header))
713
        if len(_header) != 4:
714
            raise errors.RadioError('Radio did not respond- header length')
715
        _length = ord(_header[3])
716
        _packet = self.pipe.read(_length)
717
        _rcs_xor = _packet[-1]
718
        _packet = self.decrypt(_packet)
719
        _cs = ord(self._checksum(_header[1:] + _packet))
720
        # It appears the checksum is only 4bits
721
        _cs = _cs & 0xf
722
        # read the checksum and decrypt it
723
        _rcs = ord(self.strxor(self.pipe.read(1), _rcs_xor))
724
        _rcs = _rcs & 0xf
725
        return (_rcs != _cs, _packet)
726

    
727
    def decrypt(self, data):
728
        result = ''
729
        for i in range(len(data)-1, 0, -1):
730
            result += self.strxor(data[i], data[i - 1])
731
        result += self.strxor(data[0], '\x57')
732
        return result[::-1]
733

    
734
    def encrypt(self, data):
735
        result = self.strxor('\x57', data[0])
736
        for i in range(1, len(data), 1):
737
            result += self.strxor(result[i - 1], data[i])
738
        return result
739

    
740
    def strxor(self, xora, xorb):
741
        return chr(ord(xora) ^ ord(xorb))
742

    
743
    # Identify the radio
744
    #
745
    # A Gotcha: the first identify packet returns a bad checksum, subsequent
746
    # attempts return the correct checksum... (well it does on my radio!)
747
    #
748
    # The ID record returned by the radio also includes the
749
    # current frequency range
750
    # as 4 bytes big-endian in 10Hz increments
751
    #
752
    # Offset
753
    #  0:10     Model, zero padded
754

    
755
    @classmethod
756
    def match_model(cls, filedata, filename):
757
        id = cls._file_ident
758
        return cls._file_ident in filedata[0x426:0x430]
759

    
760
    def _identify(self):
761
        """Do the identification dance"""
762
        for _i in range(0, 3):
763
            LOG.debug("ID try #"+str(_i))
764
            self._write_record(CMD_ID)
765
            _chksum_err, _resp = self._read_record()
766
            if len(_resp) == 0:
767
                raise Exception("Radio not responding")
768
            else:
769
                LOG.debug("Got:\n%s" % util.hexprint(_resp))
770
                LOG.debug("Model received is %s" % _resp[0:10])
771
                LOG.debug("Model expected is %s" % self._model)
772
                if _chksum_err:
773
                    LOG.error("Checksum error: retrying ident...")
774
                    time.sleep(0.100)
775
                    continue
776
                else:
777
                    LOG.debug("checksum passed")
778
                    if _resp[0:8] == self._model[0:8]:
779
                        LOG.debug("Passed identify")
780
                        break
781
                    else:
782
                        LOG.debug("FAILED to identify")
783

    
784
    def _finish(self):
785
        self._write_record(CMD_END)
786

    
787
    def process_mmap(self):
788
        self._memobj = bitwise.parse(_MEM_FORMAT, self._mmap)
789

    
790
    def sync_in(self):
791
        try:
792
            self._mmap = self._download()
793
        except errors.RadioError:
794
            raise
795
        except Exception, e:
796
            raise errors.RadioError("Failed to communicate with radio: %s" % e)
797
        self.process_mmap()
798

    
799
    def sync_out(self):
800
        self._upload()
801

    
802
    # TODO: Load all memory.
803
    # It would be smarter to only load the active areas and none of
804
    # the padding/unused areas. Padding still need to be investigated.
805
    def _download(self):
806
        """Talk to a wouxun KG-1000G Plus and do a download"""
807
        try:
808
            self._identify()
809
            return self._do_download(0, 32768, 64)
810
        except errors.RadioError:
811
            raise
812
        except Exception, e:
813
            LOG.exception('Unknown error during download process')
814
            raise errors.RadioError("Failed to communicate with radio: %s" % e)
815

    
816
    def _do_download(self, start, end, blocksize):
817
        # allocate & fill memory
818
        LOG.debug("Start Download")
819
        image = ""
820
        for i in range(start, end, blocksize):
821
            req = chr(i / 256) + chr(i % 256) + chr(blocksize)
822
            self._write_record(CMD_RD, req)
823
            cs_error, resp = self._read_record()
824
            LOG.debug("Got:\n%s" % util.hexprint(resp))
825

    
826
            if cs_error:
827
                LOG.debug(util.hexprint(resp))
828
                raise Exception("Checksum error on read")
829
            # LOG.debug("Got:\n%s" % util.hexprint(resp))
830
            image += resp[2:]
831
            if self.status_fn:
832
                status = chirp_common.Status()
833
                status.cur = i
834
                status.max = end
835
                status.msg = "Cloning from radio"
836
                self.status_fn(status)
837
        self._finish()
838
        return memmap.MemoryMap(''.join(image))
839

    
840
    def _upload(self):
841
        """Talk to a wouxun KG-1000G Plus and do a upload"""
842
        try:
843
            self._identify()
844
            LOG.debug("Done with Upload Identify")
845
            # self._do_upload(0, 1856, 16)
846
            # LOG.debug("Done with Limits Upload")
847
            # self._do_upload(1856, 32768, 64)
848
            self._do_upload()
849
            LOG.debug("Done with Mem and Settings Upload")
850
            self._finish()
851
        except errors.RadioError:
852
            raise
853
        except Exception, e:
854
            raise errors.RadioError("Failed to communicate with radio: %s" % e)
855
        return
856

    
857
    def _do_upload(self):
858
        LOG.debug("Start of _do_upload")
859
        for ar, size, count in config_map:
860
            for addr in range(ar, ar + (size*count), size):
861
                start = ar
862
                ptr = start
863
                LOG.debug("ptr = " + str(ptr))
864
                end = ar + (size*count)
865
                blocksize = size
866
                LOG.debug("Start of loop in _do_upload index = "+str(addr))
867
                LOG.debug("Start %i End %i Size %i" % (start, end, blocksize))
868
                req = chr(addr / 256) + chr(addr % 256)
869
                LOG.debug("REQ")
870
                chunk = self.get_mmap()[addr:addr + blocksize]
871
                LOG.debug("CHUNK")
872
                self._write_record(CMD_WR, req + chunk)
873
    #            LOG.debug("Upload-- SENT : " % util.hexprint(_sent))
874
                cserr, ack = self._read_record()
875
                LOG.debug("Upload-- CSUM ERROR : " + str(cserr))
876
                LOG.debug("Upload-- RCVD :\n%s " % util.hexprint(ack))
877

    
878
                j = ord(ack[0]) * 256 + ord(ack[1])
879
                LOG.debug("j = " + str(j))
880
                LOG.debug("addr= " + str(addr))
881

    
882
                if cserr or j != addr:
883
                    raise Exception("Radio did not ack block %i" % addr)
884
                # ptr += blocksize
885
                if self.status_fn:
886
                    status = chirp_common.Status()
887
                    status.cur = addr
888
                    status.max = 0x73e7
889
                    status.msg = "Cloning to radio"
890
                    self.status_fn(status)
891
        # self._finish()
892

    
893
    def get_features(self):
894
        rf = chirp_common.RadioFeatures()
895
        rf.has_settings = True
896
        rf.has_ctone = True
897
        rf.has_rx_dtcs = True
898
        rf.has_cross = True
899
        rf.has_tuning_step = False
900
        rf.has_bank = False
901
        rf.can_odd_split = True
902
        rf.valid_skips = ["", "S"]
903
        rf.valid_tmodes = ["", "Tone", "TSQL", "DTCS", "Cross"]
904
        rf.valid_cross_modes = [
905
            "Tone->Tone",
906
            "Tone->DTCS",
907
            "DTCS->Tone",
908
            "DTCS->",
909
            "->Tone",
910
            "->DTCS",
911
            "DTCS->DTCS",
912
        ]
913
        rf.valid_modes = ["FM", "NFM", "AM", "NAM"]
914
        rf.valid_power_levels = self.POWER_LEVELS
915
        rf.valid_name_length = 8
916
        rf.valid_duplexes = ["", "-", "+", "split", "off"]
917
#   MRT - Open up channel memory freq range to support RxFreq limit expansion
918
        rf.valid_bands = [(26000000, 299999990),  # supports VHF
919
                          (300000000, 999999990)]  # supports UHF
920

    
921
        rf.valid_characters = chirp_common.CHARSET_ASCII
922
        rf.memory_bounds = (1, 999)  # 999 memories
923
        rf.valid_tuning_steps = STEPS
924
        return rf
925

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

    
946
    def get_raw_memory(self, number):
947
        return repr(self._memobj.memory[number])
948
# MRT - corrected the Polarity decoding to match 1000G Plus implementation
949
# use 0x4000 bit mask for R
950
# MRT - 0x4000 appears to be the bit mask for Inverted DCS tones
951
# MRT - n DCS Tone will be 0x8xxx values - i DCS Tones will
952
# be 0xCxxx values.
953
# MRT - Chirp Uses N for n DCS Tones and R for i DCS Tones
954
# MRT - 1000G Plus encodes DCS tone # in decimal -  NOT OCTAL
955

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

    
988
        if txmode == "Tone" and not rxmode:
989
            mem.tmode = "Tone"
990
        elif txmode == rxmode and txmode == "Tone" and mem.rtone == mem.ctone:
991
            mem.tmode = "TSQL"
992
        elif txmode == rxmode and txmode == "DTCS" and mem.dtcs == mem.rx_dtcs:
993
            mem.tmode = "DTCS"
994
        elif rxmode or txmode:
995
            mem.tmode = "Cross"
996
            mem.cross_mode = "%s->%s" % (txmode, rxmode)
997

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

    
1001
        LOG.debug("Got TX %s (%i) RX %s (%i)" %
1002
                  (txmode, _mem.txtone, rxmode, _mem.rxtone))
1003

    
1004
    def get_memory(self, number):
1005
        _mem = self._memobj.memory[number]
1006
        _nam = self._memobj.names[number]
1007

    
1008
        mem = chirp_common.Memory()
1009
        mem.number = number
1010
        _valid = self._memobj.valid[mem.number]
1011

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

    
1046
        if _mem.named:
1047
            mem.name = _str_decode(self._memobj.names[number].name)
1048
        else:
1049
            mem.name = ''
1050

    
1051
        self._get_tone(_mem, mem)
1052

    
1053
        mem.skip = "" if bool(_mem.scan_add) else "S"
1054

    
1055
        LOG.debug("Mem Power " + str(_mem.power))
1056
        pwr_index = _mem.power
1057
        if _mem.power == 3:
1058
            pwr_index = 2
1059
            LOG.debug("Force Mem Power to" + str(pwr_index))
1060
        if _mem.power:
1061
            mem.power = self.POWER_LEVELS[pwr_index]
1062
        else:
1063
            mem.power = self.POWER_LEVELS[0]
1064

    
1065
        # mem.am_mode = _mem.power & 0x2
1066

    
1067
        # LOG.debug("Mem Power Index " + str(_mem.power))
1068
#        mem.power = self.POWER_LEVELS[_mem.power]
1069

    
1070
        if _mem.am_mode:
1071
            if _mem.isnarrow:
1072
                mem.mode = "NAM"
1073
            else:
1074
                mem.mode = "AM"
1075
        else:
1076
            mem.mode = _mem.isnarrow and "NFM" or "FM"
1077

    
1078
        mem.extra = RadioSettingGroup("Extra", "extra")
1079

    
1080
        _scram = _mem.scrambler
1081
        if _mem.scrambler > 8:
1082
            _scram = 0
1083
        # rs = RadioSetting("scrambler", "Scrambler",
1084
        #                   RadioSettingValueList(SCRAMBLER_LIST,
1085
        #                                         SCRAMBLER_LIST[_scram]))
1086
        # mem.extra.append(rs)
1087

    
1088
        # rs = RadioSetting("compander", "Compander",
1089
        #                   RadioSettingValueBoolean(_mem.compander))
1090
        # mem.extra.append(rs)
1091

    
1092
        # rs = RadioSetting("mute_mode", "Mute",
1093
        #                   RadioSettingValueMap(
1094
        #                       MUTE_MODE_MAP, _mem.mute_mode))
1095
        # mem.extra.append(rs)
1096

    
1097
        return mem
1098

    
1099
    def _set_tone(self, mem, _mem):
1100
        def _set_dcs(code, pol):
1101
            # MRT Change to 0x8000 to
1102
            # set the bit for DCS- code is a decimal version
1103
            # of the code # - NOT OCTAL
1104
            val = int("%i" % code, 10) | 0x8000
1105
            if pol == "R":
1106
                # MRT Change to 0x4000 to set the bit for
1107
                # i/R polarity
1108
                val += 0x4000
1109
            return val
1110

    
1111
        rx_mode = tx_mode = None
1112
        rxtone = txtone = 0x0000
1113

    
1114
        if mem.tmode == "Tone":
1115
            tx_mode = "Tone"
1116
            rx_mode = None
1117
            txtone = int(mem.rtone * 10)
1118
        elif mem.tmode == "TSQL":
1119
            rx_mode = tx_mode = "Tone"
1120
            rxtone = txtone = int(mem.ctone * 10)
1121
        elif mem.tmode == "DTCS":
1122
            tx_mode = rx_mode = "DTCS"
1123
            txtone = _set_dcs(mem.dtcs, mem.dtcs_polarity[0])
1124
            rxtone = _set_dcs(mem.dtcs, mem.dtcs_polarity[1])
1125
        elif mem.tmode == "Cross":
1126
            tx_mode, rx_mode = mem.cross_mode.split("->")
1127
            if tx_mode == "DTCS":
1128
                txtone = _set_dcs(mem.dtcs, mem.dtcs_polarity[0])
1129
            elif tx_mode == "Tone":
1130
                txtone = int(mem.rtone * 10)
1131
            if rx_mode == "DTCS":
1132
                rxtone = _set_dcs(mem.rx_dtcs, mem.dtcs_polarity[1])
1133
            elif rx_mode == "Tone":
1134
                rxtone = int(mem.ctone * 10)
1135

    
1136
        _mem.rxtone = rxtone
1137
        _mem.txtone = txtone
1138

    
1139
        LOG.debug("Set TX %s (%i) RX %s (%i)" %
1140
                  (tx_mode, _mem.txtone, rx_mode, _mem.rxtone))
1141

    
1142
    def set_memory(self, mem):
1143
        #   _mem = Stored Memory value
1144
        #    mem = New value from user entry
1145
        number = mem.number
1146
        _mem = self._memobj.memory[number]
1147
        _nam = self._memobj.names[number]
1148
        _valid = self._memobj.valid[mem.number]
1149

    
1150
        # if mem.empty:
1151
        #     _mem.set_raw("\x00" * (_mem.size() / 8))
1152
        #     self._memobj.valid[number] = 0
1153
        #     self._memobj.names[number].set_raw("\x00" * (_nam.size() / 8))
1154
        #     return
1155

    
1156
        if mem.empty:
1157
            LOG.debug("Mem %s is Empty", number)
1158
            self._memobj.valid[number] = 0xFF
1159
            LOG.debug("Set Mem %s Not Valid", number)
1160
            _mem.rxfreq = 0xFFFFFFFF
1161
            LOG.debug("Set Rx Freq = FFFFFFF")
1162
            _mem.txfreq = 0xFFFFFFFF
1163
            LOG.debug("Set Tx Freq = FFFFFFF")
1164
            self._memobj.names[number].set_raw("\xFF" * (_nam.size() / 8))
1165
            LOG.debug("Name %s Cleared", number)
1166
            # The following line is a hack to make CPS happy and not
1167
            # show memory entries that were deleted with CHIRP
1168
            # _mem=0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
1169
            # LOG.debug("Set _mem = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF")
1170
        else:
1171
            LOG.debug("Mem %s is NOT Empty", number)
1172
            if len(mem.name) > 0:
1173
                LOG.debug("new name = %s", (mem.name))
1174
                _mem.named = True
1175
                name_encoded = _str_encode(mem.name)
1176
                LOG.debug("name endcoded = %s", (name_encoded))
1177
                LOG.debug("number = %s", (number))
1178
                for i in range(0, 8):
1179
                    _nam.name[i] = ord(name_encoded[i])
1180
            else:
1181
                _mem.named = False
1182

    
1183
            _mem.rxfreq = _freq_encode(mem.freq)
1184
            if mem.duplex == "off":
1185
                _mem.txfreq = 0xFFFFFFFF
1186
            elif mem.duplex == "split":
1187
                _mem.txfreq = _freq_encode(mem.offset)
1188
            elif mem.duplex == "+":
1189
                _mem.txfreq = _freq_encode(mem.freq + mem.offset)
1190
            elif mem.duplex == "-":
1191
                _mem.txfreq = _freq_encode(mem.freq - mem.offset)
1192
            else:
1193
                _mem.txfreq = _freq_encode(mem.freq)
1194

    
1195
            _mem.scan_add = int(mem.skip != "S")
1196

    
1197
            if mem.mode == "AM":
1198
                _mem.am_mode = True
1199
                _mem.isnarrow = False
1200
            elif mem.mode == "NAM":
1201
                _mem.am_mode = True
1202
                _mem.isnarrow = True
1203
            else:
1204
                _mem.am_mode = False
1205
                if mem.mode == "NFM":
1206
                    _mem.isnarrow = True
1207
                else:
1208
                    _mem.isnarrow = False
1209

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

    
1246
            # if mem.power:
1247
            #     _mem.power = self.POWER_LEVELS.index[mem.power]
1248
            # else:
1249
            #     _mem.power = True
1250

    
1251
            # MRT set to mute mode to QT (not QT+DTMF or QT*DTMF) by default
1252
            # MRT This changes them in the channel memory
1253
            _mem.mute_mode = 1
1254

    
1255
    def _get_settings(self):
1256
        _settings = self._memobj.settings
1257
        _limits = self._memobj.bandlimits
1258
        _oem = self._memobj.oem
1259
#        _vfoa = self._memobj.vfoa
1260
#        _vfob = self._memobj.vfob
1261
#        _scan = self._memobj.scan_groups
1262
#        _call = self._memobj.call_groups
1263
#        _callname = self._memobj.call_names
1264
#        _fmpreset = self._memobj.fm_preset
1265

    
1266
        cfg_grp = RadioSettingGroup("cfg_grp", "Config Settings")
1267
        cfg1_grp = RadioSettingGroup("cfg1_grp", "Config Settings 1")
1268
        cfg2_grp = RadioSettingGroup("cfg2_grp", "Config Settings 2")
1269
        vfoa_grp = RadioSettingGroup("vfoa_grp", "VFO A Settings")
1270
        vfo150_grp = RadioSettingGroup("vfo150_grp", "150M Settings")
1271
        vfo450_grp = RadioSettingGroup("vfo450_grp", "450M Settings")
1272
        # vfo20_grp = RadioSettingGroup("vfo20_grp", "20M Settings")
1273
        vfo50_grp = RadioSettingGroup("vfo50_grp", "50M Settings")
1274
        vfo350_grp = RadioSettingGroup("vfo350_grp", "350M Settings")
1275
        vfo850_grp = RadioSettingGroup("vfo850_grp", "850M Settings")
1276
        vfoabands_grp = RadioSettingGroup(
1277
                            "vfoabands_grp", "VFO A Band Settings")
1278
        vfob_grp = RadioSettingGroup("vfob_grp", "VFO B Settings")
1279
        key_grp = RadioSettingGroup("key_grp", "Key Settings")
1280
        fmradio_grp = RadioSettingGroup("fmradio_grp", "FM Broadcast Memory")
1281
        lmt_grp = RadioSettingGroup("lmt_grp", "Frequency Limits")
1282
        lmwrn_grp = RadioSettingGroup("lmwrn_grp", "USE AT YOUR OWN RISK")
1283
        rxlim_grp = RadioSettingGroup("rxlim_grp", "Rx Limits")
1284
        txwrn_grp = RadioSettingGroup(
1285
                        "txwrn_grp", "Radio Locked to Tx on GMRS ONLY")
1286
#        txlim_grp = RadioSettingGroup("txlim_grp",
1287
#                            "Tx Limits - Not Used by Radio")
1288
        uhf_lmt_grp = RadioSettingGroup("uhf_lmt_grp", "UHF")
1289
        vhf_lmt_grp = RadioSettingGroup("vhf_lmt_grp", "VHF")
1290
        oem_grp = RadioSettingGroup("oem_grp", "Area Message")
1291
        scan_grp = RadioSettingGroup("scan_grp", "Scan Group")
1292
        scanname_grp = RadioSettingGroup("scanname_grp", "Scan Names")
1293
        call_grp = RadioSettingGroup("call_grp", "Call Settings")
1294
        remote_grp = RadioSettingGroup("remote_grp", "Remote Settings")
1295
        extra_grp = RadioSettingGroup("extra_grp",
1296
                                      "Extra Settings"
1297
                                      "\nNOT Changed by RESET or CPS")
1298
        vfo_grp = RadioSettingGroup("vfo_grp",
1299
                                    "Freq Mode Settings")
1300
        memxtras_grp = RadioSettingGroup("memxtras_grp", "Memory Extras")
1301
        cfg_grp.append(cfg1_grp)
1302
        cfg_grp.append(cfg2_grp)
1303
        cfg_grp.append(oem_grp)
1304
        lmt_grp.append(lmwrn_grp)
1305
        lmt_grp.append(txwrn_grp)
1306
        lmt_grp.append(rxlim_grp)
1307
        # lmt_grp.append(txlim_grp)
1308
        # extra_grp.append(lmt_grp)
1309
        vfo_grp.append(vfoa_grp)
1310
        vfo_grp.append(vfob_grp)
1311
        vfoa_grp.append(vfo150_grp)
1312
        vfoa_grp.append(vfo450_grp)
1313
        # vfoa_grp.append(vfo20_grp)
1314
        vfoa_grp.append(vfo50_grp)
1315
        vfoa_grp.append(vfo350_grp)
1316
        vfoa_grp.append(vfo850_grp)
1317
        scan_grp.append(scanname_grp)
1318

    
1319
        group = RadioSettings(cfg_grp, vfo_grp, fmradio_grp,
1320
                              remote_grp, scan_grp, lmt_grp)
1321

    
1322
# Memory extras
1323
        # rs = RadioSetting("_mem.mute_mode", "Mute Mode"+str(number),
1324
        #                   RadioSettingValueBoolean(_mem.mute_mode))
1325
        # memxtras_grp.append(rs)
1326

    
1327
# Configuration Settings
1328

    
1329
        rs = RadioSetting("roger", "Roger Beep",
1330
                          RadioSettingValueList(ROGER_LIST,
1331
                                                ROGER_LIST[_settings.
1332
                                                           roger]))
1333
        cfg1_grp.append(rs)
1334

    
1335
        rs = RadioSetting("beep", "Keypad Beep",
1336
                          RadioSettingValueBoolean(_settings.beep))
1337
        cfg1_grp.append(rs)
1338

    
1339
        rs = RadioSetting("voice", "Voice Guide",
1340
                          RadioSettingValueMap(VOICE_MAP, _settings.voice))
1341
        cfg1_grp.append(rs)
1342

    
1343
        rs = RadioSetting("bcl_a", "Busy Channel Lock-out A",
1344
                          RadioSettingValueBoolean(_settings.bcl_a))
1345
        cfg1_grp.append(rs)
1346

    
1347
        rs = RadioSetting("bcl_b", "Busy Channel Lock-out B",
1348
                          RadioSettingValueBoolean(_settings.bcl_b))
1349
        cfg1_grp.append(rs)
1350

    
1351
        rs = RadioSetting("sc_rev", "Scan Mode",
1352
                          RadioSettingValueMap(SC_REV_MAP, _settings.sc_rev))
1353
        cfg1_grp.append(rs)
1354
        rs = RadioSetting("tot", "Timeout Timer (TOT)",
1355
                          RadioSettingValueMap(
1356
                              TOT_MAP, _settings.tot))
1357
        cfg1_grp.append(rs)
1358

    
1359
        rs = RadioSetting("toa", "Overtime Alarm (TOA)",
1360
                          RadioSettingValueMap(
1361
                              TOA_MAP, _settings.toa))
1362
        cfg1_grp.append(rs)
1363

    
1364
        # rs = RadioSetting("ani_sw", "Caller ID Tx - ANI-SW",
1365
        #                   RadioSettingValueBoolean(_settings.ani_sw))
1366
        # cfg1_grp.append(rs)
1367

    
1368
        rs = RadioSetting("ring", "Ring Time (Sec)",
1369
                          RadioSettingValueMap(
1370
                              RING_MAP, _settings.ring))
1371
        cfg1_grp.append(rs)
1372

    
1373
        rs = RadioSetting("dtmfsf", "Sidetone",
1374
                          RadioSettingValueList(
1375
                              DTMF_ST_LIST,
1376
                              DTMF_ST_LIST[_settings.dtmfsf]))
1377
        cfg1_grp.append(rs)
1378

    
1379
        rs = RadioSetting("ptt_id", "DTMF ID",
1380
                          RadioSettingValueMap(PTT_ID_MAP, _settings.ptt_id))
1381
        cfg1_grp.append(rs)
1382

    
1383
        rs = RadioSetting("wt_led", "Standby LED",
1384
                          RadioSettingValueList(
1385
                              BACKLIGHT_LIST,
1386
                              BACKLIGHT_LIST[_settings.wt_led]))
1387
        cfg1_grp.append(rs)
1388

    
1389
        rs = RadioSetting("tx_led", "TX LED",
1390
                          RadioSettingValueList(
1391
                              BACKLIGHT_LIST,
1392
                              BACKLIGHT_LIST[_settings.tx_led]))
1393
        cfg1_grp.append(rs)
1394

    
1395
        rs = RadioSetting("rx_led", "Rx LED",
1396
                          RadioSettingValueList(
1397
                              BACKLIGHT_LIST,
1398
                              BACKLIGHT_LIST[_settings.rx_led]))
1399
        cfg1_grp.append(rs)
1400

    
1401
        rs = RadioSetting("prich_sw", "Priority Scan",
1402
                          RadioSettingValueList(
1403
                            PRI_CH_SCAN_LIST,
1404
                            PRI_CH_SCAN_LIST[_settings.prich_sw]))
1405
        cfg1_grp.append(rs)
1406

    
1407
        rs = RadioSetting("spk_cont", "Speaker Control",
1408
                          RadioSettingValueMap(
1409
                              SPEAKER_MAP,
1410
                              _settings.spk_cont))
1411
        cfg1_grp.append(rs)
1412

    
1413
        rs = RadioSetting("autolock", "Autolock",
1414
                          RadioSettingValueBoolean(_settings.autolock))
1415
        cfg1_grp.append(rs)
1416

    
1417
        rs = RadioSetting("low_v", "Voltage Alert",
1418
                          RadioSettingValueBoolean(_settings.low_v))
1419
        cfg1_grp.append(rs)
1420

    
1421
        rs = RadioSetting("fan", "Fan Setting",
1422
                          RadioSettingValueList(
1423
                              FAN_MODE_LIST,
1424
                              FAN_MODE_LIST[_settings.fan]))
1425
        cfg1_grp.append(rs)
1426

    
1427
        rs = RadioSetting("apo_time", "Auto Power-Off (Min)",
1428
                          RadioSettingValueList(
1429
                              APO_TIME_LIST,
1430
                              APO_TIME_LIST[_settings.apo_time]))
1431
        cfg1_grp.append(rs)
1432

    
1433
        rs = RadioSetting("alert", "Alert Tone(Hz)",
1434
                          RadioSettingValueMap(ALERT_MAP, _settings.alert))
1435
        cfg1_grp.append(rs)
1436
        rs = RadioSetting("m_pwr", "Medium Power Level (W)",
1437
                          RadioSettingValueMap(M_POWER_MAP,
1438
                                               _settings.m_pwr))
1439
        cfg1_grp.append(rs)
1440

    
1441
        rs = RadioSetting("rpt_set_model", "Repeater Mode",
1442
                          RadioSettingValueMap(
1443
                              RPT_MODE_MAP,
1444
                              _settings.rpt_set_model))
1445
        cfg2_grp.append(rs)
1446

    
1447
        rs = RadioSetting("rpt_spk", "Repeater Speaker Switch (RPT-SPK)",
1448
                          RadioSettingValueBoolean(_settings.rpt_spk))
1449
        cfg2_grp.append(rs)
1450

    
1451
        rs = RadioSetting("rpt_ptt", "Repeater PTT (RPT-PTT)",
1452
                          RadioSettingValueBoolean(_settings.rpt_ptt))
1453
        cfg2_grp.append(rs)
1454

    
1455
        rs = RadioSetting("dtmf_time", "DTMF Tx Duration (ms)",
1456
                          RadioSettingValueList(
1457
                              DTMF_TIMES,
1458
                              DTMF_TIMES[_settings.dtmf_time]))
1459
        cfg2_grp.append(rs)
1460
        rs = RadioSetting("dtmf_int", "DTMF Interval (ms)",
1461
                          RadioSettingValueList(
1462
                              DTMF_INTERVALS,
1463
                              DTMF_INTERVALS[_settings.dtmf_int]))
1464
        cfg2_grp.append(rs)
1465

    
1466
        rs = RadioSetting("sc_qt", "Tone Save",
1467
                          RadioSettingValueMap(
1468
                              SC_QT_MAP, _settings.sc_qt))
1469
        cfg2_grp.append(rs)
1470

    
1471
        rs = RadioSetting("pri_ch", "Priority Channel",
1472
                          RadioSettingValueInteger(
1473
                              1, 999, _chnum_decode(_settings.pri_ch)))
1474
        cfg2_grp.append(rs)
1475

    
1476
        rs = RadioSetting("ptt_id_dly", "DTMF ID Delay (ms)",
1477
                          RadioSettingValueMap(PTT_ID_DELAY_MAP,
1478
                                               _settings.ptt_id_dly))
1479
        cfg2_grp.append(rs)
1480

    
1481
        rs = RadioSetting("rc_sw", "Remote Control RC-SW",
1482
                          RadioSettingValueBoolean(_settings.rc_sw))
1483
        cfg2_grp.append(rs)
1484

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

    
1489
        rs = RadioSetting("menu", "Menu Available",
1490
                          RadioSettingValueBoolean(_settings.menu))
1491
        cfg2_grp.append(rs)
1492

    
1493
        rs = RadioSetting("thr_vol_tx", "Tx Voltage Limit",
1494
                          RadioSettingValueBoolean(_settings.thr_vol_tx))
1495
        cfg2_grp.append(rs)
1496

    
1497
        rs = RadioSetting("hold_time_rpt", "Repeater Hold Time (ms)",
1498
                          RadioSettingValueList(
1499
                              HOLD_TIMES,
1500
                              HOLD_TIMES[_settings.hold_time_rpt]))
1501
        cfg2_grp.append(rs)
1502

    
1503
        rs = RadioSetting("auto_am", "Auto AM",
1504
                          RadioSettingValueBoolean(_settings.auto_am))
1505
        cfg2_grp.append(rs)
1506

    
1507
        rs = RadioSetting("rpt_tone", "Repeat Tone",
1508
                          RadioSettingValueBoolean(_settings.rpt_tone))
1509
        cfg2_grp.append(rs)
1510

    
1511
        rs = RadioSetting("pf1_set", "PF1 setting",
1512
                          RadioSettingValueList(
1513
                              PF1_SETTINGS,
1514
                              PF1_SETTINGS[_settings.pf1_set]))
1515
        cfg2_grp.append(rs)
1516

    
1517
        rs = RadioSetting("settings.thr_vol_lvl", "Tx Voltage Min",
1518
                          RadioSettingValueFloat(
1519
                              9.5, 10.5,
1520
                              _settings.thr_vol_lvl / 100.0, 0.1, 1))
1521
        cfg2_grp.append(rs)
1522

    
1523
        dtmfchars = "0123456789"
1524
        _code = ''
1525
        test = int(_oem.mode_psw)
1526
        _codeobj = '0x{0:0{1}X}'.format(test, 6)
1527
        LOG.debug("codeobj = %s" % _codeobj)
1528
        _psw = str(_codeobj)
1529
        for i in range(2, 8):
1530
            LOG.debug("psw[i] = %s" % _psw[i])
1531
            if _psw[i] in dtmfchars:
1532
                _code += _psw[i]
1533
        val_psw = int(_code)
1534
        LOG.debug("psw = %s" % val_psw)
1535
        val_psw = RadioSettingValueString(6, 6, _code, False)
1536
        val_psw.set_charset(dtmfchars)
1537
        rs = RadioSetting("oem.mode_psw", "Freq Mode Password", val_psw)
1538

    
1539
        def apply_psw_id(setting, obj):
1540
            val2 = hex(int(str(val_psw), 16))
1541
            LOG.debug("val2= %s" % val2)
1542
            if (int(val2, 16) != 0):
1543
                while len(val2) < 8:
1544
                    val2 += '0'
1545
            psw = int(str(val2), 16)
1546
            LOG.debug("val3= %s" % psw)
1547
            LOG.debug("val= %s" % val_psw)
1548
            obj.mode_psw = psw
1549
        rs.set_apply_callback(apply_psw_id, _oem)
1550
        cfg2_grp.append(rs)
1551

    
1552
        rs = RadioSetting("ABR", "Backlight On Time",
1553
                          RadioSettingValueList(
1554
                              ABR_LIST,
1555
                              ABR_LIST[_settings.ABR]))
1556
        cfg2_grp.append(rs)
1557

    
1558
        rs = RadioSetting("KeyA", "Key A",
1559
                          RadioSettingValueList(
1560
                              KEY_LIST,
1561
                              KEY_LIST[_settings.KeyA]))
1562
        cfg2_grp.append(rs)
1563
        rs = RadioSetting("KeyB", "Key B",
1564
                          RadioSettingValueList(
1565
                              KEY_LIST,
1566
                              KEY_LIST[_settings.KeyB]))
1567
        cfg2_grp.append(rs)
1568
        rs = RadioSetting("KeyC", "Key C",
1569
                          RadioSettingValueList(
1570
                              KEY_LIST,
1571
                              KEY_LIST[_settings.KeyC]))
1572
        cfg2_grp.append(rs)
1573
        rs = RadioSetting("KeyD", "Key D",
1574
                          RadioSettingValueList(
1575
                              KEY_LIST,
1576
                              KEY_LIST[_settings.KeyD]))
1577
        cfg2_grp.append(rs)
1578

    
1579
        rs = RadioSetting("key_lock", "Key Lock",
1580
                          RadioSettingValueBoolean(_settings.key_lock))
1581
        cfg2_grp.append(rs)
1582

    
1583
        rs = RadioSetting("act_area", "Active Area",
1584
                          RadioSettingValueList(
1585
                              ACTIVE_AREA_LIST,
1586
                              ACTIVE_AREA_LIST[_settings.act_area]))
1587
        cfg2_grp.append(rs)
1588
        rs = RadioSetting("tdr_off", "TDR",
1589
                          RadioSettingValueList(
1590
                              TDR_LIST,
1591
                              TDR_LIST[_settings.tdr_off]))
1592
        cfg2_grp.append(rs)
1593

    
1594
# Freq Limits settings
1595

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

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

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

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

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

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

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

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

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

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

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

    
1706
        _temp = str(hex(int("%i" %
1707
                    self._memobj.bandlimits.limit_850M_rx_stop, 10)))
1708
        _temp = int(int(_temp[2:])/10.0)
1709
        val = RadioSettingValueInteger(0, 999, _temp)
1710
        rs = RadioSetting("bandlimits.limit_850M_rx_stop",
1711
                          "850M Rx Upper Limit (MHz)",
1712
                          RadioSettingValueInteger(0, 999,
1713
                                                   val))
1714
        rxlim_grp.append(rs)
1715

    
1716
# VFO Settings
1717
        rs = RadioSetting("vfomode_a", "VFO A Working Mode",
1718
                          RadioSettingValueMap(WORKMODE_MAP,
1719
                                               _settings.vfomode_a))
1720
        vfoa_grp.append(rs)
1721

    
1722
        rs = RadioSetting("vfoband_a", "VFO A Current Band",
1723
                          RadioSettingValueMap(VFOBAND_MAP,
1724
                                               _settings.vfoband_a))
1725
        vfoa_grp.append(rs)
1726

    
1727
        rs = RadioSetting("vfochan_a", "VFO A Channel",
1728
                          RadioSettingValueInteger(1, 999,
1729
                                                   _chnum_decode(
1730
                                                    _settings.vfochan_a)))
1731
        vfoa_grp.append(rs)
1732

    
1733
        rs = RadioSetting("vfosquelch_a", "VFO A Squelch",
1734
                          RadioSettingValueInteger(0, 9,
1735
                                                   _settings.vfosquelch_a))
1736
        vfoa_grp.append(rs)
1737
        rs = RadioSetting("vfostep_a", "VFO A Step",
1738
                          RadioSettingValueList(
1739
                            STEP_LIST,
1740
                            STEP_LIST[_settings.vfostep_a]))
1741
        vfoa_grp.append(rs)
1742

    
1743
######################
1744

    
1745
        rs = RadioSetting("vfofreq1", "VFO 150M Freq",
1746
                          RadioSettingValueFloat(
1747
                             0, 999.999999, (_freq_decode
1748
                                             (_settings.vfofreq1) /
1749
                                             1000000.0), 0.000001, 6))
1750
        vfo150_grp.append(rs)
1751

    
1752
        rs = RadioSetting("vfoofst1", "VFO 150M Offset",
1753
                          RadioSettingValueFloat(
1754
                              0, 999.999999, (_freq_decode
1755
                                              (_settings.vfoofst1) /
1756
                                              1000000.0), 0.000001, 6))
1757
        vfo150_grp.append(rs)
1758

    
1759
        rs = RadioSetting("rxtone1", "VFO 150M Rx tone",
1760
                          RadioSettingValueMap(
1761
                            TONE_MAP, _settings.rxtone1))
1762
        vfo150_grp.append(rs)
1763

    
1764
        rs = RadioSetting("txtone1", "VFO 150M Tx tone",
1765
                          RadioSettingValueMap(
1766
                            TONE_MAP, _settings.txtone1))
1767
        vfo150_grp.append(rs)
1768

    
1769
        rs = RadioSetting("power1", "VFO 150M Power",
1770
                          RadioSettingValueMap(
1771
                            POWER_MAP, _settings.power1))
1772
        vfo150_grp.append(rs)
1773

    
1774
        rs = RadioSetting("narrow1", "VFO 150M W/N",
1775
                          RadioSettingValueMap(
1776
                            BANDWIDTH_MAP, _settings.narrow1))
1777
        vfo150_grp.append(rs)
1778

    
1779
        rs = RadioSetting("mute1", "VFO 150M SP Mute",
1780
                          RadioSettingValueMap(
1781
                            MUTE_MODE_MAP, _settings.mute1))
1782
        vfo150_grp.append(rs)
1783

    
1784
        rs = RadioSetting("shft_dir1", "VFO 150M Repeater",
1785
                          RadioSettingValueBoolean(
1786
                            _settings.shft_dir1))
1787
        vfo150_grp.append(rs)
1788

    
1789
        rs = RadioSetting("compander1", "VFO 150M Compander",
1790
                          RadioSettingValueBoolean(
1791
                            _settings.compander1))
1792
        vfo150_grp.append(rs)
1793

    
1794
        rs = RadioSetting("scrambler1", "VFO 150M Descrambler",
1795
                          RadioSettingValueList(
1796
                            SCRAMBLER_LIST,
1797
                            SCRAMBLER_LIST[_settings.scrambler1]))
1798
        vfo150_grp.append(rs)
1799
        rs = RadioSetting("am_mode1", "VFO 150M AM Mode",
1800
                          RadioSettingValueBoolean(
1801
                            _settings.am_mode1))
1802
        vfo150_grp.append(rs)
1803
############################
1804

    
1805
        rs = RadioSetting("vfofreq2", "VFO 450M Freq",
1806
                          RadioSettingValueFloat(
1807
                             0, 999.999999, (_freq_decode
1808
                                             (_settings.vfofreq2) /
1809
                                             1000000.0), 0.000001, 6))
1810
        vfo450_grp.append(rs)
1811

    
1812
        rs = RadioSetting("vfoofst2", "VFO 450M Offset",
1813
                          RadioSettingValueFloat(
1814
                              0, 999.999999, (_freq_decode
1815
                                              (_settings.vfoofst2) /
1816
                                              1000000.0), 0.000001, 6))
1817
        vfo450_grp.append(rs)
1818

    
1819
        rs = RadioSetting("rxtone2", "VFO 450M Rx tone",
1820
                          RadioSettingValueMap(
1821
                            TONE_MAP, _settings.rxtone2))
1822
        vfo450_grp.append(rs)
1823

    
1824
        rs = RadioSetting("txtone2", "VFO 450M Tx tone",
1825
                          RadioSettingValueMap(
1826
                            TONE_MAP, _settings.txtone2))
1827
        vfo450_grp.append(rs)
1828

    
1829
        rs = RadioSetting("power2", "VFO 450M Power",
1830
                          RadioSettingValueMap(
1831
                            POWER_MAP, _settings.power2))
1832
        vfo450_grp.append(rs)
1833

    
1834
        rs = RadioSetting("narrow2", "VFO 450M W/N",
1835
                          RadioSettingValueMap(
1836
                            BANDWIDTH_MAP, _settings.narrow2))
1837
        vfo450_grp.append(rs)
1838

    
1839
        rs = RadioSetting("mute2", "VFO 450M SP Mute",
1840
                          RadioSettingValueMap(
1841
                            MUTE_MODE_MAP, _settings.mute2))
1842
        vfo450_grp.append(rs)
1843

    
1844
        rs = RadioSetting("shft_dir2", "VFO 450M Repeater",
1845
                          RadioSettingValueBoolean(
1846
                            _settings.shft_dir2))
1847
        vfo450_grp.append(rs)
1848

    
1849
        rs = RadioSetting("compander2", "VFO 450M Compander",
1850
                          RadioSettingValueBoolean(
1851
                            _settings.compander2))
1852
        vfo450_grp.append(rs)
1853

    
1854
        rs = RadioSetting("scrambler2", "VFO 450M Descrambler",
1855
                          RadioSettingValueList(
1856
                            SCRAMBLER_LIST,
1857
                            SCRAMBLER_LIST[_settings.scrambler2]))
1858
        vfo450_grp.append(rs)
1859

    
1860
        rs = RadioSetting("am_mode2", "VFO 450M AM Mode",
1861
                          RadioSettingValueBoolean(
1862
                            _settings.am_mode2))
1863
        vfo450_grp.append(rs)
1864
############################
1865
        # rs = RadioSetting("vfofreq3", "VFO 20M Freq",
1866
        #                   RadioSettingValueFloat(
1867
        #                      0, 999.999999, (_freq_decode
1868
        #                      (_settings.vfofreq3)/1000000.0) ,0.000001, 6))
1869
        # vfo20_grp.append(rs)
1870

    
1871
        # rs = RadioSetting("vfoofst3", "VFO 20M Offset",
1872
        #                   RadioSettingValueFloat(
1873
        #                       0, 999.999999, (_freq_decode
1874
        #                       (_settings.vfoofst3)/1000000.0),0.000001, 6))
1875
        # vfo20_grp.append(rs)
1876

    
1877
        # rs = RadioSetting("rxtone3", "VFO 20M Rx tone",
1878
        #                   RadioSettingValueMap(
1879
        #                     TONE_MAP, _settings.rxtone3))
1880
        # vfo20_grp.append(rs)
1881

    
1882
        # rs = RadioSetting("txtone3", "VFO 20M Tx tone",
1883
        #                   RadioSettingValueMap(
1884
        #                     TONE_MAP, _settings.txtone3))
1885
        # vfo20_grp.append(rs)
1886

    
1887
        # rs = RadioSetting("power3", "VFO 20M Power",
1888
        #                   RadioSettingValueMap(
1889
        #                     POWER_MAP, _settings.power3))
1890
        # vfo20_grp.append(rs)
1891

    
1892
        # rs = RadioSetting("narrow3", "VFO 20M Bandwidth",
1893
        #                   RadioSettingValueMap(
1894
        #                     BANDWIDTH_MAP, _settings.narrow3))
1895
        # vfo20_grp.append(rs)
1896

    
1897
        # rs = RadioSetting("mute3", "VFO 20M Mute Mode",
1898
        #                   RadioSettingValueMap(
1899
        #                     MUTE_MODE_MAP, _settings.mute3))
1900
        # vfo20_grp.append(rs)
1901

    
1902
        # rs = RadioSetting("shft_dir3", "VFO 20M Repeater",
1903
        #                   RadioSettingValueList(
1904
        #                     DUPLEX_LIST,
1905
        #                     DUPLEX_LIST[_settings.shft_dir3]))
1906
        # vfo20_grp.append(rs)
1907

    
1908
        # rs = RadioSetting("compander3", "VFO 20M Compander",
1909
        #                   RadioSettingValueBoolean(
1910
        #                     _settings.compander3))
1911
        # vfo20_grp.append(rs)
1912

    
1913
        # rs = RadioSetting("scrambler3", "VFO 20M Descrambler",
1914
        #                   RadioSettingValueList(
1915
        #                     SCRAMBLER_LIST,
1916
        #                     SCRAMBLER_LIST[_settings.scrambler3]))
1917
        # vfo20_grp.append(rs)
1918

    
1919
        # rs = RadioSetting("am_mode3", "VFO 20M AM Mode",
1920
        #                   RadioSettingValueBoolean(
1921
        #                     _settings.am_mode3))
1922
        # vfo20_grp.append(rs)
1923
############################
1924
        rs = RadioSetting("vfofreq4", "VFO 50M Freq",
1925
                          RadioSettingValueFloat(
1926
                             0, 999.999999, (_freq_decode
1927
                                             (_settings.vfofreq4) /
1928
                                             1000000.0), 0.000001, 6))
1929
        vfo50_grp.append(rs)
1930

    
1931
        # rs = RadioSetting("vfoofst4", "VFO 50M Offset",
1932
        #                   RadioSettingValueFloat(
1933
        #                       0, 999.999999, (_freq_decode
1934
        #                       (_settings.vfoofst4)/1000000.0),0.000001, 6))
1935
        # vfo50_grp.append(rs)
1936

    
1937
        rs = RadioSetting("rxtone4", "VFO 50M Rx tone",
1938
                          RadioSettingValueMap(
1939
                            TONE_MAP, _settings.rxtone4))
1940
        vfo50_grp.append(rs)
1941

    
1942
        rs = RadioSetting("txtone4", "VFO 50M Tx tone",
1943
                          RadioSettingValueMap(
1944
                            TONE_MAP, _settings.txtone4))
1945
        vfo50_grp.append(rs)
1946

    
1947
        rs = RadioSetting("power4", "VFO 50M Power",
1948
                          RadioSettingValueMap(
1949
                            POWER_MAP, _settings.power4))
1950
        vfo50_grp.append(rs)
1951

    
1952
        rs = RadioSetting("narrow4", "VFO 50M W/N",
1953
                          RadioSettingValueMap(
1954
                            BANDWIDTH_MAP, _settings.narrow4))
1955
        vfo50_grp.append(rs)
1956

    
1957
        rs = RadioSetting("mute4", "VFO 50M SP Mute",
1958
                          RadioSettingValueMap(
1959
                            MUTE_MODE_MAP, _settings.mute4))
1960
        vfo50_grp.append(rs)
1961

    
1962
        rs = RadioSetting("shft_dir4", "VFO 50M Repeater",
1963
                          RadioSettingValueBoolean(
1964
                            _settings.shft_dir4))
1965
        vfo50_grp.append(rs)
1966

    
1967
        rs = RadioSetting("compander4", "VFO 50M Compander",
1968
                          RadioSettingValueBoolean(
1969
                            _settings.compander4))
1970
        vfo50_grp.append(rs)
1971

    
1972
        rs = RadioSetting("scrambler4", "VFO 50M Descrambler",
1973
                          RadioSettingValueList(
1974
                            SCRAMBLER_LIST,
1975
                            SCRAMBLER_LIST[_settings.scrambler4]))
1976
        vfo50_grp.append(rs)
1977

    
1978
        rs = RadioSetting("am_mode4", "VFO 50M AM Mode",
1979
                          RadioSettingValueBoolean(
1980
                            _settings.am_mode4))
1981
        vfo50_grp.append(rs)
1982
############################
1983
        rs = RadioSetting("vfofreq5", "VFO 350M Freq",
1984
                          RadioSettingValueFloat(
1985
                             0, 999.999999, (_freq_decode
1986
                                             (_settings.vfofreq5) /
1987
                                             1000000.0), 0.000001, 6))
1988
        vfo350_grp.append(rs)
1989

    
1990
        # rs = RadioSetting("vfoofst5", "VFO 350M Offset",
1991
        #                   RadioSettingValueFloat(
1992
        #                       0, 999.999999, (_freq_decode
1993
        #                       (_settings.vfoofst5)/1000000.0),0.000001, 6))
1994
        # vfo350_grp.append(rs)
1995

    
1996
        rs = RadioSetting("rxtone5", "VFO 350M Rx tone",
1997
                          RadioSettingValueMap(
1998
                            TONE_MAP, _settings.rxtone5))
1999
        vfo350_grp.append(rs)
2000

    
2001
        rs = RadioSetting("txtone5", "VFO 350M Tx tone",
2002
                          RadioSettingValueMap(
2003
                            TONE_MAP, _settings.txtone5))
2004
        vfo350_grp.append(rs)
2005

    
2006
        rs = RadioSetting("power5", "VFO 350M Power",
2007
                          RadioSettingValueMap(
2008
                            POWER_MAP, _settings.power5))
2009
        vfo350_grp.append(rs)
2010

    
2011
        rs = RadioSetting("narrow5", "VFO 350M W/N",
2012
                          RadioSettingValueMap(
2013
                            BANDWIDTH_MAP, _settings.narrow5))
2014
        vfo350_grp.append(rs)
2015

    
2016
        rs = RadioSetting("mute5", "VFO 350M SP Mute",
2017
                          RadioSettingValueMap(
2018
                            MUTE_MODE_MAP, _settings.mute5))
2019
        vfo350_grp.append(rs)
2020

    
2021
        rs = RadioSetting("shft_dir5", "VFO 350M Repeater",
2022
                          RadioSettingValueBoolean(
2023
                            _settings.shft_dir5))
2024
        vfo350_grp.append(rs)
2025

    
2026
        rs = RadioSetting("compander5", "VFO 350M Compander",
2027
                          RadioSettingValueBoolean(
2028
                            _settings.compander5))
2029
        vfo350_grp.append(rs)
2030

    
2031
        rs = RadioSetting("scrambler5", "VFO 350M Descrambler",
2032
                          RadioSettingValueList(
2033
                            SCRAMBLER_LIST,
2034
                            SCRAMBLER_LIST[_settings.scrambler5]))
2035
        vfo350_grp.append(rs)
2036

    
2037
        rs = RadioSetting("am_mode5", "VFO 350M AM Mode",
2038
                          RadioSettingValueBoolean(
2039
                            _settings.am_mode5))
2040
        vfo350_grp.append(rs)
2041

    
2042
# ############################
2043
        rs = RadioSetting("vfofreq6", "VFO 850M Freq",
2044
                          RadioSettingValueFloat(
2045
                             0, 999.999999, (_freq_decode
2046
                                             (_settings.vfofreq6) /
2047
                                             1000000.0), 0.000001, 6))
2048
        vfo850_grp.append(rs)
2049

    
2050
        # rs = RadioSetting("vfoofst6", "VFO 850M Offset",
2051
        #                   RadioSettingValueFloat(
2052
        #                       0, 999.999999, (_freq_decode
2053
        #                       (_settings.vfoofst6)/1000000.0),0.000001, 6))
2054
        # vfo850_grp.append(rs)
2055

    
2056
        rs = RadioSetting("rxtone6", "VFO 850M Rx tone",
2057
                          RadioSettingValueMap(
2058
                            TONE_MAP, _settings.rxtone6))
2059
        vfo850_grp.append(rs)
2060

    
2061
        rs = RadioSetting("txtone6", "VFO 850M Tx tone",
2062
                          RadioSettingValueMap(
2063
                            TONE_MAP, _settings.txtone6))
2064
        vfo850_grp.append(rs)
2065

    
2066
        rs = RadioSetting("power6", "VFO 850M Power",
2067
                          RadioSettingValueMap(
2068
                            POWER_MAP, _settings.power6))
2069
        vfo850_grp.append(rs)
2070

    
2071
        rs = RadioSetting("narrow6", "VFO 850M W/N",
2072
                          RadioSettingValueMap(
2073
                            BANDWIDTH_MAP, _settings.narrow6))
2074
        vfo850_grp.append(rs)
2075

    
2076
        rs = RadioSetting("mute6", "VFO 850M SP Mute",
2077
                          RadioSettingValueMap(
2078
                            MUTE_MODE_MAP, _settings.mute6))
2079
        vfo850_grp.append(rs)
2080

    
2081
        rs = RadioSetting("shft_dir6", "VFO 850M Repeater",
2082
                          RadioSettingValueBoolean(
2083
                            _settings.shft_dir6))
2084
        vfo850_grp.append(rs)
2085

    
2086
        rs = RadioSetting("compander6", "VFO 850M Compander",
2087
                          RadioSettingValueBoolean(
2088
                            _settings.compander6))
2089
        vfo850_grp.append(rs)
2090

    
2091
        rs = RadioSetting("scrambler6", "VFO 850M Descrambler",
2092
                          RadioSettingValueList(
2093
                            SCRAMBLER_LIST,
2094
                            SCRAMBLER_LIST[_settings.scrambler6]))
2095
        vfo850_grp.append(rs)
2096

    
2097
        rs = RadioSetting("am_mode6", "VFO 850M AM Mode",
2098
                          RadioSettingValueBoolean(
2099
                            _settings.am_mode6))
2100
        vfo850_grp.append(rs)
2101

    
2102
############################
2103

    
2104
        rs = RadioSetting("vfomode_b", "VFO B Working Mode",
2105
                          RadioSettingValueMap(WORKMODE_MAP,
2106
                                               _settings.vfomode_b))
2107
        vfob_grp.append(rs)
2108

    
2109
        rs = RadioSetting("vfochan_b", "VFO B Work Channel",
2110
                          RadioSettingValueInteger(1, 999,
2111
                                                   _chnum_decode(
2112
                                                    _settings.vfochan_b)))
2113
        vfob_grp.append(rs)
2114

    
2115
        rs = RadioSetting("vfofreq7", "VFO B Freq",
2116
                          RadioSettingValueFloat(
2117
                             0, 999.999999, (_freq_decode
2118
                                             (_settings.vfofreq7) /
2119
                                             1000000.0), 0.000001, 6))
2120
        vfob_grp.append(rs)
2121

    
2122
        # rs = RadioSetting("vfoofst7", "VFO B Offset",
2123
        #                   RadioSettingValueFloat(
2124
        #                       0, 999.999999, (_freq_decode
2125
        #                       (_settings.vfoofst7)/1000000.0),0.000001, 6))
2126
        # vfob_grp.append(rs)
2127

    
2128
        rs = RadioSetting("rxtone7", "VFOB Rx tone",
2129
                          RadioSettingValueMap(
2130
                            TONE_MAP, _settings.rxtone7))
2131
        vfob_grp.append(rs)
2132

    
2133
        rs = RadioSetting("txtone7", "VFOB Tx tone",
2134
                          RadioSettingValueMap(
2135
                            TONE_MAP, _settings.txtone7))
2136
        vfob_grp.append(rs)
2137
        rs = RadioSetting("power7", "VFOB Power",
2138
                          RadioSettingValueMap(
2139
                            POWER_MAP, _settings.power7))
2140
        vfob_grp.append(rs)
2141
        rs = RadioSetting("narrow7", "VFOB W/N",
2142
                          RadioSettingValueMap(
2143
                            BANDWIDTH_MAP, _settings.narrow7))
2144
        vfob_grp.append(rs)
2145
        rs = RadioSetting("mute7", "VFOB SP Mute",
2146
                          RadioSettingValueMap(
2147
                            MUTE_MODE_MAP, _settings.mute7))
2148
        vfob_grp.append(rs)
2149
        rs = RadioSetting("shft_dir7", "VFOB Repeater",
2150
                          RadioSettingValueBoolean(
2151
                            _settings.shft_dir7))
2152
        vfob_grp.append(rs)
2153
        rs = RadioSetting("compander7", "VFOB Compander",
2154
                          RadioSettingValueBoolean(
2155
                            _settings.compander7))
2156
        vfob_grp.append(rs)
2157

    
2158
        rs = RadioSetting("scrambler7", "VFOB Scrambler",
2159
                          RadioSettingValueList(
2160
                            SCRAMBLER_LIST,
2161
                            SCRAMBLER_LIST[_settings.scrambler7]))
2162
        vfob_grp.append(rs)
2163

    
2164
        rs = RadioSetting("vfosquelch_b", "VFO B Squelch",
2165
                          RadioSettingValueInteger(0, 9,
2166
                                                   _settings.vfosquelch_b))
2167
        vfob_grp.append(rs)
2168
        rs = RadioSetting("vfostep_b", "VFO B Step",
2169
                          RadioSettingValueList(
2170
                            STEP_LIST,
2171
                            STEP_LIST[_settings.vfostep_b]))
2172
        vfob_grp.append(rs)
2173
        # rs = RadioSetting("am_mode7", "VFOB AM Mode",
2174
        #                   RadioSettingValueBoolean(
2175
        #                     _settings.am_mode7))
2176
        # vfob_grp.append(rs)
2177

    
2178
# Scan Group Settings
2179
        def _decode(lst):
2180
            _str = ''.join([chr(c) for c in lst
2181
                            if chr(c) in SCANNAME_CHARSET])
2182
            return _str
2183

    
2184
        rs = RadioSetting("scan_a_act", "Scan A Active Group",
2185
                          RadioSettingValueList(
2186
                            SCAN_GROUP_LIST,
2187
                            SCAN_GROUP_LIST[_settings.scan_a_act]))
2188
        scan_grp.append(rs)
2189
        rs = RadioSetting("scan_b_act", "Scan B Active Group",
2190
                          RadioSettingValueList(
2191
                             SCAN_GROUP_LIST,
2192
                             SCAN_GROUP_LIST[_settings.scan_b_act]))
2193
        scan_grp.append(rs)
2194

    
2195
        for i in range(1, 11):
2196
            x = str(i)
2197
            _str = _decode(eval("_settings.scanname"+x))
2198
            LOG.debug("ScanName %s", i)
2199
            LOG.debug("is %s", _str)
2200
            # CPS treats PPPPPP as a blank name as it is the factory reset
2201
            # value"
2202
            # The Radio treats PPPPPPP as a blank name and can display 8
2203
            # chars"
2204
            # Force Chirp to blank out the scan name if value is PPPPPPP
2205
            # to match the radio"
2206
            # Blank out the name if first 6 are spaces or null and the
2207
            # 7th is a P to handle
2208
            # firmware peculiarities in handling all 8 characters.
2209
            if _str[0:7] == "PPPPPPP":
2210
                _str = ""
2211
                LOG.debug("Scan name now Blank ALL P")
2212
            elif _str[0:6] == "\x00\x00\x00\x00\x00\x00":
2213
                _str = ""
2214
                LOG.debug("Scan name now Blank ALL NULL")
2215
            elif _str[0:6] == "\x20\x20\x20\x20\x20\x20":
2216
                _str = ""
2217
                LOG.debug("Scan name now Blank ALL SPACE")
2218
            elif (len(_str) == 2) & (_str[0:2] == "PP"):
2219
                _str = ""
2220
                LOG.debug("Scan name now Blank last 2 are PP")
2221
            rs = RadioSetting("scanname" + x, "Scan Name " + x,
2222
                              RadioSettingValueString(0, 8, _str))
2223
            # rs = RadioSetting("scanname"+x, "Scan Name "+x, val)
2224
            scanname_grp.append(rs)
2225

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

    
2247
        _code = ''
2248
        test = int(_settings.ani_edit)
2249
        _codeobj = '0x{0:0{1}X}'.format(test, 6)
2250
        LOG.debug("codeobj = %s" % _codeobj)
2251
        _ani = str(_codeobj)
2252
        for i in range(2, 8):
2253
            LOG.debug("ani[i] = %s" % _ani[i])
2254
            if _ani[i] in dtmfchars:
2255
                _code += _ani[i]
2256
        val_ani = int(_code)
2257
        LOG.debug("ani = %s" % val_ani)
2258
        val_ani = RadioSettingValueString(3, 6, _code, False)
2259
        val_ani.set_charset(dtmfchars)
2260
        rs = RadioSetting("settings.ani_edit", "ANI Edit", val_ani)
2261

    
2262
        def apply_ani_id(setting, obj):
2263
            temp = list()
2264
            LOG.debug("val= %s" % val_ani)
2265
            if str(val_ani)[0] == "0":
2266
                raise errors.RadioError("ANI EDIT must start with \
2267
                                        Non-Zero Digit")
2268
            val2 = hex(int(str(val_ani), 16))
2269
            LOG.debug("val2= %s" % val2)
2270
            if (int(val2, 16) != 0):
2271
                while len(val2) < 5:
2272
                    val2 += '0'
2273
                while len(val2) < 8:
2274
                    val2 += 'C'
2275
            ani = int(str(val2), 16)
2276
            LOG.debug("ani= %s" % ani)
2277
            LOG.debug("val= %s" % val_ani)
2278
            obj.ani_edit = ani
2279
        rs.set_apply_callback(apply_ani_id, _settings)
2280
        remote_grp.append(rs)
2281

    
2282
        _code = ''
2283
        test = int(_settings.mcc_edit)
2284
        _codeobj = '0x{0:0{1}X}'.format(test, 6)
2285
        LOG.debug("codeobj = %s" % _codeobj)
2286
        _mcc = str(_codeobj)
2287
        for i in range(2, 8):
2288
            LOG.debug("mcc[i] = %s" % _mcc[i])
2289
            if _mcc[i] in dtmfchars:
2290
                _code += _mcc[i]
2291
        val_mcc = int(_code)
2292
        LOG.debug("mcc = %s" % val_mcc)
2293
        val_mcc = RadioSettingValueString(3, 6, _code, False)
2294
        val_mcc.set_charset(dtmfchars)
2295
        rs = RadioSetting("mcc_edit", "MCC Edit", val_mcc)
2296

    
2297
        def apply_mcc_id(setting, obj):
2298
            val2 = hex(int(str(val_mcc), 16))
2299
            LOG.debug("val2= %s" % val2)
2300
            if (int(val2, 16) != 0):
2301
                while len(val2) < 5:
2302
                    val2 += '0'
2303
                while len(val2) < 8:
2304
                    val2 += 'C'
2305
            mcc = int(str(val2), 16)
2306
            LOG.debug("val3= %s" % mcc)
2307
            LOG.debug("val= %s" % val_mcc)
2308
            obj.mcc_edit = mcc
2309
        rs.set_apply_callback(apply_mcc_id, _settings)
2310
        remote_grp.append(rs)
2311

    
2312
        _code = ''
2313
        test = int(_settings.scc_edit)
2314
        _codeobj = '0x{0:0{1}X}'.format(test, 6)
2315
        LOG.debug("codeobj = %s" % _codeobj)
2316
        _scc = str(_codeobj)
2317
        for i in range(2, 8):
2318
            LOG.debug("scc[i] = %s" % _scc[i])
2319
            if _scc[i] in dtmfchars:
2320
                _code += _scc[i]
2321
        val_scc = int(_code)
2322
        LOG.debug("scc = %s" % val_scc)
2323
        val_scc = RadioSettingValueString(3, 6, _code, False)
2324
        val_scc.set_charset(dtmfchars)
2325
        rs = RadioSetting("scc_edit", "SCC Edit", val_scc)
2326

    
2327
        def apply_scc_id(setting, obj):
2328
            val2 = hex(int(str(val_scc), 16))
2329
            LOG.debug("val2= %s" % val2)
2330
            if (int(val2, 16) != 0):
2331
                while len(val2) < 5:
2332
                    val2 += '0'
2333
                while len(val2) < 8:
2334
                    val2 += 'C'
2335
            scc = int(str(val2), 16)
2336
            LOG.debug("val3= %s" % scc)
2337
            LOG.debug("val= %s" % val_scc)
2338
            obj.scc_edit = scc
2339
        rs.set_apply_callback(apply_scc_id, _settings)
2340
        remote_grp.append(rs)
2341

    
2342
        _code = ''
2343
        test = int(_settings.ctrl_edit)
2344
        _codeobj = '0x{0:0{1}X}'.format(test, 6)
2345
        LOG.debug("codeobj = %s" % _codeobj)
2346
        _ctrl = str(_codeobj)
2347
        for i in range(2, 8):
2348
            LOG.debug("ctrl[i] = %s" % _ctrl[i])
2349
            if _ctrl[i] in dtmfchars:
2350
                _code += _ctrl[i]
2351
        val_ctrl = int(_code)
2352
        LOG.debug("ctrl = %s" % val_ctrl)
2353
        val_ctrl = RadioSettingValueString(3, 6, _code, False)
2354
        val_ctrl.set_charset(dtmfchars)
2355
        rs = RadioSetting("ctrl_edit", "CTRL Edit", val_ctrl)
2356

    
2357
        def apply_ctrl_id(setting, obj):
2358
            val2 = hex(int(str(val_ctrl), 16))
2359
            LOG.debug("val2= %s" % val2)
2360
            if (int(val2, 16) != 0):
2361
                while len(val2) < 5:
2362
                    val2 += '0'
2363
                while len(val2) < 8:
2364
                    val2 += 'C'
2365
            ctrl = int(str(val2), 16)
2366
            LOG.debug("val3= %s" % ctrl)
2367
            LOG.debug("val= %s" % val_ctrl)
2368
            obj.ctrl_edit = ctrl
2369
        rs.set_apply_callback(apply_ctrl_id, _settings)
2370
        remote_grp.append(rs)
2371

    
2372
# OEM Settings
2373

    
2374
        _oem_name = _oem_str_decode(self._memobj.oem.display_name)
2375
        rs = RadioSetting("oem.display_name", "Area Message",
2376
                          RadioSettingValueString(1, 8, _oem_name))
2377
        oem_grp.append(rs)
2378

    
2379
# FM RADIO PRESETS
2380

    
2381
# memory stores raw integer value like 7600
2382
# radio will divide 7600 by 100 and interpret correctly at 76.0Mhz
2383
        #
2384
        # FM Radio Presets Settings
2385
        #
2386

    
2387
        for i in range(1, 21):
2388
            chan = str(i)
2389
            rs = RadioSetting("FM_radio" + chan, "FM Preset " + chan,
2390
                              RadioSettingValueFloat(76.0, 108.0,
2391
                                                     eval(
2392
                                                        "_settings.FM_radio" +
2393
                                                        chan)/100.0,
2394
                                                     0.1, 1))
2395
            fmradio_grp.append(rs)
2396

    
2397
        return group
2398

    
2399
    def get_settings(self):
2400
        try:
2401
            return self._get_settings()
2402
        except:
2403
            import traceback
2404
            LOG.error("Failed to parse settings: %s", traceback.format_exc())
2405
            return None
2406

    
2407
    def set_settings(self, settings):
2408
        for element in settings:
2409
            if not isinstance(element, RadioSetting):
2410
                self.set_settings(element)
2411
                continue
2412
            else:
2413
                try:
2414
                    if "." in element.get_name():
2415
                        bits = element.get_name().split(".")
2416
                        obj = self._memobj
2417
                        for bit in bits[:-1]:
2418
                            obj = getattr(obj, bit)
2419
                        setting = bits[-1]
2420
                    else:
2421
                        obj = self._memobj.settings
2422
                        setting = element.get_name()
2423

    
2424
                    if element.has_apply_callback():
2425
                        LOG.debug("Using apply callback")
2426
                        element.run_apply_callback()
2427
                    else:
2428
                        LOG.debug("Setting %s = %s" % (setting, element.value))
2429
                        if self._is_freq(element):
2430
                            # setattr(obj, setting, int(element.value / 10))
2431
                            # MRT rescale freq values to match radio
2432
                            # expected values
2433
                            value = _freq_encode(
2434
                                element[0].get_value()*1000000.0)
2435
                            setattr(obj, setting, value)
2436

    
2437
                        elif self._is_fmradio_or_voltage(element):
2438
                            # MRT rescale FM Radio values to match radio
2439
                            # expected values
2440
                            setattr(obj, setting,
2441
                                    int(element.values()[0]._current * 100.0))
2442

    
2443
                        elif self._is_limit(element):
2444
                            setattr(obj, setting,
2445
                                    int(str(element.values()[0].
2446
                                        _current * 10), 16))
2447
                # Special VFO A Settings
2448
                #
2449
                        elif self._is_chan(element):
2450
                            value = _chnum_encode(element[0].get_value())
2451
                            setattr(obj, setting, value)
2452
                            continue
2453
                #
2454
                        elif self._is_display_name(element):
2455
                            string = element[0].get_value()
2456
                            nameenc = _oem_str_encode(string)
2457
                            for i in range(0, 8):
2458
                                LOG.debug("nameenc %s" % (nameenc[i]))
2459
                                self._memobj.oem.display_name[i] = \
2460
                                    ord(nameenc[i])
2461
                                # setattr(obj, setting, int(ord(nameenc[i])))
2462

    
2463
                        elif self._is_scan_name(element):
2464
                            string = element[0].get_value()
2465
                            LOG.debug("string %s" % (string))
2466
                            # scaname=element[0].get_name()
2467
                            # LOG.debug("scanname %s" % (scaname))
2468
                            value = _str_encode(string)
2469
                            LOG.debug("scaname %s" % (value))
2470
                            setattr(obj, setting, value)
2471
                            # self._memobj.eval(scaname)[i] = ord(nameenc[i])
2472
                            # setattr(obj, setting, int(ord(nameenc[i])))
2473
                        else:
2474
                            setattr(obj, setting, element.value)
2475
                except Exception, e:
2476
                    LOG.debug(element.get_name())
2477
                    raise
2478

    
2479
    def _is_freq(self, element):
2480
        return "rxfreq" in element.get_name() or \
2481
               "txoffset" in element.get_name() or \
2482
               "vfofreq" in element.get_name() or\
2483
               "vfoofst" in element.get_name()
2484
        #  "rx_start" in element.get_name() or \
2485
        #  "rx_stop" in element.get_name() or \
2486
        #  "tx_start" in element.get_name() or \
2487
        #  "tx_stop" in element.get_name()
2488

    
2489
    def _is_limit(self, element):
2490
        return "limit" in element.get_name()
2491

    
2492
    def _is_fmradio_or_voltage(self, element):
2493
        return "FM_radio" in element.get_name() or\
2494
                "thr_vol_lvl" in element.get_name()
2495

    
2496
    def _is_chan(self, element):
2497
        return "vfochan" in element.get_name() or\
2498
               "pri_ch" in element.get_name()
2499

    
2500
    def _is_display_name(self, element):
2501
        return "display_name" in element.get_name()
2502

    
2503
    def _is_scan_name(self, element):
2504
        return "scanname" in element.get_name()
2505

    
2506
    # def _is_vfofreq(self, element):
2507
    #     return "vfofreq" in element.get_name() or\
2508
    #            "vfoofst" in element.get_name()
(2-2/2)