<html>
  <head>
    <meta content="text/html; charset=UTF-8" http-equiv="Content-Type">
  </head>
  <body bgcolor="#FFFFFF" text="#000000">
    <br>
    <div class="moz-cite-prefix">On 2013-02-19 06:38, Dan Smith wrote:<br>
    </div>
    <blockquote cite="mid:20130219063826.323c1f1f@theine.danplanet.com"
      type="cite">
      <blockquote type="cite">
        <pre wrap="">Okay, here is my ID-51 (id51.py) new driver.  Also included is an
image file for same.
</pre>
      </blockquote>
      <pre wrap="">
Could you put it into the proper patch format?

<a class="moz-txt-link-freetext" href="http://chirp.danplanet.com/projects/chirp/wiki/DevelopersProcess#Submitting-a-patch">http://chirp.danplanet.com/projects/chirp/wiki/DevelopersProcess#Submitting-a-patch</a>
</pre>
    </blockquote>
    <br>
    OK, I'm confoozed.  I previously read that page, and I know that's
    the correct format for a <b>change</b>.  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:<br>
    <br>
    <i>If you are adding a new driver, you will need to add an image to
      the </i><i><code>tests/images/</code></i><i> directory which is
      correctly named for your model. <b>These do not communicate well
        in patch form</b>, so just send a sample image to the
      development mailing list to accompany your patch submission.</i><br>
    <br>
    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.<br>
    <br>
    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).<br>
    <br>
    <blockquote cite="mid:20130219063826.323c1f1f@theine.danplanet.com"
      type="cite">
      <blockquote type="cite">
        <pre wrap="">I didn't use the one in tests/images because there isn't one.
