[chirp_devel] [PATCH] [VX-6] Add settings support for Yaesu VX-6 #1289

Ray Cielencki
Wed May 22 15:10:41 PDT 2019


# HG changeset patch
# User Ray Cielencki <rayslinky at gmail.com>
# Date 1558563009 14400
#      Wed May 22 18:10:09 2019 -0400
# Node ID 76c88493bd3f873d355d08e66c624c6acf201b4d
# Parent  7f46b0213c16e4082984a8ccecf1af4bd17624c7
[VX-6] Add settings support for Yaesu VX-6 #1289

diff -r 7f46b0213c16 -r 76c88493bd3f chirp/drivers/vx6.py
--- a/chirp/drivers/vx6.py	Sun May 12 00:35:53 2019 -0400
+++ b/chirp/drivers/vx6.py	Wed May 22 18:10:09 2019 -0400
@@ -15,7 +15,11 @@
 
 from chirp.drivers import yaesu_clone
 from chirp import chirp_common, directory, bitwise
+from chirp.settings import RadioSettingGroup, RadioSetting, RadioSettings
+from chirp.settings import RadioSettingValueString, RadioSettingValueList
+from chirp.settings import RadioSettingValueBoolean
 from textwrap import dedent
+import re
 
 # flags.{even|odd}_pskip: These are actually "preferential *scan* channels".
 # Is that what they mean on other radios as well?
