# HG changeset patch
# User Sean Burford <sburford@google.com>
# Date 1363134002 -39600
# Node ID fa1ac806391ea053a903ca6dd64eb5508b3b88c0
# Parent  443ea98c0840de12f8ee149ccd8eecc78bb69a51
Add support for band plans (Bug 681)

diff -r 443ea98c0840 -r fa1ac806391e chirp/bandplan_au.py
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/chirp/bandplan_au.py	Wed Mar 13 11:20:02 2013 +1100
@@ -0,0 +1,182 @@
+# Copyright 2013 Sean Burford <sburford@google.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/>.
+
+
+BANDPLAN = {
+  "name": "Australian Amateur Band Plans",
+  "updated": "April 2010",
+  "url": "http://www.wia.org.au/members/bandplans/data/documents/Australian%20Band%20Plans%20100404.pdf",
+  "bands": {
+    (28.000e6, 29.700e6): {
+      "name": "6 Metre Band",
+      (29.520e6, 29.680e6): {
+        "name": "FM Simplex and Repeaters",
+        "mode": "FM",
+        "step": 20,
+        (29.620e6, 29.680e6): {
+          "name": "FM Repeater Outputs",
+          "offset": -100000,
+        },
+      },
+    },
+    (50.000e6, 54.000e6): {
+      (52.525e6, 53.975e6): {
+        "name": "FM Simplex and Repeaters",
+        "mode": "FM",
+        "step": 25,
+        (53.550e6, 53.975e6): {
+          "name": "FM Repeater Outputs",
+          "offset": -1e6,
+        },
+      },
+    },
+    (144.000e6, 148.000e6): {
+      "name": "2 Metre Band",
+      "tones": (91.5, 123.0, 141.3, 146.2, 85.4),
+      (144.400e6, 144.600e6): {
+        "name": "Narrow Band Beacons",
+        "step": 2,
+      },
+      (146.025e6, 147.975e6): {
+        "name": "FM Simplex and Repeaters",
+        "mode": "FM",
+        "step": 25,
+        (146.625e6, 147.000e6): {
+          "name": "FM Repeater Outputs Group A",
+          "offset": -600000,
+        },
+        (147.025e6, 147.375e6): {
+          "name": "FM Repeater Outputs Group B",
+          "offset": 600000,
+        }
+      }
+    },
+    (420.000e6, 450.000e6): {
+      "name": "70cm Band",
+      "tones": (91.5, 123.0, 141.3, 146.2, 85.4),
+      (432.400e6, 432.600e6): {
+        "name": "Beacons",
+        "step": 2,
+      },
+      (438.025e6, 439.975e6): {
+        "name": "FM Simplex and Repeaters",
+        "mode": "FM",
+        "step": 25,
+        (438.025e6, 438.725e6): {
+          "name": "FM Repeater Outputs Group A",
+          "offset": -5e6,
+        },
+        (439.275e6, 439.975e6): {
+          "name": "FM Repeater Outputs Group B",
+          "offset": -5e6,
+        },
+      },
+    },
+    (1240.000e6, 1270.000e6): {
+      "name": "23cm Band",
+      (1273.025e6, 1273.975e6): {
+        "name": "FM Repeater Outputs",
+        "mode": "FM",
+        "step": 25,
+        "offset": 20e6,
+      },
+      (1296.400e6, 1296.600e6): {
+        "name": "Beacons",
+        "step": 2,
+      },
+      (1297.025e6, 1300.400e6): {
+        "name": "General FM Simplex Data",
+        "mode": "FM",
+        "step": 25,
+      },
+    },
+    (2300.000e6, 2450.000e6): {
+      "name": "13cm Band",
+      (2403.400e6, 2403.600e6): {
+        "name": "Beacons",
+        "step": 2,
+      },
+      (2425.000e6, 2428.000e6): {
+        "name": "FM Simplex",
+        "mode": "FM",
+        "step": 25,
+      },
+      (2428.025e6, 2429.000e6): {
+        "name": "FM Duplex (Voice)",
+        "mode": "FM",
+        "step": 25,
+        "offset": 20e6,
+      },
+      (2429.000e6, 2429.975e6): {
+        "name": "FM Duplex (Data)",
+        "mode": "FM",
+        "step": 100,
+        "offset": 20e6,
+      },
+    },
+    (3300.000e6, 3600.000e6): {
+      "name": "9cm Band",
+      (3320.000e6, 3340.000e6): {
+        "name": "9cm Wideband Channel 2: Voice or Data",
+        "step": 100,
+      },
+      (3400.400e6, 3400.600e6): {
+        "name": "Beacons",
+        "step": 2,
+      },
+      (3402.000e6, 3403.000e6): {
+        "name": "FM Simplex (Voice)",
+        "mode": "FM",
+        "step": 100,
+      },
+      (3403.000e6, 3405.000e6): {
+        "name": "FM Simplex (Data)",
+        "mode": "FM",
+        "step": 100,
+      },
+    },
+    (5650.000e6, 5850.000e6): {
+      "name": "6cm Band",
+      (5760.400e6, 5760.600e6): {
+        "name": "Beacons",
+        "step": 2,
+      },
+      (5700.000e6, 5720.000e6): {
+        "name": "6cm Wideband Channel 2: Data",
+        "step": 100,
+        "offset": 70e6,
+      },
+      (5720.000e6, 5740.000e6): {
+        "name": "6cm Wideband Channel 3: Voice",
+        "step": 100,
+        "offset": 70e6,
+      },
+      (5762.000e6, 5763.000e6): {
+        "name": "FM Simplex (Voice)",
+        "mode": "FM",
+        "step": 100,
+      },
+      (5763.000e6, 5765.000e6): {
+        "name": "FM Simplex (Data)",
+        "mode": "FM",
+        "step": 100,
+      },
+    },
+    (10.000e9, 10.500e9): {
+      "name": "3cm Band",
+    }
+  }
+}
+
diff -r 443ea98c0840 -r fa1ac806391e chirp/bandplan_iaru_r1.py
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/chirp/bandplan_iaru_r1.py	Wed Mar 13 11:20:02 2013 +1100
@@ -0,0 +1,19 @@
+# Copyright 2013 Sean Burford <sburford@google.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/>.
+
+BANDPLAN = {
+  "name": "IARU Region 1 Band Plans",
+  }
+
diff -r 443ea98c0840 -r fa1ac806391e chirp/bandplan_iaru_r2.py
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/chirp/bandplan_iaru_r2.py	Wed Mar 13 11:20:02 2013 +1100
@@ -0,0 +1,20 @@
+# Copyright 2013 Sean Burford <sburford@google.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/>.
+
+BANDPLAN = {
+  "name": "IARU Region 2 Band Plans",
+  }
+
+
diff -r 443ea98c0840 -r fa1ac806391e chirp/bandplan_iaru_r3.py
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/chirp/bandplan_iaru_r3.py	Wed Mar 13 11:20:02 2013 +1100
@@ -0,0 +1,19 @@
+# Copyright 2013 Sean Burford <sburford@google.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/>.
+
+BANDPLAN = {
+  "name": "IARU Region 3 Band Plans",
+  }
+
diff -r 443ea98c0840 -r fa1ac806391e chirp/bandplan_na.py
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/chirp/bandplan_na.py	Wed Mar 13 11:20:02 2013 +1100
@@ -0,0 +1,80 @@
+# Copyright 2013 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/>.
+
+STD_6M_OFFSETS = [
+    (51620000, 51980000, -500000),
+    (52500000, 52980000, -500000),
+    (53500000, 53980000, -500000),
+    ]
+
+STD_2M_OFFSETS = [
+    (145100000, 145500000, -600000),
+    (146000000, 146400000,  600000),
+    (146600000, 147000000, -600000),
+    (147000000, 147400000,  600000),
+    (147600000, 148000000, -600000),
+    ]
+
+STD_220_OFFSETS = [
+    (223850000, 224980000, -1600000),
+    ]
+
+STD_70CM_OFFSETS = [
+    (440000000, 445000000,  5000000),
+    (447000000, 450000000, -5000000),
+    ]
+
+STD_23CM_OFFSETS = [
+    (1282000000, 1288000000, -12000000),
+    ]
+
+# Standard offsets, indexed by band (wavelength in cm)
+STD_OFFSETS = {
+    600 : STD_6M_OFFSETS,
+    200 : STD_2M_OFFSETS,
+    125 : STD_220_OFFSETS,
+     70 : STD_70CM_OFFSETS,
+     23 : STD_23CM_OFFSETS,
+    }
+
+BAND_TO_MHZ = {
+    600 : (   50000000,   54000000 ),
+    200 : (  144000000,  148000000 ),
+    125 : (  219000000,  225000000 ),
+    70 :  (  420000000,  450000000 ),
+    23 :  ( 1240000000, 1300000000 ),
+}
+
+# NB: This only works for some bands, throws an Exception otherwise
+def freq_to_band(freq):
+    """Returns the band (in cm) for a given frequency"""
+    for band, (lo, hi) in BAND_TO_MHZ.items():
+        if int(freq) >= lo and int(freq) < hi:
+            return band
+    raise ValueError("No conversion for frequency %i" % freq)
+
+def get_offset(freq):
+    chosen_offset = None
+
+    try:
+        band = freq_to_band(freq)
+        for lo, hi, offset in STD_OFFSETS[band]:
+            if int(freq) >= lo and int(freq) < hi:
+                chosen_offset = offset
+    except ValueError:
+        pass
+
+    return chosen_offset
+
diff -r 443ea98c0840 -r fa1ac806391e chirp/chirp_common.py
--- a/chirp/chirp_common.py	Tue Mar 05 09:49:47 2013 -0800
+++ b/chirp/chirp_common.py	Wed Mar 13 11:20:02 2013 +1100
@@ -68,58 +68,6 @@
 MODES = ["WFM", "FM", "NFM", "AM", "NAM", "DV", "USB", "LSB", "CW", "RTTY",
          "DIG", "PKT", "NCW", "NCWR", "CWR", "P25", "Auto"]
 
