Project

General

Profile

Bug #857 » ft857.py

Filippi Marco, 05/09/2013 10:41 AM

 
1
#
2
# Copyright 2012 Filippi Marco <iz3gme.marco@gmail.com>
3
#
4
# This program is free software: you can redistribute it and/or modify
5
# it under the terms of the GNU General Public License as published by
6
# the Free Software Foundation, either version 3 of the License, or
7
# (at your option) any later version.
8
#
9
# This program is distributed in the hope that it will be useful,
10
# but WITHOUT ANY WARRANTY; without even the implied warranty of
11
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
# GNU General Public License for more details.
13
#
14
# You should have received a copy of the GNU General Public License
15
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
16

    
17
"""FT857 - FT857/US management module"""
18

    
19
from chirp import ft817, chirp_common, errors, directory
20
from chirp.settings import RadioSetting, RadioSettingGroup, \
21
    RadioSettingValueInteger, RadioSettingValueList, \
22
    RadioSettingValueBoolean, RadioSettingValueString
23
import os
24

    
25
@directory.register
26
class FT857Radio(ft817.FT817Radio):
27
    """Yaesu FT-857/897"""
28
    MODEL = "FT-857/897"
29
    _model = ""
30

    
31
    TMODES = {
32
        0x04 : "Tone",
33
        0x05 : "TSQL",
34
        # 0x08 : "DTCS Enc", not supported in UI yet
35
        0x0a : "DTCS",
36
        0xff : "Cross",
37
        0x00 : "",
38
    }
39
    TMODES_REV = dict(zip(TMODES.values(), TMODES.keys()))
40

    
41
    CROSS_MODES = {
42
        0x01 : "->Tone",
43
        0x02 : "->DTCS",
44
        # 0x04 : "Tone->", not supported in UI yet
45
        0x05 : "Tone->Tone",
46
        0x06 : "Tone->DTCS",
47
        0x08 : "DTCS->",
48
        0x09 : "DTCS->Tone",
49
        0x0a : "DTCS->DTCS",
50
    }
51
    CROSS_MODES_REV = dict(zip(CROSS_MODES.values(), CROSS_MODES.keys()))
52

    
53
    _memsize = 7341
54
    # block 9 (140 Bytes long) is to be repeted 40 times 
55
    # should be 42 times but this way I can use original 817 functions
56
    _block_lengths = [ 2, 82, 252, 196, 252, 196, 212, 55, 140, 140, 140,
57
                       38, 176]
58
    # warning ranges has to be in this exact order
59
    VALID_BANDS = [(100000, 33000000), (33000000, 56000000),
60
                   (76000000, 108000000), (108000000, 137000000),
61
                   (137000000, 164000000), (420000000, 470000000)]
62

    
63
    MEM_FORMAT = """
64
        struct mem_struct{
65
        u8   tag_on_off:1,
66
            tag_default:1,
67
            unknown1:3,
68
            mode:3;
69
        u8   duplex:2,
70
            is_duplex:1,
71
            is_cwdig_narrow:1,
72
            is_fm_narrow:1,
73
            freq_range:3;
74
        u8   skip:1,
75
            unknokwn1_1:1,
76
            ipo:1,
77
            att:1,
78
            unknown2:4;
79
        u8   ssb_step:2,
80
            am_step:3,
81
            fm_step:3;
82
        u8   unknown3:3,
83
            is_split_tone:1,
84
            tmode:4;
85
        u8   unknown4:2,
86
            tx_mode:3,
87
            tx_freq_range:3;
88
        u8   unknown5:1,
89
            unknown_toneflag:1,
90
            tone:6;
91
        u8   unknown6:1,
92
            unknown_rxtoneflag:1,
93
            rxtone:6;
94
        u8   unknown7:1,
95
            dcs:7;
96
        u8   unknown8:1,
97
            rxdcs:7;
98
        ul16 rit;
99
        u32 freq;
100
        u32 offset;
101
        u8   name[8];
102
        };
103
        
104
        #seekto 0x5;
105
        struct {
106
            u8  unknown1:4,
107
                cw_speed_unit:1,
108
                cw_key_rev:1,
109
                unknown2:2;
110
            u8  unknown3[2];
111
            u8  disp_mode:2,
112
                unknown4:2,
113
                disp_contrast:4;
114
            u8  unknown5:4,
115
                clar_dial_sel:2,
116
                beep_tone:2;
117
            u8  arts_beep:2,
118
                dial_step:1,
119
                arts_id:1,
120
                unknown6:1,
121
                pkt_rate:1,
122
                unknown7:2;
123
            u8  unknown8:2,
124
                lock_mode:2,
125
                unknown9:1,
126
                cw_pitch:3;
127
            u8  sql_rf_gain:1,
128
                ars_144:1,
129
                ars_430:1,
130
                cw_weight:5;
131
            u8  cw_delay;
132
            u8  cw_delay_hi:1
133
                cw_sidetone:7;
134
            u8  unknown10:2,
135
                cw_speed:6;
136
            u8  disable_amfm_dial:1,
137
                vox_gain:7;
138
            u8  cat_rate:2,
139
                emergency:1,
140
                vox_delay:5;
141
            u8  dig_mode:3,
142
                mem_group:1,
143
                unknown11:1,
144
                apo_time:3;
145
            u8  dcs_inv:2,
146
                unknown12:1,
147
                tot_time:5;
148
            u8  mic_scan:1,
149
                ssb_mic:7;
150
            u8  cw_paddle:1,
151
                am_mic:7;
152
            u8  unknown13:1,
153
                fm_mic:7;
154
            u8  unknown14:1,
155
                dig_mic:7;
156
            u8  extended_menu:1,
157
                pkt1200:7;
158
            u8  unknown15:1,
159
                pkt9600:7;
160
            ul16 dig_shift;
161
            ul16 dig_disp;
162
            u8  r_lsb_car;
163
            u8  r_usb_car;
164
            u8  t_lsb_car;
165
            u8  t_usb_car;
166
            u8  unknown16:1,
167
                menu_item:7;
168
            u8  unknown17[5];
169
            u8  unknown18:1,
170
                mtr_peak_hold:1,
171
                mic_sel:2,
172
                cat_lin_tun:2,
173
                unknown19:1,
174
                split_tone:1;
175
            u8  unknown20:1,
176
                beep_vol:7;
177
            u8  unknown21:1,
178
                dig_vox:7;
179
            u8  ext_menu:1,
180
                home_vfo:1,
181
                scan_mode:2,
182
                scan_resume:4;
183
            u8  cw_auto_mode:1,
184
                cw_training:2,
185
                cw_qsk:3,
186
                cw_bfo:2;
187
            u8  dsp_nr:4,
188
                dsp_bpf:2,
189
                dsp_mic_eq:2;
190
            u8  unknown22:3,
191
                dsp_lpf:5;
192
            u8  mtr_atx_sel:3,
193
                unknown23:1,
194
                dsp_hpf:4;
195
            u8  unknown24:2,
196
                disp_intensity:2,
197
                unknown25:1,
198
                disp_color:3;
199
            u8  unknown26:1,
200
                disp_color_vfo:1,
201
                disp_color_mtr:1,
202
                disp_color_mode:1,
203
                disp_color_memgrp:1,
204
                unknown27:1,
205
                disp_color_band:1,
206
                disp_color_arts:1;
207
            u8  unknown28:3,
208
                disp_color_fix:5;
209
            u8  unknown29:1,
210
                nb_level:7;
211
            u8  unknown30:1,
212
                proc_level:7;
213
            u8  unknown31:1,
214
                rf_power_hf:7;
215
            u8  unknown32:2,
216
                tuner_atas:3,
217
                mem_vfo_dial_mode:3;
218
            u8  pg_a;
219
            u8  pg_b;
220
            u8  pg_c;
221
            u8  pg_acc;
222
            u8  pg_p1;
223
            u8  pg_p2;
224
            u8  unknown33:3,
225
                xvtr_sel:2,
226
                unknown33_1:2,
227
                op_filter1:1;
228
            u8  unknown34:6,
229
                tx_if_filter:2;
230
            u8  unknown35:3,
231
                xvtr_a_negative:1,
232
                xvtr_b_negative:1,
233
                mtr_arx_sel:3;
234
            u8  beacon_time;
235
            u8  unknown36[2];
236
            u8  dig_vox_enable:1,
237
                unknown37:7;
238
            u8  unknown39:1,
239
                rf_power_6m:7;
240
            u8  unknown40:1,
241
                rf_power_vhf:7;
242
            u8  unknown41:1,
243
                rf_power_uhf:7;
244
        } settings;
245

    
246
        #seekto 0x54;
247
        struct mem_struct vfoa[16];
248
        struct mem_struct vfob[16];
249
        struct mem_struct home[4];
250
        struct mem_struct qmb;
251
        struct mem_struct mtqmb;
252
        struct mem_struct mtune;
253
        
254
        #seekto 0x4a9;
255
        u8 visible[25];
256
        ul16 pmsvisible;
257
        
258
        #seekto 0x4c4;
259
        u8 filled[25];
260
        ul16 pmsfilled;
261
        
262
        #seekto 0x4df;
263
        struct mem_struct memory[200];
264
        struct mem_struct pms[10];
265
        
266
        #seekto 0x1bf3;
267
        u8 arts_idw[10];
268
        u8 beacon_text1[40];
269
        u8 beacon_text2[40];
270
        u8 beacon_text3[40];
271

    
272
        #seekto 0x1CAD;
273
        struct mem_struct sixtymeterchannels[5];
274
    
275
    """
