Project

General

Profile

New Model #7223 » kguv980p b1.1.py

Fixes SP_Mute mode when in Channel Mode - Allows Squelch to open when receiving transmission - Mel Terechenok, 10/07/2022 04:19 PM

 
1
# melvin.terechenok@gmail.com
2
# modify for KG-UV980P
3

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

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

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

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

    
36

    
37
LOG = logging.getLogger(__name__)
38

    
39
CMD_ID = 128    # \x80
40
CMD_END = 129   # \x81
41
CMD_RD = 130    # \x82
42
CMD_X1 = 131    # \x83
43
CMD_WR = 132    # \x84
44
CMD_X2 = 133    # \x85
45

    
46
MEM_VALID = 0x00
47

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

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

    
130
_MEM_FORMAT = """
131
    #seekto 0x004c;
132
    struct {
133
        u24      mode_psw;
134
    } mode;
135

    
136
    #seekto 0x0060;
137
    struct {
138
        u16    limit_144M_ChA_rx_start;
139
        u16    limit_144M_ChA_rx_stop;    
140
        u16    limit_70cm_rx_start;
141
        u16    limit_70cm_rx_stop;    
142
        u16    limit_10m_rx_start;
143
        u16    limit_10m_rx_stop;    
144
        u16    limit_6m_rx_start;
145
        u16    limit_6m_rx_stop;    
146
        u16    limit_350M_rx_start;
147
        u16    limit_350M_rx_stop;    
148
        u16    limit_850M_rx_start;
149
        u16    limit_850M_rx_stop;    
150
        u16    limit_144M_ChA_tx_start;
151
        u16    limit_144M_ChA_tx_stop;    
152
        u16    limit_70cm_tx_start;
153
        u16    limit_70cm_tx_stop;    
154
        u16    limit_10m_tx_start;
155
        u16    limit_10m_tx_stop;    
156
        u16    limit_6m_tx_start;
157
        u16    limit_6m_tx_stop;    
158
        u16    limit_144M_ChB_rx_start;
159
        u16    limit_144M_ChB_rx_stop;
160
    } bandlimits;
161

    
162

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

    
532

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

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

    
561
    #seekto 0x6fff;
562
    u8          valid[1000];
563
    """
564
def _freq_decode(in_freq, bytes=4):
565
    out_freq = 0
566
    for i in range(bytes*2):
567
        out_freq += (in_freq & 0xF) * (10 ** i)
568
        in_freq = in_freq >> 4
569
    if bytes == 4:
570
        return out_freq * 10
571
    elif bytes == 2:
572
        return out_freq * 100000
573

    
574

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

    
581
def _str_decode(in_str):
582
    out_str = ''
583
    stopchar = FALSE
584
    for c in in_str:
585
        if c !=0x00 and stopchar==FALSE:
586
            if chr(c) in chirp_common.CHARSET_ASCII:
587
                out_str+= chr(c)
588
        else:
589
            out_str+=''
590
            stopchar = TRUE
591
    return out_str
592

    
593

    
594
def _str_encode(in_str):
595
    out_str = ''
596
    for c in in_str:
597
        try:
598
            out_str += chr(ord(c))
599
        except ValueError:
600
            pass
601
    while len(out_str) < 8:
602
        out_str += chr(0x00)
603
    return out_str
604

    
605
def _chnum_decode(in_ch):
606
    return int(('%04x' % in_ch)[0:3])
607

    
608

    
609
def _chnum_encode(in_ch):
610
    return int('%03d0' % in_ch, 16)
611

    
612
# Support for the Wouxun KG-UV980P radio
613
# Serial coms are at 19200 baud
614
# The data is passed in variable length records
615
# Record structure:
616
#  Offset   Usage
617
#    0      start of record (\x7c)
618
#    1      Command (\x80 Identify \x81 End/Reboot \x82 Read \x83 Write)
619
#    2      direction (\xff PC-> Radio, \x00 Radio -> PC)
620
#    3      length of payload (excluding header/checksum) (n)
621
#    4      payload (n bytes)
622
#    4+n+1  checksum - only lower 4 bits of byte sum (% 256) of bytes 1 -> 4+n
623
#
624
# Memory Read Records:
625
# the payload is 3 bytes, first 2 are offset (big endian),
626
# 3rd is number of bytes to read
627
# Memory Write Records:
628
# the maximum payload size (from the Wouxun software) seems to be 66 bytes
629
#  (2 bytes location + 64 bytes data).
630

    
631

    
632

    
633
class KGUV8TRadio(chirp_common.Alias):
634
    VENDOR = "Wouxun"
635
    MODEL = "KG-UV980P"
636

    
637

    
638
@directory.register
639
class KG980GRadio(chirp_common.CloneModeRadio,
640
                  chirp_common.ExperimentalRadio):
641

    
642
    """Wouxun KG-UV980P"""
643
    VENDOR = "Wouxun"
644
    MODEL = "KG-UV980P"
645
    _model = "KG-UV950R2"
646
    _file_ident = "980P"
647
    BAUD_RATE = 19200
648

    
649
    POWER_LEVELS = [chirp_common.PowerLevel("L", watts=1.0), 
650
                    chirp_common.PowerLevel("M", watts=20.0), 
651
                    chirp_common.PowerLevel("H", watts=50.0)]
652
    _mmap = ""
653
    ALIASES = [KGUV8TRadio, ]
654

    
655
    def _checksum(self, data):
656
        cs = 0
657
        for byte in data:
658
            cs += ord(byte)
659
        return chr(cs % 256)
660

    
661
    # def _write_record_id(self):
662
	# _header = '\xda\x80\xff\x00\x58'
663
    #     LOG.error("Sent:\n%s" % util.hexprint(_header))
664
	# self.pipe.write(_header)
665

    
666
    def _write_record(self, cmd, payload=None):
667
        # build the packet
668
        _header = '\xda' + chr(cmd) + '\xff'
669

    
670
        _length = 0
671
        if payload:
672
            _length = len(payload)
673

    
674
        # update the length field
675
        _header += chr(_length)
676

    
677
        if payload:
678
            # calculate checksum then add it with the payload
679
            # to the packet and encrypt
680
            crc = self._checksum(_header[1:] + payload)
681
            # Checksum is only the lower 4 bits
682
            crc = chr(ord(crc) & 0xf)
683
            payload += crc
684
            _header += self.encrypt(payload)
685
        else:
686
            # calculate and add encrypted checksum to the packet
687
            crc = self._checksum(_header[1:])
688
            # Checksum is only the lower 4 bits
689
            crc = chr(ord(crc) & 0xf)
690
            _header += self.strxor(crc, '\x57')
691

    
692
        try:
693
            LOG.debug("Sent:\n%s" % util.hexprint(_header))
694
            self.pipe.write(_header)
695
        except Exception, e:
696
            raise errors.RadioError("Failed to communicate with radio: %s" % e)
697

    
698
    def _read_record(self):
699
        # read 4 chars for the header
700
        _header = self.pipe.read(4)
701
        #LOG.debug("header = " % util.hexprint(_header))
702
        if len(_header) != 4:
703
            raise errors.RadioError('Radio did not respond- header length')
704
        _length = ord(_header[3])
705
        _packet = self.pipe.read(_length)
706
        _rcs_xor = _packet[-1]
707
        _packet = self.decrypt(_packet)
708
        _cs = ord(self._checksum(_header[1:] + _packet))
709
        #It appears the checksum is only 4bits
710
        _cs = _cs & 0xf
711
#        LOG.debug("csum = " % _cs)
712
        #read the checksum and decrypt it 
713
        _rcs = ord(self.strxor(self.pipe.read(1), _rcs_xor))
714
        _rcs = _rcs & 0xf
715
#        LOG.debug("Rcsum = " % _rcs)
716
        return (_rcs != _cs, _packet)
717

    
718
    def decrypt(self, data):
719
        result = ''
720
        for i in range(len(data)-1, 0, -1):
721
            result += self.strxor(data[i], data[i - 1])
722
        result += self.strxor(data[0], '\x57')
723
        return result[::-1]
724

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

    
731
    def strxor(self, xora, xorb):
732
        return chr(ord(xora) ^ ord(xorb))
733

    
734
    # Identify the radio
735
    #
736
    # A Gotcha: the first identify packet returns a bad checksum, subsequent
737
    # attempts return the correct checksum... (well it does on my radio!)
738
    #
739
    # The ID record returned by the radio also includes the
740
    # current frequency range
741
    # as 4 bytes big-endian in 10Hz increments
