[chirp_devel] [PATCH] [AT-778UV] Add Function Settings Tab to AnyTone AT-778UV [1 of 3]
Jim Unroe
Thu Nov 26 18:46:49 PST 2020
# HG changeset patch
# User Jim Unroe <rock.unroe at gmail.com>
# Date 1606445200 18000
# Thu Nov 26 21:46:40 2020 -0500
# Node ID b29aea463aabd57ca7ec4e21451895edda36dd47
# Parent 1418baa380c17365abd1837578fe892d40dee90c
[AT-778UV] Add Function Settings Tab to AnyTone AT-778UV [1 of 3]
This patch adds a Function settings tab that nearly mirrors the OEM software
related to #8447
diff -r 1418baa380c1 -r b29aea463aab chirp/drivers/anytone778uv.py
--- a/chirp/drivers/anytone778uv.py Tue Nov 24 09:34:21 2020 -0800
+++ b/chirp/drivers/anytone778uv.py Thu Nov 26 21:46:40 2020 -0500
@@ -40,6 +40,10 @@
from chirp import chirp_common, directory, memmap, errors, util
from chirp import bitwise
+from chirp.settings import RadioSettingGroup, RadioSetting, \
+ RadioSettingValueBoolean, RadioSettingValueList, \
+ RadioSettingValueString, RadioSettingValueInteger, \
+ RadioSettingValueFloat, RadioSettings, InvalidValueError
import struct
import time
@@ -110,24 +114,96 @@
u8 occupied_bitfield[32];
u8 scan_enabled_bitfield[32];
} memory_status;
+
+#seekto 0x1980;
+struct {
+ char line[7]; // starting display
+} starting_display;
+
+#seekto 0x3200;
+struct {
+ u8 unk3200:5, // 0x3200
+ beepVolume:3; // beep volume
+ u8 unk3201:4, // 0x3201
+ frequencyStep:4; // frequency step
+ u8 unk3202:6, // 0x3202
+ displayMode:2; // display mode
+ u8 unk0x3203;
+ u8 unk3204:4, // 0x3204
+ squelchLevelA:4; // squelch level a
+ u8 unk3205:4, // 0x3205
+ squelchLevelB:4; // squelch level b
+ u8 unk3206:2, // 0x3206
+ speakerVol:6; // speaker volume
+ u8 unk3207:7, // 0x3207
+ powerOnPasswd:1; // power-on password
+ u8 unk3208:6, // 0x3208
+ scanType:2; // scan type
+ u8 unk3209:6, // 0x3209
+ scanRecoveryT:2; // scan recovery time
+ u8 unk320a:7, // 0x320A
+ autoPowerOn:1; // auto power on
+ u8 unk320b:7, // 0x320B
+ main:1; // main
+ u8 unk320c:7, // 0x320C
+ dualWatch:1; // dual watch (rx way select)
+ u8 unk320d:5, // 0x320D
+ backlightBr:3; // backlight brightness
+ u8 unk320e:3, // 0x320E
+ timeOutTimer:5; // time out timer
+ u8 unk320f:6, // 0x320F
+ autoPowerOff:2; // auto power off
+ u8 unk3210:6, // 0x3210
+ tbstFrequency:2; // tbst frequency
+ u8 unk3211:7, // 0x3211
+ screenDir:1; // screen direction
+ u8 unk3212:2, // 0x3212
+ micKeyBrite:6; // hand mic key brightness
+ u8 unk3213:6, // 0x3213
+ speakerSwitch:2; // speaker switch
+ u8 unk0x3214;
+ u8 unk0x3215;
+ u8 unk0x3216;
+ u8 unk0x3217;
+ u8 unk3218:5, // 0x3218
+ steType:3; // ste type
+ u8 unk3219:6, // 0x3219
+ steFrequency:2; // ste frequency
+ u8 unk0x321A;
+ u8 unk_bit7_6:2, // 0x321B
+ monKeyFunction:1, // mon key function
+ channelLocked:1, // channel locked
+ saveChParameter:1, // save channel parameter
+ powerOnReset:1, // power on reset
+ trfEnable:1, // trf enable
+ knobMode:1; // knob mode
+} settings;
+
+#seekto 0x3240;
+struct {
+ char digits[6]; // password
+} password;
+
#seekto 0x3260;
struct {
- u8 vfoa_current_channel; // 0
- u8 unknown1;
+ u8 mrChanA; // 0x3260 mr channel a
+ u8 unknown1_0:7, // 0x3261
+ vfomrA:1; // vfo/mr mode a
u8 unknown2;
u8 unknown3;
u8 unknown4;
u8 unknown5;
u8 unknown6;
- u8 scan_channel; // 7
- u8 unknown8_0:4, // 8
+ u8 mrChanB; // 0x3267 mr channel b
+ u8 unknown8_0:4, // 0x3268
scan_active:1,
- unknown8_1:3;
+ unknown8_1:2,
+ vfomrB:1; // vfo/mr mode b
u8 unknown9;
u8 unknowna;
u8 unknownb;
u8 unknownc;
- u8 bandlimit; // d
+ u8 bandlimit; // 0x326D mode
u8 unknownd;
u8 unknowne;
u8 unknownf;
@@ -525,7 +601,7 @@
def get_features(self):
rf = chirp_common.RadioFeatures()
rf.has_bank = False
- rf.has_settings = False
+ rf.has_settings = True
rf.can_odd_split = True
rf.has_name = True
rf.has_offset = True
@@ -938,6 +1014,289 @@
_mem.unknown9 = 0x00
_mem.unknown10 = 0x00
+ def get_settings(self):
+ """Translate the MEM_FORMAT structs into setstuf in the UI"""
+ _settings = self._memobj.settings
+ _radio_settings = self._memobj.radio_settings
+ _password = self._memobj.password
+
+ # Function Setup
+ function = RadioSettingGroup("function", "Function Setup")
+ group = RadioSettings(function)
+
+ # MODE SET
+ # Channel Locked
+ rs = RadioSettingValueBoolean(_settings.channelLocked)
+ rset = RadioSetting("settings.channelLocked", "Channel locked", rs)
+ function.append(rset)
+
+ # Menu 3 - Display Mode
+ options = ["Frequency", "Channel", "Name"]
+ rs = RadioSettingValueList(options, options[_settings.displayMode])
+ rset = RadioSetting("settings.displayMode", "Display Mode", rs)
+ function.append(rset)
+
+ # VFO/MR A
+ options = ["MR", "VFO"]
+ rs = RadioSettingValueList(options, options[_radio_settings.vfomrA])
+ rset = RadioSetting("radio_settings.vfomrA", "VFO/MR mode A", rs)
+ function.append(rset)
+
+ # MR Channel A
+ options = ["%s" % x for x in range(1, 201)]
+ rs = RadioSettingValueList(options, options[_radio_settings.mrChanA])
+ rset = RadioSetting("radio_settings.mrChanA", "MR channel A", rs)
+ function.append(rset)
+
+ # VFO/MR B
+ options = ["MR", "VFO"]
+ rs = RadioSettingValueList(options, options[_radio_settings.vfomrB])
+ rset = RadioSetting("radio_settings.vfomrB", "VFO/MR mode B", rs)
+ function.append(rset)
+
+ # MR Channel B
+ options = ["%s" % x for x in range(1, 201)]
+ rs = RadioSettingValueList(options, options[_radio_settings.mrChanB])
+ rset = RadioSetting("radio_settings.mrChanB", "MR channel B", rs)
+ function.append(rset)
+
+ # DISPLAY SET
+ # Starting Display
+ name = ""
+ for i in range(7): # 0 - 7
+ name += chr(self._memobj.starting_display.line[i])
+ name = name.upper().rstrip() # remove trailing spaces
+
+ rs = RadioSettingValueString(0, 7, name)
+ rs.set_charset(chirp_common.CHARSET_ALPHANUMERIC)
+ rset = RadioSetting("starting_display.line", "Starting display", rs)
+ function.append(rset)
+
+ # Menu 11 - Backlight Brightness
+ options = ["%s" % x for x in range(1, 4)]
+ rs = RadioSettingValueList(options, options[_settings.backlightBr - 1])
+ rset = RadioSetting("settings.backlightBr", "Backlight brightness", rs)
+ function.append(rset)
+
+ # Menu 15 - Screen Direction
+ options = ["Positive", "Inverted"]
+ rs = RadioSettingValueList(options, options[_settings.screenDir])
+ rset = RadioSetting("settings.screenDir", "Screen direction", rs)
+ function.append(rset)
+
+ # Hand Mic Key Brightness
+ options = ["%s" % x for x in range(1, 32)]
+ rs = RadioSettingValueList(options, options[_settings.micKeyBrite - 1])
+ rset = RadioSetting("settings.micKeyBrite",
+ "Hand mic key brightness", rs)
+ function.append(rset)
+
+ # VOL SET
+ # Menu 1 - Beep Volume
+ options = ["OFF"] + ["%s" % x for x in range(1, 6)]
+ rs = RadioSettingValueList(options, options[_settings.beepVolume])
+ rset = RadioSetting("settings.beepVolume", "Beep volume", rs)
+ function.append(rset)
+
+ # Menu 5 - Volume level Setup
+ options = ["%s" % x for x in range(1, 37)]
+ rs = RadioSettingValueList(options, options[_settings.speakerVol - 1])
+ rset = RadioSetting("settings.speakerVol", "Speaker volume", rs)
+ function.append(rset)
+
+ # Menu 16 - Speaker Switch
+ options = ["Host on | Hand mic off", "Host on | Hand mic on",
+ "Host off | Hand mic on"]
+ rs = RadioSettingValueList(options, options[_settings.speakerSwitch])
+ rset = RadioSetting("settings.speakerSwitch", "Speaker switch", rs)
+ function.append(rset)
+
+ # STE SET
+ # STE Frequency
+ options = ["Off", "55.2 Hz", "259.2 Hz"]
+ rs = RadioSettingValueList(options, options[_settings.steFrequency])
+ rset = RadioSetting("settings.steFrequency", "STE frequency", rs)
+ function.append(rset)
+
+ # STE Type
+ options = ["Off", "Silent", "120 degrees", "180 degrees",
+ "240 degrees"]
+ rs = RadioSettingValueList(options, options[_settings.steType])
+ rset = RadioSetting("settings.steType", "STE type", rs)
+ function.append(rset)
+
+ # ON/OFF SET
+ # Power-on Password
+ rs = RadioSettingValueBoolean(_settings.powerOnPasswd)
+ rset = RadioSetting("settings.powerOnPasswd", "Power-on Password", rs)
+ function.append(rset)
+
+ # Password
+ def _char_to_str(chrx):
+ """ Remove ff pads from char array """
+ # chrx is char array
+ str1 = ""
+ for sx in chrx:
+ if int(sx) > 31 and int(sx) < 127:
+ str1 += chr(sx)
+ return str1
+
+ def _pswd_vfy(setting, obj, atrb):
+ """ Verify password is 1-6 chars, numbers 1-5 """
+ str1 = str(setting.value).strip() # initial
+ str2 = filter(lambda c: c in '0123456789', str1) # valid chars
+ if str1 != str2:
+ # Two lines due to python 73 char limit
+ sx = "Bad characters in Password"
+ raise errors.RadioError(sx)
+ str2 = str1.ljust(6, chr(00)) # pad to 6 with 00's
+ setattr(obj, atrb, str2)
+ return
+
+ sx = _char_to_str(_password.digits).strip()
+ rx = RadioSettingValueString(0, 6, sx)
+ sx = "Password (numerals 0-9)"
+ rset = RadioSetting("password.digits", sx, rx)
+ rset.set_apply_callback(_pswd_vfy, _password, "digits")
+ function.append(rset)
+
+ # Menu 9 - Auto Power On
+ rs = RadioSettingValueBoolean(_settings.autoPowerOn)
+ rset = RadioSetting("settings.autoPowerOn", "Auto power on", rs)
+ function.append(rset)
+
+ # Menu 13 - Auto Power Off
+ options = ["Off", "30 minutes", "60 minutes", "120 minutes"]
+ rs = RadioSettingValueList(options, options[_settings.autoPowerOff])
+ rset = RadioSetting("settings.autoPowerOff", "Auto power off", rs)
+ function.append(rset)
+
+ # Power On Reset Enable
+ rs = RadioSettingValueBoolean(_settings.powerOnReset)
+ rset = RadioSetting("settings.powerOnReset", "Power on reset", rs)
+ function.append(rset)
+
+ # FUNCTION SET
+ # Menu 4 - Squelch Level A
+ options = ["OFF"] + ["%s" % x for x in range(1, 10)]
+ rs = RadioSettingValueList(options, options[_settings.squelchLevelA])
+ rset = RadioSetting("settings.squelchLevelA", "Squelch level A", rs)
+ function.append(rset)
+
+ # Squelch Level B
+ options = ["OFF"] + ["%s" % x for x in range(1, 10)]
+ rs = RadioSettingValueList(options, options[_settings.squelchLevelB])
+ rset = RadioSetting("settings.squelchLevelB", "Squelch level B", rs)
+ function.append(rset)
+
+ # Menu 7 - Scan Type
+ options = ["Time operated (TO)", "Carrier operated (CO)",
+ "Search (SE)"]
+ rs = RadioSettingValueList(options, options[_settings.scanType])
+ rset = RadioSetting("settings.scanType", "Scan mode", rs)
+ function.append(rset)
+
+ # Menu 8 - Scan Recovery Time
+ options = ["%s seconds" % x for x in range(5, 20, 5)]
+ rs = RadioSettingValueList(options, options[_settings.scanRecoveryT])
+ rset = RadioSetting("settings.scanRecoveryT", "Scan recovery time", rs)
+ function.append(rset)
+
+ # Main
+ options = ["A", "B"]
+ rs = RadioSettingValueList(options, options[_settings.main])
+ rset = RadioSetting("settings.main", "Main", rs)
+ function.append(rset)
+
+ # Menu 10 - Dual Watch (RX Way Select)
+ rs = RadioSettingValueBoolean(_settings.dualWatch)
+ rset = RadioSetting("settings.dualWatch", "Dual watch", rs)
+ function.append(rset)
+
+ # Menu 12 - Time Out Timer
+ options = ["OFF"] + ["%s minutes" % x for x in range(1, 31)]
+ rs = RadioSettingValueList(options, options[_settings.timeOutTimer])
+ rset = RadioSetting("settings.timeOutTimer", "Time out timer", rs)
+ function.append(rset)
+
+ # TBST Frequency
+ options = ["1000 Hz", "1450 Hz", "1750 Hz", "2100 Hz"]
+ rs = RadioSettingValueList(options, options[_settings.tbstFrequency])
+ rset = RadioSetting("settings.tbstFrequency", "TBST frequency", rs)
+ function.append(rset)
+
+ # Save Channel Perameter
+ rs = RadioSettingValueBoolean(_settings.saveChParameter)
+ rset = RadioSetting("settings.saveChParameter",
+ "Save channel parameter", rs)
+ function.append(rset)
+
+ # MON Key Function
+ options = ["Squelch off momentary", "Squelch off"]
+ rs = RadioSettingValueList(options, options[_settings.monKeyFunction])
+ rset = RadioSetting("settings.monKeyFunction", "MON key function", rs)
+ function.append(rset)
+
+ # Frequency Step
+ options = ["2.5 KHz", "5 KHz", "6.25 KHz", "10 KHz", "12.5 KHz",
+ "20 KHz", "25 KHz", "30 KHz", "50 KHz"]
+ rs = RadioSettingValueList(options, options[_settings.frequencyStep])
+ rset = RadioSetting("settings.frequencyStep", "Frequency step", rs)
+ function.append(rset)
+
+ # Knob Mode
+ options = ["Volume", "Channel"]
+ rs = RadioSettingValueList(options, options[_settings.knobMode])
+ rset = RadioSetting("settings.knobMode", "Knob mode", rs)
+ function.append(rset)
+
+ # TRF Enable
+ rs = RadioSettingValueBoolean(_settings.trfEnable)
+ rset = RadioSetting("settings.trfEnable", "TRF enable", rs)
+ function.append(rset)
+
+ return group
+
+ def set_settings(self, settings):
+ _settings = self._memobj.settings
+ _mem = self._memobj
+ for element in settings:
+ if not isinstance(element, RadioSetting):
+ self.set_settings(element)
+ continue
+ else:
+ try:
+ name = element.get_name()
+ if "." in name:
+ bits = name.split(".")
+ obj = self._memobj
+ for bit in bits[:-1]:
+ if "/" in bit:
+ bit, index = bit.split("/", 1)
+ index = int(index)
+ obj = getattr(obj, bit)[index]
+ else:
+ obj = getattr(obj, bit)
+ setting = bits[-1]
+ else:
+ obj = _settings
+ setting = element.get_name()
+
+ if element.has_apply_callback():
+ LOG.debug("Using apply callback")
+ element.run_apply_callback()
+ elif setting == "backlightBr":
+ setattr(obj, setting, int(element.value) + 1)
+ elif setting == "micKeyBrite":
+ setattr(obj, setting, int(element.value) + 1)
+ elif setting == "speakerVol":
+ setattr(obj, setting, int(element.value) + 1)
+ elif element.value.get_mutable():
+ LOG.debug("Setting %s = %s" % (setting, element.value))
+ setattr(obj, setting, element.value)
+ except Exception, e:
+ LOG.debug(element.get_name())
+ raise
if has_future:
@directory.register
More information about the chirp_devel
mailing list