276

    
277
    _CALLSIGN_CHARSET = [chr(x) for x in range(ord("0"), ord("9")+1) +
278
                           range(ord("A"), ord("Z")+1)] + [" ", "/"]
279
    _CALLSIGN_CHARSET_REV = dict(zip(_CALLSIGN_CHARSET,
280
                                    range(0,len(_CALLSIGN_CHARSET))))
281
    _BEACON_CHARSET =  _CALLSIGN_CHARSET + ["+", "."]
282
    _BEACON_CHARSET_REV = dict(zip(_BEACON_CHARSET,
283
                                    range(0,len(_BEACON_CHARSET))))
284

    
285
    # WARNING Index are hard wired in memory management code !!!
286
    SPECIAL_MEMORIES = {
287
        "VFOa-1.8M" : -37,
288
        "VFOa-3.5M" : -36,
289
        "VFOa-5M" : -35,
290
        "VFOa-7M" : -34,
291
        "VFOa-10M" : -33,
292
        "VFOa-14M" : -32,
293
        "VFOa-18M" : -31,
294
        "VFOa-21M" : -30,
295
        "VFOa-24M" : -29,
296
        "VFOa-28M" : -28,
297
        "VFOa-50M" : -27,
298
        "VFOa-FM" : -26,
299
        "VFOa-AIR" : -25,
300
        "VFOa-144" : -24,
301
        "VFOa-430" : -23,
302
        "VFOa-HF" : -22,
303
        "VFOb-1.8M" : -21,
304
        "VFOb-3.5M" : -20,
305
        "VFOb-5M" : -19,
306
        "VFOb-7M" : -18,
307
        "VFOb-10M" : -17,
308
        "VFOb-14M" : -16,
309
        "VFOb-18M" : -15,
310
        "VFOb-21M" : -14,
311
        "VFOb-24M" : -13,
312
        "VFOb-28M" : -12,
313
        "VFOb-50M" : -11,
314
        "VFOb-FM" : -10,
315
        "VFOb-AIR" : -9,
316
        "VFOb-144M" : -8,
317
        "VFOb-430M" : -7,
318
        "VFOb-HF" : -6,
319
        "HOME HF" : -5,
320
        "HOME 50M" : -4,
321
        "HOME 144M" : -3,
322
        "HOME 430M" : -2,
323
        "QMB" : -1,
324
    }
325
    FIRST_VFOB_INDEX = -6
326
    LAST_VFOB_INDEX = -21
327
    FIRST_VFOA_INDEX = -22
328
    LAST_VFOA_INDEX = -37
329

    
330
    SPECIAL_PMS = {
331
        "PMS-1L" : -47,
332
        "PMS-1U" : -46,
333
        "PMS-2L" : -45,
334
        "PMS-2U" : -44,
335
        "PMS-3L" : -43,
336
        "PMS-3U" : -42,
337
        "PMS-4L" : -41,
338
        "PMS-4U" : -40,
339
        "PMS-5L" : -39,
340
        "PMS-5U" : -38,
341
    }
342
    LAST_PMS_INDEX = -47
343

    
344
    SPECIAL_MEMORIES.update(SPECIAL_PMS)
345

    
346
    SPECIAL_MEMORIES_REV = dict(zip(SPECIAL_MEMORIES.values(),
347
                                    SPECIAL_MEMORIES.keys()))
348

    
349
    FILTERS  = [ "CFIL", "FIL1", "FIL2" ]