742
    #
743
    # Offset
744
    #  0:10     Model, zero padded (Looks for 'KG-UV8D-B')
745

    
746
    @classmethod
747
    def match_model(cls, filedata, filename):
748
        id = cls._file_ident
749
        return cls._file_ident in filedata[0x426:0x430]
750

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

    
776
    def _finish(self):
777
        self._write_record(CMD_END)
778

    
779
    def process_mmap(self):
780
        self._memobj = bitwise.parse(_MEM_FORMAT, self._mmap)
781

    
782
    def sync_in(self):
783
        try:
784
            self._mmap = self._download()
785
        except errors.RadioError:
786
            raise
787
        except Exception, e:
788
            raise errors.RadioError("Failed to communicate with radio: %s" % e)
789
        self.process_mmap()
790

    
791
    def sync_out(self):
792
        self._upload()
793

    
794
    # TODO: Load all memory.
795
    # It would be smarter to only load the active areas and none of
796
    # the padding/unused areas. Padding still need to be investigated.
797
    def _download(self):
798
        """Talk to a wouxun KG-UV980P and do a download"""
799
        try:
800
            self._identify()
801
            return self._do_download(0, 32768, 64)
802
        except errors.RadioError:
803
            raise
804
        except Exception, e:
805
            LOG.exception('Unknown error during download process')
806
            raise errors.RadioError("Failed to communicate with radio: %s" % e)
807

    
808
    def _do_download(self, start, end, blocksize):
809
        # allocate & fill memory
810
        LOG.debug("Start Download")
811
        image = ""
812
        for i in range(start, end, blocksize):
813
            req = chr(i / 256) + chr(i % 256) + chr(blocksize)
814
            self._write_record(CMD_RD, req)
815
            cs_error, resp = self._read_record()
816
            LOG.debug("Got:\n%s" % util.hexprint(resp))
817

    
818
            if cs_error:
819
                LOG.debug(util.hexprint(resp))
820
                raise Exception("Checksum error on read")
821
            # LOG.debug("Got:\n%s" % util.hexprint(resp))
822
            image += resp[2:]
823
            if self.status_fn:
824
                status = chirp_common.Status()
825
                status.cur = i
826
                status.max = end
827
                status.msg = "Cloning from radio"
828
                self.status_fn(status)
829
        self._finish()
830
        return memmap.MemoryMap(''.join(image))
831

    
832
    def _upload(self):
833
        """Talk to a wouxun KG-UV980P and do a upload"""
834
        try:
835
            self._identify()
836
            LOG.debug("Done with Upload Identify")
837
            self._do_upload(1856, 32768, 64)
838
        except errors.RadioError:
839
            raise
840
        except Exception, e:
841
            raise errors.RadioError("Failed to communicate with radio: %s" % e)
842
        return
843

    
844
    def _do_upload(self, start, end, blocksize):
845
        LOG.debug("Start of _do_upload")
846
        ptr = start
847
        LOG.debug("ptr = " + str(ptr))
848
        for i in range(start, end, blocksize):
849
            LOG.debug("Start of loop in _do_upload index = "+str(i))
850
            LOG.debug("Start %i End %i Size %i" % (start, end, blocksize))
851
            req = chr(i/ 256) + chr(i % 256)
852
            LOG.debug("REQ")
853
            chunk = self.get_mmap()[ptr:ptr + blocksize]
854
            LOG.debug("CHUNK")
855
            self._write_record(CMD_X1, req + chunk)
856
#            LOG.debug("Upload-- SENT : " % util.hexprint(_sent))
857
            cserr, ack = self._read_record()
858
            LOG.debug("Upload-- CSUM ERROR : " + str(cserr))
859
            LOG.debug("Upload-- RCVD :\n%s " % util.hexprint(ack))
860
            
861
            j = ord(ack[0]) * 256 + ord(ack[1])
862
            if cserr or j != ptr:
863
                raise Exception("Radio did not ack block %i" % ptr)
864
            ptr += blocksize
865
            if self.status_fn:
866
                status = chirp_common.Status()
867
                status.cur = i
868
                status.max = end
869
                status.msg = "Cloning to radio"
870
                self.status_fn(status)
871
        self._finish()
872

    
873
    def get_features(self):
874
        rf = chirp_common.RadioFeatures()
875
        rf.has_settings = True
876
        rf.has_ctone = True
877
        rf.has_rx_dtcs = True
878
        rf.has_cross = True
879
        rf.has_tuning_step = False
880
        rf.has_bank = False
881
        rf.can_odd_split = True
882
        rf.valid_skips = ["", "S"]
883
        rf.valid_tmodes = ["", "Tone", "TSQL", "DTCS", "Cross"]
884
        rf.valid_cross_modes = [
885
            "Tone->Tone",
886
            "Tone->DTCS",
887
            "DTCS->Tone",
888
            "DTCS->",
889
            "->Tone",
890
            "->DTCS",
891
            "DTCS->DTCS",
892
        ]
893
        rf.valid_modes = ["FM", "NFM", "AM", "NAM"]
894
        rf.valid_power_levels = self.POWER_LEVELS
895
        rf.valid_name_length = 8
896
        rf.valid_duplexes = ["", "-", "+", "split", "off"]
897
#   MRT - Open up channel memory freq range to support RxFreq limit expansion
898
        rf.valid_bands = [(26000000, 299999999),  # supports VHF
899
                          (300000000, 999999999)]  # supports UHF
900

    
901
        rf.valid_characters = chirp_common.CHARSET_ASCII
902
        rf.memory_bounds = (1, 999)  # 999 memories
903
        rf.valid_tuning_steps = STEPS
904
        return rf
905

    
906
    @classmethod
907
    def get_prompts(cls):
908
        rp = chirp_common.RadioPrompts()
909
        rp.experimental = \
910
            ('This driver is experimental and may contain bugs. \n'
911
              'USE AT YOUR OWN RISK \n'
912
              '\nAll CPS available settings are implemented EXCEPT \n'
913
              '---- MODE-PSW \n'
914
              '---- Remote Settings\n'
915
              '\n'
916
              'Mute, Compander and Scrambler are defaulted to '
917
              'QT, OFF , OFF for all channel memories\n\n'
918
              'Development continuing to implement other settings \n'
919
              'found on radio menu\n'
920
             )
921
        return rp
922

    
923
    def get_raw_memory(self, number):
924
        return repr(self._memobj.memory[number])
925
# MRT - corrected the Polarity decoding to match 980P implementation
926
# use 0x4000 bit mask for R
927
# MRT - 0x4000 appears to be the bit mask for Inverted DCS tones
928
# MRT - n DCS Tone will be 0x8xxx values - i DCS Tones will
929
# be 0xCxxx values.
930
# MRT - Chirp Uses N for n DCS Tones and R for i DCS Tones
931
# MRT - 980P encodes DCS tone # in decimal -  NOT OCTAL
932

    
933
    def _get_tone(self, _mem, mem):
934
        def _get_dcs(val):
935
            code = int("%03d" % (val & 0x07FF))
936
            pol = (val & 0x4000) and "R" or "N"
937
            return code, pol
938
# MRT - Modified the function below to bitwise AND with 0x4000
939
# to check for 980P DCS Tone decoding
940
# MRT 0x8000 appears to be the bit mask for DCS tones
941
        tpol = False
942
# MRT Beta 1.1 - Fix the txtone compare to 0x8000 - was rxtone.
943
        if _mem.txtone != 0xFFFF and (_mem.txtone & 0x8000) == 0x8000:
944
            tcode, tpol = _get_dcs(_mem.txtone)
945
            mem.dtcs = tcode
946
            txmode = "DTCS"
947
        elif _mem.txtone != 0xFFFF and _mem.txtone != 0x0:
948
            mem.rtone = (_mem.txtone & 0x7fff) / 10.0
949
            txmode = "Tone"
950
        else:
951
            txmode = ""
952
# MRT - Modified the function below to bitwise AND with 0x4000
953
# to check for 980P DCS Tone decoding
954
        rpol = False
955
        if _mem.rxtone != 0xFFFF and (_mem.rxtone & 0x8000) == 0x8000:
956
            rcode, rpol = _get_dcs(_mem.rxtone)
957
            mem.rx_dtcs = rcode
958
            rxmode = "DTCS"
959
        elif _mem.rxtone != 0xFFFF and _mem.rxtone != 0x0:
960
            mem.ctone = (_mem.rxtone & 0x7fff) / 10.0
961
            rxmode = "Tone"
962
        else:
