[chirp_devel] #553 Icom ID-51 support
Dean Gibson AE7Q
Tue Feb 19 08:27:17 PST 2013
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-a-patch
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 at 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]
+
+ at 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
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://intrepid.danplanet.com/pipermail/chirp_devel/attachments/20130219/67d5d243/attachment-0001.html
More information about the chirp_devel
mailing list