350
    PROGRAMMABLEOPTIONS = [
351
        "MFa:A/B",              "MFa:A=B",          "MFa:SPL",
352
        "MFb:MW",               "MFb:SKIP/MCLR",    "MFb:TAG",
353
        "MFc:STO",              "MFc:RCL",          "MFc:PROC",
354
        "MFd:RPT",              "MFd:REV",          "MFd:VOX",
355
        "MFe:TON/ENC",          "MFe:TON/DEC",      "MFe:TDCH",   
356
        "MFf:ARTS",             "MFf:SRCH",         "MFf:PMS",
357
        "MFg:SCN",              "MFg:PRI",          "MFg:DW",     
358
        "MFh:SCOP",             "MFh:WID",          "MFh:STEP",
359
        "MFi:MTR",              "MFi:SWR",          "MFi:DISP",   
360
        "MFj:SPOT",             "MFj:BK",           "MFj:KYR",
361
        "MFk:TUNE",             "MFk:DOWN",         "MFk:UP",     
362
        "MFl:NB",               "MFl:AGC",          "MFl:AGC SEL",
363
        "MFm:IPO",              "MFm:ATT",          "MFm:NAR",    
364
        "MFn:CFIL",             "MFn:FIL1",         "MFn:FIL2",
365
        "MFo:PLY1",             "MFo:PLY2",         "MFo:PLY3",   
366
        "MFp:DNR",              "MFp:DNF",          "MFp:DBF",
367
        "01:EXT MENU",          "02:144MHz ARS",    "03:430MHz ARS",     
368
        "04:AM&FM DIAL",        "05:AM MIC GAIN",   "06:AM STEP",        
369
        "07:APO TIME",          "08:ARTS BEEP",     "09:ARTS ID",          
370
        "10:ARTS IDW",          "11:BEACON TEXT",   "12:BEACON TIME",
371
        "13:BEEP TONE",         "14:BEEP VOL",      "15:CAR LSB R",     
372
        "16:CAR LSB T",         "17:CAR USB R",     "18:CAR USB T",
373
        "19:CAT RATE",          "20:CAT/LIN/TUN",   "21:CLAR DIAL SEL",
374
        "22:CW AUTO MODE",      "23:CW BFO",        "24:CW DELAY",
375
        "25:CW KEY REV",        "26:CW PADDLE",     "27:CW PITCH",      
376
        "28:CW QSK",            "29:CW SIDE TONE",  "30:CW SPEED",
377
        "31:CW TRAINING",       "32:CW WEIGHT",     "33:DCS CODE",
378
        "34:DCS INV",           "35:DIAL STEP",     "36:DIG DISP",
379
        "37:DIG GAIN",          "38:DIG MODE",      "39:DIG SHIFT",      
380
        "40:DIG VOX",           "41:DISP COLOR",    "42:DISP CONTRAST",
381
        "43:DISP INTENSITY",    "44:DISP MODE",     "45:DSP BPF WIDTH",
382
        "46:DSP HPF CUTOFF",    "47:DSP LPF CUTOFF","48:DSP MIC EQ",
383
        "49:DSP NR LEVEL",      "50:EMERGENCY",     "51:FM MIC GAIN",   
384
        "52:FM STEP",           "53:HOME->VFO",     "54:LOCK MODE",
385
        "55:MEM GROUP",         "56:MEM TAG",       "57:MEM/VFO DIAL MODE",
386
        "58:MIC SCAN",          "59:MIC SEL",       "60:MTR ARX",
387
        "61:MTR ATX",           "62:MTR PEAK HOLD", "63:NB LEVEL",
388
        "64:OP FILTER",         "71:PKT 1200",      "72:PKT 9600",
389
        "73:PKT RATE",          "74:PROC LEVEL",    "75:RF POWER SET",
390
        "76:RPT SHIFT",         "77:SCAN MODE",     "78:SCAN RESUME",
391
        "79:SPLIT TONE",        "80:SQL/RF GAIN",   "81:SSB MIC GAIN",
392
        "82:SSB STEP",          "83:TONE FREQ",     "84:TX TIME",
393
        "85:TUNER/ATAS",        "86:TX IF FILTER",  "87:VOX DELAY",
394
        "88:VOX GAIN",          "89:XVTR A FREQ",   "90:XVTR B FREQ",
395
        "91:XVTR SEL",
396
        "MONI", "Q.SPL",  "TCALL",  "ATC",  "USER"]
397
        
398
    def get_features(self):
399
        rf = ft817.FT817Radio.get_features(self)
400
        rf.has_cross = True
401
        rf.has_ctone = True
402
        rf.has_rx_dtcs = True
403
        rf.valid_tmodes = self.TMODES_REV.keys()
404
        rf.valid_cross_modes = self.CROSS_MODES_REV.keys()
405
        return rf
406

    
407
    def _get_duplex(self, mem, _mem):
408
        # radio set is_duplex only for + and - but not for split
409
        # at the same time it does not complain if we set it same way 817 does
410
        # (so no set_duplex here)
411
        mem.duplex = self.DUPLEX[_mem.duplex]
412

    
413
    def _get_tmode(self, mem, _mem):
414
        if not _mem.is_split_tone:
415
            mem.tmode = self.TMODES[int(_mem.tmode)]
416
        else:
417
            mem.tmode = "Cross"
418
            mem.cross_mode = self.CROSS_MODES[int(_mem.tmode)]
419

    
420
        if mem.tmode == "Tone":
421
             mem.rtone = mem.ctone = chirp_common.TONES[_mem.tone]
422
        elif mem.tmode == "TSQL":
423
             mem.rtone = mem.ctone = chirp_common.TONES[_mem.tone]
424
        elif mem.tmode == "DTCS Enc": # UI does not support it yet but
425
                                      # this code has alreay been tested
426
             mem.dtcs = mem.rx_dtcs = chirp_common.DTCS_CODES[_mem.dcs]
427
        elif mem.tmode == "DTCS":
428
             mem.dtcs = mem.rx_dtcs = chirp_common.DTCS_CODES[_mem.dcs]
429
        elif mem.tmode == "Cross":
430
            mem.ctone = chirp_common.TONES[_mem.rxtone]
431
            # don't want to fail for this
432
            try:
433
                mem.rtone = chirp_common.TONES[_mem.tone]
434
            except IndexError:
435
                mem.rtone = chirp_common.TONES[0]
436
            mem.dtcs = chirp_common.DTCS_CODES[_mem.dcs]
437
            mem.rx_dtcs = chirp_common.DTCS_CODES[_mem.rxdcs]
438

    
439
    def _set_tmode(self, mem, _mem):
440
        if mem.tmode != "Cross":
441
            _mem.is_split_tone = 0
442
            _mem.tmode = self.TMODES_REV[mem.tmode]
443
        else:
444
            _mem.tmode = self.CROSS_MODES_REV[mem.cross_mode]
445
            _mem.is_split_tone = 1
446

    
447
        if mem.tmode == "Tone":
448
            _mem.tone = _mem.rxtone = chirp_common.TONES.index(mem.rtone)
449
        elif mem.tmode == "TSQL":
450
            _mem.tone = _mem.rxtone = chirp_common.TONES.index(mem.ctone)
451
        elif mem.tmode == "DTCS Enc": # UI does not support it yet but
452
                                      # this code has alreay been tested
453
            _mem.dcs = _mem.rxdcs = chirp_common.DTCS_CODES.index(mem.dtcs)
454
        elif mem.tmode == "DTCS":
455
            _mem.dcs = _mem.rxdcs = chirp_common.DTCS_CODES.index(mem.rx_dtcs)
456
        elif mem.tmode == "Cross":
457
            _mem.tone = chirp_common.TONES.index(mem.rtone)
458
            _mem.rxtone = chirp_common.TONES.index(mem.ctone)
459
            _mem.dcs = chirp_common.DTCS_CODES.index(mem.dtcs)
460
            _mem.rxdcs = chirp_common.DTCS_CODES.index(mem.rx_dtcs)
461
        # have to put this bit to 0 otherwise we get strange display in tone
462
        # frequency (menu 83). See bug #88 and #163
463
        _mem.unknown_toneflag = 0
464
        # dunno if there's the same problem here but to be safe ...
465
        _mem.unknown_rxtoneflag = 0
466

    
467
    def _get_memory(self, mem, _mem):
468
        mem.freq = int(_mem.freq) * 10
469
        mem.offset = int(_mem.offset) * 10
470
        self._get_duplex(mem, _mem)
471
        mem.mode = self.MODES[_mem.mode]
472
        if mem.mode == "FM":
473
            if _mem.is_fm_narrow == 1:
474
                mem.mode = "NFM"
475
            mem.tuning_step = self.STEPSFM[_mem.fm_step]
476
        elif mem.mode == "AM":
477
            mem.tuning_step = self.STEPSAM[_mem.am_step]
478
        elif mem.mode == "CW" or mem.mode == "CWR":
479
            if _mem.is_cwdig_narrow == 1:
480
                mem.mode = "N" + mem.mode
481
            mem.tuning_step = self.STEPSSSB[_mem.ssb_step]
482
        else:
483
            try:
484
                mem.tuning_step = self.STEPSSSB[_mem.ssb_step]
485
            except IndexError:
486
                pass
487
        mem.skip = _mem.skip and "S" or ""
488
        self._get_tmode(mem, _mem)
489

    
490
        if _mem.tag_on_off == 1:
491
            for i in _mem.name:
492
                if i == "\xFF":
493
                    break
494
                if i < 0x80:
495
                    mem.name += self.CHARSET[i]
496
                else:
497
                    mem.name += "*"
498
            mem.name = mem.name.rstrip()
499
        else:
500
            mem.name = ""
501

    
502
        mem.extra = RadioSettingGroup("extra", "Extra")
503
        ipo = RadioSetting("ipo", "IPO",
504
                           RadioSettingValueBoolean(bool(_mem.ipo)))
505
        ipo.set_doc("Bypass preamp")
506
        mem.extra.append(ipo)
507
        
508
        att = RadioSetting("att", "ATT",
509
                           RadioSettingValueBoolean(bool(_mem.att)))
510
        att.set_doc("10dB front end attenuator")
511
        mem.extra.append(att)
512

    
513
        return mem
514

    
515
    def get_settings(self):
516
        _settings = self._memobj.settings
517
        basic = RadioSettingGroup("basic", "Basic")
518
        cw = RadioSettingGroup("cw", "CW")
519
        packet = RadioSettingGroup("packet", "Digital & packet")
520
        panel = RadioSettingGroup("panel", "Panel settings")
521
        extended = RadioSettingGroup("extended", "Extended")
522
        antenna = RadioSettingGroup("antenna", "Antenna selection")
523
        panelcontr = RadioSettingGroup("panelcontr", "Panel controls")
524
        top = RadioSettingGroup("top", "All Settings", basic, cw, packet,
525
                                panelcontr, panel, extended, antenna)
526

    
527
        rs = RadioSetting("extended_menu", "Extended menu",
528
                          RadioSettingValueBoolean(_settings.extended_menu))
529
        extended.append(rs)
530
        rs = RadioSetting("ars_144", "144MHz ARS",
531
                          RadioSettingValueBoolean(_settings.ars_144))
532
        basic.append(rs)
533
        rs = RadioSetting("ars_430", "430MHz ARS",
534
                          RadioSettingValueBoolean(_settings.ars_430))
535
        basic.append(rs)
536
        options = ["enable", "disable"]
537
        rs = RadioSetting("disable_amfm_dial", "AM&FM Dial",
538
                          RadioSettingValueList(options,
539
                                        options[_settings.disable_amfm_dial]))
540
        panel.append(rs)
541
        rs = RadioSetting("am_mic", "AM mic gain",
542
                          RadioSettingValueInteger(0, 100, _settings.am_mic))
543
        basic.append(rs)
544
        options = ["OFF", "1h", "2h", "3h", "4h", "5h", "6h"]
545
        rs = RadioSetting("apo_time", "APO time",
546
                          RadioSettingValueList(options,
547
                                        options[_settings.apo_time]))
548
        basic.append(rs)
549
        options = ["OFF", "Range", "All"]
550
        rs = RadioSetting("arts_beep", "ARTS beep",
551
                          RadioSettingValueList(options,
552
                                        options[_settings.arts_beep]))
553
        basic.append(rs)
554
        rs = RadioSetting("arts_id", "ARTS ID",
555
                          RadioSettingValueBoolean(_settings.arts_id))
556
        extended.append(rs)
557
        s = RadioSettingValueString(0, 10, 
558
                            ''.join([self._CALLSIGN_CHARSET[x] for x in 
559
                                        self._memobj.arts_idw]))
560
        s.set_charset(self._CALLSIGN_CHARSET)
561
        rs = RadioSetting("arts_idw", "ARTS IDW", s)
562
        extended.append(rs)
563
        s = RadioSettingValueString(0, 40, 
564
                            ''.join([self._BEACON_CHARSET[x] for x in 
565
                                        self._memobj.beacon_text1]))
566
        s.set_charset(self._BEACON_CHARSET)
567
        rs = RadioSetting("beacon_text1", "Beacon text1", s)
568
        extended.append(rs)
569
        s = RadioSettingValueString(0, 40, 
570
                            ''.join([self._BEACON_CHARSET[x] for x in 
571
                                        self._memobj.beacon_text2]))