963
            rxmode = ""
964

    
965
        if txmode == "Tone" and not rxmode:
966
            mem.tmode = "Tone"
967
        elif txmode == rxmode and txmode == "Tone" and mem.rtone == mem.ctone:
968
            mem.tmode = "TSQL"
969
        elif txmode == rxmode and txmode == "DTCS" and mem.dtcs == mem.rx_dtcs:
970
            mem.tmode = "DTCS"
971
        elif rxmode or txmode:
972
            mem.tmode = "Cross"
973
            mem.cross_mode = "%s->%s" % (txmode, rxmode)
974

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

    
978
        LOG.debug("Got TX %s (%i) RX %s (%i)" %
979
                  (txmode, _mem.txtone, rxmode, _mem.rxtone))
980

    
981
    def get_memory(self, number):
982
        _mem = self._memobj.memory[number]
983
        _nam = self._memobj.names[number]
984

    
985
        mem = chirp_common.Memory()
986
        mem.number = number
987
        _valid = self._memobj.valid[mem.number]
988

    
989
        LOG.debug("Mem %d valid is %s", number, _valid == MEM_VALID)
990
        LOG.debug("Rx Freq %s", _mem.rxfreq)
991
        if (_valid != MEM_VALID) & (_mem.rxfreq == 0xFFFFFFFF):
992
            mem.empty = True
993
            return mem
994
        elif (_valid != MEM_VALID) & ((_mem.rxfreq != 0xFFFFFFFF)
995
              or (_mem.rxfreq != 0x00000000)):
996
            LOG.debug("Changed chan %d %s", number, "to valid")
997
            _valid = MEM_VALID
998
            mem.empty = False
999
        else:
1000
            _valid = MEM_VALID
1001
            mem.empty = False
1002
        mem.freq = int(_mem.rxfreq) * 10
1003
        _rxfreq = _freq_decode(_mem.rxfreq)
1004
        _txfreq = _freq_decode(_mem.txfreq)
1005
        mem.freq = _rxfreq
1006
        LOG.debug("Tx Freq is "+ str(_mem.txfreq))
1007
        if  _mem.txfreq == 0xFFFFFFFF:
1008
            # TX freq not set
1009
            mem.duplex = "off"
1010
            mem.offset = 0
1011
        elif int(_rxfreq) == int(_txfreq):
1012
            mem.duplex = ""
1013
            mem.offset = 0
1014
        elif abs(_rxfreq - _txfreq) > 70000000:
1015
            mem.duplex = "split"
1016
            mem.offset = _txfreq
1017
        else:
1018
            mem.duplex = _rxfreq > _txfreq and "-" or "+"
1019
            mem.offset = abs(_rxfreq - _txfreq)
1020

    
1021
        if _mem.named:
1022
            mem.name = _str_decode(self._memobj.names[number].name)
1023
        else:
1024
            mem.name = ''
1025

    
1026

    
1027
        self._get_tone(_mem, mem)
1028

    
1029
        mem.skip = "" if bool(_mem.scan_add) else "S"
1030

    
1031
        LOG.debug("Mem Power " + str(_mem.power))
1032
        pwr_index= _mem.power
1033
        if _mem.power == 3:
1034
            pwr_index = 2
1035
            LOG.debug("Force Mem Power to" + str(pwr_index))
1036
        if _mem.power:
1037
            mem.power = self.POWER_LEVELS[pwr_index]
1038
        else: 
1039
            mem.power = self.POWER_LEVELS[0]
1040
        
1041
        # mem.am_mode = _mem.power & 0x2
1042

    
1043
        # LOG.debug("Mem Power Index " + str(_mem.power))
1044
#        mem.power = self.POWER_LEVELS[_mem.power]
1045

    
1046
        if _mem.am_mode:
1047
            if _mem.isnarrow:
1048
                mem.mode = "NAM"
1049
            else:
1050
                mem.mode = "AM"
1051
        else:
1052
            mem.mode = _mem.isnarrow and "NFM" or "FM"
1053

    
1054
        mem.extra = RadioSettingGroup("Extra", "extra")
1055

    
1056
        _scram = _mem.scrambler
1057
        if _mem.scrambler > 8:
1058
            _scram = 0
1059
        # rs = RadioSetting("scrambler", "Scrambler",
1060
        #                   RadioSettingValueList(SCRAMBLER_LIST,
1061
        #                                         SCRAMBLER_LIST[_scram]))
1062
        # mem.extra.append(rs)
1063

    
1064
        # rs = RadioSetting("compander", "Compander",
1065
        #                   RadioSettingValueBoolean(_mem.compander))
1066
        # mem.extra.append(rs)
1067

    
1068
        # rs = RadioSetting("mute_mode", "Mute",
1069
        #                   RadioSettingValueMap(MUTE_MODE_MAP, _mem.mute_mode))
1070
        # mem.extra.append(rs)
1071

    
1072
        return mem
1073

    
1074
    def _set_tone(self, mem, _mem):
1075
        def _set_dcs(code, pol):
1076
            # MRT Change to 0x8000 to
1077
            # set the bit for DCS- code is a decimal version of the code # - NOT OCTAL
1078
            val = int("%i" % code, 10) | 0x8000
1079
            if pol == "R":
1080
                # MRT Change to 0x4000 to set the bit for
1081
                # i/R polarity
1082
                val += 0x4000
1083
            return val
1084

    
1085
        rx_mode = tx_mode = None
1086
        rxtone = txtone = 0x0000
1087

    
1088
        if mem.tmode == "Tone":
1089
            tx_mode = "Tone"
1090
            rx_mode = None
1091
            txtone = int(mem.rtone * 10) 
1092
        elif mem.tmode == "TSQL":
1093
            rx_mode = tx_mode = "Tone"
1094
            rxtone = txtone = int(mem.ctone * 10) 
1095
        elif mem.tmode == "DTCS":
1096
            tx_mode = rx_mode = "DTCS"
1097
            txtone = _set_dcs(mem.dtcs, mem.dtcs_polarity[0])
1098
            rxtone = _set_dcs(mem.dtcs, mem.dtcs_polarity[1])
1099
        elif mem.tmode == "Cross":
1100
            tx_mode, rx_mode = mem.cross_mode.split("->")
1101
            if tx_mode == "DTCS":
1102
                txtone = _set_dcs(mem.dtcs, mem.dtcs_polarity[0])
1103
            elif tx_mode == "Tone":
1104
                txtone = int(mem.rtone * 10) 
1105
            if rx_mode == "DTCS":
1106
                rxtone = _set_dcs(mem.rx_dtcs, mem.dtcs_polarity[1])
1107
            elif rx_mode == "Tone":
1108
                rxtone = int(mem.ctone * 10) 
1109

    
1110
        _mem.rxtone = rxtone
1111
        _mem.txtone = txtone
1112

    
1113
        LOG.debug("Set TX %s (%i) RX %s (%i)" %
1114
                  (tx_mode, _mem.txtone, rx_mode, _mem.rxtone))
1115

    
1116
    def set_memory(self, mem):
1117
#   _mem = Stored Memory value 
1118
#    mem = New value from user entry
1119
        number = mem.number
1120
        _mem = self._memobj.memory[number]
1121
        _nam = self._memobj.names[number]
1122

    
1123
        if len(mem.name) > 0:
1124
            LOG.debug("new name = %s", (mem.name))
1125
            _mem.named = True
1126
            name_encoded = _str_encode(mem.name)
1127
            LOG.debug("name endcoded = %s", (name_encoded))
1128
            LOG.debug("number = %s", (number))
1129
            for i in range(0, 8):
1130
                _nam.name[i] = ord(name_encoded[i])
1131
        else:
1132
            _mem.named = False
1133

    
1134
        # if mem.empty:
1135
        #     _mem.set_raw("\x00" * (_mem.size() / 8))
1136
        #     self._memobj.valid[number] = 0
1137
        #     self._memobj.names[number].set_raw("\x00" * (_nam.size() / 8))
1138
        #     return
1139

    
1140
        _mem.rxfreq = _freq_encode(mem.freq)
1141
        if mem.duplex == "off":
1142
            _mem.txfreq = 0xFFFFFFFF
1143
        elif mem.duplex == "split":
1144
            _mem.txfreq = _freq_encode(mem.offset)
1145
        elif mem.duplex == "+":
1146
            _mem.txfreq = _freq_encode(mem.freq + mem.offset)
1147
        elif mem.duplex == "-":
1148
            _mem.txfreq = _freq_encode(mem.freq - mem.offset)
