<html><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class="">Dan,<div class=""><br class=""></div><div class=""><div style="margin: 0px; font-stretch: normal; line-height: normal;" class="">[These thoughts were written to augment the existing page at <i class=""><a href="https://chirp.danplanet.com/projects/chirp/wiki/DevelopersAdd_a_Radio" class="">https://chirp.danplanet.com/projects/chirp/wiki/DevelopersAdd_a_Radio</a></i>.</div><div style="margin: 0px; font-stretch: normal; line-height: normal; min-height: 14px;" class=""><br class=""></div><div style="margin: 0px; font-stretch: normal; line-height: normal; min-height: 14px;" class="">They may be TMI for many of you experienced folks, but beginners might appreciate lessons-learned. And I’ve not written anything yet about how a Git noob can make your life miserable.</div><div style="margin: 0px; font-stretch: normal; line-height: normal; min-height: 14px;" class=""><br class=""></div><div style="margin: 0px; font-stretch: normal; line-height: normal;" class="">Declan Rieb, <a href="mailto:WD5EQY@arrl.net" class="">WD5EQY@arrl.net</a> ]</div><div style="margin: 0px; font-stretch: normal; line-height: normal; min-height: 14px;" class=""><br class=""></div><div style="margin: 0px; font-stretch: normal; line-height: normal; min-height: 14px;" class=""><br class=""></div><div style="margin: 0px; font-stretch: normal; line-height: normal;" class="">Write <b class="">get_memory(number: int | str)</b></div><div style="margin: 0px; font-stretch: normal; line-height: normal; min-height: 14px;" class=""><br class=""></div><div style="margin: 0px; font-stretch: normal; line-height: normal;" class="">This is called to get your driver to populate the CHIRP memory model with the data for one radio memory. On startup, it’s called once for each memory register you’ve delimited for your radio and once for each special memory. Later it will be called as needed.</div><div style="margin: 0px; font-stretch: normal; line-height: normal; min-height: 14px;" class=""><br class=""></div><div style="margin: 0px; font-stretch: normal; line-height: normal;" class="">-<span class="Apple-tab-span" style="white-space:pre">        </span><b class="">get_memory()</b> returns a populated CHIRP memory object that the driver creates as a new instance of the <b class="">chirp_common.Memory</b> structure<b class="">.</b> You’ll want to become familiar with the fields in the Memory structure (presently specified in the source tree in the source file <i class="">chirp/chirp_common.py</i>).</div><p style="margin: 0px; font-stretch: normal; line-height: normal; min-height: 14px;" class=""> <br class="webkit-block-placeholder"></p><div style="margin: 0px; font-stretch: normal; line-height: normal;" class="">-<span class="Apple-tab-span" style="white-space:pre">        </span>The number of memories is specified in <b class="">chirp_common.RadioFeatures.memory_bounds</b>, which is a pair of numbers (first memory register number, last memory register number.) get_memory will be called with an integer parameter for regular memory with a value up to the last memory register number.</div><div style="margin: 0px; font-stretch: normal; line-height: normal; min-height: 14px;" class=""><br class=""></div><div style="margin: 0px; font-stretch: normal; line-height: normal;" class="">-<span class="Apple-tab-span" style="white-space:pre">        </span>Special memories are radio-specific registers that can hold special meaning in the radio (such as scan limits, home registers, skip registers, etc.) They are specified in your driver as members of the list that you set at <b class="">chirp_common.RadioFeatures.valid_special_chans</b>. <b class="">get_memory()</b> will be called with a string containing the name of the special register, and you must set the <b class="">Memory.number</b> field of the resulting memory object to an index that is greater than the last memory register number and different than other special memories without holes in the sequence. Subsequent calls to <b class="">get_memory()</b> may receive either the index or the name.</div><div style="margin: 0px; font-stretch: normal; line-height: normal; min-height: 14px;" class=""><br class=""></div><div style="margin: 0px; font-stretch: normal; line-height: normal;" class="">Do read the example driver at <i class="">chirp/chirp/drivers/template.py.</i> There is a commented stub version of this routine in <i class="">chirp/chirp.common.py</i>. Your driver is expected to overload it.</div><div style="margin: 0px; font-stretch: normal; line-height: normal; min-height: 14px;" class=""><br class=""></div><div style="margin: 0px; font-stretch: normal; line-height: normal; min-height: 14px;" class=""><br class=""></div><div style="margin: 0px; font-stretch: normal; line-height: normal; min-height: 14px;" class=""><br class=""></div><div style="margin: 0px; font-stretch: normal; line-height: normal;" class="">Write <b class="">set_memory(memory: chirp_common.Memory)</b></div><div style="margin: 0px; font-stretch: normal; line-height: normal; min-height: 14px;" class=""><br class=""></div><div style="margin: 0px; font-stretch: normal; line-height: normal;" class="">This is called whenever CHIRP wants your driver to set the radio’s memory according to the fields described in the specific <b class="">chirp_common.Memory</b> parameter. The driver will presumably need to determine the specific radio memory based upon the value of <b class="">memory.number</b> (e.g. integer less than or greater than last memory number.) The driver should not change the <b class="">memory</b> structure.</div><div style="margin: 0px; font-stretch: normal; line-height: normal; min-height: 14px;" class=""><br class=""></div><div style="margin: 0px; font-stretch: normal; line-height: normal;" class="">There is no special return to CHIRP required.</div><div style="margin: 0px; font-stretch: normal; line-height: normal; min-height: 14px;" class=""><br class=""></div><div style="margin: 0px; font-stretch: normal; line-height: normal;" class="">Do read the example driver at <i class="">chirp/chirp/drivers/template.py.</i> There is a commented stub version of this routine in <i class="">chirp/chirp.common.py</i>. Your driver is expected to overload it.</div><div style="margin: 0px; font-stretch: normal; line-height: normal; min-height: 14px;" class=""><br class=""></div><div style="margin: 0px; font-stretch: normal; line-height: normal; min-height: 14px;" class=""><br class=""></div><div style="margin: 0px; font-stretch: normal; line-height: normal; min-height: 14px;" class=""><br class=""></div><div style="margin: 0px; font-stretch: normal; line-height: normal;" class=""><b class="">Radio memory settings that are not included in CHIRP chirp_common.Memory.</b></div><div style="margin: 0px; font-stretch: normal; line-height: normal; min-height: 14px;" class=""><br class=""></div><div style="margin: 0px; font-stretch: normal; line-height: normal;" class="">CHIRP can (optionally) manage and display other settings for each memory. These are stored in a separate subject chirp_common.Memory.extra, and are handled during the get_memory and set_memory by calling _get_mem_extra(mem, _mem) and _set_mem_extra(mem, _mem), respectively. “mem” is the CHIRP memory structure, and “_mem” is the corresponding radio memory structure. You’ll get to write code to handle them similar to “RadioSettings.”</div><div style="margin: 0px; font-stretch: normal; line-height: normal; min-height: 14px;" class=""><br class=""></div><div style="margin: 0px; font-stretch: normal; line-height: normal; min-height: 14px;" class=""><br class=""></div><div style="margin: 0px; font-stretch: normal; line-height: normal;" class=""><b class="">Run tests</b></div><div style="margin: 0px; font-stretch: normal; line-height: normal; min-height: 14px;" class=""><br class=""></div><div style="margin: 0px; font-stretch: normal; line-height: normal;" class="">Read the wiki page at h<i class=""><a href="ttps://chirp.danplanet.com/projects/chirp/wiki/DevelopersPython3Environment" class="">ttps://chirp.danplanet.com/projects/chirp/wiki/DevelopersPython3Environment</a></i></div><div style="margin: 0px; font-stretch: normal; line-height: normal; min-height: 14px;" class=""><br class=""></div><div style="margin: 0px; font-stretch: normal; line-height: normal;" class="">Tox is a separate application used to run tests for CHIRP. (I got it by “pip install tox” and it installed into my Python instance.) It will check syntax and stylistic features of the python source. It will also run many logic tests on all drivers that have changed in your tree since the last time it was run. Use:</div><div style="margin: 0px; font-stretch: normal; line-height: normal; min-height: 14px;" class=""><br class=""></div><div style="margin: 0px; font-stretch: normal; line-height: normal;" class="">$ tox -e style</div><div style="margin: 0px; font-stretch: normal; line-height: normal; min-height: 14px;" class=""><br class=""></div><div style="margin: 0px; font-stretch: normal; line-height: normal;" class="">You may then wish to run the driver test only on your driver. It appears that you can do so by executing </div><div style="margin: 0px; font-stretch: normal; line-height: normal; min-height: 14px;" class=""><br class=""></div><div style="margin: 0px; font-stretch: normal; line-height: normal;" class="">$ tox -e driver -- -k Vendor_Model</div><div style="margin: 0px; font-stretch: normal; line-height: normal;" class="">Or (to only test drivers with changes:)</div><div style="margin: 0px; font-stretch: normal; line-height: normal;" class="">$ tox -e fast-driver</div><div style="margin: 0px; font-stretch: normal; line-height: normal; min-height: 14px;" class=""><br class=""></div><div style="margin: 0px; font-stretch: normal; line-height: normal;" class="">When your new driver gets to the GitHub and a Pull request is made, the CHIRP folks will cause even more extensive tests to be run on it, so try to pass these tests first.</div><div style="margin: 0px; font-stretch: normal; line-height: normal; min-height: 14px;" class=""><br class=""></div><div style="margin: 0px; font-stretch: normal; line-height: normal; min-height: 14px;" class=""><br class=""></div><div style="margin: 0px; font-stretch: normal; line-height: normal;" class=""><b class="">Things not said elsewhere:</b></div><div style="margin: 0px; font-stretch: normal; line-height: normal; min-height: 14px;" class=""><br class=""></div><div style="margin: 0px; font-stretch: normal; line-height: normal;" class="">Some of the following are hinted at in the example driver “<i class="">chirp/chirp/drivers/template.py</i>.”</div><div style="margin: 0px; font-stretch: normal; line-height: normal; min-height: 14px;" class=""><b class=""></b><br class=""></div><div style="margin: 0px; font-stretch: normal; line-height: normal;" class="">CHIRP has a “directory” structure of all the radios it should know about. Your driver will have one or more “<i class="">@directory.register</i>” statement, wherein a class is defined for each radio you’re working on. They can inherit from each other (even other models and vendors) once the classes are read by CHIRP. The directory is sorted by text (vendor, model) pairs.</div><div style="margin: 0px; font-stretch: normal; line-height: normal; min-height: 14px;" class=""><br class=""></div><div style="margin: 0px; font-stretch: normal; line-height: normal;" class="">That class will have definitions (and some redefinitions) for your radio. It will also implement a function</div><div style="margin: 0px; font-stretch: normal; line-height: normal;" class=""><b class="">get_features()</b> -> chirp_common.RadioFeatures()</div><div style="margin: 0px; font-stretch: normal; line-height: normal;" class="">You get to return basic information about your radio in the structure that CHIRP defines in <i class="">chirp/chirp_common.py</i> and you instantiate. Any existing driver should have one for you to copy and modify. CHIRP calls it fairly often when starting, so it’s expected to be lightweight. You probably don’t want this function to be querying the radio each time it’s called.</div><div style="margin: 0px; font-stretch: normal; line-height: normal; min-height: 14px;" class=""><br class=""></div><div style="margin: 0px; font-stretch: normal; line-height: normal; min-height: 14px;" class=""><br class=""></div><div style="margin: 0px; font-stretch: normal; line-height: normal;" class=""><b class="">Modes</b>:</div><div style="margin: 0px; font-stretch: normal; line-height: normal;" class="">CHIRP has a predefined set of “modes” available for each memory entry. Whatever your radio defines as modes, they MUST map into the CHIRP model. If the radio’s modes don’t fit into CHIRP’s model, you’ll get to add some translation into your driver. The current list (as of 2023-07-28 f<span style="font-kerning: none" class="">rom <i class="">chirp/chirp_common.py</i></span>) is:</div><div style="margin: 0px; font-stretch: normal; line-height: normal; min-height: 14px;" class=""><br class=""></div><div style="margin: 0px; font-stretch: normal; line-height: normal;" class="">MODES = ("WFM", "FM", "NFM", "AM", "NAM", "DV", "USB", "LSB", "CW", "RTTY",</div><div style="margin: 0px; font-stretch: normal; line-height: normal;" class=""> "DIG", "PKT", "NCW", "NCWR", "CWR", "P25", "Auto", "RTTYR",</div><div style="margin: 0px; font-stretch: normal; line-height: normal;" class=""> "FSK", "FSKR", "DMR", "DN")</div><div style="margin: 0px; font-stretch: normal; line-height: normal; min-height: 14px;" class=""><br class=""></div><div style="margin: 0px; font-stretch: normal; line-height: normal; min-height: 14px;" class=""><br class=""></div><div style="margin: 0px; font-stretch: normal; line-height: normal;" class=""><b class="">Live drivers</b></div><div style="margin: 0px; font-stretch: normal; line-height: normal;" class="">A more-official description can be found at <i class=""><a href="https://chirp.danplanet.com/projects/chirp/wiki/FAQ" class="">https://chirp.danplanet.com/projects/chirp/wiki/FAQ</a></i>.</div><div style="margin: 0px; font-stretch: normal; line-height: normal;" class="">Most radios seem to have a mode for which memory can be read or written as a large block, and their drivers reflect that. A few radios can only be accessed on what is effectively memory-by-memory reads/writes. These radios will almost surely need to be written as “live”. An example driver is at <i class="">chirp/chirp/drivers/kenwood_live.py.</i> Several other Kenwood drivers inherit from that one (at least ts480.py, tmd710.py, ts2000.py.) These drivers do not use the same radio-memory model as most of the others, but can keep a kind of cache.</div></div><br class=""><br class=""><div class="">
<div style="color: rgb(0, 0, 0); letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class=""><div style="color: rgb(0, 0, 0); letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class="">______</div><div style="color: rgb(0, 0, 0); letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class="">Declan Rieb WD5EQY<div class=""><a href="mailto:wd5eqy@arrl.net" class="">wd5eqy@arrl.net</a></div><div class=""><br class=""></div><div class=""><br class=""></div></div><br class="Apple-interchange-newline"></div><br class="Apple-interchange-newline"><br class="Apple-interchange-newline">
</div>
<br class=""></body></html>