On 2013-02-19 06:38, Dan Smith wrote:
Okay, here is my ID-51 (id51.py) new driver. Also included is an image file for same.
Could you put it into the proper patch format?
http://chirp.danplanet.com/projects/chirp/wiki/DevelopersProcess#Submitting-...
OK, I'm confoozed. I previously read that page, and I know that's the correct format for a *change*. Once you/me have decided that the changes I have for the ID-31 are appropriate as well, those will obviously be in patch format. However, for a new driver, the whole file is new, so I don't understand the procedure for that. For the image file, your page says:
/If you are adding a new driver, you will need to add an image to the //|tests/images/|//directory which is correctly named for your model. *These do not communicate well in patch form*, so just send a sample image to the development mailing list to accompany your patch submission./
So, that's what I did. "hg status -mar" only shows the id31.py changes, which I'm not ready (per above) to submit yet. I included the complete id51.py file in my previous eMail so you could see the differences (via the two diffs) before I formally submitted a patch.
So, just now I did "hg add chirp/id51.py", and now "hg status -mar" shows the id51.py. I then did "hg diff" and got the output shown at the bottom of this eMail. Note that the diff does not (yet) include adding the D-Star tag field into the "mycall" structure in id31.py; that needs to be verified as needed (98% guess it's needed).
I didn't use the one in tests/images because there isn't one.
There is, but I suppose you're using a tarball snapshot which perhaps doesn't have it:
% ls tests/images/Icom_ID-31A.img -l -rw-r--r-- 1 dan dan 86K May 6 2012 tests/images/Icom_ID-31A.img
No, I did a "hg clone http://d-rats.com/hg/chirp.hg" I got lots of test files, but none for the ID-31. When I ran the tests, it ran one for the ID-51 (I suppose because I had an image file there -- the test passed), but none for the ID-31.
hg diff:
diff -r 5528bdcdc34e chirp/id31.py --- a/chirp/id31.py Sun Feb 17 18:58:44 2013 -0800 +++ b/chirp/id31.py Tue Feb 19 08:19:42 2013 -0800 @@ -33,7 +33,7 @@ duplex:2, dtcs_polarity:2; char name[16]; - u8 unknow13; + u8 unknown13; u8 urcall[7]; u8 rpt1call[7]; u8 rpt2call[7]; @@ -88,6 +88,8 @@
"""
+MODES = [ "FM", "NFM", "DV" ] +MODE_INDEX = [ 0, 1, 5 ] TMODES = ["", "Tone", "TSQL", "TSQL", "DTCS", "DTCS", "TSQL-R", "DTCS-R"] DUPLEX = ["", "-", "+"] DTCS_POLARITY = ["NN", "NR", "RN", "RR"] @@ -198,7 +200,7 @@ rf.has_bank_names = True rf.valid_tmodes = list(TMODES) rf.valid_tuning_steps = sorted(list(TUNING_STEPS)) - rf.valid_modes = ["FM", "NFM", "DV"] + rf.valid_modes = list(MODES) rf.valid_skips = ["", "S", "P"] rf.valid_characters = chirp_common.CHARSET_ASCII rf.valid_name_length = 16 @@ -218,7 +220,7 @@
bit = (1 << (number % 8))
- if _mem.is_dv: + if MODES[MODE_INDEX.index(_mem.mode)] == "DV": mem = chirp_common.DVMemory() else: mem = chirp_common.Memory() @@ -237,16 +239,12 @@ mem.dtcs = chirp_common.DTCS_CODES[_mem.dtcs] mem.dtcs_polarity = DTCS_POLARITY[_mem.dtcs_polarity] mem.tuning_step = TUNING_STEPS[_mem.tune_step] - - if _mem.is_dv: - mem.mode = "DV" + mem.mode = MODES[MODE_INDEX.index(_mem.mode)] + + if mem.mode == "DV": mem.dv_urcall = _decode_call(_mem.urcall).rstrip() mem.dv_rpt1call = _decode_call(_mem.rpt1call).rstrip() mem.dv_rpt2call = _decode_call(_mem.rpt2call).rstrip() - elif _mem.is_narrow: - mem.mode = "NFM" - else: - mem.mode = "FM"
if _psk & bit: mem.skip = "P" @@ -279,9 +277,7 @@ _mem.dtcs = chirp_common.DTCS_CODES.index(memory.dtcs) _mem.dtcs_polarity = DTCS_POLARITY.index(memory.dtcs_polarity) _mem.tune_step = TUNING_STEPS.index(memory.tuning_step) - - _mem.is_narrow = memory.mode in ["NFM", "DV"] - _mem.is_dv = memory.mode == "DV" + _mem.mode = MODE_INDEX[MODES.index(memory.mode)]
if isinstance(memory, chirp_common.DVMemory): _mem.urcall = _encode_call(memory.dv_urcall.ljust(8)) @@ -327,8 +323,3 @@ call = "" calls.append(call.rstrip()) return calls - -if __name__ == "__main__": - print repr(_decode_call(_encode_call("KD7REX B"))) - print repr(_decode_call(_encode_call(" B"))) - print repr(_decode_call(_encode_call(" "))) diff -r 5528bdcdc34e chirp/id51.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/chirp/id51.py Tue Feb 19 08:19:42 2013 -0800 @@ -0,0 +1,323 @@ +# Copyright 2012 Dan Smith dsmith@danplanet.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 +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see http://www.gnu.org/licenses/. + +from chirp import directory, icf, bitwise, chirp_common + +MEM_FORMAT = """ +struct { + u24 freq; + u16 offset; + u16 rtone:6, + ctone:6, + unknown2:1, + mode:3; + u8 dtcs; + u8 tune_step:4, + unknown5:4; + u8 unknown4; + u8 tmode:4, + duplex:2, + dtcs_polarity:2; + char name[16]; + u8 unknown13; + u8 urcall[7]; + u8 rpt1call[7]; + u8 rpt2call[7]; +} memory[500]; + +#seekto 0x6A40; +u8 used_flags[70]; + +#seekto 0x6A86; +u8 skip_flags[69]; + +#seekto 0x6ACB; +u8 pskp_flags[69]; + +#seekto 0x6B40; +struct { + u8 bank; + u8 index; +} banks[500]; + +#seekto 0x6FD0; +struct { + char name[16]; +} bank_names[26]; + +#seekto 0xA8C0; +struct { + u24 freq; + u16 offset; + u8 unknown1[3]; + u8 call[7]; + char name[16]; + char subname[8]; + u8 unknown3[10]; +} repeaters[700]; + +#seekto 0x1384E; +struct { + u8 call[7]; +} rptcall[700]; + +#seekto 0x14E60; +struct { + char call[8]; + char tag[4]; +} mycall[6]; + +#seekto 0x14EA8; +struct { + char call[8]; +} urcall[200]; + +""" + +MODES = [ "FM", "NFM", "AM", "DV" ] +MODE_INDEX = [ 0, 1, 3, 5 ] +TMODES = ["", "Tone", "TSQL", "TSQL", "DTCS", "DTCS", "TSQL-R", "DTCS-R"] +DUPLEX = ["", "-", "+"] +DTCS_POLARITY = ["NN", "NR", "RN", "RR"] +TUNING_STEPS = [5.0, 6.25, 0, 0, 10.0, 12.5, 15.0, 20.0, 25.0, 30.0, 50.0, + 100.0, 125.0, 200.0] + +def _decode_call(_call): + # Why Icom, why? + call = "" + shift = 1 + acc = 0 + for val in _call: + mask = (1 << (shift)) - 1 + call += chr((val >> shift) | acc) + acc = (val & mask) << (7 - shift) + shift += 1 + call += chr(acc) + return call + +def _encode_call(call): + _call = [0x00] * 7 + for i in range(0, 7): + val = ord(call[i]) << (i + 1) + if i > 0: + _call[i-1] |= (val & 0xFF00) >> 8 + _call[i] = val + _call[6] |= (ord(call[7]) & 0x7F) + + return _call + +def _get_freq(_mem): + freq = int(_mem.freq) + offs = int(_mem.offset) + + if freq & 0x00200000: + mult = 6250 + else: + mult = 5000 + + freq &= 0x0003FFFF + + return (freq * mult), (offs * mult) + +def _set_freq(_mem, freq, offset): + if chirp_common.is_fractional_step(freq): + mult = 6250 + flag = 0x00200000 + else: + mult = 5000 + flag = 0x00000000 + + _mem.freq = (freq / mult) | flag + _mem.offset = (offset / mult) + +class ID51Bank(icf.IcomBank): + """A ID-51 Bank""" + def get_name(self): + _banks = self._model._radio._memobj.bank_names + return str(_banks[self.index].name).rstrip() + + def set_name(self, name): + _banks = self._model._radio._memobj.bank_names + _banks[self.index].name = str(name).ljust(16)[:16] + +@directory.register +class ID51Radio(icf.IcomCloneModeRadio, chirp_common.IcomDstarSupport): + """Icom ID-51""" + MODEL = "ID-51A" + + _memsize = 0x1FB40 + _model = "\x33\x90\x00\x01" + _endframe = "Icom Inc\x2E\x44\x41" + _num_banks = 26 + _bank_class = ID51Bank + _can_hispeed = True + + _ranges = [(0x00000, 0x1FB40, 32)] + + def _get_bank(self, loc): + _bank = self._memobj.banks[loc] + if _bank.bank == 0xFF: + return None + else: + return _bank.bank + + def _set_bank(self, loc, bank): + _bank = self._memobj.banks[loc] + if bank is None: + _bank.bank = 0xFF + else: + _bank.bank = bank + + def _get_bank_index(self, loc): + _bank = self._memobj.banks[loc] + return _bank.index + + def _set_bank_index(self, loc, index): + _bank = self._memobj.banks[loc] + _bank.index = index + + def get_features(self): + rf = chirp_common.RadioFeatures() + rf.memory_bounds = (0, 499) + rf.valid_bands = [(108000000, 174000000), (400000000, 479000000)] + rf.has_settings = True + rf.has_ctone = True + rf.has_bank_index = True + rf.has_bank_names = True + rf.valid_tmodes = list(TMODES) + rf.valid_tuning_steps = sorted(list(TUNING_STEPS)) + rf.valid_modes = list(MODES) + rf.valid_skips = ["", "S", "P"] + rf.valid_characters = chirp_common.CHARSET_ASCII + rf.valid_name_length = 16 + return rf + + def process_mmap(self): + self._memobj = bitwise.parse(MEM_FORMAT, self._mmap) + + def get_raw_memory(self, number): + return repr(self._memobj.memory[number]) + + def get_memory(self, number): + _mem = self._memobj.memory[number] + _usd = self._memobj.used_flags[number / 8] + _skp = self._memobj.skip_flags[number / 8] + _psk = self._memobj.pskp_flags[number / 8] + + bit = (1 << (number % 8)) + + if MODES[MODE_INDEX.index(_mem.mode)] == "DV": + mem = chirp_common.DVMemory() + else: + mem = chirp_common.Memory() + mem.number = number + + if _usd & bit: + mem.empty = True + return mem + + mem.freq, mem.offset = _get_freq(_mem) + mem.name = str(_mem.name).rstrip() + mem.rtone = chirp_common.TONES[_mem.rtone] + mem.ctone = chirp_common.TONES[_mem.ctone] + mem.tmode = TMODES[_mem.tmode] + mem.duplex = DUPLEX[_mem.duplex] + mem.dtcs = chirp_common.DTCS_CODES[_mem.dtcs] + mem.dtcs_polarity = DTCS_POLARITY[_mem.dtcs_polarity] + mem.tuning_step = TUNING_STEPS[_mem.tune_step] + mem.mode = MODES[MODE_INDEX.index(_mem.mode)] + + if mem.mode == "DV": + mem.dv_urcall = _decode_call(_mem.urcall).rstrip() + mem.dv_rpt1call = _decode_call(_mem.rpt1call).rstrip() + mem.dv_rpt2call = _decode_call(_mem.rpt2call).rstrip() + + if _psk & bit: + mem.skip = "P" + if _skp & bit: + mem.skip = "S" + + return mem + + def set_memory(self, memory): + _mem = self._memobj.memory[memory.number] + _usd = self._memobj.used_flags[memory.number / 8] + _skp = self._memobj.skip_flags[memory.number / 8] + _psk = self._memobj.pskp_flags[memory.number / 8] + + bit = (1 << (memory.number % 8)) + + if memory.empty: + _usd |= bit + self._set_bank(memory.number, None) + return + + _usd &= ~bit + + _set_freq(_mem, memory.freq, memory.offset) + _mem.name = memory.name.ljust(16)[:16] + _mem.rtone = chirp_common.TONES.index(memory.rtone) + _mem.ctone = chirp_common.TONES.index(memory.ctone) + _mem.tmode = TMODES.index(memory.tmode) + _mem.duplex = DUPLEX.index(memory.duplex) + _mem.dtcs = chirp_common.DTCS_CODES.index(memory.dtcs) + _mem.dtcs_polarity = DTCS_POLARITY.index(memory.dtcs_polarity) + _mem.tune_step = TUNING_STEPS.index(memory.tuning_step) + _mem.mode = MODE_INDEX[MODES.index(memory.mode)] + + if isinstance(memory, chirp_common.DVMemory): + _mem.urcall = _encode_call(memory.dv_urcall.ljust(8)) + _mem.rpt1call = _encode_call(memory.dv_rpt1call.ljust(8)) + _mem.rpt2call = _encode_call(memory.dv_rpt2call.ljust(8)) + elif memory.mode == "DV": + raise Exception("BUG") + + if memory.skip == "S": + _skp |= bit + _psk &= ~bit + elif memory.skip == "P": + _skp &= ~bit + _psk |= bit + else: + _skp &= ~bit + _psk &= ~bit + + def get_urcall_list(self): + calls = [] + for i in range(0, 200): + call = str(self._memobj.urcall[i].call) + if call == "CALLSIGN": + call = "" + calls.append(call) + return calls + + def get_mycall_list(self): + calls = [] + for i in range(0, 6): + calls.append(str(self._memobj.mycall[i].call)) + return calls + + def get_repeater_call_list(self): + calls = [] + for rptcall in self._memobj.rptcall: + call = _decode_call(rptcall.call) + if call.rstrip() and not call == "CALLSIGN": + calls.append(call) + for repeater in self._memobj.repeaters: + call = _decode_call(repeater.call) + if call == "CALLSIGN": + call = "" + calls.append(call.rstrip()) + return calls