1149
        else:
1150
            _mem.txfreq = _freq_encode(mem.freq)
1151

    
1152
        _mem.scan_add = int(mem.skip != "S")
1153

    
1154
        if mem.mode == "AM":
1155
            _mem.am_mode = True
1156
            _mem.isnarrow = False
1157
        elif mem.mode == "NAM":
1158
            _mem.am_mode = True
1159
            _mem.isnarrow = True
1160
        else:
1161
            _mem.am_mode = False
1162
            if mem.mode =="NFM":
1163
                _mem.isnarrow = True
1164
            else:
1165
                _mem.isnarrow = False
1166

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

    
1204
        # MRT set to mute mode to QT (not QT+DTMF or QT*DTMF) by default
1205
        # MRT This changes them in the channel memory
1206
        _mem.mute_mode = 1
1207

    
1208
    def _get_settings(self):
1209
        _settings = self._memobj.settings
1210
        _limits = self._memobj.bandlimits
1211
#        _vfoa = self._memobj.vfoa
1212
#        _vfob = self._memobj.vfob
1213
#        _scan = self._memobj.scan_groups
1214
#        _call = self._memobj.call_groups
1215
#        _callname = self._memobj.call_names
1216
#        _fmpreset = self._memobj.fm_preset
1217

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

    
1272
# Memory extras
1273
        # rs = RadioSetting("_mem.mute_mode", "Mute Mode"+str(number),
1274
        #                   RadioSettingValueBoolean(_mem.mute_mode))
1275
        # memxtras_grp.append(rs)
1276

    
1277
# Configuration Settings
1278

    
1279
        rs = RadioSetting("roger", "Roger Beep",
1280
                          RadioSettingValueList(ROGER_LIST,
1281
                                                ROGER_LIST[_settings.
1282
                                                           roger]))
1283
        cfg1_grp.append(rs)
1284

    
1285
        rs = RadioSetting("beep", "Keypad Beep",
1286
                          RadioSettingValueBoolean(_settings.beep))
1287
        cfg1_grp.append(rs)
1288

    
1289
        rs = RadioSetting("voice", "Voice Guide",
1290
                          RadioSettingValueBoolean(_settings.voice))
1291
        cfg1_grp.append(rs)
1292

    
1293
        rs = RadioSetting("bcl_a", "Busy Channel Lock-out A",
1294
                          RadioSettingValueBoolean(_settings.bcl_a))
1295
        cfg1_grp.append(rs)
1296

    
1297
        rs = RadioSetting("bcl_b", "Busy Channel Lock-out B",
1298
                          RadioSettingValueBoolean(_settings.bcl_b))
1299
        cfg1_grp.append(rs)
1300

    
1301
        rs = RadioSetting("sc_rev", "Scan Mode",
1302
                          RadioSettingValueMap(SC_REV_MAP, _settings.sc_rev))
1303
        cfg1_grp.append(rs)
1304
        rs = RadioSetting("tot", "Timeout Timer (TOT)",
1305
                          RadioSettingValueMap(
1306
                              TOT_MAP, _settings.tot))
1307
        cfg1_grp.append(rs)
1308

    
1309
        rs = RadioSetting("toa", "Timeout Alarm (TOA)",
1310
                          RadioSettingValueMap(
1311
                              TOA_MAP, _settings.toa))
1312
        cfg1_grp.append(rs)
1313

    
1314
        rs = RadioSetting("ani_sw", "Caller ID Tx - ANI-SW",
1315
                          RadioSettingValueBoolean(_settings.ani_sw))
1316
        cfg1_grp.append(rs)
1317

    
1318
        rs = RadioSetting("ring", "Ring Time (Sec)",
1319
                          RadioSettingValueMap(RING_MAP, _settings.ring))
1320
        cfg1_grp.append(rs)
1321

    
1322

    
1323
        rs = RadioSetting("dtmfsf", "DTMF Sidetone",
1324
                          RadioSettingValueList(
1325
                              DTMF_ST_LIST,
1326
                              DTMF_ST_LIST[_settings.dtmfsf]))
1327
        cfg1_grp.append(rs)
1328

    
1329

    
1330
        rs = RadioSetting("ptt_id", "Caller ID Tx Mode (PTT_ID)",
1331
                          RadioSettingValueMap(PTT_ID_MAP, _settings.ptt_id))
1332
        cfg1_grp.append(rs)
1333

    
1334

    
1335
        rs = RadioSetting("wt_led", "Standby / WT LED",
1336
                          RadioSettingValueList(
1337
                              BACKLIGHT_LIST,
1338
                              BACKLIGHT_LIST[_settings.wt_led]))
1339
        cfg1_grp.append(rs)
1340

    
1341
        rs = RadioSetting("tx_led", "TX LED",
1342
                          RadioSettingValueList(
1343
                              BACKLIGHT_LIST,
1344
                              BACKLIGHT_LIST[_settings.tx_led]))
1345
        cfg1_grp.append(rs)
1346

    
1347
        rs = RadioSetting("rx_led", "Rx LED",
1348
                          RadioSettingValueList(
1349
                              BACKLIGHT_LIST,
1350
                              BACKLIGHT_LIST[_settings.rx_led]))
1351
        cfg1_grp.append(rs)
1352

    
1353
        rs = RadioSetting("prich_sw", "Priority Channel Scan",
1354
                          RadioSettingValueBoolean(_settings.prich_sw))
1355
        cfg1_grp.append(rs)
1356

    
1357
        rs = RadioSetting("spk_cont", "Speaker Control",
1358
                          RadioSettingValueMap(
1359
                              SPEAKER_MAP,
1360
                              _settings.spk_cont))
1361
        cfg1_grp.append(rs)
1362

    
1363
        rs = RadioSetting("autolock", "Autolock",
1364
                          RadioSettingValueBoolean(_settings.autolock))
1365
        cfg1_grp.append(rs)
1366

    
1367
        rs = RadioSetting("low_v", "Low Voltage Shutoff",
1368
                          RadioSettingValueBoolean(_settings.low_v))
1369
        cfg1_grp.append(rs)
1370

    
1371
        rs = RadioSetting("fan", "Fan Mode",
1372
                          RadioSettingValueList(
1373
                              FAN_MODE_LIST,
1374
                              FAN_MODE_LIST[_settings.fan]))
1375
        cfg1_grp.append(rs)
1376

    
1377
        rs = RadioSetting("apo_time", "Auto Power-Off (Min)",
1378
                          RadioSettingValueList(
1379
                              APO_TIME_LIST,
1380
                              APO_TIME_LIST[_settings.apo_time]))
1381
        cfg1_grp.append(rs)
1382

    
1383
        rs = RadioSetting("alert", "Alert Pulse (Hz)",
1384
                          RadioSettingValueMap(ALERT_MAP, _settings.alert))
1385
        cfg1_grp.append(rs)
1386
        rs = RadioSetting("m_pwr", "Medium Power Level (W)",
1387
                          RadioSettingValueMap(M_POWER_MAP,
1388
                                               _settings.m_pwr))
1389
        cfg1_grp.append(rs)
1390

    
1391
        rs = RadioSetting("rpt_set_model", "Model (RPT-SET)",
1392
                          RadioSettingValueList(
1393
                              RPT_MODE_LIST,
1394
                              RPT_MODE_LIST[_settings.rpt_set_model]))
1395
        cfg2_grp.append(rs)
1396

    
1397
        rs = RadioSetting("rpt_spk", "Repeater Speaker Switch (RPT-SPK)",
1398
                          RadioSettingValueBoolean(_settings.rpt_spk))
1399
        cfg2_grp.append(rs)
1400

    
1401
        rs = RadioSetting("rpt_ptt", "Repeater PTT (RPT-PTT)",
1402
                          RadioSettingValueBoolean(_settings.rpt_ptt))
1403
        cfg2_grp.append(rs)
1404

    
1405
        rs = RadioSetting("dtmf_time", "DTMF Tx Duration (ms)",
1406
                          RadioSettingValueList(
1407
                              DTMF_TIMES,
1408
                              DTMF_TIMES[_settings.dtmf_time]))
1409
        cfg2_grp.append(rs)
1410
        rs = RadioSetting("dtmf_int", "DTMF Interval (ms)",
1411
                          RadioSettingValueList(
1412
                              DTMF_INTERVALS,
1413
                              DTMF_INTERVALS[_settings.dtmf_int]))
1414
        cfg2_grp.append(rs)