572
        s.set_charset(self._BEACON_CHARSET)
573
        rs = RadioSetting("beacon_text2", "Beacon text2", s)
574
        extended.append(rs)
575
        s = RadioSettingValueString(0, 40, 
576
                            ''.join([self._BEACON_CHARSET[x] for x in 
577
                                        self._memobj.beacon_text3]))
578
        s.set_charset(self._BEACON_CHARSET)
579
        rs = RadioSetting("beacon_text3", "Beacon text3", s)
580
        extended.append(rs)
581
        options = ["OFF"]+["%i sec" % i for i in range(1,256)]
582
        rs = RadioSetting("beacon_time", "Beacon time",
583
                          RadioSettingValueList(options,
584
                                        options[_settings.beacon_time]))
585
        extended.append(rs)
586
        options = ["440Hz", "880Hz", "1760Hz"]
587
        rs = RadioSetting("beep_tone", "Beep tone",
588
                          RadioSettingValueList(options,
589
                                        options[_settings.beep_tone]))
590
        panel.append(rs)
591
        rs = RadioSetting("beep_vol", "Beep volume",
592
                          RadioSettingValueInteger(0, 100, _settings.beep_vol))
593
        panel.append(rs)
594
        rs = RadioSetting("r_lsb_car", "LSB Rx carrier point (*10 Hz)",
595
                          RadioSettingValueInteger(-30, 30, _settings.r_lsb_car))
596
        extended.append(rs)
597
        rs = RadioSetting("r_usb_car", "USB Rx carrier point (*10 Hz)",
598
                          RadioSettingValueInteger(-30, 30, _settings.r_usb_car))
599
        extended.append(rs)
600
        rs = RadioSetting("t_lsb_car", "LSB Tx carrier point (*10 Hz)",
601
                          RadioSettingValueInteger(-30, 30, _settings.t_lsb_car))
602
        extended.append(rs)
603
        rs = RadioSetting("t_usb_car", "USB Tx carrier point (*10 Hz)",
604
                          RadioSettingValueInteger(-30, 30, _settings.t_usb_car))
605
        extended.append(rs)
606
        options = ["4800", "9600", "38400"]
607
        rs = RadioSetting("cat_rate", "CAT rate",
608
                          RadioSettingValueList(options,
609
                                        options[_settings.cat_rate]))
610
        basic.append(rs)
611
        options = ["CAT", "Linear", "Tuner"]
612
        rs = RadioSetting("cat_lin_tun", "CAT/LIN/TUN selection",
613
                          RadioSettingValueList(options,
614
                                        options[_settings.cat_lin_tun]))
615
        extended.append(rs)
616
        options = ["MAIN", "VFO/MEM", "CLAR"]   # TODO test the 3 options on non D radio
617
                                                # which have only SEL and MAIN
618
        rs = RadioSetting("clar_dial_sel", "Clarifier dial selection",
619
                          RadioSettingValueList(options,
620
                                        options[_settings.clar_dial_sel]))
621
        panel.append(rs)
622
        rs = RadioSetting("cw_auto_mode", "CW Automatic mode",
623
                          RadioSettingValueBoolean(_settings.cw_auto_mode))
624
        cw.append(rs)
625
        options = ["USB", "LSB", "AUTO"]
626
        rs = RadioSetting("cw_bfo", "CW BFO",
627
                          RadioSettingValueList(options,
628
                                        options[_settings.cw_bfo]))
629
        cw.append(rs)
630
        options = ["FULL"]+["%i ms" % (i*10) for i in range(3,301)]
631
        val = (_settings.cw_delay + _settings.cw_delay_hi * 256) - 2
632
        rs = RadioSetting("cw_delay", "CW delay",
633
                          RadioSettingValueList(options,
634
                                        options[val]))
635
        cw.append(rs)
636
        options = ["Normal", "Reverse"]
637
        rs = RadioSetting("cw_key_rev", "CW key reverse",
638
                          RadioSettingValueList(options,
639
                                        options[_settings.cw_key_rev]))
640
        cw.append(rs)
641
        rs = RadioSetting("cw_paddle", "CW paddle",
642
                          RadioSettingValueBoolean(_settings.cw_paddle))
643
        cw.append(rs)
644
        options = ["%i Hz" % i for i in range(400,801,100)]
645
        rs = RadioSetting("cw_pitch", "CW pitch",
646
                          RadioSettingValueList(options,
647
                                        options[_settings.cw_pitch]))
648
        cw.append(rs)
649
        options = ["%i ms" % i for i in range(5,31,5)]
650
        rs = RadioSetting("cw_qsk", "CW QSK",
651
                          RadioSettingValueList(options,
652
                                        options[_settings.cw_qsk]))
653
        cw.append(rs)
654
        rs = RadioSetting("cw_sidetone", "CW sidetone volume",
655
                          RadioSettingValueInteger(0, 100, _settings.cw_sidetone))
656
        cw.append(rs)
657
        options = ["%i wpm" % i for i in range(4,61)]
658
        rs = RadioSetting("cw_speed", "CW speed",
659
                          RadioSettingValueList(options,
660
                                        options[_settings.cw_speed]))
661
        cw.append(rs)
662
        options = ["Numeric", "Alphabet", "AlphaNumeric"]
663
        rs = RadioSetting("cw_training", "CW trainig",
664
                          RadioSettingValueList(options,
665
                                        options[_settings.cw_training]))
666
        cw.append(rs)
667
        options = ["1:%1.1f" % (i/10) for i in range(25,46,1)]
668
        rs = RadioSetting("cw_weight", "CW weight",
669
                          RadioSettingValueList(options,
670
                                        options[_settings.cw_weight]))
671
        cw.append(rs)
672
        options = ["Tn-Rn", "Tn-Riv", "Tiv-Rn", "Tiv-Riv"]
673
        rs = RadioSetting("dcs_inv", "DCS inv",
674
                          RadioSettingValueList(options,
675
                                        options[_settings.dcs_inv]))
676
        extended.append(rs)
677
        options = ["Fine", "Coarse"]
678
        rs = RadioSetting("dial_step", "Dial step",
679
                          RadioSettingValueList(options,
680
                                        options[_settings.dial_step]))
681
        panel.append(rs)
682
        rs = RadioSetting("dig_disp", "Dig disp (*10 Hz)",
683
                          RadioSettingValueInteger(-300, 300, _settings.dig_disp))
684
        packet.append(rs)
685
        rs = RadioSetting("dig_mic", "Dig gain",
686
                          RadioSettingValueInteger(0, 100, _settings.dig_mic))
