[chirp_devel] [PATCH] [FT2900] Add support for settings. Fix #2867
# HG changeset patch # User Richard Cochran ag6qr@sonic.net # Date 1456721059 28800 # Sun Feb 28 20:44:19 2016 -0800 # Node ID 432300d60fae4c517c8f98f3d52aef115c9a96e8 # Parent 1c398653986fb3e0a50bfbbc58f1a2f5c9ab2b95 [FT2900] Add support for settings. Fix #2867 This submission adds support for settings to the ft-2900/ft-1900 driver. Special thanks to Chris Fosnight for getting a start at the settings code. He gave his code to me (Rich Cochran), and I finished implementing more settings, and tested both reading and writing of all the settings. Settings are grouped into categories according to the manual, pp 72-73.
Issue #2867
diff -r 1c398653986f -r 432300d60fae chirp/drivers/ft2900.py --- a/chirp/drivers/ft2900.py Sat Feb 27 17:33:04 2016 -0800 +++ b/chirp/drivers/ft2900.py Sun Feb 28 20:44:19 2016 -0800 @@ -1,6 +1,7 @@ # Copyright 2011 Dan Smith dsmith@danplanet.com # # FT-2900-specific modifications by Richard Cochran, ag6qr@sonic.net +# Initial work on settings by Chris Fosnight, chris.fosnight@gmail.com # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -21,6 +22,8 @@
from chirp import util, memmap, chirp_common, bitwise, directory, errors from chirp.drivers.yaesu_clone import YaesuCloneModeRadio +from chirp.settings import RadioSetting, RadioSettingGroup, \ + RadioSettingValueList, RadioSettingValueString, RadioSettings
from textwrap import dedent
@@ -164,6 +167,87 @@ _send(radio.pipe, chr(cs & 0xFF))
MEM_FORMAT = """ +#seekto 0x0080; +struct { + u8 apo; + u8 arts_beep; + u8 bell; + u8 dimmer; + u8 cw_id_string[16]; + u8 cw_trng; + u8 x95; + u8 x96; + u8 x97; + u8 int_cd; + u8 int_set; + u8 x9A; + u8 x9B; + u8 lock; + u8 x9D; + u8 mic_gain; + u8 open_msg; + u8 openMsg_Text[6]; + u8 rf_sql; + u8 unk:6, + pag_abk:1, + unk:1; + u8 pag_cdr_1; + u8 pag_cdr_2; + u8 pag_cdt_1; + u8 pag_cdt_2; + u8 prog_p1; + u8 xAD; + u8 prog_p2; + u8 xAF; + u8 prog_p3; + u8 xB1; + u8 prog_p4; + u8 xB3; + u8 resume; + u8 tot; + u8 unk:1, + cw_id:1, + unk:1, + ts_speed:1, + ars:1, + unk:2, + dtmf_mode:1; + u8 unk:1, + ts_mut:1 + wires_auto:1, + busy_lockout:1, + edge_beep:1, + unk:3; + u8 unk:2, + s_search:1, + unk:2, + cw_trng_units:1, + unk:2; + u8 dtmf_speed:1, + unk:2, + arts_interval:1, + unk:1, + inverted_dcs:1, + unk:1, + mw_mode:1; + u8 unk:2, + wires_mode:1, + wx_alert:1, + unk:1, + wx_vol_max:1, + revert:1, + unk:1; + u8 vfo_scan; + u8 scan_mode; + u8 dtmf_delay; + u8 beep; + u8 xBF; +} settings; + +#seekto 0x00d0; + u8 passwd[4]; + u8 mbs; + #seekto 0x00c0; struct { u16 in_use; @@ -175,6 +259,11 @@ #seekto 0x00f0; u8 curChannelMem[20];
+#seekto 0x1e0; +struct { + u8 dtmf_string[16]; +} dtmf_strings[10]; + #seekto 0x0127; u8 curChannelNum;
@@ -424,6 +513,7 @@ rf.has_dtcs_polarity = False rf.has_bank = True rf.has_bank_names = True + rf.has_settings = True
rf.valid_tuning_steps = STEPS rf.valid_modes = MODES @@ -620,6 +710,496 @@
LOG.debug("encoded mem\n%s\n" % (util.hexprint(_mem.get_raw()[0:20])))
+ def get_settings(self): + _settings = self._memobj.settings + _dtmf_strings = self._memobj.dtmf_strings + _passwd = self._memobj.passwd + + repeater = RadioSettingGroup("repeater", "Repeater Settings") + ctcss = RadioSettingGroup("ctcss", "CTCSS/DCS/EPCS Settings") + arts = RadioSettingGroup("arts", "ARTS Settings") + mbls = RadioSettingGroup("banks", "Memory Settings") + scan = RadioSettingGroup("scan", "Scan Settings") + dtmf = RadioSettingGroup("dtmf", "DTMF Settings") + wires = RadioSettingGroup("wires", "WiRES(tm) Settings") + switch = RadioSettingGroup("switch", "Switch/Knob Settings") + disp = RadioSettingGroup("disp", "Display Settings") + misc = RadioSettingGroup("misc", "Miscellaneous Settings") + + setmode = RadioSettings(repeater, ctcss, arts, mbls, scan, + dtmf, wires, switch, disp, misc) + + # numbers and names of settings refer to the way they're + # presented in the set menu, as well as the list starting on + # page 74 of the manual + + # 1 APO + opts = ["Off", "30 Min", "1 Hour", "3 Hour", "5 Hour", "8 Hour"] + misc.append( + RadioSetting( + "apo", "Automatic Power Off", + RadioSettingValueList(opts, opts[_settings.apo]))) + + # 2 AR.BEP + opts = ["Off", "In Range", "Always"] + arts.append( + RadioSetting( + "arts_beep", "ARTS Beep", + RadioSettingValueList(opts, opts[_settings.arts_beep]))) + + # 3 AR.INT + opts = ["15 Sec", "25 Sec"] + arts.append( + RadioSetting( + "arts_interval", "ARTS Polling Interval", + RadioSettingValueList(opts, opts[_settings.arts_interval]))) + + # 4 ARS + opts = ["Off", "On"] + repeater.append( + RadioSetting( + "ars", "Automatic Repeater Shift", + RadioSettingValueList(opts, opts[_settings.ars]))) + + # 5 BCLO + opts = ["Off", "On"] + misc.append(RadioSetting( + "busy_lockout", "Busy Channel Lock-Out", + RadioSettingValueList(opts, opts[_settings.busy_lockout]))) + + # 6 BEEP + opts = ["Off", "Key+Scan", "Key"] + switch.append(RadioSetting( + "beep", "Enable the Beeper", + RadioSettingValueList(opts, opts[_settings.beep]))) + + # 7 BELL + opts = ["Off", "1", "3", "5", "8", "Continuous"] + ctcss.append(RadioSetting("bell", "Bell Repetitions", + RadioSettingValueList(opts, opts[_settings.bell]))) + + # 8 BNK.LNK + for i in range(0, 8): + opts = ["Off", "On"] + mbs = (self._memobj.mbs >> i) & 1 + rs = RadioSetting("mbs%i" % i, "Bank %s Scan" % (i + 1), + RadioSettingValueList(opts, opts[mbs])) + + def apply_mbs(s, index): + if int(s.value): + self._memobj.mbs |= (1 << index) + else: + self._memobj.mbs &= ~(1 << index) + rs.set_apply_callback(apply_mbs, i) + mbls.append(rs) + + # 9 BNK.NM - A per-bank attribute, nothing to do here. + + # 10 CLK.SFT - A per-channel attribute, nothing to do here. + + # 11 CW.ID + opts = ["Off", "On"] + arts.append(RadioSetting("cw_id", "CW ID Enable", + RadioSettingValueList(opts, opts[_settings.cw_id]))) + + cw_id_text = "" + for i in _settings.cw_id_string: + try: + cw_id_text += CHARSET[i & 0x7F] + except IndexError: + if i != 0xff: + LOG.debug("unknown char index in cw id: %x " % (i)) + + val = RadioSettingValueString(0, 16, cw_id_text, True) + val.set_charset(CHARSET + "abcdefghijklmnopqrstuvwxyz") + rs = RadioSetting("cw_id_string", "CW Identifier Text", val) + + def apply_cw_id(s): + str = s.value.get_value().upper().rstrip() + mval = "" + mval = [chr(CHARSET.index(x)) for x in str] + for x in range(len(mval), 16): + mval.append(chr(0xff)) + for x in range(0, 16): + _settings.cw_id_string[x] = ord(mval[x]) + rs.set_apply_callback(apply_cw_id) + arts.append(rs) + + # 12 CWTRNG + opts = ["Off", "4WPM", "5WPM", "6WPM", "7WPM", "8WPM", "9WPM", + "10WPM", "11WPM", "12WPM", "13WPM", "15WPM", "17WPM", + "20WPM", "24WPM", "30WPM", "40WPM"] + misc.append(RadioSetting("cw_trng", "CW Training", + RadioSettingValueList(opts, opts[_settings.cw_trng]))) + + # todo: make the setting of the units here affect the display + # of the speed. Not critical, but would be slick. + opts = ["CPM", "WPM"] + misc.append(RadioSetting("cw_trng_units", "CW Training Units", + RadioSettingValueList(opts, + opts[_settings.cw_trng_units]))) + + # 13 DC VLT - a read-only status, so nothing to do here + + # 14 DCS CD - A per-channel attribute, nothing to do here + + # 15 DCS.RV + opts = ["Disabled", "Enabled"] + ctcss.append(RadioSetting( + "inverted_dcs", + ""Inverted" DCS Code Decoding", + RadioSettingValueList(opts, + opts[_settings.inverted_dcs]))) + + # 16 DIMMER + opts = ["Off"] + ["Level %d" % (x) for x in range(1, 11)] + disp.append(RadioSetting("dimmer", "Dimmer", + RadioSettingValueList(opts, + opts[_settings + .dimmer]))) + + # 17 DT.A/M + opts = ["Manual", "Auto"] + dtmf.append(RadioSetting("dtmf_mode", "DTMF Autodialer", + RadioSettingValueList(opts, + opts[_settings + .dtmf_mode]))) + + # 18 DT.DLY + opts = ["50 ms", "250 ms", "450 ms", "750 ms", "1000 ms"] + dtmf.append(RadioSetting("dtmf_delay", "DTMF Autodialer Delay Time", + RadioSettingValueList(opts, + opts[_settings + .dtmf_delay]))) + + # 19 DT.SET + for memslot in range(0, 10): + dtmf_memory = "" + for i in _dtmf_strings[memslot].dtmf_string: + if i != 0xFF: + try: + dtmf_memory += CHARSET[i] + except IndexError: + LOG.debug("unknown char index in dtmf: %x " % (i)) + + val = RadioSettingValueString(0, 16, dtmf_memory, True) + val.set_charset(CHARSET + "abcdef") + rs = RadioSetting("dtmf_string_%d" % memslot, + "DTMF Memory %d" % memslot, val) + + def apply_dtmf(s, i): + LOG.debug("applying dtmf for %x\n" % i) + str = s.value.get_value().upper().rstrip() + LOG.debug("str is %s\n" % str) + mval = "" + mval = [chr(CHARSET.index(x)) for x in str] + for x in range(len(mval), 16): + mval.append(chr(0xff)) + for x in range(0, 16): + _dtmf_strings[i].dtmf_string[x] = ord(mval[x]) + rs.set_apply_callback(apply_dtmf, memslot) + dtmf.append(rs) + + # 20 DT.SPD + opts = ["50 ms", "100 ms"] + dtmf.append(RadioSetting("dtmf_speed", + "DTMF Autodialer Sending Speed", + RadioSettingValueList(opts, + opts[_settings. + dtmf_speed]))) + + # 21 EDG.BEP + opts = ["Off", "On"] + mbls.append(RadioSetting("edge_beep", "Band Edge Beeper", + RadioSettingValueList(opts, + opts[_settings. + edge_beep]))) + + # 22 INT.CD + opts = ["DTMF %X" % (x) for x in range(0, 16)] + wires.append(RadioSetting("int_cd", "Access Number for WiRES(TM)", + RadioSettingValueList(opts, opts[_settings.int_cd]))) + + # 23 ING MD + opts = ["Sister Radio Group", "Friends Radio Group"] + wires.append(RadioSetting("wires_mode", + "Internet Link Connection Mode", + RadioSettingValueList(opts, + opts[_settings. + wires_mode]))) + + # 24 INT.A/M + opts = ["Manual", "Auto"] + wires.append(RadioSetting("wires_auto", "Internet Link Autodialer", + RadioSettingValueList(opts, + opts[_settings + .wires_auto]))) + # 25 INT.SET + opts = ["F%d" % (x) for x in range(0, 10)] + + wires.append(RadioSetting("int_set", "Memory Register for " + "non-WiRES Internet", + RadioSettingValueList(opts, + opts[_settings + .int_set]))) + + # 26 LOCK + opts = ["Key", "Dial", "Key + Dial", "PTT", + "Key + PTT", "Dial + PTT", "All"] + switch.append(RadioSetting("lock", "Control Locking", + RadioSettingValueList(opts, + opts[_settings + .lock]))) + + # 27 MCGAIN + opts = ["Level %d" % (x) for x in range(1, 10)] + misc.append(RadioSetting("mic_gain", "Microphone Gain", + RadioSettingValueList(opts, + opts[_settings + .mic_gain]))) + + # 28 MEM.SCN + opts = ["Tag 1", "Tag 2", "All Channels"] + rs = RadioSetting("scan_mode", "Memory Scan Mode", + RadioSettingValueList(opts, + opts[_settings + .scan_mode - 1])) + # this setting is unusual in that it starts at 1 instead of 0. + # that is, index 1 corresponds to "Tag 1", and index 0 is invalid. + # so we create a custom callback to handle this. + + def apply_scan_mode(s): + myopts = ["Tag 1", "Tag 2", "All Channels"] + _settings.scan_mode = myopts.index(s.value.get_value()) + 1 + rs.set_apply_callback(apply_scan_mode) + mbls.append(rs) + + # 29 MW MD + opts = ["Lower", "Next"] + mbls.append(RadioSetting("mw_mode", "Memory Write Mode", + RadioSettingValueList(opts, + opts[_settings + .mw_mode]))) + + # 30 NM SET - This is per channel, so nothing to do here + + # 31 OPN.MSG + opts = ["Off", "DC Supply Voltage", "Text Message"] + disp.append(RadioSetting("open_msg", "Opening Message Type", + RadioSettingValueList(opts, + opts[_settings. + open_msg]))) + + openmsg = "" + for i in _settings.openMsg_Text: + try: + openmsg += CHARSET[i & 0x7F] + except IndexError: + if i != 0xff: + LOG.debug("unknown char index in openmsg: %x " % (i)) + + val = RadioSettingValueString(0, 6, openmsg, True) + val.set_charset(CHARSET + "abcdefghijklmnopqrstuvwxyz") + rs = RadioSetting("openMsg_Text", "Opening Message Text", val) + + def apply_openmsg(s): + str = s.value.get_value().upper().rstrip() + mval = "" + mval = [chr(CHARSET.index(x)) for x in str] + for x in range(len(mval), 6): + mval.append(chr(0xff)) + for x in range(0, 6): + _settings.openMsg_Text[x] = ord(mval[x]) + rs.set_apply_callback(apply_openmsg) + disp.append(rs) + + # 32 PAGER - a per-channel attribute + + # 33 PAG.ABK + opts = ["Off", "On"] + ctcss.append(RadioSetting("pag_abk", "Paging Answer Back", + RadioSettingValueList(opts, + opts[_settings + .pag_abk]))) + + # 34 PAG.CDR + opts = ["%2.2d" % (x) for x in range(1, 50)] + ctcss.append(RadioSetting("pag_cdr_1", "Receive Page Code 1", + RadioSettingValueList(opts, + opts[_settings + .pag_cdr_1]))) + + ctcss.append(RadioSetting("pag_cdr_2", "Receive Page Code 2", + RadioSettingValueList(opts, + opts[_settings + .pag_cdr_2]))) + + # 35 PAG.CDT + opts = ["%2.2d" % (x) for x in range(1, 50)] + ctcss.append(RadioSetting("pag_cdt_1", "Transmit Page Code 1", + RadioSettingValueList(opts, + opts[_settings + .pag_cdt_1]))) + + ctcss.append(RadioSetting("pag_cdt_2", "Transmit Page Code 2", + RadioSettingValueList(opts, + opts[_settings + .pag_cdt_2]))) + + # Common Button Options + button_opts = ["Squelch Off", "Weather", "Smart Search", + "Tone Scan", "Scan", "T Call", "ARTS"] + + # 36 PRG P1 + opts = button_opts + ["DC Volts"] + switch.append(RadioSetting( + "prog_p1", "P1 Button", + RadioSettingValueList(opts, opts[_settings.prog_p1]))) + + # 37 PRG P2 + opts = button_opts + ["Dimmer"] + switch.append(RadioSetting( + "prog_p2", "P2 Button", + RadioSettingValueList(opts, opts[_settings.prog_p2]))) + + # 38 PRG P3 + opts = button_opts + ["Mic Gain"] + switch.append(RadioSetting( + "prog_p3", "P3 Button", + RadioSettingValueList(opts, opts[_settings.prog_p3]))) + + # 39 PRG P4 + opts = button_opts + ["Skip"] + switch.append(RadioSetting( + "prog_p4", "P4 Button", + RadioSettingValueList(opts, opts[_settings.prog_p4]))) + + # 40 PSWD + password = "" + for i in _passwd: + if i != 0xFF: + try: + password += CHARSET[i] + except IndexError: + LOG.debug("unknown char index in password: %x " % (i)) + + val = RadioSettingValueString(0, 4, password, True) + val.set_charset(CHARSET[0:15] + "abcdef ") + rs = RadioSetting("passwd", "Password", val) + + def apply_password(s): + str = s.value.get_value().upper().rstrip() + mval = "" + mval = [chr(CHARSET.index(x)) for x in str] + for x in range(len(mval), 4): + mval.append(chr(0xff)) + for x in range(0, 4): + _passwd[x] = ord(mval[x]) + rs.set_apply_callback(apply_password) + misc.append(rs) + + # 41 RESUME + opts = ["3 Sec", "5 Sec", "10 Sec", "Busy", "Hold"] + scan.append(RadioSetting("resume", "Scan Resume Mode", + RadioSettingValueList(opts, opts[_settings.resume]))) + + # 42 RF.SQL + opts = ["Off"] + ["S-%d" % (x) for x in range(1, 10)] + misc.append(RadioSetting("rf_sql", "RF Squelch Threshold", + RadioSettingValueList(opts, opts[_settings.rf_sql]))) + + # 43 RPT - per channel attribute, nothing to do here + + # 44 RVRT + opts = ["Off", "On"] + misc.append(RadioSetting("revert", "Priority Revert", + RadioSettingValueList(opts, opts[_settings.revert]))) + + # 45 S.SRCH + opts = ["Single", "Continuous"] + misc.append(RadioSetting("s_search", "Smart Search Sweep Mode", + RadioSettingValueList(opts, opts[_settings.s_search]))) + + # 46 SHIFT - per channel setting, nothing to do here + + # 47 SKIP = per channel setting, nothing to do here + + # 48 SPLIT - per channel attribute, nothing to do here + + # 49 SQL.TYP - per channel attribute, nothing to do here + + # 50 STEP - per channel attribute, nothing to do here + + # 51 TEMP - read-only status, nothing to do here + + # 52 TN FRQ - per channel attribute, nothing to do here + + # 53 TOT + opts = ["Off", "1 Min", "3 Min", "5 Min", "10 Min"] + misc.append(RadioSetting("tot", "Timeout Timer", + RadioSettingValueList(opts, + opts[_settings.tot]))) + + # 54 TS MUT + opts = ["Off", "On"] + ctcss.append(RadioSetting("ts_mut", "Tone Search Mute", + RadioSettingValueList(opts, + opts[_settings + .ts_mut]))) + + # 55 TS SPEED + opts = ["Fast", "Slow"] + ctcss.append(RadioSetting("ts_speed", "Tone Search Scanner Speed", + RadioSettingValueList(opts, + opts[_settings + .ts_speed]))) + + # 56 VFO.SCN + opts = ["+/- 1MHz", "+/- 2MHz", "+/-5MHz", "All"] + scan.append(RadioSetting("vfo_scan", "VFO Scanner Width", + RadioSettingValueList(opts, + opts[_settings + .vfo_scan]))) + + # 57 WX.ALT + opts = ["Off", "On"] + misc.append(RadioSetting("wx_alert", "Weather Alert Scan", + RadioSettingValueList(opts, opts[_settings.wx_alert]))) + + # 58 WX.VOL + opts = ["Normal", "Maximum"] + misc.append(RadioSetting("wx_vol_max", "Weather Alert Volume", + RadioSettingValueList(opts, opts[_settings.wx_vol_max]))) + + # 59 W/N DV - this is a per-channel attribute, nothing to do here + + return setmode + + def set_settings(self, uisettings): + _settings = self._memobj.settings + for element in uisettings: + if not isinstance(element, RadioSetting): + self.set_settings(element) + continue + if not element.changed(): + continue + + try: + name = element.get_name() + value = element.value + + if element.has_apply_callback(): + LOG.debug("Using apply callback") + element.run_apply_callback() + else: + obj = getattr(_settings, name) + setattr(_settings, name, value) + + LOG.debug("Setting %s: %s" % (name, value)) + except Exception, e: + LOG.debug(element.get_name()) + raise + def get_bank_model(self): return FT2900BankModel(self)
# HG changeset patch # User Richard Cochran ag6qr@sonic.net # Date 1456721059 28800 # Sun Feb 28 20:44:19 2016 -0800 # Node ID 432300d60fae4c517c8f98f3d52aef115c9a96e8 # Parent 1c398653986fb3e0a50bfbbc58f1a2f5c9ab2b95 [FT2900] Add support for settings. Fix #2867 This submission adds support for settings to the ft-2900/ft-1900 driver. Special thanks to Chris Fosnight for getting a start at the settings code. He gave his code to me (Rich Cochran), and I finished implementing more settings, and tested both reading and writing of all the settings. Settings are grouped into categories according to the manual, pp 72-73.
I didn't notice this until now, but this brought the current failure we're seeing. The 2900 and 2900Mod radios are not distinguishable for file detection.
Can you figure out some way to do that so we can get the tests fixed up?
Thanks!
--Dan
Yeah, I’ll take a look.
For clarification, the patch quoted below is the one that added support of settings to all of the FT1900/FT2900 series, and I don’t believe that particular patch is what was causing the problem. I suspect you’re talking about another submission, which added support for a modded version of the FT2900. That was submitted in a similar timeframe, and is here: http://chirp.danplanet.com/projects/chirp/repository/revisions/1c398653986f http://chirp.danplanet.com/projects/chirp/repository/revisions/1c398653986f
I’m now digging through the logic in that test. It’s not obvious to me how adding the support of a modified radio is different from adding support of a European version of the FT-2900/FT-1900 radio, which was done a long time ago (a year or more? I don’t remember, but it was long ago). In both cases, we didn’t add a new .img file to the test cases, there was just a new class added with the same settings overridden.
Anyway, I’ve got to step away from the computer for a while right now, but I just wanted to let you know I’ll be digging into this.
Richard Cochran ag6qr@sonic.net
Sent from my Nye Viking Speed-X
On Apr 1, 2016, at 12:32 PM, Dan Smith dsmith@danplanet.com wrote:
# HG changeset patch # User Richard Cochran ag6qr@sonic.net # Date 1456721059 28800 # Sun Feb 28 20:44:19 2016 -0800 # Node ID 432300d60fae4c517c8f98f3d52aef115c9a96e8 # Parent 1c398653986fb3e0a50bfbbc58f1a2f5c9ab2b95 [FT2900] Add support for settings. Fix #2867 This submission adds support for settings to the ft-2900/ft-1900 driver. Special thanks to Chris Fosnight for getting a start at the settings code. He gave his code to me (Rich Cochran), and I finished implementing more settings, and tested both reading and writing of all the settings. Settings are grouped into categories according to the manual, pp 72-73.
I didn't notice this until now, but this brought the current failure we're seeing. The 2900 and 2900Mod radios are not distinguishable for file detection.
Can you figure out some way to do that so we can get the tests fixed up?
Thanks!
--Dan
For clarification, the patch quoted below is the one that added support of settings to all of the FT1900/FT2900 series, and I don’t believe that particular patch is what was causing the problem. I suspect you’re talking about another submission, which added support for a modded version of the FT2900. That was submitted in a similar timeframe, and is here: http://chirp.danplanet.com/projects/chirp/repository/revisions/1c398653986f
Yep, sorry, my bad :)
I’m now digging through the logic in that test. It’s not obvious to me how adding the support of a modified radio is different from adding support of a European version of the FT-2900/FT-1900 radio, which was done a long time ago (a year or more? I don’t remember, but it was long ago). In both cases, we didn’t add a new .img file to the test cases, there was just a new class added with the same settings overridden.
Because the euro version has a different ident string or something. We've got to be able to detect which model class to use from the file when we open it. Some radios do that by file size, while others look at some identification bytes inside. Some a combination of both.
If the mod bits are stored in the file anywhere, then you can just modify both classes to look at the mod bytes and return the appropriate match. Right now the class uses file size only:
http://chirp.danplanet.com/projects/chirp/repository/entry/chirp/drivers/ft2...
If you look at a couple other examples in other files you'll see some of the more complicated ones.
Anyway, I’ve got to step away from the computer for a while right now, but I just wanted to let you know I’ll be digging into this.
No problem, thanks much!
--Dan
Just a few cents here from memory (which might not be worth much over time-depreciation ;) long: I recall from playing with several yaesu radios (VX-2/3/6/170?,FT-90,FT-7900) that the memory layouts and protocols were quite similar.They usually started with some ident (ascii?) string, e.g. AH017$, whch identified the model class, e.g. VX-2 vs VX-3.That was followed by a few bytes (1-3 or 4 cant recall exactly), which seemed to indicate either the regional variation (EU vs US), and also if it was "modded" or stock. I want to say that the first byte might have been a direct result of the jumper configuration (which I think also had to do with the regional setting and mods). Let's call this the "feature bits".
Note that whenever you changed jumpers, you were supposed to default/reset the radio, in order for the change to take effect. (It seemed that the radio used the feature bits in the running image, not the jumper settings, and the jumper settings were only transferred to running image during a default.) So after changing jumpers, defaulting, and downloading, some of those feature bits in the image would change. I attempted to exploit this, as I was trying to find a way to "soft-mod" the radio by tweaking these bits in the image, however the radio would not accept the image with the modded bits (if they did not match the bits in the running radio image). The result of this was that the radio would refuse to accept a clone image which was previously made from that same radio after you changed the jumper settings (and defaulted). So what this means for chirp interaction is that although the model id was the same, there differences in the features, and they are not portable between direct images. As with other radios, the best pattern is to pull a fresh image from the radio, and import the channels from previous image of the radio. You might also be able to detect the capabilities of the radio by looking at these feature bits (e.g. frequency range of EU vs US, unlocked, etc). short: The summary is that I dont think you need to treat the variants of a radio model for Yaesu as separate models in chirp.I think these feature bits are just attributes of model capabilities.
-Jens From: Dan Smith via chirp_devel chirp_devel@intrepid.danplanet.com To: Cc: chirp_devel@intrepid.danplanet.com Sent: Friday, April 1, 2016 3:25 PM Subject: Re: [chirp_devel] [PATCH] [FT2900] Add support for settings. Fix #2867
For clarification, the patch quoted below is the one that added support of settings to all of the FT1900/FT2900 series, and I don’t believe that particular patch is what was causing the problem. I suspect you’re talking about another submission, which added support for a modded version of the FT2900. That was submitted in a similar timeframe, and is here: http://chirp.danplanet.com/projects/chirp/repository/revisions/1c398653986f
Yep, sorry, my bad :)
I’m now digging through the logic in that test. It’s not obvious to me how adding the support of a modified radio is different from adding support of a European version of the FT-2900/FT-1900 radio, which was done a long time ago (a year or more? I don’t remember, but it was long ago). In both cases, we didn’t add a new .img file to the test cases, there was just a new class added with the same settings overridden.
Because the euro version has a different ident string or something. We've got to be able to detect which model class to use from the file when we open it. Some radios do that by file size, while others look at some identification bytes inside. Some a combination of both.
If the mod bits are stored in the file anywhere, then you can just modify both classes to look at the mod bytes and return the appropriate match. Right now the class uses file size only:
http://chirp.danplanet.com/projects/chirp/repository/entry/chirp/drivers/ft2...
If you look at a couple other examples in other files you'll see some of the more complicated ones.
Anyway, I’ve got to step away from the computer for a while right now, but I just wanted to let you know I’ll be digging into this.
No problem, thanks much!
--Dan _______________________________________________ chirp_devel mailing list chirp_devel@intrepid.danplanet.com http://intrepid.danplanet.com/mailman/listinfo/chirp_devel Developer docs: http://chirp.danplanet.com/projects/chirp/wiki/Developers
participants (3)
-
af5mi@yahoo.com
-
Dan Smith
-
Richard Cochran