1415

    
1416
        rs = RadioSetting("sc_qt", "CTCSS/DCS Scan",
1417
                          RadioSettingValueMap(
1418
                              SC_QT_MAP,_settings.sc_qt))
1419
        cfg2_grp.append(rs)
1420

    
1421
        rs = RadioSetting("pri_ch", "Priority Channel",
1422
                          RadioSettingValueInteger(
1423
                              1, 999, _chnum_decode(_settings.pri_ch)))
1424
        cfg2_grp.append(rs)
1425

    
1426
        rs = RadioSetting("ptt_id_dly", "Caller ID Tx Delay PTT-ID-DLY (ms)",
1427
                          RadioSettingValueMap(PTT_ID_DELAY_MAP,
1428
                                               _settings.ptt_id_dly))
1429
        cfg2_grp.append(rs)
1430

    
1431
        rs = RadioSetting("rc_sw", "Remote Control RC-SW",
1432
                          RadioSettingValueBoolean(_settings.rc_sw))
1433
        cfg2_grp.append(rs)
1434

    
1435
        rs = RadioSetting("scan_det", "Scan DET",
1436
                          RadioSettingValueBoolean(_settings.scan_det))
1437
        cfg2_grp.append(rs)
1438

    
1439
        rs = RadioSetting("menu", "Menu Available",
1440
                          RadioSettingValueBoolean(_settings.menu))
1441
        cfg2_grp.append(rs)
1442

    
1443
        rs = RadioSetting("thr_vol_tx", "Threshold Voltage Tx",
1444
                          RadioSettingValueBoolean(_settings.thr_vol_tx))
1445
        cfg2_grp.append(rs)
1446

    
1447
        rs = RadioSetting("hold_time_rpt", "Hold Time of Repeat (ms)",
1448
                          RadioSettingValueList(
1449
                              HOLD_TIMES,
1450
                              HOLD_TIMES[_settings.hold_time_rpt]))
1451
        cfg2_grp.append(rs)
1452

    
1453
        rs = RadioSetting("auto_am", "Auto AM",
1454
                          RadioSettingValueBoolean(_settings.auto_am))
1455
        cfg2_grp.append(rs)
1456

    
1457
        rs = RadioSetting("rpt_tone", "Repeat Tone",
1458
                          RadioSettingValueBoolean(_settings.rpt_tone))
1459
        cfg2_grp.append(rs)
1460

    
1461
        rs = RadioSetting("pf1_set", "PF1 setting",
1462
                          RadioSettingValueList(
1463
                              PF1_SETTINGS,
1464
                              PF1_SETTINGS[_settings.pf1_set]))
1465
        cfg2_grp.append(rs)
1466

    
1467
        rs = RadioSetting("settings.thr_vol_lvl", "Threshold Voltage Level",
1468
                          RadioSettingValueFloat(
1469
                              9.5, 10.5, _settings.thr_vol_lvl / 100.0 , 0.1, 1))
1470
        cfg2_grp.append(rs)
1471

    
1472

    
1473
# Freq Limits settings
1474
        
1475
        # Conver Integer back to correct limit HEX value:  limit = hex(int(str(limit*10),16))        
1476
        # # LOG.debug("limit =" % limit)
1477

    
1478
        _temp =str(hex(int("%i" % self._memobj.bandlimits.limit_144M_ChA_rx_start, 10)))
1479
        _temp = int(int(_temp[2:])/10.0)
1480
        val= RadioSettingValueInteger(0,999, _temp)
1481
        rs = RadioSetting("bandlimits.limit_144M_ChA_rx_start", "144M ChA Rx Lower Limit (MHz)",
1482
                          val)
1483
        rxlim_grp.append(rs)
1484

    
1485
        _temp =str(hex(int("%i" % self._memobj.bandlimits.limit_144M_ChA_rx_stop, 10)))
1486
        _temp = int(int(_temp[2:])/10.0)
1487
        val= RadioSettingValueInteger(0,999, _temp)
1488
        rs = RadioSetting("bandlimits.limit_144M_ChA_rx_stop", "144M ChA Rx Upper Limit (MHz)",
1489
                          RadioSettingValueInteger(0,999,
1490
                              val))
1491
        rxlim_grp.append(rs)
1492

    
1493
        _temp =str(hex(int("%i" % self._memobj.bandlimits.limit_144M_ChB_rx_start, 10)))
1494
        _temp = int(int(_temp[2:])/10.0)
1495
        val= RadioSettingValueInteger(0,999, _temp)
1496
        rs = RadioSetting("bandlimits.limit_144M_ChB_rx_start", "144M ChB Rx Lower Limit (MHz)",
1497
                          val)
1498
        rxlim_grp.append(rs)
1499

    
1500
        _temp =str(hex(int("%i" % self._memobj.bandlimits.limit_144M_ChB_rx_stop, 10)))
1501
        _temp = int(int(_temp[2:])/10.0)
1502
        val= RadioSettingValueInteger(0,999, _temp)
1503
        rs = RadioSetting("bandlimits.limit_144M_ChB_rx_stop", "144M ChB Rx Upper Limit (MHz)",
1504
                          RadioSettingValueInteger(0,999,
1505
                              val))
1506
        rxlim_grp.append(rs)
1507

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

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

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

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

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

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

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

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

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

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

    
1588

    
1589
        _temp =str(hex(int("%i" % self._memobj.bandlimits.limit_144M_ChA_tx_start, 10)))
1590
        _temp = int(int(_temp[2:])/10.0)
1591
        val= RadioSettingValueInteger(0,999, _temp)
1592
        rs = RadioSetting("bandlimits.limit_144M_ChA_tx_start", "144M ChA Tx Lower Limit (MHz)",
1593
                          RadioSettingValueInteger(0,999,
1594
                              val))
1595
        txlim_grp.append(rs)
1596

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

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

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

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

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

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

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

    
1653
# VFO Settings
1654
        rs = RadioSetting("vfomode_a", "VFO A Working Mode",
1655
                          RadioSettingValueMap(WORKMODE_MAP,
1656
                                               _settings.vfomode_a))
1657
        vfoa_grp.append(rs)
1658

    
1659
        rs = RadioSetting("vfoband_a", "VFO A Current Band",
1660
                          RadioSettingValueMap(VFOBAND_MAP,
1661
                                               _settings.vfoband_a))
1662
        vfoa_grp.append(rs)
1663

    
1664
        rs = RadioSetting("vfochan_a", "VFO A Channel",
1665
                          RadioSettingValueInteger(1, 999,
1666
                              _chnum_decode(_settings.vfochan_a)))
1667
        vfoa_grp.append(rs)
1668

    
1669
        rs = RadioSetting("vfosquelch_a", "VFO A Squelch",
1670
                          RadioSettingValueInteger(0, 9,
1671
                              _settings.vfosquelch_a))
1672
        vfoa_grp.append(rs)
1673
        rs = RadioSetting("vfostep_a", "VFO A Step",
1674
                          RadioSettingValueList(
1675
                            STEP_LIST,
1676
                            STEP_LIST[_settings.vfostep_a]))
1677
        vfoa_grp.append(rs)
1678
######################
1679

    
1680
        rs = RadioSetting("vfofreq1", "VFO 150M Freq",
1681
                          RadioSettingValueFloat(
1682
                             0, 999.999999, (_freq_decode
1683
                             (_settings.vfofreq1)/1000000.0) ,0.000001, 6))
1684
        vfo150_grp.append(rs)
1685

    
1686
        rs = RadioSetting("vfoofst1", "VFO 150M Offset",
1687
                          RadioSettingValueFloat(
1688
                              0, 999.999999, (_freq_decode
1689
                              (_settings.vfoofst1)/1000000.0),0.000001, 6))
1690
        vfo150_grp.append(rs)
1691

    
1692
        rs = RadioSetting("rxtone1", "VFO 150M Rx tone",
1693
                          RadioSettingValueMap(
1694
                            TONE_MAP, _settings.rxtone1))
1695
        vfo150_grp.append(rs)
1696

    
1697
        rs = RadioSetting("txtone1", "VFO 150M Tx tone",
1698
                          RadioSettingValueMap(
1699
                            TONE_MAP, _settings.txtone1))
1700
        vfo150_grp.append(rs)
1701

    
1702
        rs = RadioSetting("power1", "VFO 150M Power",
1703
                          RadioSettingValueMap(
1704
                            POWER_MAP, _settings.power1))
1705
        vfo150_grp.append(rs)