</pre>
      </blockquote>
      <pre wrap="">
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</pre>
    </blockquote>
    <br>
    <br>
    No, I did a "hg clone <a class="moz-txt-link-freetext" href="http://d-rats.com/hg/chirp.hg">http://d-rats.com/hg/chirp.hg</a>"  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.<br>
    <br>
    hg diff:<br>
    <br>
    <br>
    diff -r 5528bdcdc34e chirp/id31.py<br>
    --- a/chirp/id31.py     Sun Feb 17 18:58:44 2013 -0800<br>
    +++ b/chirp/id31.py     Tue Feb 19 08:19:42 2013 -0800<br>
    @@ -33,7 +33,7 @@<br>
          duplex:2,<br>
          dtcs_polarity:2;<br>
       char name[16];<br>
    -  u8 unknow13;<br>
    +  u8 unknown13;<br>
       u8 urcall[7];<br>
       u8 rpt1call[7];<br>
       u8 rpt2call[7];<br>
    @@ -88,6 +88,8 @@<br>
    <br>
     """<br>
    <br>
    +MODES = [ "FM", "NFM", "DV" ]<br>
    +MODE_INDEX = [ 0, 1, 5 ]<br>
     TMODES = ["", "Tone", "TSQL", "TSQL", "DTCS", "DTCS", "TSQL-R",
    "DTCS-R"]<br>
     DUPLEX = ["", "-", "+"]<br>
     DTCS_POLARITY = ["NN", "NR", "RN", "RR"]<br>
    @@ -198,7 +200,7 @@<br>
             rf.has_bank_names = True<br>
             rf.valid_tmodes = list(TMODES)<br>
             rf.valid_tuning_steps = sorted(list(TUNING_STEPS))<br>
    -        rf.valid_modes = ["FM", "NFM", "DV"]<br>
    +        rf.valid_modes = list(MODES)<br>
             rf.valid_skips = ["", "S", "P"]<br>
             rf.valid_characters = chirp_common.CHARSET_ASCII<br>
             rf.valid_name_length = 16<br>
    @@ -218,7 +220,7 @@<br>
    <br>
             bit = (1 &lt;&lt; (number % 8))<br>
    <br>
    -        if _mem.is_dv:<br>
    +        if MODES[MODE_INDEX.index(_mem.mode)] == "DV":<br>
                 mem = chirp_common.DVMemory()<br>
             else:<br>
                 mem = chirp_common.Memory()<br>
    @@ -237,16 +239,12 @@<br>
             mem.dtcs = chirp_common.DTCS_CODES[_mem.dtcs]<br>
             mem.dtcs_polarity = DTCS_POLARITY[_mem.dtcs_polarity]<br>
             mem.tuning_step = TUNING_STEPS[_mem.tune_step]<br>
    -<br>
    -        if _mem.is_dv:<br>
    -            mem.mode = "DV"<br>
    +        mem.mode = MODES[MODE_INDEX.index(_mem.mode)]<br>
    +<br>
    +        if mem.mode == "DV":<br>
                 mem.dv_urcall = _decode_call(_mem.urcall).rstrip()<br>
                 mem.dv_rpt1call = _decode_call(_mem.rpt1call).rstrip()<br>
                 mem.dv_rpt2call = _decode_call(_mem.rpt2call).rstrip()<br>
    -        elif _mem.is_narrow:<br>
    -            mem.mode = "NFM"<br>
    -        else:<br>
    -            mem.mode = "FM"<br>
    <br>
             if _psk &amp; bit:<br>
                 mem.skip = "P"<br>
    @@ -279,9 +277,7 @@<br>
             _mem.dtcs = chirp_common.DTCS_CODES.index(memory.dtcs)<br>
             _mem.dtcs_polarity =
    DTCS_POLARITY.index(memory.dtcs_polarity)<br>
             _mem.tune_step = TUNING_STEPS.index(memory.tuning_step)<br>
    -<br>
    -        _mem.is_narrow = memory.mode in ["NFM", "DV"]<br>
    -        _mem.is_dv = memory.mode == "DV"<br>
    +        _mem.mode = MODE_INDEX[MODES.index(memory.mode)]<br>
    <br>
             if isinstance(memory, chirp_common.DVMemory):<br>
                 _mem.urcall = _encode_call(memory.dv_urcall.ljust(8))<br>
    @@ -327,8 +323,3 @@<br>
                     call = ""<br>
                 calls.append(call.rstrip())<br>
             return calls<br>
    -<br>
    -if __name__ == "__main__":<br>
    -    print repr(_decode_call(_encode_call("KD7REX B")))<br>
    -    print repr(_decode_call(_encode_call("       B")))<br>
    -    print repr(_decode_call(_encode_call("        ")))<br>
    diff -r 5528bdcdc34e chirp/id51.py<br>
    --- /dev/null   Thu Jan 01 00:00:00 1970 +0000<br>
    +++ b/chirp/id51.py     Tue Feb 19 08:19:42 2013 -0800<br>
    @@ -0,0 +1,323 @@<br>
    +# Copyright 2012 Dan Smith <a class="moz-txt-link-rfc2396E" href="mailto:dsmith@danplanet.com">&lt;dsmith@danplanet.com&gt;</a><br>
    +#<br>
    +# This program is free software: you can redistribute it and/or
    modify<br>
    +# it under the terms of the GNU General Public License as published
    by<br>
    +# the Free Software Foundation, either version 3 of the License, or<br>
    +# (at your option) any later version.<br>
    +#<br>
    +# This program is distributed in the hope that it will be useful,<br>
    +# but WITHOUT ANY WARRANTY; without even the implied warranty of<br>
    +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the<br>
    +# GNU General Public License for more details.<br>
    +#<br>
    +# You should have received a copy of the GNU General Public License<br>
    +# along with this program.  If not, see
    <a class="moz-txt-link-rfc2396E" href="http://www.gnu.org/licenses/">&lt;http://www.gnu.org/licenses/&gt;</a>.<br>
    +<br>
    +from chirp import directory, icf, bitwise, chirp_common<br>
    +<br>
    +MEM_FORMAT = """<br>
    +struct {<br>
    +  u24 freq;<br>
    +  u16 offset;<br>
    +  u16 rtone:6,<br>
    +      ctone:6,<br>
    +      unknown2:1,<br>
    +      mode:3;<br>
    +  u8 dtcs;<br>
    +  u8 tune_step:4,<br>
    +     unknown5:4;<br>
    +  u8 unknown4;<br>
    +  u8 tmode:4,<br>
    +     duplex:2,<br>
    +     dtcs_polarity:2;<br>
    +  char name[16];<br>
    +  u8 unknown13;<br>
    +  u8 urcall[7];<br>
    +  u8 rpt1call[7];<br>
    +  u8 rpt2call[7];<br>
    +} memory[500];<br>
    +<br>
    +#seekto 0x6A40;<br>
    +u8 used_flags[70];<br>
    +<br>
    +#seekto 0x6A86;<br>
    +u8 skip_flags[69];<br>
    +<br>
    +#seekto 0x6ACB;<br>
    +u8 pskp_flags[69];<br>
    +<br>
    +#seekto 0x6B40;<br>
    +struct {<br>
    +  u8 bank;<br>
    +  u8 index;<br>
    +} banks[500];<br>
    +<br>
    +#seekto 0x6FD0;<br>
    +struct {<br>
    +  char name[16];<br>
    +} bank_names[26];<br>
    +<br>
    +#seekto 0xA8C0;<br>
    +struct {<br>
    +  u24 freq;<br>
    +  u16 offset;<br>
    +  u8 unknown1[3];<br>
    +  u8 call[7];<br>
    +  char name[16];<br>
    +  char subname[8];<br>
    +  u8 unknown3[10];<br>
    +} repeaters[700];<br>
    +<br>
    +#seekto 0x1384E;<br>
    +struct {<br>
    +  u8 call[7];<br>
    +} rptcall[700];<br>
    +<br>
    +#seekto 0x14E60;<br>
    +struct {<br>
    +  char call[8];<br>
    +  char tag[4];<br>
    +} mycall[6];<br>
    +<br>
    +#seekto 0x14EA8;<br>
    +struct {<br>
    +  char call[8];<br>
    +} urcall[200];<br>
    +<br>
    +"""<br>
    +<br>
    +MODES = [ "FM", "NFM", "AM", "DV" ]<br>
    +MODE_INDEX = [ 0, 1, 3, 5 ]<br>
    +TMODES = ["", "Tone", "TSQL", "TSQL", "DTCS", "DTCS", "TSQL-R",
    "DTCS-R"]<br>
    +DUPLEX = ["", "-", "+"]<br>
    +DTCS_POLARITY = ["NN", "NR", "RN", "RR"]<br>
    +TUNING_STEPS = [5.0, 6.25, 0, 0, 10.0, 12.5, 15.0, 20.0, 25.0,
    30.0, 50.0,<br>
    +                100.0, 125.0, 200.0]<br>
    +<br>
    +def _decode_call(_call):<br>
    +    # Why Icom, why?<br>
    +    call = ""<br>
    +    shift = 1<br>
    +    acc = 0<br>
    +    for val in _call:<br>
    +        mask = (1 &lt;&lt; (shift)) - 1<br>
    +        call += chr((val &gt;&gt; shift) | acc)<br>
    +        acc = (val &amp; mask) &lt;&lt; (7 - shift)<br>
    +        shift += 1<br>
    +    call += chr(acc)<br>
    +    return call<br>
    +<br>
    +def _encode_call(call):<br>
    +    _call = [0x00] * 7<br>
    +    for i in range(0, 7):<br>
    +        val = ord(call[i]) &lt;&lt; (i + 1)<br>
    +        if i &gt; 0:<br>
    +            _call[i-1] |= (val &amp; 0xFF00) &gt;&gt; 8<br>
    +        _call[i] = val<br>
    +    _call[6] |= (ord(call[7]) &amp; 0x7F)<br>
    +<br>
    +    return _call<br>
    +<br>
    +def _get_freq(_mem):<br>
    +    freq = int(_mem.freq)<br>
    +    offs = int(_mem.offset)<br>
    +<br>
    +    if freq &amp; 0x00200000:<br>
    +        mult = 6250<br>
    +    else:<br>
    +        mult = 5000<br>
    +<br>
    +    freq &amp;= 0x0003FFFF<br>
    +<br>
    +    return (freq * mult), (offs * mult)<br>
    +<br>
    +def _set_freq(_mem, freq, offset):<br>
    +    if chirp_common.is_fractional_step(freq):<br>
    +        mult = 6250<br>
    +        flag = 0x00200000<br>
    +    else:<br>
    +        mult = 5000<br>
    +        flag = 0x00000000<br>
    +<br>
    +    _mem.freq = (freq / mult) | flag<br>
    +    _mem.offset = (offset / mult)<br>
    +<br>
    +class ID51Bank(icf.IcomBank):<br>
    +    """A ID-51 Bank"""<br>
    +    def get_name(self):<br>
    +        _banks = self._model._radio._memobj.bank_names<br>
    +        return str(_banks[self.index].name).rstrip()<br>
    +<br>
    +    def set_name(self, name):<br>
    +        _banks = self._model._radio._memobj.bank_names<br>
    +        _banks[self.index].name = str(name).ljust(16)[:16]<br>
    +<br>
    +@directory.register<br>
    +class ID51Radio(icf.IcomCloneModeRadio,
    chirp_common.IcomDstarSupport):<br>
    +    """Icom ID-51"""<br>
    +    MODEL = "ID-51A"<br>
    +<br>
    +    _memsize = 0x1FB40<br>
    +    _model = "\x33\x90\x00\x01"<br>
    +    _endframe = "Icom Inc\x2E\x44\x41"<br>
    +    _num_banks = 26<br>
    +    _bank_class = ID51Bank<br>
    +    _can_hispeed = True<br>
    +<br>
    +    _ranges = [(0x00000, 0x1FB40, 32)]<br>
    +<br>
    +    def _get_bank(self, loc):<br>
    +        _bank = self._memobj.banks[loc]<br>
    +        if _bank.bank == 0xFF:<br>
    +            return None<br>
    +        else:<br>
    +            return _bank.bank<br>
    +<br>
    +    def _set_bank(self, loc, bank):<br>
    +        _bank = self._memobj.banks[loc]<br>
    +        if bank is None:<br>
    +            _bank.bank = 0xFF<br>
    +        else:<br>
    +            _bank.bank = bank<br>
    +<br>
    +    def _get_bank_index(self, loc):<br>
    +        _bank = self._memobj.banks[loc]<br>
    +        return _bank.index<br>
    +<br>
    +    def _set_bank_index(self, loc, index):<br>
    +        _bank = self._memobj.banks[loc]<br>
    +        _bank.index = index<br>
    +<br>
    +    def get_features(self):<br>
    +        rf = chirp_common.RadioFeatures()<br>
    +        rf.memory_bounds = (0, 499)<br>
    +        rf.valid_bands = [(108000000, 174000000), (400000000,
    479000000)]<br>
    +        rf.has_settings = True<br>
    +        rf.has_ctone = True<br>
    +        rf.has_bank_index = True<br>
    +        rf.has_bank_names = True<br>
    +        rf.valid_tmodes = list(TMODES)<br>
    +        rf.valid_tuning_steps = sorted(list(TUNING_STEPS))<br>
    +        rf.valid_modes = list(MODES)<br>
    +        rf.valid_skips = ["", "S", "P"]<br>
    +        rf.valid_characters = chirp_common.CHARSET_ASCII<br>
    +        rf.valid_name_length = 16<br>
    +        return rf<br>
    +<br>
    +    def process_mmap(self):<br>
    +        self._memobj = bitwise.parse(MEM_FORMAT, self._mmap)<br>
    +<br>
    +    def get_raw_memory(self, number):<br>
    +        return repr(self._memobj.memory[number])<br>
    +<br>
    +    def get_memory(self, number):<br>
    +        _mem = self._memobj.memory[number]<br>
    +        _usd = self._memobj.used_flags[number / 8]<br>
    +        _skp = self._memobj.skip_flags[number / 8]<br>
    +        _psk = self._memobj.pskp_flags[number / 8]<br>
    +<br>
    +        bit = (1 &lt;&lt; (number % 8))<br>
    +<br>
    +        if MODES[MODE_INDEX.index(_mem.mode)] == "DV":<br>
    +            mem = chirp_common.DVMemory()<br>
    +        else:<br>
    +            mem = chirp_common.Memory()<br>
    +        mem.number = number<br>
    +<br>
    +        if _usd &amp; bit:<br>
    +            mem.empty = True<br>
    +            return mem<br>
    +<br>
    +        mem.freq, mem.offset = _get_freq(_mem)<br>
    +        mem.name = str(_mem.name).rstrip()<br>
    +        mem.rtone = chirp_common.TONES[_mem.rtone]<br>
    +        mem.ctone = chirp_common.TONES[_mem.ctone]<br>
    +        mem.tmode = TMODES[_mem.tmode]<br>
    +        mem.duplex = DUPLEX[_mem.duplex]<br>
    +        mem.dtcs = chirp_common.DTCS_CODES[_mem.dtcs]<br>
    +        mem.dtcs_polarity = DTCS_POLARITY[_mem.dtcs_polarity]<br>
    +        mem.tuning_step = TUNING_STEPS[_mem.tune_step]<br>
    +        mem.mode = MODES[MODE_INDEX.index(_mem.mode)]<br>
    +<br>
    +        if mem.mode == "DV":<br>
    +            mem.dv_urcall = _decode_call(_mem.urcall).rstrip()<br>
    +            mem.dv_rpt1call = _decode_call(_mem.rpt1call).rstrip()<br>
    +            mem.dv_rpt2call = _decode_call(_mem.rpt2call).rstrip()<br>
    +<br>
    +        if _psk &amp; bit:<br>
    +            mem.skip = "P"<br>
    +        if _skp &amp; bit:<br>
    +            mem.skip = "S"<br>
    +<br>
    +        return mem<br>
    +<br>
    +    def set_memory(self, memory):<br>
    +        _mem = self._memobj.memory[memory.number]<br>
    +        _usd = self._memobj.used_flags[memory.number / 8]<br>
    +        _skp = self._memobj.skip_flags[memory.number / 8]<br>
    +        _psk = self._memobj.pskp_flags[memory.number / 8]<br>
    +<br>
    +        bit = (1 &lt;&lt; (memory.number % 8))<br>
    +<br>
    +        if memory.empty:<br>
    +            _usd |= bit<br>
    +            self._set_bank(memory.number, None)<br>
    +            return<br>
    +<br>
    +        _usd &amp;= ~bit<br>
    +<br>
    +        _set_freq(_mem, memory.freq, memory.offset)<br>
    +        _mem.name = memory.name.ljust(16)[:16]<br>
    +        _mem.rtone = chirp_common.TONES.index(memory.rtone)<br>
    +        _mem.ctone = chirp_common.TONES.index(memory.ctone)<br>
    +        _mem.tmode = TMODES.index(memory.tmode)<br>
    +        _mem.duplex = DUPLEX.index(memory.duplex)<br>
    +        _mem.dtcs = chirp_common.DTCS_CODES.index(memory.dtcs)<br>
    +        _mem.dtcs_polarity =
    DTCS_POLARITY.index(memory.dtcs_polarity)<br>
    +        _mem.tune_step = TUNING_STEPS.index(memory.tuning_step)<br>
    +        _mem.mode = MODE_INDEX[MODES.index(memory.mode)]<br>
    +<br>
    +        if isinstance(memory, chirp_common.DVMemory):<br>
    +            _mem.urcall = _encode_call(memory.dv_urcall.ljust(8))<br>
    +            _mem.rpt1call =
    _encode_call(memory.dv_rpt1call.ljust(8))<br>
    +            _mem.rpt2call =
    _encode_call(memory.dv_rpt2call.ljust(8))<br>
    +        elif memory.mode == "DV":<br>
    +            raise Exception("BUG")<br>
    +<br>
    +        if memory.skip == "S":<br>
    +            _skp |=  bit<br>
    +            _psk &amp;= ~bit<br>
    +        elif memory.skip == "P":<br>
    +            _skp &amp;= ~bit<br>
    +            _psk |=  bit<br>
    +        else:<br>
    +            _skp &amp;= ~bit<br>
    +            _psk &amp;= ~bit<br>
    +<br>
    +    def get_urcall_list(self):<br>
    +        calls = []<br>
    +        for i in range(0, 200):<br>
    +            call = str(self._memobj.urcall[i].call)<br>
    +            if call == "CALLSIGN":<br>
    +                call = ""<br>
    +            calls.append(call)<br>
    +        return calls<br>
    +<br>
    +    def get_mycall_list(self):<br>
    +        calls = []<br>
    +        for i in range(0, 6):<br>
    +            calls.append(str(self._memobj.mycall[i].call))<br>
    +        return calls<br>
    +<br>
    +    def get_repeater_call_list(self):<br>
    +        calls = []<br>
    +        for rptcall in self._memobj.rptcall:<br>
    +            call = _decode_call(rptcall.call)<br>
    +            if call.rstrip() and not call == "CALLSIGN":<br>
    +                calls.append(call)<br>
    +        for repeater in self._memobj.repeaters:<br>
    +            call = _decode_call(repeater.call)<br>
    +            if call == "CALLSIGN":<br>
    +                call = ""<br>
    +            calls.append(call.rstrip())<br>
    +        return calls<br>
    <br>
    <br>
  </body>
</html>