-STD_6M_OFFSETS = [
-    (51620000, 51980000, -500000),
-    (52500000, 52980000, -500000),
-    (53500000, 53980000, -500000),
-    ]
-
-STD_2M_OFFSETS = [
-    (145100000, 145500000, -600000),
-    (146000000, 146400000,  600000),
-    (146600000, 147000000, -600000),
-    (147000000, 147400000,  600000),
-    (147600000, 148000000, -600000),
-    ]
-
-STD_220_OFFSETS = [
-    (223850000, 224980000, -1600000),
-    ]
-
-STD_70CM_OFFSETS = [
-    (440000000, 445000000,  5000000),
-    (447000000, 450000000, -5000000),
-    ]
-
-STD_23CM_OFFSETS = [
-    (1282000000, 1288000000, -12000000),
-    ]
-
-# Standard offsets, indexed by band (wavelength in cm)
-STD_OFFSETS = {
-    600 : STD_6M_OFFSETS,
-    200 : STD_2M_OFFSETS,
-    125 : STD_220_OFFSETS,
-     70 : STD_70CM_OFFSETS,
-     23 : STD_23CM_OFFSETS,
-    }
-
-BAND_TO_MHZ = {
-    600 : (   50000000,   54000000 ),
-    200 : (  144000000,  148000000 ),
-    125 : (  219000000,  225000000 ),
-    70 :  (  420000000,  450000000 ),
-    23 :  ( 1240000000, 1300000000 ),
-}
-
-# NB: This only works for some bands, throws an Exception otherwise
-def freq_to_band(freq):
-    """Returns the band (in cm) for a given frequency"""
-    for band, (lo, hi) in BAND_TO_MHZ.items():
-        if int(freq) > lo and int(freq) < hi:
-            return band
-    raise Exception("No conversion for frequency %i" % freq)
-
 TONE_MODES = [
     "",
     "Tone",
diff -r 443ea98c0840 -r fa1ac806391e chirpui/bandplans.py
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/chirpui/bandplans.py	Wed Mar 13 11:20:02 2013 +1100
@@ -0,0 +1,90 @@
+# Copyright 2013 Sean Burford <sburford@google.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 chirpui import config
+from chirp import bandplan_na, bandplan_au
+from chirp import bandplan_iaru_r1, bandplan_iaru_r2, bandplan_iaru_r3
+
+PLANS = {
+    "iaru_r1": "IARU Region 1",
+    "iaru_r2": "IARU Region 2",
+    "iaru_r3": "IARU Region 3",
+    "north_america": "North American Amateur",
+    "australia": "Australian Amateur",
+    }
+
+def conf(cf=None):
+    vals = {}
+    if cf is None:
+        cf = config.get()
+
+    for plan, desc in PLANS.items():
+        val = cf.get_bool(plan, "bandplan")
+        vals[plan] = (desc, val)
+
+    return vals
+
+def _walk_bandplan(freq, bandplan, defaults):
+    # Override defaults with values from this level.
+    for name in defaults:
+        defaults[name] = bandplan.get(name, defaults[name])
+
+    # Go more specific if the frequency fits within an available sublevel.
+    for key, vals in bandplan.items():
+        if key in defaults:
+            pass
+        elif isinstance(key, tuple):
+            if key[0] > key[1]:
+                raise Exception("Invalid range %s - %s" % key)
+            if int(freq) >= key[0] and int(freq) < key[1]:
+                _walk_bandplan(freq, vals, defaults)
+                break
+        else:
+            raise Exception("Invalid key %s" % key)
+
+def _determine_defaults(freq, bandplan, defaults):
+    try:
+        _walk_bandplan(freq, bandplan.get("bands", {}), defaults)
+    except Exception, e:
+        print "Failed to parse %s band plan: %s" % (
+            bandplan.get("name", "???"), e)
+
+def get_defaults(freq):
+    defaults = {"name": None,
+                "url": None,
+                "mode": None,
+                "step": None,
+                "tones": None,
+                "offset": None,
+               }
+
+    cf = conf()
+    # This should be ordered from least specific to most specific as
+    # later bandplans take precedence.
+    if cf.get("iaru_r1")[1]:
+        _determine_defaults(freq, bandplan_iaru_r1.BANDPLAN, defaults)
+    if cf.get("iaru_r2")[1]:
+        _determine_defaults(freq, bandplan_iaru_r2.BANDPLAN, defaults)
+    if cf.get("iaru_r3")[1]:
+        _determine_defaults(freq, bandplan_iaru_r3.BANDPLAN, defaults)
+    if cf.get("australia")[1]:
+        _determine_defaults(freq, bandplan_au.BANDPLAN, defaults)
+    if cf.get("north_america")[1]:
+        bp_off = bandplan_na.get_offset(freq)
+        if bp_off is not None:
+            defaults["offset"] = bp_off
+
+    return defaults
+
diff -r 443ea98c0840 -r fa1ac806391e chirpui/config.py
--- a/chirpui/config.py	Tue Mar 05 09:49:47 2013 -0800
+++ b/chirpui/config.py	Wed Mar 13 11:20:02 2013 +1100
@@ -54,6 +54,12 @@
     def is_defined(self, key, section):
         return self.__config.has_option(section, key)
 
+    def remove_option(self, section, key):
+        self.__config.remove_option(section, key)
+
+        if not self.__config.items(section):
+            self.__config.remove_section(section)
+
 class ChirpConfigProxy:
     def __init__(self, config, section="global"):
         self._config = config
@@ -98,6 +104,10 @@
     def is_defined(self, key, section=None):
         return self._config.is_defined(key, section or self._section)
 
+    def remove_option(self, key, section):
+        self._config.remove_option(section, key)
+
+
 _CONFIG = None
 def get(section="global"):
     global _CONFIG
diff -r 443ea98c0840 -r fa1ac806391e chirpui/mainapp.py
--- a/chirpui/mainapp.py	Tue Mar 05 09:49:47 2013 -0800
+++ b/chirpui/mainapp.py	Wed Mar 13 11:20:02 2013 +1100
@@ -40,6 +40,7 @@
 from chirp import CHIRP_VERSION, chirp_common, detect, errors
 from chirp import icf, ic9x_icf
 from chirpui import editorset, clone, miscwidgets, config, reporting, fips
+from chirpui import bandplans
 
 CONF = config.get()
 
@@ -1256,8 +1257,9 @@
         conf = config.get()
         conf.set_bool("no_report", not action.get_active())
 
-    def do_toggle_autorpt(self, action):
-        CONF.set_bool("autorpt", action.get_active(), "memedit")
+    def do_toggle_bp(self, _action):
+        action = _action.get_name()
+        CONF.set_bool(action, _action.get_active(), "bandplan")
 
     def do_toggle_no_smart_tmode(self, action):
         CONF.set_bool("no_smart_tmode", not action.get_active(), "memedit")
@@ -1351,8 +1353,8 @@
             self.do_clearq()
         elif action == "report":
             self.do_toggle_report(_action)
-        elif action == "autorpt":
-            self.do_toggle_autorpt(_action)
+        elif action in bandplans.PLANS:
+            self.do_toggle_bp(_action)
         elif action == "no_smart_tmode":
             self.do_toggle_no_smart_tmode(_action)
         elif action == "developer":
@@ -1429,7 +1431,10 @@
       </menu>
       <menu action="stock" name="stock"/>
       <separator/>
-      <menuitem action="autorpt"/>
+      <menu action="bandplan" name="bandplan">
+        <menuitem action="north_america"/>
+        <menuitem action="australia"/>
+      </menu>
       <separator/>
       <menuitem action="cancelq"/>
     </menu>
@@ -1485,6 +1490,7 @@
             ('export_chirp', None, _("CHIRP Native File"), None, None, self.mh),
             ('export_csv', None, _("CSV File"), None, None, self.mh),
             ('stock', None, _("Import from stock config"), None, None, self.mh),
+            ('bandplan', None, _("Use band plans"), None, None, self.mh),
             ('cancelq', gtk.STOCK_STOP, None, "Escape", None, self.mh),
             ('help', None, _('Help'), None, None, self.mh),
             ('about', gtk.STOCK_ABOUT, None, None, None, self.mh),
@@ -1493,17 +1499,24 @@
         conf = config.get()
         re = not conf.get_bool("no_report");
         hu = conf.get_bool("hide_unused", "memedit")
-        ro = conf.get_bool("autorpt", "memedit")
         dv = conf.get_bool("developer", "state")
         st = not conf.get_bool("no_smart_tmode", "memedit")
 
+        # Migrate old "automatic repeater offset" setting to
+        # "North American Amateur Band Plan"
+        ro = conf.get("autorpt", "memedit")
+        if ro is not None:
+            conf.set_bool("north_america", "bandplan", ro)
+            conf.remove_option("autorpt", "memedit")
+
         toggles = [\
             ('report', None, _("Report statistics"), None, None, self.mh, re),
             ('hide_unused', None, _("Hide Unused Fields"), None, None, self.mh, hu),
             ('no_smart_tmode', None, _("Smart Tone Modes"), None, None, self.mh, st),
-            ('autorpt', None, _("Automatic Repeater Offset"), None, None, self.mh, ro),
             ('developer', None, _("Enable Developer Functions"), None, None, self.mh, dv),
             ]
+        for plan, setting in bandplans.conf(conf).items():
+            toggles.append((plan, None, _(setting[0]), None, None, self.mh, setting[1]))
 
         self.menu_uim = gtk.UIManager()
         self.menu_ag = gtk.ActionGroup("MenuBar")
@@ -1695,10 +1708,6 @@
             d.destroy()
         CONF.set_bool("warned_about_reporting", True)
 
-        if not CONF.is_defined("autorpt", "memedit"):
-            print "autorpt not set et"
-            CONF.set_bool("autorpt", True, "memedit")
-
         self.update_recent_files()
         self.update_stock_configs()
         self.setup_extra_hotkeys()
diff -r 443ea98c0840 -r fa1ac806391e chirpui/memedit.py
--- a/chirpui/memedit.py	Tue Mar 05 09:49:47 2013 -0800
+++ b/chirpui/memedit.py	Wed Mar 13 11:20:02 2013 +1100
@@ -32,7 +32,7 @@
 import pickle
 import os
 
-from chirpui import common, shiftdialog, miscwidgets, config, memdetail
+from chirpui import common, shiftdialog, miscwidgets, config, memdetail, bandplans
 from chirp import chirp_common, errors, directory, import_logic
 
 def handle_toggle(_, path, store, col):
@@ -122,10 +122,10 @@
         return chirp_common.parse_freq(new)
 
     def ed_freq(self, _foo, path, new, colnum):
-        iter = self.store.get_iter(path)
-        prev, = self.store.get(iter, colnum)
+        path_iter = self.store.get_iter(path)
+        prev, = self.store.get(path_iter, colnum)
 
-        def set_offset(path, offset):
+        def set_offset(offset):
             if offset > 0:
                 dup = "+"
             elif offset == 0:
@@ -135,15 +135,24 @@
                 offset *= -1
 
             if offset:
-                self.store.set(iter, self.col(_("Offset")), offset)
+                self.store.set(path_iter, self.col(_("Offset")), offset)
 
-            self.store.set(iter, self.col(_("Duplex")), dup)
+            self.store.set(path_iter, self.col(_("Duplex")), dup)
 
         def set_ts(ts):
-            self.store.set(iter, self.col(_("Tune Step")), ts)
+            if ts in chirp_common.TUNING_STEPS:
+                self.store.set(path_iter, self.col(_("Tune Step")), ts)
 
         def get_ts(path):
-            return self.store.get(iter, self.col(_("Tune Step")))[0]
+            return self.store.get(path_iter, self.col(_("Tune Step")))[0]
+
+        def set_mode(mode):
+            if mode in chirp_common.MODES:
+                self.store.set(path_iter, self.col(_("Mode")), mode)
+
+        def set_tone(tone):
+            if tone in chirp_common.TONES:
+                self.store.set(path_iter, self.col(_("Tone")), tone)
 
         try:
             new = chirp_common.parse_freq(new)
@@ -154,16 +163,13 @@
         if not self._features.has_nostep_tuning:
             set_ts(chirp_common.required_step(new))
 
-        if new and self._config.get_bool("autorpt") and new != prev:
-            try:
-                band = chirp_common.freq_to_band(new)
-                set_offset(path, 0)
-                for lo, hi, offset in chirp_common.STD_OFFSETS[band]:
-                    if new > lo and new < hi:
-                        set_offset(path, offset)
-                        break
-            except Exception, e:
-                pass
+        if new and new != prev:
+            defaults = bandplans.get_defaults(new)
+            set_offset(defaults.get("offset") or 0)
+            set_ts(defaults.get("step"))
+            set_mode(defaults.get("mode"))
+            if defaults.get("tones"):
+                set_tone(defaults.get("tones")[0])
 
         return new
 
@@ -190,11 +196,8 @@
             # RX frequency as the default TX frequency
             self.store.set(iter, self.col("Offset"), freq)
         else:
-            band = int(freq / 100000000)
-            if chirp_common.STD_OFFSETS.has_key(band):
-                offset = chirp_common.STD_OFFSETS[band][0][2]
-            else:
-                offset = 0
+            defaults = bandplans.get_defaults(freq)
+            offset = defaults.get("offset") or 0
             self.store.set(iter, self.col(_("Offset")), abs(offset))
 
         return new