1706

    
1707
        rs = RadioSetting("narrow1", "VFO 150M Bandwidth",
1708
                          RadioSettingValueMap(
1709
                            BANDWIDTH_MAP, _settings.narrow1))
1710
        vfo150_grp.append(rs)
1711

    
1712
        rs = RadioSetting("mute1", "VFO 150M Mute Mode",
1713
                          RadioSettingValueMap(
1714
                            MUTE_MODE_MAP, _settings.mute1))
1715
        vfo150_grp.append(rs)
1716

    
1717
        rs = RadioSetting("shft_dir1", "VFO 150M Shift Direction",
1718
                          RadioSettingValueList(
1719
                            DUPLEX_LIST,
1720
                            DUPLEX_LIST[_settings.shft_dir1]))
1721
        vfo150_grp.append(rs)
1722

    
1723
        rs = RadioSetting("compander1", "VFO 150M Compander",
1724
                          RadioSettingValueBoolean(
1725
                            _settings.compander1))
1726
        vfo150_grp.append(rs)
1727

    
1728
        rs = RadioSetting("scrambler1", "VFO 150M Scrambler",
1729
                          RadioSettingValueList(
1730
                            SCRAMBLER_LIST,
1731
                            SCRAMBLER_LIST[_settings.scrambler1]))
1732
        vfo150_grp.append(rs)
1733
        rs = RadioSetting("am_mode1", "VFO 150M AM Mode",
1734
                          RadioSettingValueBoolean(
1735
                            _settings.am_mode1))
1736
        vfo150_grp.append(rs)
1737
############################
1738

    
1739
        rs = RadioSetting("vfofreq2", "VFO 450M Freq",
1740
                          RadioSettingValueFloat(
1741
                             0, 999.999999, (_freq_decode
1742
                             (_settings.vfofreq2)/1000000.0) ,0.000001, 6))
1743
        vfo450_grp.append(rs)
1744

    
1745
        rs = RadioSetting("vfoofst2", "VFO 450M Offset",
1746
                          RadioSettingValueFloat(
1747
                              0, 999.999999, (_freq_decode
1748
                              (_settings.vfoofst2)/1000000.0),0.000001, 6))
1749
        vfo450_grp.append(rs)
1750

    
1751
        rs = RadioSetting("rxtone2", "VFO 450M Rx tone",
1752
                          RadioSettingValueMap(
1753
                            TONE_MAP, _settings.rxtone2))
1754
        vfo450_grp.append(rs)
1755

    
1756
        rs = RadioSetting("txtone2", "VFO 450M Tx tone",
1757
                          RadioSettingValueMap(
1758
                            TONE_MAP, _settings.txtone2))
1759
        vfo450_grp.append(rs)
1760
        
1761
        rs = RadioSetting("power2", "VFO 450M Power",
1762
                          RadioSettingValueMap(
1763
                            POWER_MAP, _settings.power2))
1764
        vfo450_grp.append(rs)
1765

    
1766
        rs = RadioSetting("narrow2", "VFO 450M Bandwidth",
1767
                          RadioSettingValueMap(
1768
                            BANDWIDTH_MAP, _settings.narrow2))
1769
        vfo450_grp.append(rs)
1770

    
1771
        rs = RadioSetting("mute2", "VFO 450M Mute Mode",
1772
                          RadioSettingValueMap(
1773
                            MUTE_MODE_MAP, _settings.mute2))
1774
        vfo450_grp.append(rs)
1775

    
1776
        rs = RadioSetting("shft_dir2", "VFO 450M Shift Direction",
1777
                          RadioSettingValueList(
1778
                            DUPLEX_LIST,
1779
                            DUPLEX_LIST[_settings.shft_dir2]))
1780
        vfo450_grp.append(rs)
1781

    
1782
        rs = RadioSetting("compander2", "VFO 450M Compander",
1783
                          RadioSettingValueBoolean(
1784
                            _settings.compander2))
1785
        vfo450_grp.append(rs)
1786

    
1787
        rs = RadioSetting("scrambler2", "VFO 450M Scrambler",
1788
                          RadioSettingValueList(
1789
                            SCRAMBLER_LIST,
1790
                            SCRAMBLER_LIST[_settings.scrambler2]))
1791
        vfo450_grp.append(rs)
1792

    
1793
        rs = RadioSetting("am_mode2", "VFO 450M AM Mode",
1794
                          RadioSettingValueBoolean(
1795
                            _settings.am_mode2))
1796
        vfo450_grp.append(rs)
1797
############################
1798
        rs = RadioSetting("vfofreq3", "VFO 20M Freq",
1799
                          RadioSettingValueFloat(
1800
                             0, 999.999999, (_freq_decode
1801
                             (_settings.vfofreq3)/1000000.0) ,0.000001, 6))
1802
        vfo20_grp.append(rs)
1803

    
1804
        rs = RadioSetting("vfoofst3", "VFO 20M Offset",
1805
                          RadioSettingValueFloat(
1806
                              0, 999.999999, (_freq_decode
1807
                              (_settings.vfoofst3)/1000000.0),0.000001, 6))
1808
        vfo20_grp.append(rs)
1809

    
1810
        rs = RadioSetting("rxtone3", "VFO 20M Rx tone",
1811
                          RadioSettingValueMap(
1812
                            TONE_MAP, _settings.rxtone3))
1813
        vfo20_grp.append(rs)
1814

    
1815
        rs = RadioSetting("txtone3", "VFO 20M Tx tone",
1816
                          RadioSettingValueMap(
1817
                            TONE_MAP, _settings.txtone3))
1818
        vfo20_grp.append(rs)
1819
        
1820
        rs = RadioSetting("power3", "VFO 20M Power",
1821
                          RadioSettingValueMap(
1822
                            POWER_MAP, _settings.power3))
1823
        vfo20_grp.append(rs)
1824

    
1825
        rs = RadioSetting("narrow3", "VFO 20M Bandwidth",
1826
                          RadioSettingValueMap(
1827
                            BANDWIDTH_MAP, _settings.narrow3))
1828
        vfo20_grp.append(rs)
1829

    
1830
        rs = RadioSetting("mute3", "VFO 20M Mute Mode",
1831
                          RadioSettingValueMap(
1832
                            MUTE_MODE_MAP, _settings.mute3))
1833
        vfo20_grp.append(rs)
1834

    
1835
        rs = RadioSetting("shft_dir3", "VFO 20M Shift Direction",
1836
                          RadioSettingValueList(
1837
                            DUPLEX_LIST,
1838
                            DUPLEX_LIST[_settings.shft_dir3]))
1839
        vfo20_grp.append(rs)
1840

    
1841
        rs = RadioSetting("compander3", "VFO 20M Compander",
1842
                          RadioSettingValueBoolean(
1843
                            _settings.compander3))
1844
        vfo20_grp.append(rs)
1845

    
1846
        rs = RadioSetting("scrambler3", "VFO 20M Scrambler",
1847
                          RadioSettingValueList(
1848
                            SCRAMBLER_LIST,
1849
                            SCRAMBLER_LIST[_settings.scrambler3]))
1850
        vfo20_grp.append(rs)
1851

    
1852
        rs = RadioSetting("am_mode3", "VFO 20M AM Mode",
1853
                          RadioSettingValueBoolean(
1854
                            _settings.am_mode3))
1855
        vfo20_grp.append(rs)
1856
############################
1857
        rs = RadioSetting("vfofreq4", "VFO 50M Freq",
1858
                          RadioSettingValueFloat(
1859
                             0, 999.999999, (_freq_decode
1860
                             (_settings.vfofreq4)/1000000.0) ,0.000001, 6))
1861
        vfo50_grp.append(rs)
1862

    
1863
        rs = RadioSetting("vfoofst4", "VFO 50M Offset",
1864
                          RadioSettingValueFloat(
1865
                              0, 999.999999, (_freq_decode
1866
                              (_settings.vfoofst4)/1000000.0),0.000001, 6))
1867
        vfo50_grp.append(rs)
1868

    
1869
        rs = RadioSetting("rxtone4", "VFO 50M Rx tone",
1870
                          RadioSettingValueMap(
1871
                            TONE_MAP, _settings.rxtone4))
1872
        vfo50_grp.append(rs)
1873

    
1874
        rs = RadioSetting("txtone4", "VFO 50M Tx tone",
1875
                          RadioSettingValueMap(
1876
                            TONE_MAP, _settings.txtone4))
1877
        vfo50_grp.append(rs)
1878
        
1879
        rs = RadioSetting("power4", "VFO 50M Power",
1880
                          RadioSettingValueMap(
1881
                            POWER_MAP, _settings.power4))