687
        packet.append(rs)
688
        options = ["RTTYL", "RTTYU", "PSK31-L", "PSK31-U", "USER-L", "USER-U"]
689
        rs = RadioSetting("dig_mode", "Dig mode",
690
                          RadioSettingValueList(options,
691
                                        options[_settings.dig_mode]))
692
        packet.append(rs)
693
        rs = RadioSetting("dig_shift", "Dig shift (*10 Hz)",
694
                          RadioSettingValueInteger(-300, 300, _settings.dig_shift))
695
        packet.append(rs)
696
        rs = RadioSetting("dig_vox", "Dig vox",
697
                          RadioSettingValueInteger(0, 100, _settings.dig_vox))
698
        packet.append(rs)
699
        options = ["ARTS", "BAND", "FIX", "MEMGRP", "MODE", "MTR", "VFO"]
700
        rs = RadioSetting("disp_color", "Display color mode",
701
                          RadioSettingValueList(options,
702
                                        options[_settings.disp_color]))
703
        panel.append(rs)
704
        rs = RadioSetting("disp_color_arts", "Display color ARTS set",
705
                          RadioSettingValueInteger(0, 1,_settings.disp_color_arts))
706
        panel.append(rs)
707
        rs = RadioSetting("disp_color_band", "Display color band set",
708
                          RadioSettingValueInteger(0, 1,_settings.disp_color_band))
709
        panel.append(rs)
710
        rs = RadioSetting("disp_color_memgrp", "Display color memory group set",
711
                          RadioSettingValueInteger(0, 1,_settings.disp_color_memgrp))
712
        panel.append(rs)
713
        rs = RadioSetting("disp_color_mode", "Display color mode set",
714
                          RadioSettingValueInteger(0, 1,_settings.disp_color_mode))
715
        panel.append(rs)
716
        rs = RadioSetting("disp_color_mtr", "Display color meter set",
717
                          RadioSettingValueInteger(0, 1,_settings.disp_color_mtr))
718
        panel.append(rs)
719
        rs = RadioSetting("disp_color_vfo", "Display color VFO set",
720
                          RadioSettingValueInteger(0, 1,_settings.disp_color_vfo))
721
        panel.append(rs)
722
        rs = RadioSetting("disp_color_fix", "Display color fix set",
723
                          RadioSettingValueInteger(1, 32,_settings.disp_color_fix+1)) 
724
        panel.append(rs)
725
        rs = RadioSetting("disp_contrast", "Contrast",
726
                          RadioSettingValueInteger(3, 15,_settings.disp_contrast+2))
727
        panel.append(rs)
728
        rs = RadioSetting("disp_intensity", "Intensity",
729
                          RadioSettingValueInteger(1, 3,_settings.disp_intensity))
730
        panel.append(rs)
731
        options = ["OFF", "Auto1", "Auto2", "ON"]
732
        rs = RadioSetting("disp_mode", "Display backlight mode",
733
                          RadioSettingValueList(options,
734
                                        options[_settings.disp_mode]))
735
        panel.append(rs)
736
        options = ["60Hz", "120Hz", "240Hz"]
737
        rs = RadioSetting("dsp_bpf", "Dsp band pass filter",
738
                          RadioSettingValueList(options,
739
                                        options[_settings.dsp_bpf]))
740
        cw.append(rs)
741
        options = ["100Hz", "160Hz", "220Hz", "280Hz", "340Hz", "400Hz", "460Hz", "520Hz",
742
            "580Hz", "640Hz", "720Hz", "760Hz", "820Hz", "880Hz", "940Hz", "1000Hz"]
743
        rs = RadioSetting("dsp_hpf", "Dsp hi pass filter cut off",
744
                          RadioSettingValueList(options,
745
                                        options[_settings.dsp_hpf]))
746
        basic.append(rs)
747
        options = ["1000Hz", "1160Hz", "1320Hz", "1480Hz", "1650Hz", "1800Hz", "1970Hz", "2130Hz",
748
            "2290Hz", "2450Hz", "2610Hz", "2770Hz", "2940Hz", "3100Hz", "3260Hz", "3420Hz",
749
            "3580Hz", "3740Hz", "3900Hz", "4060Hz", "4230Hz", "4390Hz", "4550Hz", "4710Hz",
750
            "4870Hz", "5030Hz", "5190Hz", "5390Hz", "5520Hz", "5680Hz", "5840Hz", "6000Hz"]
751
        rs = RadioSetting("dsp_lpf", "Dsp low pass filter cut off",
752
                          RadioSettingValueList(options,
753
                                        options[_settings.dsp_lpf]))
754
        basic.append(rs)
755
        options = ["OFF", "LPF", "HPF", "BOTH"]
756
        rs = RadioSetting("dsp_mic_eq", "Dsp mic equalization",
757
                          RadioSettingValueList(options,
758
                                        options[_settings.dsp_mic_eq]))
759
        basic.append(rs)
760
        rs = RadioSetting("dsp_nr", "DSP noise reduction level",
761
                          RadioSettingValueInteger(1, 16, _settings.dsp_nr+1))
762
        basic.append(rs)
763
        # emergency only for US model
764
        rs = RadioSetting("fm_mic", "FM mic gain",
765
                          RadioSettingValueInteger(0, 100, _settings.fm_mic))
766
        basic.append(rs)
767
        rs = RadioSetting("home_vfo", "Enable HOME to VFO moving",
768
                          RadioSettingValueBoolean(_settings.home_vfo))
769
        panel.append(rs)
770
        options = ["Dial", "Freq", "Panel", "All"]
771
        rs = RadioSetting("lock_mode", "Lock mode",
772
                          RadioSettingValueList(options,
773
                                        options[_settings.lock_mode]))
774
        panel.append(rs)
775
        rs = RadioSetting("mem_group", "Mem group",
776
                          RadioSettingValueBoolean(_settings.mem_group))
777
        basic.append(rs)
778
        options = ["CW SIDETONE", "CW SPEED", "MHz/MEM GRP", "MIC GAIN",
779
            "NB LEVEL", "RF POWER", "STEP"]
780
        rs = RadioSetting("mem_vfo_dial_mode", "Mem/VFO dial mode",
781
                          RadioSettingValueList(options,
782
                                        options[_settings.mem_vfo_dial_mode]))
783
        panel.append(rs)
784
        rs = RadioSetting("mic_scan", "Mic scan",
785
                          RadioSettingValueBoolean(_settings.mic_scan))
786
        basic.append(rs)
787
        options = ["NOR", "RMT", "CAT"]
788
        rs = RadioSetting("mic_sel", "Mic selection",
789
                          RadioSettingValueList(options,
790
                                        options[_settings.mic_sel]))