@@ -37,15 +41,110 @@
 #                      D Tone: Encodes DCS code, decodes tone
 # }
 MEM_FORMAT = """
+#seekto 0x010A;
+struct {
+  u8 auto_power_off;
+  u8 arts_beep;
+  u8 bell;
+  u8 beep_level;
+  u8 arts_cwid_alpha[16];
+  u8 unk1[2];
+  u8 channel_counter_width;
+  u8 lcd_dimmer;
+  u8 last_dtmf;
+  u8 unk2;
+  u8 internet_code;
+  u8 last_internet_dtmf;
+  u8 unk3[3];
+  u8 emergency;
+  u8 unk4[16];
+  u8 lamp;
+  u8 lock;
+  u8 unk5;
+  u8 mic_gain;
+  u8 unk6[2];
+  u8 on_timer;
+  u8 open_message_mode;
+  u8 open_message[6];
+  u8 unk7;
+  u8 unk8:6,
+     pager_answer_back:1,
+     unk9:1;
+  u8 pager_rx_tone1;
+  u8 pager_rx_tone2;
+  u8 pager_tx_tone1;
+  u8 pager_tx_tone2;
+  u8 password[4];
+  u8 ptt_delay;
+  u8 rf_squelch;
+  u8 rx_save;
+  u8 resume;
+  u8 unk10[5];
+  u8 tx_timeout;
+  u8 wakeup;
+  u8 vfo_mode:1,
+     arts_cwid:1,
+     scan_lamp:1,
+     ts_speed:1,
+     unk11:1,
+     beep:1,
+     unk12:1,
+     dtmf_autodial:1;
+  u8 busy_led:1,
+     tone_search_mute:1,
+     int_autodial:1,
+     bclo:1,
+     edge_beep:1,
+     unk13:1,
+     dmr_wrt:1,
+     tx_saver:1;
+  u8 unk14:2,
+     smart_search:1,
+     unk15:3,
+     home_rev:1,
+     moni_tcall:1;
+  u8 unk16:3,
+     arts_interval:1,
+     unk17:3,
+     memory_method:1;
+  u8 unk18:2,
+     internet_mode:1,
+     wx_alert:1,
+     unk19:1,
+     att:1,
+     unk20:2;
+} settings;
+
 #seekto 0x018A;
 struct {
-    u16 in_use;
+  u16 in_use;
 } bank_used[24];
 
+#seekto 0x01D8;
+u8 clock_shift;
+
 #seekto 0x0214;
-u16  banksoff1;
+u16 banksoff1;
+
+#seekto 0x0248;
+u8 lastsetting1;
+
 #seekto 0x0294;
-u16  banksoff2;
+u16 banksoff2;
+
+#seekto 0x0248;
+u8 lastsetting2;
+
+#seekto 0x02CA;
+struct {
+  u8 memory[16];
+} dtmf[10];
+
+#seekto 0x03CA;
+struct {
+  u8 memory[8];
+  u8 empty_ff[8];
+} internet_dtmf[64];
 
 #seekto 0x097A;
 struct {
@@ -95,15 +194,17 @@
 DUPLEX = ["", "-", "+", "split"]
 MODES = ["FM", "AM", "WFM", "FM"]  # last is auto
 TMODES = ["", "Tone", "TSQL", "DTCS"]
+DTMFCHARSET = list("0123456789ABCD*#-")
 STEPS = [5.0, 10.0, 12.5, 15.0, 20.0, 25.0, 50.0, 100.0,
          9.0, 200.0, 5.0]  # last is auto, 9.0k and 200.0k are unadvertised
 
-
-CHARSET = ["%i" % int(x) for x in range(0, 10)] + \
+CHARSET = ["%i" % int(x) for x in range(10)] + \
     [chr(x) for x in range(ord("A"), ord("Z")+1)] + \
     list(" +-/\x00[]__" + ("\x00" * 9) + "$%%\x00**.|=\\\x00@") + \
     list("\x00" * 100)
 
+PASS_CHARSET = list("0123456789ABCDEF")
+
 POWER_LEVELS = [chirp_common.PowerLevel("Hi", watts=5.00),
                 chirp_common.PowerLevel("L3", watts=2.50),
                 chirp_common.PowerLevel("L2", watts=1.00),
@@ -220,6 +321,42 @@
     _block_lengths = [10, 32577]
     _block_size = 16
 
+    _APO = ("OFF", "30 min", "1 hour", "3 hour", "5 hour", "8 hour")
+    _ARTSBEEP = ("Off", "In Range", "Always")
+    _ARTS_INT = ("15 S", "25 S")
+    _BELL = ("OFF", "1", "3", "5", "8", "Continuous")
+    _BEEP_LEVEL = ["%i" % int(x) for x in range(1, 10)]
+    _CH_CNT = ("5 MHZ", "10 MHZ", "50 MHZ", "100 MHZ")
+    _DIM_LEVEL = ["%i" % int(x) for x in range(0, 13)]
+    _EMERGENCY = ("Beep", "Strobe", "Bp+Str", "Beam", "Bp+Bem", "CW",
+                  "Bp+CW", "CWT")
+    _HOME_REV = ("HOME", "REV")
+    _INT_CD = ["%i" % int(x) for x in range(0, 10)] + \
+        [chr(x) for x in range(ord("A"), ord("F")+1)]
+    _INT_MD = ("SRG: Sister Radio Group", "FRG: Friendly Radio Group")
+    _LAMP = ("Key", "Continuous", "Off")
+    _LOCK = ("Key", "Dial", "Key+Dial", "PTT", "Key+PTT", "Dial+PTT", "All")
+    _MAN_AUTO = ("Manual", "Auto")
+    _MEM_W_MD = ("Lower", "Next")
+    _MONI_TCALL = ("MONI", "T-CALL")
+    _NUM_1_9 = ["%i" % int(x) for x in range(1, 10)]
+    _NUM_0_9 = ["%i" % int(x) for x in range(10)]
+    _NUM_0_63 = ["%i" % int(x) for x in range(64)]
+    _NUM_1_50 = ["%i" % int(x) for x in range(1, 51)]
+    _ON_TIMER = ["OFF"] + \
+        ["%02d:%02d" % (t / 60, t % 60) for t in range(10, 1450, 10)]
+    _OPEN_MSG = ("Off", "DC Voltage", "Message")
+    _PTT_DELAY = ("OFF", "20MS", "50MS", "100MS", "200MS")
+    _RF_SQL = ("OFF", "S1", "S2", "S3", "S4", "S5",
+               "S6", "S7", "S8", "S9", "S9+")
+    _RX_SAVE = ("OFF", "200 ms", "300 MS", "500 MS", "1 S", "2 S")
+    _RESUME = ("3 SEC", "5 SEC", "10 SEC", "BUSY", "HOLD")
+    _SMART_SEARCH = ("SINGLE", "CONT")
+    _TOT = ("OFF", "1MIN", "3MIN", "5MIN", "10MIN")
+    _TS_SPEED = ("FAST", "SLOW")
+    _VFO_MODE = ("ALL", "BAND")
+    _WAKEUP = ("OFF", "5S", "10S", "20S", "30S", "EAI")
+
     @classmethod
     def get_prompts(cls):
         rp = chirp_common.RadioPrompts()
@@ -259,6 +396,7 @@
         rf.valid_name_length = 6
         rf.can_odd_split = True
         rf.has_ctone = False
+        rf.has_settings = True
         return rf
 
     def get_raw_memory(self, number):
@@ -367,3 +505,371 @@
 
     def get_bank_model(self):
         return VX6BankModel(self)
+
+    def _decode_chars(self, inarr):
+        outstr = ""
+        for i in inarr:
+            if i == 0xFF:
+                break
+            outstr += CHARSET[i & 0x7F]
+        return outstr.rstrip()
+
+    def _encode_chars(self, instr, length=16):
+        outarr = []
+        instr = str(instr)
+        for i in range(length):
+            if i < len(instr):
+                outarr.append(CHARSET.index(instr[i]))
+            else:
+                outarr.append(0xFF)
+        return outarr
+
+    def _get_settings(self):
+        _settings = self._memobj.settings
+        basic = RadioSettingGroup("basic", "Basic")
+        arts = RadioSettingGroup("arts", "ARTS")
+        dtmf = RadioSettingGroup("dtmf", "DTMF")
+        wires = RadioSettingGroup("wires", "WIRES")
+        misc = RadioSettingGroup("misc", "Misc")
+        top = RadioSettings(basic, arts, dtmf, wires, misc)
+
+        # BASIC
+
+        val = RadioSettingValueList(
+            self._APO, self._APO[_settings.auto_power_off])
+        rs = RadioSetting("auto_power_off", "Auto Power Off", val)
+        basic.append(rs)
+
+        val = RadioSettingValueList(
+            self._BEEP_LEVEL, self._BEEP_LEVEL[_settings.beep_level])
+        rs = RadioSetting("beep_level", "Beep Level", val)
+        basic.append(rs)
+
+        val = RadioSettingValueList(
+            self._DIM_LEVEL, self._DIM_LEVEL[_settings.lcd_dimmer])
+        rs = RadioSetting("lcd_dimmer", "Dimmer Level", val)
+        basic.append(rs)
+
+        val = RadioSettingValueList(
+            self._LAMP, self._LAMP[_settings.lamp])
+        rs = RadioSetting("lamp", "Keypad Lamp", val)
+        basic.append(rs)
+
+        val = RadioSettingValueList(
+            self._LOCK, self._LOCK[_settings.lock])
+        rs = RadioSetting("lock", "Lock", val)
+        basic.append(rs)
+
+        val = RadioSettingValueList(
+            self._NUM_1_9, self._NUM_1_9[_settings.mic_gain])
+        rs = RadioSetting("mic_gain", "Mic Gain", val)
+        basic.append(rs)
+
+        val = RadioSettingValueList(
+            self._OPEN_MSG, self._OPEN_MSG[_settings.open_message_mode])
+        rs = RadioSetting("open_message_mode",
+                          "Open Message Mode", val)
+        basic.append(rs)
+
+        val = RadioSettingValueString(0, 6,
+                                      self._decode_chars(
+                                          _settings.open_message))
+        val.set_charset(CHARSET)
+        rs = RadioSetting("open_message", "Opening Message", val)
+        basic.append(rs)
+
+        passstr = ""
+        for c in _settings.password:
+            if c < len(PASS_CHARSET):
+                passstr += PASS_CHARSET[c]
+        val = RadioSettingValueString(0, 4, passstr)
+        val.set_charset(PASS_CHARSET)
+        rs = RadioSetting("password", "Password", val)
+        basic.append(rs)
+
+        val = RadioSettingValueList(
+            self._RESUME, self._RESUME[_settings.resume])
+        rs = RadioSetting("resume", "Scan Resume", val)
+        basic.append(rs)
+
+        val = RadioSettingValueList(
+            self._MONI_TCALL, self._MONI_TCALL[_settings.moni_tcall])
+        rs = RadioSetting("moni_tcall", "MONI/T-CALL switch", val)
+        basic.append(rs)
+
+        rs = RadioSetting("scan_lamp", "Scan Lamp",
+                          RadioSettingValueBoolean(_settings.scan_lamp))
+        basic.append(rs)
+
+        rs = RadioSetting("beep", "Keypad Beep",
+                          RadioSettingValueBoolean(_settings.beep))
+        basic.append(rs)
+
+        rs = RadioSetting("busy_led", "Busy LED",
+                          RadioSettingValueBoolean(_settings.busy_led))
+        basic.append(rs)
+
+        rs = RadioSetting("bclo", "Busy Channel Lock-Out",
+                          RadioSettingValueBoolean(_settings.bclo))
+        basic.append(rs)
+
+        rs = RadioSetting("wx_alert", "WX Alert",
+                          RadioSettingValueBoolean(_settings.wx_alert))
+        basic.append(rs)
+
+        rs = RadioSetting("att", "Attenuator",
+                          RadioSettingValueBoolean(_settings.att))
+        basic.append(rs)
+
+        # ARTS
+
+        val = RadioSettingValueList(
+            self._ARTS_INT, self._ARTS_INT[_settings.arts_interval])
+        rs = RadioSetting("arts_interval", "ARTS Interval", val)
+        arts.append(rs)
+
+        val = RadioSettingValueList(
+            self._ARTSBEEP, self._ARTSBEEP[_settings.arts_beep])
+        rs = RadioSetting("arts_beep", "ARTS Beep", val)
+        arts.append(rs)
+
+        rs = RadioSetting("arts_cwid", "ARTS Send CWID",
+                          RadioSettingValueBoolean(_settings.arts_cwid))
+        arts.append(rs)
+
+        val = RadioSettingValueString(0, 16,
+                                      self._decode_chars(
+                                          _settings.arts_cwid_alpha))
+        val.set_charset(CHARSET)
+        rs = RadioSetting("arts_cwid_alpha", "ARTS CW ID", val)
+        arts.append(rs)
+
+        # DTMF
+
+        val = RadioSettingValueList(
+            self._MAN_AUTO, self._MAN_AUTO[_settings.dtmf_autodial])
+        rs = RadioSetting("dtmf_autodial", "DTMF Autodial", val)
+        dtmf.append(rs)
+
+        val = RadioSettingValueList(
+            self._NUM_0_9, self._NUM_0_9[_settings.last_dtmf])
+        rs = RadioSetting("last_dtmf", "Last DTMF Memory Set", val)
+        dtmf.append(rs)
+
+        for i in range(10):
+            name = "dtmf_" + str(i)
+            dtmfsetting = self._memobj.dtmf[i]
+            dtmfstr = ""
+            for c in dtmfsetting.memory:
+                if c < len(DTMFCHARSET):
+                    dtmfstr += DTMFCHARSET[c]
+            dtmfentry = RadioSettingValueString(0, 16, dtmfstr)
+            rs = RadioSetting(name, name.upper(), dtmfentry)
+            dtmf.append(rs)
+
+        # WIRES
+
+        val = RadioSettingValueList(
+            self._INT_CD, self._INT_CD[_settings.internet_code])
+        rs = RadioSetting("internet_code", "Internet Code", val)
+        wires.append(rs)
+
+        val = RadioSettingValueList(
+            self._INT_MD, self._INT_MD[_settings.internet_mode])
+        rs = RadioSetting("internet_mode",
+                          "Internet Link Connection mode", val)
+        wires.append(rs)
+
+        val = RadioSettingValueList(
+            self._MAN_AUTO, self._MAN_AUTO[_settings.int_autodial])
+        rs = RadioSetting("int_autodial", "Internet Autodial", val)
+        wires.append(rs)
+
+        val = RadioSettingValueList(
+            self._NUM_0_63, self._NUM_0_63[_settings.last_internet_dtmf])
+        rs = RadioSetting("last_internet_dtmf",
+                          "Last Internet DTMF Memory Set", val)
+        wires.append(rs)
+
+        for i in range(64):
+            name = "wires_dtmf_" + str(i)
+            dtmfsetting = self._memobj.internet_dtmf[i]
+            dtmfstr = ""
+            for c in dtmfsetting.memory:
+                if c < len(DTMFCHARSET):
+                    dtmfstr += DTMFCHARSET[c]
+            dtmfentry = RadioSettingValueString(0, 8, dtmfstr)
+            rs = RadioSetting(name, name.upper(), dtmfentry)
+            wires.append(rs)
+
+        # MISC
+
+        val = RadioSettingValueList(
+            self._BELL, self._BELL[_settings.bell])
+        rs = RadioSetting("bell", "CTCSS/DCS Bell", val)
+        misc.append(rs)
+
+        val = RadioSettingValueList(
+            self._CH_CNT, self._CH_CNT[_settings.channel_counter_width])
+        rs = RadioSetting("channel_counter_width",
+                          "Channel Counter Search Width", val)
+        misc.append(rs)
+
+        val = RadioSettingValueList(
+            self._EMERGENCY, self._EMERGENCY[_settings.emergency])
+        rs = RadioSetting("emergency", "Emergency alarm", val)
+        misc.append(rs)
+
+        val = RadioSettingValueList(
+            self._ON_TIMER, self._ON_TIMER[_settings.on_timer])
+        rs = RadioSetting("on_timer", "On Timer", val)
+        misc.append(rs)
+
+        rs = RadioSetting("pager_answer_back", "Pager Answer Back",
+                          RadioSettingValueBoolean(
+                              _settings.pager_answer_back))
+        misc.append(rs)
+
+        val = RadioSettingValueList(
+            self._NUM_1_50, self._NUM_1_50[_settings.pager_rx_tone1])
+        rs = RadioSetting("pager_rx_tone1", "Pager RX Tone 1", val)
+        misc.append(rs)
+
+        val = RadioSettingValueList(
+            self._NUM_1_50, self._NUM_1_50[_settings.pager_rx_tone2])
+        rs = RadioSetting("pager_rx_tone2", "Pager RX Tone 2", val)
+        misc.append(rs)
+
+        val = RadioSettingValueList(
+            self._NUM_1_50, self._NUM_1_50[_settings.pager_tx_tone1])
+        rs = RadioSetting("pager_tx_tone1", "Pager TX Tone 1", val)
+        misc.append(rs)
+
+        val = RadioSettingValueList(
+            self._NUM_1_50, self._NUM_1_50[_settings.pager_tx_tone2])
+        rs = RadioSetting("pager_tx_tone2", "Pager TX Tone 2", val)
+        misc.append(rs)
+
+        val = RadioSettingValueList(
+            self._PTT_DELAY, self._PTT_DELAY[_settings.ptt_delay])
+        rs = RadioSetting("ptt_delay", "PTT Delay", val)
+        misc.append(rs)
+
+        val = RadioSettingValueList(
+            self._RF_SQL, self._RF_SQL[_settings.rf_squelch])
+        rs = RadioSetting("rf_squelch", "RF Squelch", val)
+        misc.append(rs)
+
+        val = RadioSettingValueList(
+            self._RX_SAVE, self._RX_SAVE[_settings.rx_save])
+        rs = RadioSetting("rx_save", "RX Save", val)
+        misc.append(rs)
+
+        val = RadioSettingValueList(
+            self._TOT, self._TOT[_settings.tx_timeout])
+        rs = RadioSetting("tx_timeout", "TOT", val)
+        misc.append(rs)
+
+        val = RadioSettingValueList(
+            self._WAKEUP, self._WAKEUP[_settings.wakeup])
+        rs = RadioSetting("wakeup", "Wakeup", val)
+        misc.append(rs)
+
+        rs = RadioSetting("edge_beep", "Band-Edge Beep",
+                          RadioSettingValueBoolean(_settings.edge_beep))
+        misc.append(rs)
+
+        val = RadioSettingValueList(
+            self._VFO_MODE, self._VFO_MODE[_settings.vfo_mode])
+        rs = RadioSetting("vfo_mode", "VFO Band Edge Limiting", val)
+        misc.append(rs)
+
+        rs = RadioSetting("tone_search_mute", "Tone Search Mute",
+                          RadioSettingValueBoolean(_settings.tone_search_mute))
+        misc.append(rs)
+
+        val = RadioSettingValueList(
+            self._TS_SPEED, self._TS_SPEED[_settings.ts_speed])
+        rs = RadioSetting("ts_speed", "Tone Search Speed", val)
+        misc.append(rs)
+
+        rs = RadioSetting("dmr_wrt", "Direct Memory Recall Overwrite",
+                          RadioSettingValueBoolean(_settings.dmr_wrt))
+        misc.append(rs)
+
+        rs = RadioSetting("tx_saver", "TX Battery Saver",
+                          RadioSettingValueBoolean(_settings.tx_saver))
+        misc.append(rs)
+
+        val = RadioSettingValueList(
+            self._SMART_SEARCH, self._SMART_SEARCH[_settings.smart_search])
+        rs = RadioSetting("smart_search", "Smart Search", val)
+        misc.append(rs)
+
+        val = RadioSettingValueList(
+            self._HOME_REV, self._HOME_REV[_settings.home_rev])
+        rs = RadioSetting("home_rev", "HM/RV(EMG)R/H key", val)
+        misc.append(rs)
+
+        val = RadioSettingValueList(
+            self._MEM_W_MD, self._MEM_W_MD[_settings.memory_method])
+        rs = RadioSetting("memory_method", "Memory Write Method", val)
+        misc.append(rs)
+
+        return top
+
+    def get_settings(self):
+        try:
+            return self._get_settings()
+        except:
+            import traceback
+            pring(traceback.format_exc())
+            return None
+
+    def set_settings(self, uisettings):
+        for element in uisettings:
+            if not isinstance(element, RadioSetting):
+                self.set_settings(element)
+                continue
+            if not element.changed():
+                continue
+            try:
+                setting = element.get_name()
+                _settings = self._memobj.settings
+                if re.match('internet_dtmf_\d', setting):
+                    # set dtmf fields
+                    dtmfstr = str(element.value).strip()
+                    newval = []
+                    for i in range(0, 8):
+                        if i < len(dtmfstr):
+                            newval.append(DTMFCHARSET.index(dtmfstr[i]))
+                        else:
+                            newval.append(0xFF)
+                    idx = int(setting[-1:])
+                    _settings = self._memobj.internet_dtmf[idx]
+                    _settings.memory = newval
+                    continue
+                elif re.match('dtmf_\d', setting):
+                    # set dtmf fields
+                    dtmfstr = str(element.value).strip()
+                    newval = []
+                    for i in range(0, 16):
+                        if i < len(dtmfstr):
+                            newval.append(DTMFCHARSET.index(dtmfstr[i]))
+                        else:
+                            newval.append(0xFF)
+                    idx = int(setting[-1:])
+                    _settings = self._memobj.dtmf[idx]
+                    _settings.memory = newval
+                    continue
+                oldval = getattr(_settings, setting)
+                newval = element.value
+                if setting == "arts_cwid_alpha":
+                    newval = self._encode_chars(newval)
+                elif setting == "open_message":
+                    newval = self._encode_chars(newval, 6)
+                elif setting == "password":
+                    newval = self._encode_chars(newval, 4)
+                setattr(_settings, setting, newval)
+            except Exception, e:
+                raise



More information about the chirp_devel mailing list