1882
        vfo50_grp.append(rs)
1883

    
1884
        rs = RadioSetting("narrow4", "VFO 50M Bandwidth",
1885
                          RadioSettingValueMap(
1886
                            BANDWIDTH_MAP, _settings.narrow4))
1887
        vfo50_grp.append(rs)
1888

    
1889
        rs = RadioSetting("mute4", "VFO 50M Mute Mode",
1890
                          RadioSettingValueMap(
1891
                            MUTE_MODE_MAP, _settings.mute4))
1892
        vfo50_grp.append(rs)
1893

    
1894
        rs = RadioSetting("shft_dir4", "VFO 50M Shift Direction",
1895
                          RadioSettingValueList(
1896
                            DUPLEX_LIST,
1897
                            DUPLEX_LIST[_settings.shft_dir4]))
1898
        vfo50_grp.append(rs)
1899

    
1900
        rs = RadioSetting("compander4", "VFO 50M Compander",
1901
                          RadioSettingValueBoolean(
1902
                            _settings.compander4))
1903
        vfo50_grp.append(rs)
1904

    
1905
        rs = RadioSetting("scrambler4", "VFO 50M Scrambler",
1906
                          RadioSettingValueList(
1907
                            SCRAMBLER_LIST,
1908
                            SCRAMBLER_LIST[_settings.scrambler4]))
1909
        vfo50_grp.append(rs)
1910

    
1911
        rs = RadioSetting("am_mode4", "VFO 50M AM Mode",
1912
                          RadioSettingValueBoolean(
1913
                            _settings.am_mode4))
1914
        vfo50_grp.append(rs)
1915
############################
1916
        rs = RadioSetting("vfofreq5", "VFO 350M Freq",
1917
                          RadioSettingValueFloat(
1918
                             0, 999.999999, (_freq_decode
1919
                             (_settings.vfofreq5)/1000000.0) ,0.000001, 6))
1920
        vfo350_grp.append(rs)
1921

    
1922
        rs = RadioSetting("vfoofst5", "VFO 350M Offset",
1923
                          RadioSettingValueFloat(
1924
                              0, 999.999999, (_freq_decode
1925
                              (_settings.vfoofst5)/1000000.0),0.000001, 6))
1926
        vfo350_grp.append(rs)
1927

    
1928
        rs = RadioSetting("rxtone5", "VFO 350M Rx tone",
1929
                          RadioSettingValueMap(
1930
                            TONE_MAP, _settings.rxtone5))
1931
        vfo350_grp.append(rs)
1932

    
1933
        rs = RadioSetting("txtone5", "VFO 350M Tx tone",
1934
                          RadioSettingValueMap(
1935
                            TONE_MAP, _settings.txtone5))
1936
        vfo350_grp.append(rs)
1937
        
1938
        rs = RadioSetting("power5", "VFO 350M Power",
1939
                          RadioSettingValueMap(
1940
                            POWER_MAP, _settings.power5))
1941
        vfo350_grp.append(rs)
1942

    
1943
        rs = RadioSetting("narrow5", "VFO 350M Bandwidth",
1944
                          RadioSettingValueMap(
1945
                            BANDWIDTH_MAP, _settings.narrow5))
1946
        vfo350_grp.append(rs)
1947

    
1948
        rs = RadioSetting("mute5", "VFO 350M Mute Mode",
1949
                          RadioSettingValueMap(
1950
                            MUTE_MODE_MAP, _settings.mute5))
1951
        vfo350_grp.append(rs)
1952

    
1953
        rs = RadioSetting("shft_dir5", "VFO 350M Shift Direction",
1954
                          RadioSettingValueList(
1955
                            DUPLEX_LIST,
1956
                            DUPLEX_LIST[_settings.shft_dir5]))
1957
        vfo350_grp.append(rs)
1958

    
1959
        rs = RadioSetting("compander5", "VFO 350M Compander",
1960
                          RadioSettingValueBoolean(
1961
                            _settings.compander5))
1962
        vfo350_grp.append(rs)
1963

    
1964
        rs = RadioSetting("scrambler5", "VFO 350M Scrambler",
1965
                          RadioSettingValueList(
1966
                            SCRAMBLER_LIST,
1967
                            SCRAMBLER_LIST[_settings.scrambler5]))
1968
        vfo350_grp.append(rs)
1969

    
1970
        rs = RadioSetting("am_mode5", "VFO 350M AM Mode",
1971
                          RadioSettingValueBoolean(
1972
                            _settings.am_mode5))
1973
        vfo350_grp.append(rs)
1974

    
1975
# ############################
1976
        rs = RadioSetting("vfofreq6", "VFO 850M Freq",
1977
                          RadioSettingValueFloat(
1978
                             0, 999.999999, (_freq_decode
1979
                             (_settings.vfofreq6)/1000000.0) ,0.000001, 6))
1980
        vfo850_grp.append(rs)
1981

    
1982
        rs = RadioSetting("vfoofst6", "VFO 850M Offset",
1983
                          RadioSettingValueFloat(
1984
                              0, 999.999999, (_freq_decode
1985
                              (_settings.vfoofst6)/1000000.0),0.000001, 6))
1986
        vfo850_grp.append(rs)
1987

    
1988
        rs = RadioSetting("rxtone6", "VFO 850M Rx tone",
1989
                          RadioSettingValueMap(
1990
                            TONE_MAP, _settings.rxtone6))
1991
        vfo850_grp.append(rs)
1992

    
1993
        rs = RadioSetting("txtone6", "VFO 850M Tx tone",
1994
                          RadioSettingValueMap(
1995
                            TONE_MAP, _settings.txtone6))
1996
        vfo850_grp.append(rs)
1997
        
1998
        rs = RadioSetting("power6", "VFO 850M Power",
1999
                          RadioSettingValueMap(
2000
                            POWER_MAP, _settings.power6))
2001
        vfo850_grp.append(rs)
2002

    
2003
        rs = RadioSetting("narrow6", "VFO 850M Bandwidth",
2004
                          RadioSettingValueMap(
2005
                            BANDWIDTH_MAP, _settings.narrow6))
2006
        vfo850_grp.append(rs)
2007

    
2008
        rs = RadioSetting("mute6", "VFO 850M Mute Mode",
2009
                          RadioSettingValueMap(
2010
                            MUTE_MODE_MAP, _settings.mute6))
2011
        vfo850_grp.append(rs)
2012

    
2013
        rs = RadioSetting("shft_dir6", "VFO 850M Shift Direction",
2014
                          RadioSettingValueList(
2015
                            DUPLEX_LIST,
2016
                            DUPLEX_LIST[_settings.shft_dir6]))
2017
        vfo850_grp.append(rs)
2018

    
2019
        rs = RadioSetting("compander6", "VFO 850M Compander",
2020
                          RadioSettingValueBoolean(
2021
                            _settings.compander6))
2022
        vfo850_grp.append(rs)
2023

    
2024
        rs = RadioSetting("scrambler6", "VFO 850M Scrambler",
2025
                          RadioSettingValueList(
2026
                            SCRAMBLER_LIST,
2027
                            SCRAMBLER_LIST[_settings.scrambler6]))
2028
        vfo850_grp.append(rs)
2029

    
2030
        rs = RadioSetting("am_mode6", "VFO 850M AM Mode",
2031
                          RadioSettingValueBoolean(
2032
                            _settings.am_mode6))
2033
        vfo850_grp.append(rs)
2034

    
2035
############################
2036

    
2037
        rs = RadioSetting("vfomode_b", "VFO B Working Mode",
2038
                          RadioSettingValueMap(WORKMODE_MAP,
2039
                                               _settings.vfomode_b))
2040
        vfob_grp.append(rs)
2041

    
2042
        rs = RadioSetting("vfochan_b", "VFO B Work Channel",
2043
                          RadioSettingValueInteger(1, 999,
2044
                              _chnum_decode(_settings.vfochan_b)))
2045
        vfob_grp.append(rs)
2046

    
2047
        rs = RadioSetting("vfofreq7", "VFO B Freq",
2048
                          RadioSettingValueFloat(
2049
                             0, 999.999999, (_freq_decode
2050
                             (_settings.vfofreq7)/1000000.0) ,0.000001, 6))
2051
        vfob_grp.append(rs)
2052

    
2053
        rs = RadioSetting("vfoofst7", "VFO B Offset",
2054
                          RadioSettingValueFloat(
2055
                              0, 999.999999, (_freq_decode
2056
                              (_settings.vfoofst7)/1000000.0),0.000001, 6))