791
        extended.append(rs)
792
        options = ["SIG", "CTR", "VLT", "N/A", "FS",  "OFF"]
793
        rs = RadioSetting("mtr_arx_sel", "Meter receive selection",
794
                          RadioSettingValueList(options,
795
                                        options[_settings.mtr_arx_sel]))
796
        extended.append(rs)
797
        options = ["PWR", "ALC", "MOD", "SWR", "VLT", "N/A", "OFF"]
798
        rs = RadioSetting("mtr_atx_sel", "Meter transmit selection",
799
                          RadioSettingValueList(options,
800
                                        options[_settings.mtr_atx_sel]))
801
        extended.append(rs)
802
        rs = RadioSetting("mtr_peak_hold", "Meter peak hold",
803
                          RadioSettingValueBoolean(_settings.mtr_peak_hold))
804
        extended.append(rs)
805
        rs = RadioSetting("nb_level", "Noise blanking level",
806
                          RadioSettingValueInteger(0, 100, _settings.nb_level))
807
        basic.append(rs)
808
        # TODO op_filter1
809
        # TODO op_filter2
810
        rs = RadioSetting("pg_a", "Programmable key MFq:A",
811
                          RadioSettingValueList(self.PROGRAMMABLEOPTIONS,
812
                                        self.PROGRAMMABLEOPTIONS[_settings.pg_a]))
813
        extended.append(rs)
814
        rs = RadioSetting("pg_b", "Programmable key MFq:B",
815
                          RadioSettingValueList(self.PROGRAMMABLEOPTIONS,
816
                                        self.PROGRAMMABLEOPTIONS[_settings.pg_b]))
817
        extended.append(rs)
818
        rs = RadioSetting("pg_c", "Programmable key MFq:C",
819
                          RadioSettingValueList(self.PROGRAMMABLEOPTIONS,
820
                                        self.PROGRAMMABLEOPTIONS[_settings.pg_c]))
821
        extended.append(rs)
822
        rs = RadioSetting("pg_acc", "Programmable mic key ACC",
823
                          RadioSettingValueList(self.PROGRAMMABLEOPTIONS,
824
                                        self.PROGRAMMABLEOPTIONS[_settings.pg_acc]))
825
        extended.append(rs)
826
        rs = RadioSetting("pg_p1", "Programmable mic key P1",
827
                          RadioSettingValueList(self.PROGRAMMABLEOPTIONS,
828
                                        self.PROGRAMMABLEOPTIONS[_settings.pg_p1]))
829
        extended.append(rs)
830
        rs = RadioSetting("pg_p2", "Programmable mic key P2",
831
                          RadioSettingValueList(self.PROGRAMMABLEOPTIONS,
832
                                        self.PROGRAMMABLEOPTIONS[_settings.pg_p2]))
833
        extended.append(rs)
834
        rs = RadioSetting("pkt1200", "Packet 1200 gain level",
835
                          RadioSettingValueInteger(0, 100, _settings.pkt1200))
836
        packet.append(rs)
837
        rs = RadioSetting("pkt9600", "Packet 9600 gain level",
838
                          RadioSettingValueInteger(0, 100, _settings.pkt9600))
839
        packet.append(rs)
840
        options = ["1200", "9600"]
841
        rs = RadioSetting("pkt_rate", "Packet rate",
842
                          RadioSettingValueList(options,
843
                                        options[_settings.pkt_rate]))
844
        packet.append(rs)
845
        rs = RadioSetting("proc_level", "Proc level",
846
                          RadioSettingValueInteger(0, 100, _settings.proc_level))
847
        basic.append(rs)
848
        rs = RadioSetting("rf_power_hf", "Rf power set HF",
849
                          RadioSettingValueInteger(5, 100, _settings.rf_power_hf))
850
        basic.append(rs)
851
        rs = RadioSetting("rf_power_6m", "Rf power set 6m",
852
                          RadioSettingValueInteger(5, 100, _settings.rf_power_6m))
853
        basic.append(rs)
854
        rs = RadioSetting("rf_power_vhf", "Rf power set VHF",
855
                          RadioSettingValueInteger(5, 50, _settings.rf_power_vhf))
856
        basic.append(rs)
857
        rs = RadioSetting("rf_power_uhf", "Rf power set UHF",
858
                          RadioSettingValueInteger(2, 20, _settings.rf_power_uhf))
859
        basic.append(rs)
860
        options = ["TIME", "BUSY", "STOP"]
861
        rs = RadioSetting("scan_mode", "Scan mode",
862
                          RadioSettingValueList(options,
863
                                        options[_settings.scan_mode]))
864
        basic.append(rs)
865
        rs = RadioSetting("scan_resume", "Scan resume",
866
                          RadioSettingValueInteger(1, 10, _settings.scan_resume))
867
        basic.append(rs)
868
        rs = RadioSetting("split_tone", "Split tone enable",
869
                          RadioSettingValueBoolean(_settings.split_tone))
870
        extended.append(rs)
871
        options = ["RF-Gain", "Squelch"]
872
        rs = RadioSetting("sql_rf_gain", "Squelch/RF-Gain",
873
                          RadioSettingValueList(options,
874
                                        options[_settings.sql_rf_gain]))
875
        panel.append(rs)
876
        rs = RadioSetting("ssb_mic", "SSB Mic gain",
877
                          RadioSettingValueInteger(0, 100, _settings.ssb_mic))
878
        basic.append(rs)
879
        options = ["Off"]+["%i" % i for i in range(1, 21)]
880
        rs = RadioSetting("tot_time", "Time-out timer",
881
                          RadioSettingValueList(options,
882
                                        options[_settings.tot_time]))
883
        basic.append(rs)
884
        options = ["OFF", "ATAS(HF)", "ATAS(HF&50)", "ATAS(ALL)", "TUNER"]
885
        rs = RadioSetting("tuner_atas", "Tuner/ATAS device",
886
                          RadioSettingValueList(options,
887
                                        options[_settings.tuner_atas]))
888
        extended.append(rs)
889
        rs = RadioSetting("tx_if_filter", "Transmit IF filter",
890
                          RadioSettingValueList(self.FILTERS,
891
                                        self.FILTERS[_settings.tx_if_filter]))
892
        basic.append(rs)
893
        rs = RadioSetting("vox_delay", "VOX delay (*100 ms)",
894
                          RadioSettingValueInteger(1, 30, _settings.vox_delay))
895
        basic.append(rs)
896
        rs = RadioSetting("vox_gain", "VOX Gain",
897
                          RadioSettingValueInteger(1, 100, _settings.vox_gain))
898
        basic.append(rs)
899
        # TODO xvtr_a_freq
900
        # TODO xvtr_b_freq
901
        options = ["OFF", "XVTR A", "XVTR B"]
902
        rs = RadioSetting("xvtr_sel", "Transverter function selection",
903
                          RadioSettingValueList(options,
904
                                        options[_settings.xvtr_sel]))
905
        extended.append(rs)
906
        
907
        return top
908

    
909
    def set_settings(self, settings):
910
        _settings = self._memobj.settings
911
        for element in settings:
912
            if not isinstance(element, RadioSetting):
913
                self.set_settings(element)
914
                continue
915
            try:
916
                if "." in element.get_name():
917
                    bits = element.get_name().split(".")
918
                    obj = self._memobj
919
                    for bit in bits[:-1]:
920
                        obj = getattr(obj, bit)
921
                    setting = bits[-1]
922
                else:
923
                    obj = _settings
924
                    setting = element.get_name()
925
                if os.getenv("CHIRP_DEBUG"):
926
	                print "Setting %s(%s) <= %s" % (setting, 
927
                                    getattr(obj, setting), element.value)
928
                if setting == "arts_idw":
929
                    self._memobj.arts_idw = \
930
                        [self._CALLSIGN_CHARSET_REV[x] for x in 
931
                                                        str(element.value)]
932
                elif setting in ["beacon_text1", "beacon_text2", "beacon_text3"]:
933
                    setattr(self._memobj, setting,
934
                        [self._BEACON_CHARSET_REV[x] for x in 
935
                                                        str(element.value)])
936
                elif setting == "cw_delay":
937
                    val = int(element.value)+2
938
                    setattr(obj, "cw_delay_hi", val/256)
939
                    setattr(obj, setting, val&0xff)
940
                elif setting == "dig_vox":
941
                    val = int(element.value)
942
                    setattr(obj, "dig_vox_enable", int(val>0))
943
                    setattr(obj, setting, val)
944
                elif setting in ["disp_color_fix", "dsp_nr"]:
945
                    setattr(obj, setting, int(element.value)-1)
946
                elif setting == "disp_contrast":
947
                    setattr(obj, setting, int(element.value)-2)
948
                else:
949
                    setattr(obj, setting, element.value)
950
            except Exception, e:
951
                print element.get_name()
952
                raise
953

    
954
@directory.register
955
class FT857USRadio(FT857Radio):
956
    """Yaesu FT857/897 (US version)"""
957
    # seems that radios configured for 5MHz operations send one paket more
958
    # than others so we have to distinguish sub models
959
    MODEL = "FT-857/897 (US)"
960

    
961
    _model = ""
962
    _memsize = 7481
963
    # block 9 (140 Bytes long) is to be repeted 40 times 
964
    # should be 42 times but this way I can use original 817 functions
965
    _block_lengths = [ 2, 82, 252, 196, 252, 196, 212, 55, 140, 140, 140, 38,
966
                       176, 140]
967

    
968
    SPECIAL_60M = {
969
        "M-601" : -52,
970
        "M-602" : -51,
971
        "M-603" : -50,
972
        "M-604" : -49,
973
        "M-605" : -48,
974
        }
975
    LAST_SPECIAL60M_INDEX = -52
976
    
977
    SPECIAL_MEMORIES = dict(FT857Radio.SPECIAL_MEMORIES)
978
    SPECIAL_MEMORIES.update(SPECIAL_60M)
979

    
980
    SPECIAL_MEMORIES_REV = dict(zip(SPECIAL_MEMORIES.values(),
981
                                    SPECIAL_MEMORIES.keys()))
982

    
983
    # this is identical to the one in FT817ND_US_Radio but we inherit from 857
984
    def _get_special_60m(self, number):
985
        mem = chirp_common.Memory()
986
        mem.number = self.SPECIAL_60M[number]
987
        mem.extd_number = number
988

    
989
        _mem = self._memobj.sixtymeterchannels[-self.LAST_SPECIAL60M_INDEX +
990
                                                mem.number]
991

    
992
        mem = self._get_memory(mem, _mem)
993

    
994
        mem.immutable = ["number", "skip", "rtone", "ctone",
995
                         "extd_number", "name", "dtcs", "tmode", "cross_mode",
996
                         "dtcs_polarity", "power", "duplex", "offset",
997
                         "comment", "empty"]
998

    
999
        return mem
1000

    
1001
    # this is identical to the one in FT817ND_US_Radio but we inherit from 857
1002
    def _set_special_60m(self, mem):
1003
        if mem.empty:
1004
            # can't delete 60M memories!
1005
            raise Exception("Sorry, 60M memory can't be deleted")
1006

    
1007
        cur_mem = self._get_special_60m(self.SPECIAL_MEMORIES_REV[mem.number])
1008

    
1009
        for key in cur_mem.immutable:
1010
            if cur_mem.__dict__[key] != mem.__dict__[key]:
1011
                raise errors.RadioError("Editing field `%s' " % key +
1012
                                        "is not supported on M-60x channels")
1013

    
1014
        if mem.mode not in ["USB", "LSB", "CW", "CWR", "NCW", "NCWR", "DIG"]:
1015
            raise errors.RadioError("Mode {mode} is not valid "
1016
                                    "in 60m channels".format(mode=mem.mode))
1017
        _mem = self._memobj.sixtymeterchannels[-self.LAST_SPECIAL60M_INDEX +
1018
                                                mem.number]
1019
        self._set_memory(mem, _mem)
1020

    
1021
    def get_memory(self, number):
1022
        if number in self.SPECIAL_60M.keys():
1023
            return self._get_special_60m(number)
1024
        elif number < 0 and \
1025
                self.SPECIAL_MEMORIES_REV[number] in self.SPECIAL_60M.keys():
1026
            # I can't stop delete operation from loosing extd_number but
1027
            # I know how to get it back
1028
            return self._get_special_60m(self.SPECIAL_MEMORIES_REV[number])
1029
        else:
1030
            return FT857Radio.get_memory(self, number)
1031

    
1032
    def set_memory(self, memory):
1033
        if memory.number in self.SPECIAL_60M.values():
1034
            return self._set_special_60m(memory)
1035
        else:
1036
            return FT857Radio.set_memory(self, memory)
1037

    
1038
    def get_settings(self):
1039
        top = FT857Radio.get_settings(self)
1040
        basic = top["basic"]
1041
        rs = RadioSetting("emergency", "Emergency",
1042
                          RadioSettingValueBoolean(self._memobj.settings.emergency))
1043
        basic.append(rs)
1044
        return top
1045

    
(3-3/3)