2057
        vfob_grp.append(rs)
2058

    
2059
        rs = RadioSetting("rxtone7", "VFOB Rx tone",
2060
                          RadioSettingValueMap(
2061
                            TONE_MAP, _settings.rxtone7))
2062
        vfob_grp.append(rs)
2063

    
2064
        rs = RadioSetting("txtone7", "VFOB Tx tone",
2065
                          RadioSettingValueMap(
2066
                            TONE_MAP, _settings.txtone7))
2067
        vfob_grp.append(rs)
2068
        rs = RadioSetting("power7", "VFOB Power",
2069
                          RadioSettingValueMap(
2070
                            POWER_MAP, _settings.power7))
2071
        vfob_grp.append(rs)
2072
        rs = RadioSetting("narrow7", "VFOB Bandwidth",
2073
                          RadioSettingValueMap(
2074
                            BANDWIDTH_MAP, _settings.narrow7))
2075
        vfob_grp.append(rs)
2076
        rs = RadioSetting("mute7", "VFOB Mute Mode",
2077
                          RadioSettingValueMap(
2078
                            MUTE_MODE_MAP, _settings.mute7))
2079
        vfob_grp.append(rs)
2080
        rs = RadioSetting("shft_dir7", "VFOB Shift Direction",
2081
                          RadioSettingValueList(
2082
                            DUPLEX_LIST,
2083
                            DUPLEX_LIST[_settings.shft_dir7]))
2084
        vfob_grp.append(rs)
2085
        rs = RadioSetting("compander7", "VFOB Compander",
2086
                          RadioSettingValueBoolean(
2087
                            _settings.compander7))
2088
        vfob_grp.append(rs)
2089

    
2090
        rs = RadioSetting("scrambler7", "VFOB Scrambler",
2091
                          RadioSettingValueList(
2092
                            SCRAMBLER_LIST,
2093
                            SCRAMBLER_LIST[_settings.scrambler7]))
2094
        vfob_grp.append(rs)
2095

    
2096
        rs = RadioSetting("vfosquelch_b", "VFO B Squelch",
2097
                          RadioSettingValueInteger(0, 9,
2098
                              _settings.vfosquelch_b))
2099
        vfob_grp.append(rs)
2100
        rs = RadioSetting("vfostep_b", "VFO B Step",
2101
                          RadioSettingValueList(
2102
                            STEP_LIST,
2103
                            STEP_LIST[_settings.vfostep_b]))
2104
        vfob_grp.append(rs)
2105
        # rs = RadioSetting("am_mode7", "VFOB AM Mode",
2106
        #                   RadioSettingValueBoolean(
2107
        #                     _settings.am_mode7))
2108
        # vfob_grp.append(rs)
2109

    
2110
## Scan Group Settings
2111
        def _decode(lst):
2112
            _str = ''.join([chr(c) for c in lst
2113
                            if chr(c) in chirp_common.CHARSET_ASCII])
2114
            return _str
2115

    
2116
        rs = RadioSetting("scan_a_act", "Scan A Active Group",
2117
                        RadioSettingValueList(
2118
                            SCAN_GROUP_LIST,
2119
                            SCAN_GROUP_LIST[_settings.scan_a_act]))
2120
        scan_grp.append(rs)
2121
        rs = RadioSetting("scan_b_act", "Scan B Active Group",
2122
                        RadioSettingValueList(
2123
                             SCAN_GROUP_LIST,
2124
                             SCAN_GROUP_LIST[_settings.scan_b_act]))
2125
        scan_grp.append(rs)
2126
       
2127

    
2128
        for i in range(1,11):
2129
            x=str(i)
2130
            _str = _decode(eval("_settings.scanname"+x))
2131
            val = RadioSettingValueString(0, 6, _str)
2132
            val.set_mutable(True)
2133
            rs = RadioSetting("scanname"+x, "Scan Name "+x, val)
2134
            scanname_grp.append(rs)
2135

    
2136
            scngrp = str(i)
2137
            rs = RadioSetting("scanlower"+scngrp, "Scan Lower "+scngrp,
2138
                            RadioSettingValueInteger(1, 999,  
2139
                            eval("_settings.scanlower"+scngrp)))
2140
            scan_grp.append(rs)
2141
            rs = RadioSetting("scanupper"+scngrp, "Scan Uower "+scngrp,
2142
                            RadioSettingValueInteger(1, 999,  
2143
                            eval("_settings.scanupper"+scngrp)))
2144
            scan_grp.append(rs)
2145

    
2146

    
2147

    
2148

    
2149

    
2150
# FM RADIO PRESETS
2151

    
2152
# memory stores raw integer value like 7600
2153
# radio will divide 7600 by 100 and interpret correctly at 76.0Mhz
2154
        #
2155
        # FM Radio Presets Settings
2156
        #
2157
        for i in range(1, 21):
2158
            chan = str(i)
2159
            rs = RadioSetting("FM_radio" + chan, "FM Preset " + chan,
2160
                              RadioSettingValueFloat(76.0, 108.0,
2161
                                                     eval("_settings.FM_radio" +
2162
                                                          chan)/100.0,
2163
                                                     0.1, 1))
2164
            fmradio_grp.append(rs)
2165
        
2166
        return group
2167

    
2168
    def get_settings(self):
2169
        try:
2170
            return self._get_settings()
2171
        except:
2172
            import traceback
2173
            LOG.error("Failed to parse settings: %s", traceback.format_exc())
2174
            return None
2175

    
2176
    def set_settings(self, settings):
2177
        for element in settings:
2178
            if not isinstance(element, RadioSetting):
2179
                self.set_settings(element)
2180
                continue
2181
            else:
2182
                try:
2183
                    if "." in element.get_name():
2184
                        bits = element.get_name().split(".")
2185
                        obj = self._memobj
2186
                        for bit in bits[:-1]:
2187
                            obj = getattr(obj, bit)
2188
                        setting = bits[-1]
2189
                    else:
2190
                        obj = self._memobj.settings
2191
                        setting = element.get_name()
2192

    
2193
                    if element.has_apply_callback():
2194
                        LOG.debug("Using apply callback")
2195
                        element.run_apply_callback()
2196
                    else:
2197
                        LOG.debug("Setting %s = %s" % (setting, element.value))
2198
                        if self._is_freq(element):
2199
                            # setattr(obj, setting, int(element.value / 10))
2200
                            # MRT rescale freq values to match radio
2201
                            # expected values
2202
                            value = _freq_encode(element[0].get_value()*1000000.0)
2203
                            setattr(obj, setting, value)
2204

    
2205
                        elif self._is_fmradio_or_voltage(element):
2206
                            # MRT rescale FM Radio values to match radio
2207
                            # expected values
2208
                            setattr(obj, setting,
2209
                                    int(element.values()[0]._current * 100.0))
2210

    
2211
                        elif self._is_limit(element):
2212
                            setattr(obj, setting,
2213
                                    int(str(element.values()[0]._current * 10), 16))
2214
                # Special VFO A Settings
2215
                #
2216
                        elif self._is_chan(element):
2217
                            value = _chnum_encode(element[0].get_value())
2218
                            setattr(obj, setting, value)
2219
                            continue
2220
                #
2221
                        else:
2222
                            setattr(obj, setting, element.value)
2223
                except Exception, e:
2224
                    LOG.debug(element.get_name())
2225
                    raise
2226

    
2227
    def _is_freq(self, element):
2228
        return "rxfreq" in element.get_name() or \
2229
               "txoffset" in element.get_name() or \
2230
               "vfofreq" in element.get_name() or\
2231
               "vfoofst" in element.get_name() 
2232
        #  "rx_start" in element.get_name() or \
2233
        #  "rx_stop" in element.get_name() or \
2234
        #  "tx_start" in element.get_name() or \
2235
        #  "tx_stop" in element.get_name()
2236

    
2237
    def _is_limit(self, element):
2238
        return "limit" in element.get_name()
2239

    
2240
    def _is_fmradio_or_voltage(self, element):
2241
        return "FM_radio" in element.get_name() or\
2242
                "thr_vol_lvl" in element.get_name()
2243

    
2244
    
2245
    def _is_chan(self, element):
2246
        return "vfochan" in element.get_name() or\
2247
               "pri_ch" in element.get_name()
2248
    
2249
    # def _is_vfofreq(self, element):
2250
    #     return "vfofreq" in element.get_name() or\
2251
    #            "vfoofst" in element.get_name()
(2-2/8)