[chirp_devel] [PATCH 2 of 2] pylint fixes round 1
Dan Smith
Fri Apr 27 14:35:46 PDT 2012
# HG changeset patch
# User Dan Smith <dsmith at danplanet.com>
# Date 1335562541 25200
# Node ID f805c420592f8a8b1b0dd89107920c6bbed7fdf7
# Parent db82df47f205409ac1f71304f7372ca7f7d88e52
pylint fixes round 1
#93
diff -r db82df47f205 -r f805c420592f chirp/alinco.py
--- a/chirp/alinco.py Fri Apr 27 14:35:40 2012 -0700
+++ b/chirp/alinco.py Fri Apr 27 14:35:41 2012 -0700
@@ -13,11 +13,11 @@
# 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 chirp_common, bitwise, memmap, errors, directory
+from chirp import chirp_common, bitwise, memmap, errors, directory, util
import time
-DRx35_mem_format = """
+DRX35_MEM_FORMAT = """
#seekto 0x0120;
u8 used_flags[25];
@@ -59,7 +59,9 @@
STEPS = [5.0, 10.0, 12.5, 15.0, 20.0, 25.0, 30.0]
class AlincoStyleRadio(chirp_common.CloneModeRadio):
+ """Base class for all known Alinco radios"""
_memsize = 0
+ _model = "NONE"
def _send(self, data):
self.pipe.write(data)
@@ -96,20 +98,19 @@
time.sleep(0.1)
if self.status_fn:
- s = chirp_common.Status()
- s.cur = addr + 16
- s.max = self._memsize
- s.msg = "Downloading from radio"
- self.status_fn(s)
+ status = chirp_common.Status()
+ status.cur = addr + 16
+ status.max = self._memsize
+ status.msg = "Downloading from radio"
+ self.status_fn(status)
self._send("AL~E\r\n")
- r = self.pipe.read(20)
- #print r
+ self.pipe.read(20)
return memmap.MemoryMap(data)
def _identify(self):
- for i in range(0, 3):
+ for _i in range(0, 3):
self._send("%s\r\n" % self._model)
resp = self.pipe.read(6)
if resp.strip() == "OK":
@@ -137,18 +138,18 @@
time.sleep(0.1)
if self.status_fn:
- s = chirp_common.Status()
- s.cur = addr + 16
- s.max = self._memsize
- s.msg = "Uploading to radio"
- self.status_fn(s)
+ status = chirp_common.Status()
+ status.cur = addr + 16
+ status.max = self._memsize
+ status.msg = "Uploading to radio"
+ self.status_fn(status)
self._send("AL~E\r\n")
- r = self.pipe.read(20)
+ self.pipe.read(20)
#print r
def process_mmap(self):
- self._memobj = bitwise.parse(DRx35_mem_format, self._mmap)
+ self._memobj = bitwise.parse(DRX35_MEM_FORMAT, self._mmap)
def sync_in(self):
try:
@@ -183,32 +184,33 @@
[chr(x + ord("A")) for x in range(0, 26)] + [" "] + \
list("\x00" * 128)
+def _get_name(_mem):
+ name = ""
+ for i in _mem.name:
+ if not i:
+ break
+ name += CHARSET[i]
+ return name
+
+def _set_name(mem, _mem):
+ name = [0x00] * 7
+ j = 0
+ for i in range(0, 7):
+ try:
+ name[j] = CHARSET.index(mem.name[i])
+ j += 1
+ except IndexError:
+ pass
+ except ValueError:
+ pass
+ return name
+
class DRx35Radio(AlincoStyleRadio):
+ """Base class for the DR-x35 radios"""
_range = [(118000000, 155000000)]
_power_levels = []
_valid_tones = list(chirp_common.TONES)
- def _get_name(self, mem, _mem):
- name = ""
- for i in _mem.name:
- if not i:
- break
- name += CHARSET[i]
- return name
-
- def _set_name(self, mem, _mem):
- name = [0x00] * 7
- j = 0
- for i in range(0, 7):
- try:
- name[j] = CHARSET.index(mem.name[i])
- j += 1
- except IndexError:
- pass
- except ValueError:
- pass
- return name
-
def get_features(self):
rf = chirp_common.RadioFeatures()
rf.valid_tmodes = ["", "Tone", "TSQL", "DTCS"]
@@ -254,7 +256,7 @@
if _skp & bit:
mem.skip = "S"
- mem.name = self._get_name(mem, _mem).rstrip()
+ mem.name = _get_name(_mem).rstrip()
return mem
@@ -298,10 +300,11 @@
else:
_skp &= ~bit
- _mem.name = self._set_name(mem, _mem)
+ _mem.name = _set_name(mem, _mem)
@directory.register
class DR03Radio(DRx35Radio):
+ """Alinco DR03"""
VENDOR = "Alinco"
MODEL = "DR03T"
@@ -316,6 +319,7 @@
@directory.register
class DR06Radio(DRx35Radio):
+ """Alinco DR06"""
VENDOR = "Alinco"
MODEL = "DR06T"
@@ -330,6 +334,7 @@
@directory.register
class DR135Radio(DRx35Radio):
+ """Alinco DR135"""
VENDOR = "Alinco"
MODEL = "DR135T"
@@ -344,6 +349,7 @@
@directory.register
class DR235Radio(DRx35Radio):
+ """Alinco DR235"""
VENDOR = "Alinco"
MODEL = "DR235T"
@@ -358,6 +364,7 @@
@directory.register
class DR435Radio(DRx35Radio):
+ """Alinco DR435"""
VENDOR = "Alinco"
MODEL = "DR435T"
@@ -385,6 +392,7 @@
@directory.register
class DJ596Radio(DRx35Radio):
+ """Alinco DJ596"""
VENDOR = "Alinco"
MODEL = "DJ596"
@@ -402,6 +410,7 @@
@directory.register
class JT220MRadio(DRx35Radio):
+ """Jetstream JT220"""
VENDOR = "Jetstream"
MODEL = "JT220M"
diff -r db82df47f205 -r f805c420592f chirp/bitwise.py
--- a/chirp/bitwise.py Fri Apr 27 14:35:40 2012 -0700
+++ b/chirp/bitwise.py Fri Apr 27 14:35:41 2012 -0700
@@ -136,6 +136,10 @@
def set_raw(self, data):
self._data[self._offset] = data[:self._size]
+ def __getattr__(self, name):
+ raise AttributeError("Unknown attribute %s in %s" % (name,
+ self.__class__))
+
def __repr__(self):
return "(%s:%i bytes @ %04x)" % (self.__class__.__name__,
self._size,
@@ -542,7 +546,10 @@
self._keys.append(key)
def __getattr__(self, name):
- return self._generators[name]
+ try:
+ return self._generators[name]
+ except KeyError:
+ raise AttributeError("No attribute %s in struct" % name)
def __setattr__(self, name, value):
if not self.__dict__.has_key("_structDataElement__init"):
diff -r db82df47f205 -r f805c420592f chirp/chirp_common.py
--- a/chirp/chirp_common.py Fri Apr 27 14:35:40 2012 -0700
+++ b/chirp/chirp_common.py Fri Apr 27 14:35:41 2012 -0700
@@ -17,9 +17,7 @@
#print "Using separation character of '%s'" % SEPCHAR
-import threading
import math
-from decimal import Decimal
from chirp import errors, memmap
@@ -60,7 +58,8 @@
"->DTCS",
]
-MODES = ["WFM", "FM", "NFM", "AM", "NAM", "DV", "USB", "LSB", "CW", "RTTY", "DIG", "PKT", "NCW", "NCWR", "CWR", "P25"]
+MODES = ["WFM", "FM", "NFM", "AM", "NAM", "DV", "USB", "LSB", "CW", "RTTY",
+ "DIG", "PKT", "NCW", "NCWR", "CWR", "P25"]
STD_6M_OFFSETS = [
(51620000, 51980000, -500000),
@@ -108,6 +107,7 @@
# 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
@@ -138,12 +138,15 @@
CHARSET_ASCII = "".join([chr(x) for x in range(ord(" "), ord("~")+1)])
def watts_to_dBm(watts):
+ """Converts @watts in watts to dBm"""
return int(10 * math.log10(int(watts * 1000)))
def dBm_to_watts(dBm):
+ """Converts @dBm from dBm to watts"""
return int(math.pow(10, (dBm - 30) / 10))
class PowerLevel:
+ """Represents a power level supported by a radio"""
def __init__(self, label, watts=0, dBm=0):
if watts:
dBm = watts_to_dBm(watts)
@@ -180,6 +183,7 @@
return "%s (%i dBm)" % (self._label, self._power)
def parse_freq(freqstr):
+ """Parse a frequency string and return the value in integral Hz"""
if "." in freqstr:
MHz, kHz = freqstr.split(".")
else:
@@ -192,9 +196,12 @@
return int(("%s%-6s" % (MHz, kHz)).replace(" ", "0"))
def format_freq(freq):
+ """Format a frequency given in Hz as a string"""
+
return "%i.%06i" % (freq / 1000000, freq % 1000000)
class Memory:
+ """Base class for a single radio memory"""
freq = 0
number = 0
extd_number = ""
@@ -262,13 +269,15 @@
return "Memory[%i]" % self.number
def dupe(self):
- m = self.__class__()
+ """Return a deep copy of @self"""
+ mem = self.__class__()
for k, v in self.__dict__.items():
- m.__dict__[k] = v
+ mem.__dict__[k] = v
- return m
+ return mem
def clone(self, source):
+ """Absorb all of the properties of @source"""
for k, v in source.__dict__.items():
self.__dict__[k] = v
@@ -294,9 +303,11 @@
self.__dict__[name] = val
def format_freq(self):
+ """Return a properly-formatted string of this memory's frequency"""
return format_freq(self.freq)
def parse_freq(self, freqstr):
+ """Set the frequency from a string"""
self.freq = parse_freq(freqstr)
return self.freq
@@ -321,7 +332,7 @@
else:
dup = self.duplex
- return "Memory %i: %s%s%s %s (%s) r%.1f%s c%.1f%s d%03i%s%s [TS=%.2f]"% \
+ return "Memory %i: %s%s%s %s (%s) r%.1f%s c%.1f%s d%03i%s%s [%.2f]"% \
(self.number,
format_freq(self.freq),
dup,
@@ -338,6 +349,7 @@
self.tuning_step)
def to_csv(self):
+ """Return a CSV representation of this memory"""
return [
"%i" % self.number,
"%s" % self.name,
@@ -355,18 +367,16 @@
"%s" % self.comment,
"", "", "", ""]
- class Callable:
- def __init__(self, target):
- self.__call__ = target
-
- def _from_csv(_line):
+ @classmethod
+ def _from_csv(cls, _line):
line = _line.strip()
if line.startswith("Location"):
raise errors.InvalidMemoryLocation("Non-CSV line")
vals = line.split(SEPCHAR)
if len(vals) < 11:
- raise errors.InvalidDataError("CSV format error (14 columns expected)")
+ raise errors.InvalidDataError("CSV format error " +
+ "(14 columns expected)")
if vals[10] == "DV":
mem = DVMemory()
@@ -376,9 +386,8 @@
mem.really_from_csv(vals)
return mem
- from_csv = Callable(_from_csv)
-
def really_from_csv(self, vals):
+ """Careful parsing of split-out @vals"""
try:
self.number = int(vals[0])
except:
@@ -450,6 +459,7 @@
return True
class DVMemory(Memory):
+ """A Memory with D-STAR attributes"""
dv_urcall = "CQCQCQ"
dv_rpt1call = ""
dv_rpt2call = ""
@@ -493,10 +503,11 @@
self.dv_rpt2call = vals[17].rstrip()[:8]
try:
self.dv_code = int(vals[18].strip())
- except:
+ except Exception:
self.dv_code = 0
class Bank:
+ """Base class for a radio's Bank"""
def __init__(self, model, index, name):
self._model = model
self._index = index
@@ -520,6 +531,7 @@
return self.get_index() == other.get_index()
class NamedBank(Bank):
+ """A bank that can have a name"""
def set_name(self, name):
"""Changes the user-adjustable bank name"""
self._name = name
@@ -556,6 +568,7 @@
raise Exception("Not implemented")
class BankIndexInterface:
+ """Interface for banks with index capabilities"""
def get_index_bounds(self):
"""Returns a tuple (lo,hi) of the minimum and maximum bank indices"""
raise Exception("Not implemented")
@@ -579,18 +592,16 @@
pass
def console_status(status):
+ """Write a status object to the console"""
import sys
sys.stderr.write("\r%s" % status)
-class Callable:
- def __init__(self, target):
- self.__call__ = target
-
BOOLEAN = [True, False]
class RadioFeatures:
+ """Radio Feature Flags"""
_valid_map = {
# General
"has_bank_index" : BOOLEAN,
@@ -602,7 +613,6 @@
"has_bank" : BOOLEAN,
"has_bank_names" : BOOLEAN,
"has_tuning_step" : BOOLEAN,
- "has_name" : BOOLEAN,
"has_ctone" : BOOLEAN,
"has_cross" : BOOLEAN,
"has_infinite_number" : BOOLEAN,
@@ -663,11 +673,17 @@
name))
self.__dict__[name] = val
+ def __getattr__(self, name):
+ raise AttributeError("pylint is confused by RadioFeatures")
+
def init(self, attribute, default, doc=None):
+ """Initialize a feature flag @attribute with default value @default,
+ and documentation string @doc"""
self.__setattr__(attribute, default)
self.__docs[attribute] = doc
def get_doc(self, attribute):
+ """Return the description of @attribute"""
return self.__docs[attribute]
def __init__(self):
@@ -751,70 +767,79 @@
"callsign at the beginning of the master URCALL list")
def is_a_feature(self, name):
+ """Returns True if @name is a valid feature flag name"""
return name in self._valid_map.keys()
def __getitem__(self, name):
return self.__dict__[name]
class ValidationMessage(str):
+ """Base class for Validation Errors and Warnings"""
pass
class ValidationWarning(ValidationMessage):
+ """A non-fatal warning during memory validation"""
pass
class ValidationError(ValidationMessage):
+ """A fatal error during memory validation"""
pass
class Radio:
+ """Base class for all Radio drivers"""
BAUD_RATE = 9600
HARDWARE_FLOW = False
VENDOR = "Unknown"
MODEL = "Unknown"
VARIANT = ""
- status_fn = lambda x, y: console_status(y)
+ def status_fn(self, status):
+ """Deliver @status to the UI"""
+ console_status(status)
def __init__(self, pipe):
self.errors = []
self.pipe = pipe
def get_features(self):
+ """Return a RadioFeatures object for this radio"""
return RadioFeatures()
def get_settings(self):
+ """Return a RadioSettingsGroup object for this radio"""
return None
def set_settings(self, settings):
+ """Sets the settings contained in the @settings object that has
+ been queried with get_settings() and modified"""
raise Exception("Not implemented")
- def _get_name_raw(*args):
- cls = args[-1]
+ @classmethod
+ def get_name(cls):
+ """Return a printable name for this radio"""
return "%s %s" % (cls.VENDOR, cls.MODEL)
- def get_name(self):
- return self._get_name_raw(self.__class__)
-
- _get_name = Callable(_get_name_raw)
-
def set_pipe(self, pipe):
+ """Set the serial object to be used for communications"""
self.pipe = pipe
def get_memory(self, number):
+ """Return a Memory object for the memory at location @number"""
pass
def erase_memory(self, number):
- m = Memory()
- m.number = number
- m.empty = True
- self.set_memory(m)
+ """Erase memory at location @number"""
+ mem = Memory()
+ mem.number = number
+ mem.empty = True
+ self.set_memory(mem)
def get_memories(self, lo=None, hi=None):
+ """Get all the memories between @lo and @hi"""
pass
def set_memory(self, memory):
- pass
-
- def set_memories(self, memories):
+ """Set the memory object @memory"""
pass
def get_bank_model(self):
@@ -822,22 +847,30 @@
return None
def get_raw_memory(self, number):
+ """Return a raw string describing the memory at @number"""
pass
def get_special_locations(self):
+ """Return a list of special memory location names"""
return []
def filter_name(self, name):
+ """Filter @name to just the length and characters supported"""
rf = self.get_features()
if rf.valid_characters == rf.valid_characters.upper():
# Radio only supports uppercase, so help out here
name = name.upper()
- return "".join([x for x in name[:rf.valid_name_length] if x in rf.valid_characters])
+ return "".join([x for x in name[:rf.valid_name_length]
+ if x in rf.valid_characters])
def get_sub_devices(self):
+ """Return a list of sub-device Radio objects, if
+ RadioFeatures.has_sub_devices is True"""
return []
def validate_memory(self, mem):
+ """Return a list of warnings and errors that will be encoundered
+ if trying to set @mem on the current radio"""
msgs = []
rf = self.get_features()
@@ -857,8 +890,10 @@
msgs.append(msg)
else:
if mem.tmode == "Cross":
- if rf.valid_cross_modes and mem.cross_mode not in rf.valid_cross_modes:
- msg = ValidationError("Cross tone mode %s not supported" % mem.cross_mode)
+ if rf.valid_cross_modes and \
+ mem.cross_mode not in rf.valid_cross_modes:
+ msg = ValidationError("Cross tone mode %s not supported" % \
+ mem.cross_mode)
msgs.append(msg)
if rf.has_dtcs_polarity and mem.dtcs_polarity not in rf.valid_dtcs_pols:
@@ -933,16 +968,24 @@
"""A file-backed radio stores its data in a file"""
FILE_EXTENSION = "img"
+ def __init__(self, *args, **kwargs):
+ Radio.__init__(self, *args, **kwargs)
+ self._memobj = None
+
def save(self, filename):
+ """Save the radio's memory map to @filename"""
self.save_mmap(filename)
def load(self, filename):
+ """Load the radio's memory map object from @filename"""
self.load_mmap(filename)
def process_mmap(self):
+ """Process a newly-loaded or downloaded memory map"""
pass
def load_mmap(self, filename):
+ """Load the radio's memory map from @filename"""
mapfile = file(filename, "rb")
self._mmap = memmap.MemoryMap(mapfile.read())
mapfile.close()
@@ -957,26 +1000,13 @@
mapfile = file(filename, "wb")
mapfile.write(self._mmap.get_packed())
mapfile.close()
- except IOError,e:
+ except IOError:
raise Exception("File Access Error")
def get_mmap(self):
+ """Return the radio's memory map object"""
return self._mmap
- def get_memsize(self):
- return self._memsize
-
- @classmethod
- def match_model(cls, filedata, filename):
- """Given contents of a stored file (@filedata), return True if
- this radio driver handles the represented model"""
-
- # Unless the radio driver does something smarter, claim
- # support if the data is the same size as our memory.
- # Ideally, each radio would perform an intelligent analysis to
- # make this determination to avoid model conflicts with
- # memories of the same size.
- return len(filedata) == cls._memsize
class CloneModeRadio(FileBackedRadio):
@@ -997,7 +1027,23 @@
self._mmap = pipe
self.process_mmap()
else:
- Radio.__init__(self, pipe)
+ FileBackedRadio.__init__(self, pipe)
+
+ def get_memsize(self):
+ """Return the radio's memory size"""
+ return self._memsize
+
+ @classmethod
+ def match_model(cls, filedata, filename):
+ """Given contents of a stored file (@filedata), return True if
+ this radio driver handles the represented model"""
+
+ # Unless the radio driver does something smarter, claim
+ # support if the data is the same size as our memory.
+ # Ideally, each radio would perform an intelligent analysis to
+ # make this determination to avoid model conflicts with
+ # memories of the same size.
+ return len(filedata) == cls._memsize
def sync_in(self):
"Initiate a radio-to-PC clone operation"
@@ -1008,36 +1054,47 @@
pass
class LiveRadio(Radio):
+ """Base class for all Live-Mode radios"""
pass
class NetworkSourceRadio(Radio):
+ """Base class for all radios based on a network source"""
def do_fetch(self):
+ """Fetch the source data from the network"""
pass
class IcomDstarSupport:
+ """Base interface for radios supporting Icom's D-STAR technology"""
MYCALL_LIMIT = (1, 1)
URCALL_LIMIT = (1, 1)
RPTCALL_LIMIT = (1, 1)
def get_urcall_list(self):
+ """Return a list of URCALL callsigns"""
return []
def get_repeater_call_list(self):
+ """Return a list of RPTCALL callsigns"""
return []
def get_mycall_list(self):
+ """Return a list of MYCALL callsigns"""
return []
def set_urcall_list(self, calls):
+ """Set the URCALL callsign list"""
pass
def set_repeater_call_list(self, calls):
+ """Set the RPTCALL callsign list"""
pass
def set_mycall_list(self, calls):
+ """Set the MYCALL callsign list"""
pass
class Status:
+ """Clone status object for conveying clone progress to the UI"""
name = "Job"
msg = "Unknown"
max = 100
@@ -1055,21 +1112,27 @@
return "|%-10s| %2.1f%% %s" % (ticks, pct, self.msg)
def is_fractional_step(freq):
+ """Returns True if @freq requires a 12.5kHz or 6.25kHz step"""
return not is_5_0(freq) and (is_12_5(freq) or is_6_25(freq))
def is_5_0(freq):
+ """Returns True if @freq is reachable by a 5kHz step"""
return (freq % 5000) == 0
def is_12_5(freq):
+ """Returns True if @freq is reachable by a 12.5kHz step"""
return (freq % 12500) == 0
def is_6_25(freq):
+ """Returns True if @freq is reachable by a 6.25kHz step"""
return (freq % 6250) == 0
def is_2_5(freq):
+ """Returns True if @freq is reachable by a 2.5kHz step"""
return (freq % 2500) == 0
def required_step(freq):
+ """Returns the simplest tuning step that is required to reach @freq"""
if is_5_0(freq):
return 5.0
elif is_12_5(freq):
@@ -1080,10 +1143,13 @@
return 2.5
else:
raise errors.InvalidDataError("Unable to calculate the required " +
- "tuning step for %i.%5i" % (freq / 1000000,
- freq % 1000000))
+ "tuning step for %i.%5i" % \
+ (freq / 1000000,
+ freq % 1000000))
def fix_rounded_step(freq):
+ """Some radios imply the last bit of 12.5kHz and 6.25kHz step
+ frequencies. Take the base @freq and return the corrected one"""
try:
required_step(freq)
return freq
@@ -1112,57 +1178,43 @@
format_freq(freq))
def _name(name, len, just_upper):
+ """Justify @name to @len, optionally converting to all uppercase"""
if just_upper:
name = name.upper()
return name.ljust(len)[:len]
def name6(name, just_upper=True):
+ """6-char name"""
return _name(name, 6, just_upper)
def name8(name, just_upper=False):
+ """8-char name"""
return _name(name, 8, just_upper)
def name16(name, just_upper=False):
+ """16-char name"""
return _name(name, 16, just_upper)
-class KillableThread(threading.Thread):
- def __tid(self):
- if not self.isAlive():
- raise threading.ThreadError("Not running")
-
- for tid, thread in threading._active.items():
- if thread == self:
- return tid
-
- raise threading.ThreadError("I don't know my own TID")
-
- def kill(self, exception):
- import ctypes
- import inspect
-
- if not inspect.isclass(exception):
- raise Exception("Parameter is not an Exception")
-
- ctype = ctypes.py_object(exception)
- ret = ctypes.pythonapi.PyThreadState_SetAsyncExc(self.__tid(), ctype)
- if ret != 1:
- ctypes.pythonapi.PyThreadState_SetAsyncExc(self.__tid(), 0)
- raise Exception("Failed to signal thread!")
-
def to_GHz(val):
+ """Convert @val in GHz to Hz"""
return val * 1000000000
def to_MHz(val):
+ """Convert @val in MHz to Hz"""
return val * 1000000
def to_kHz(val):
+ """Convert @val in kHz to Hz"""
return val * 1000
def from_GHz(val):
+ """Convert @val in Hz to GHz"""
return val / 100000000
def from_MHz(val):
+ """Convert @val in Hz to MHz"""
return val / 100000
def from_kHz(val):
+ """Convert @val in Hz to kHz"""
return val / 100
diff -r db82df47f205 -r f805c420592f chirp/detect.py
--- a/chirp/detect.py Fri Apr 27 14:35:40 2012 -0700
+++ b/chirp/detect.py Fri Apr 27 14:35:41 2012 -0700
@@ -15,16 +15,16 @@
import serial
-from chirp import chirp_common, errors, idrp, util, icf, directory, ic9x_ll
-from chirp import kenwood_live, tmv71, tmv71_ll, icomciv, thd72
+from chirp import errors, icf, directory, ic9x_ll
+from chirp import kenwood_live, icomciv
def _icom_model_data_to_rclass(md):
- for rtype, rclass in directory.DRV_TO_RADIO.items():
+ for _rtype, rclass in directory.DRV_TO_RADIO.items():
if rclass.VENDOR != "Icom":
continue
- if not rclass._model:
+ if not rclass.get_model():
continue
- if rclass._model[:4] == md[:4]:
+ if rclass.get_model()[:4] == md[:4]:
return rclass
raise errors.RadioError("Unknown radio type %02x%02x%02x%02x" %\
@@ -33,22 +33,21 @@
ord(md[2]),
ord(md[3])))
-def _detect_icom_radio(s):
+def _detect_icom_radio(ser):
# ICOM VHF/UHF Clone-type radios @ 9600 baud
try:
- s.setBaudrate(9600)
- md = icf.get_model_data(s)
+ ser.setBaudrate(9600)
+ md = icf.get_model_data(ser)
return _icom_model_data_to_rclass(md)
except errors.RadioError, e:
print e
- pass
# ICOM IC-91/92 Live-mode radios @ 4800/38400 baud
- s.setBaudrate(4800)
+ ser.setBaudrate(4800)
try:
- ic9x_ll.send_magic(s)
+ ic9x_ll.send_magic(ser)
return _icom_model_data_to_rclass("ic9x")
except errors.RadioError:
pass
@@ -57,25 +56,26 @@
for rate in [9600, 4800, 19200]:
try:
- s.setBaudrate(rate)
- return icomciv.probe_model(s)
+ ser.setBaudrate(rate)
+ return icomciv.probe_model(ser)
except errors.RadioError:
pass
- s.close()
+ ser.close()
raise errors.RadioError("Unable to get radio model")
def detect_icom_radio(port):
- s = serial.Serial(port=port, timeout=0.5)
+ """Detect which Icom model is connected to @port"""
+ ser = serial.Serial(port=port, timeout=0.5)
try:
- result = _detect_icom_radio(s)
+ result = _detect_icom_radio(ser)
except Exception:
- s.close()
+ ser.close()
raise
- s.close()
+ ser.close()
print "Auto-detected %s %s on %s" % (result.VENDOR,
result.MODEL,
@@ -84,9 +84,10 @@
return result
def detect_kenwoodlive_radio(port):
- s = serial.Serial(port=port, baudrate=9600, timeout=0.5)
- r_id = kenwood_live.get_id(s)
- s.close()
+ """Detect which Kenwood model is connected to @port"""
+ ser = serial.Serial(port=port, baudrate=9600, timeout=0.5)
+ r_id = kenwood_live.get_id(ser)
+ ser.close()
models = {}
for rclass in directory.DRV_TO_RADIO.values():
@@ -102,8 +103,3 @@
"Icom" : detect_icom_radio,
"Kenwood" : detect_kenwoodlive_radio,
}
-
-if __name__ == "__main__":
- import sys
-
- print "Found %s" % detect_radio(sys.argv[1])
diff -r db82df47f205 -r f805c420592f chirp/directory.py
--- a/chirp/directory.py Fri Apr 27 14:35:40 2012 -0700
+++ b/chirp/directory.py Fri Apr 27 14:35:41 2012 -0700
@@ -21,6 +21,7 @@
from chirp import chirp_common, util, rfinder, radioreference, errors
def radio_class_id(cls):
+ """Return a unique identification string for @cls"""
ident = "%s_%s" % (cls.VENDOR, cls.MODEL)
if cls.VARIANT:
ident += "_%s" % cls.VARIANT
@@ -31,6 +32,7 @@
return ident
def register(cls):
+ """Register radio @cls with the directory"""
global DRV_TO_RADIO
ident = radio_class_id(cls)
if ident in DRV_TO_RADIO.keys():
@@ -45,20 +47,24 @@
RADIO_TO_DRV = {}
def get_radio(driver):
+ """Get radio driver class by identification string"""
if DRV_TO_RADIO.has_key(driver):
return DRV_TO_RADIO[driver]
else:
raise Exception("Unknown radio type `%s'" % driver)
-def get_driver(radio):
- if RADIO_TO_DRV.has_key(radio):
- return RADIO_TO_DRV[radio]
- elif RADIO_TO_DRV.has_key(radio.__bases__[0]):
- return RADIO_TO_DRV[radio.__bases__[0]]
+def get_driver(rclass):
+ """Get the identification string for a given class"""
+ if RADIO_TO_DRV.has_key(rclass):
+ return RADIO_TO_DRV[rclass]
+ elif RADIO_TO_DRV.has_key(rclass.__bases__[0]):
+ return RADIO_TO_DRV[rclass.__bases__[0]]
else:
- raise Exception("Unknown radio type `%s'" % radio)
+ raise Exception("Unknown radio type `%s'" % rclass)
def icf_to_image(icf_file, img_file):
+ # FIXME: Why is this here?
+ """Convert an ICF file to a .img file"""
mdata, mmap = icf.read_file(icf_file)
img_data = None
@@ -80,16 +86,17 @@
raise Exception("Unsupported model")
def get_radio_by_image(image_file):
+ """Attempt to get the radio class that owns @image_file"""
if image_file.startswith("radioreference://"):
- method, _, zipcode, username, password = image_file.split("/", 4)
+ _, _, zipcode, username, password = image_file.split("/", 4)
rr = radioreference.RadioReferenceRadio(None)
rr.set_params(zipcode, username, password)
return rr
if image_file.startswith("rfinder://"):
- method, _, email, passwd, lat, lon, miles = image_file.split("/")
+ _, _, email, passwd, lat, lon, miles = image_file.split("/")
rf = rfinder.RFinderRadio(None)
- rf.set_params(float(lat), float(lon), int(miles), email, passwd)
+ rf.set_params((float(lat), float(lon)), int(miles), email, passwd)
return rf
if os.path.exists(image_file) and icf.is_icf_file(image_file):
@@ -105,27 +112,9 @@
else:
filedata = ""
- for radio in DRV_TO_RADIO.values():
- if not issubclass(radio, chirp_common.FileBackedRadio):
+ for rclass in DRV_TO_RADIO.values():
+ if not issubclass(rclass, chirp_common.FileBackedRadio):
continue
- if radio.match_model(filedata, image_file):
- return radio(image_file)
+ if rclass.match_model(filedata, image_file):
+ return rclass(image_file)
raise errors.ImageDetectFailed("Unknown file format")
-
-def get_radio_name(driver):
- cls = DRV_TO_RADIO[driver]
- return cls._get_name(cls)
-
-if __name__ == "__main__":
- vendors = {
- "Icom" : {},
- "Yaesu" : {},
- "Kenwood" : {},
- }
-
- for radio in DRV_TO_RADIO.values():
- vendors[radio.VENDOR][radio.MODEL]
- print "%s %s:" % (radio.VENDOR, radio.MODEL)
- if radio.VARIANT:
- print " Variant: %s" % radio.VARIANT
- print " Baudrate: %i" % radio.BAUD_RATE
diff -r db82df47f205 -r f805c420592f chirp/errors.py
--- a/chirp/errors.py Fri Apr 27 14:35:40 2012 -0700
+++ b/chirp/errors.py Fri Apr 27 14:35:41 2012 -0700
@@ -14,19 +14,25 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
class InvalidDataError(Exception):
+ """The radio driver encountered some invalid data"""
pass
class InvalidValueError(Exception):
+ """An invalid value for a given parameter was used"""
pass
class InvalidMemoryLocation(Exception):
+ """The requested memory location does not exist"""
pass
class RadioError(Exception):
+ """An error occurred while talking to the radio"""
pass
class UnsupportedToneError(Exception):
+ """The radio does not support the specified tone value"""
pass
class ImageDetectFailed(Exception):
+ """The driver for the supplied image could not be determined"""
pass
diff -r db82df47f205 -r f805c420592f chirp/ft2800.py
--- a/chirp/ft2800.py Fri Apr 27 14:35:40 2012 -0700
+++ b/chirp/ft2800.py Fri Apr 27 14:35:41 2012 -0700
@@ -14,7 +14,6 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import time
-import struct
import os
from chirp import util, memmap, chirp_common, bitwise, directory, errors
@@ -23,7 +22,7 @@
DEBUG = os.getenv("CHIRP_DEBUG") and True or False
CHUNK_SIZE = 16
-def send(s, data):
+def _send(s, data):
for i in range(0, len(data), CHUNK_SIZE):
chunk = data[i:i+CHUNK_SIZE]
s.write(chunk)
@@ -35,9 +34,9 @@
TRAILER = "\x0c\x02\x41\x33\x35\x00\x00\xb7"
ACK = "\x0C\x06\x00"
-def download(radio):
+def _download(radio):
data = ""
- for i in range(0, 10):
+ for _i in range(0, 10):
data = radio.pipe.read(8)
if data == IDBLOCK:
break
@@ -48,7 +47,7 @@
if len(data) != 8:
raise Exception("Failed to read header")
- send(radio.pipe, ACK)
+ _send(radio.pipe, ACK)
data = ""
@@ -72,7 +71,7 @@
data += chunk[5:-1]
- send(radio.pipe, ACK)
+ _send(radio.pipe, ACK)
if radio.status_fn:
status = chirp_common.Status()
status.max = radio._block_sizes[1]
@@ -85,14 +84,14 @@
return memmap.MemoryMap(data)
-def upload(radio):
- for i in range(0, 10):
+def _upload(radio):
+ for _i in range(0, 10):
data = radio.pipe.read(256)
if not data:
break
print "What is this garbage?\n%s" % util.hexprint(data)
- send(radio.pipe, IDBLOCK)
+ _send(radio.pipe, IDBLOCK)
time.sleep(1)
ack = radio.pipe.read(300)
if DEBUG:
@@ -101,9 +100,9 @@
raise Exception("Radio did not ack ID")
block = 0
- while block < (radio._memsize / 32):
+ while block < (radio.get_memsize() / 32):
data = "\x0C\x03\x00\x00" + chr(block)
- data += radio._mmap[block*32:(block+1)*32]
+ data += radio.get_mmap()[block*32:(block+1)*32]
cs = 0
for byte in data:
cs += ord(byte)
@@ -112,7 +111,7 @@
if DEBUG:
print "Writing block %i:\n%s" % (block, util.hexprint(data))
- send(radio.pipe, data)
+ _send(radio.pipe, data)
time.sleep(0.1)
ack = radio.pipe.read(3)
if ack != ACK:
@@ -126,9 +125,9 @@
radio.status_fn(status)
block += 1
- send(radio.pipe, TRAILER)
+ _send(radio.pipe, TRAILER)
-mem_format = """
+MEM_FORMAT = """
struct {
bbcd freq[4];
u8 unknown1[4];
@@ -164,6 +163,7 @@
@directory.register
class FT2800Radio(YaesuCloneModeRadio):
+ """Yaesu FT-2800"""
VENDOR = "Yaesu"
MODEL = "FT-2800M"
@@ -196,7 +196,7 @@
self.pipe.setParity("E")
start = time.time()
try:
- self._mmap = download(self)
+ self._mmap = _download(self)
except errors.RadioError:
raise
except Exception, e:
@@ -209,7 +209,7 @@
self.pipe.setParity("E")
start = time.time()
try:
- upload(self)
+ _upload(self)
except errors.RadioError:
raise
except Exception, e:
@@ -217,7 +217,7 @@
print "Uploaded in %.2f sec" % (time.time() - start)
def process_mmap(self):
- self._memobj = bitwise.parse(mem_format, self._mmap)
+ self._memobj = bitwise.parse(MEM_FORMAT, self._mmap)
def get_raw_memory(self, number):
return repr(self._memobj.memory[number])
diff -r db82df47f205 -r f805c420592f chirp/ft60.py
--- a/chirp/ft60.py Fri Apr 27 14:35:40 2012 -0700
+++ b/chirp/ft60.py Fri Apr 27 14:35:41 2012 -0700
@@ -19,13 +19,13 @@
ACK = "\x06"
-def send(pipe, data):
+def _send(pipe, data):
pipe.write(data)
echo = pipe.read(len(data))
if echo != data:
raise errors.RadioError("Error reading echo (Bad cable?)")
-def download(radio):
+def _download(radio):
data = ""
for i in range(0, 10):
chunk = radio.pipe.read(8)
@@ -40,12 +40,12 @@
if not data:
raise Exception("Radio is not responding")
- send(radio.pipe, ACK)
+ _send(radio.pipe, ACK)
for i in range(0, 448):
chunk = radio.pipe.read(64)
data += chunk
- send(radio.pipe, ACK)
+ _send(radio.pipe, ACK)
if len(chunk) == 1 and i == 447:
break
elif len(chunk) != 64:
@@ -53,14 +53,14 @@
if radio.status_fn:
status = chirp_common.Status()
status.cur = i * 64
- status.max = radio._memsize
+ status.max = radio.get_memsize()
status.msg = "Cloning from radio"
radio.status_fn(status)
return memmap.MemoryMap(data)
-def upload(radio):
- send(radio.pipe, radio._mmap[0:8])
+def _upload(radio):
+ _send(radio.pipe, radio.get_mmap()[0:8])
ack = radio.pipe.read(1)
if ack != ACK:
@@ -68,7 +68,7 @@
for i in range(0, 448):
offset = 8 + (i * 64)
- send(radio.pipe, radio._mmap[offset:offset+64])
+ _send(radio.pipe, radio.get_mmap()[offset:offset+64])
ack = radio.pipe.read(1)
if ack != ACK:
raise Exception("Radio did not ack block %i" % i)
@@ -76,11 +76,11 @@
if radio.status_fn:
status = chirp_common.Status()
status.cur = offset+64
- status.max = radio._memsize
+ status.max = radio.get_memsize()
status.msg = "Cloning to radio"
radio.status_fn(status)
-mem_format = """
+MEM_FORMAT = """
#seekto 0x0238;
struct {
u8 used:1,
@@ -136,6 +136,7 @@
@directory.register
class FT60Radio(yaesu_clone.YaesuCloneModeRadio):
+ """Yaesu FT-60"""
BAUD_RATE = 9600
VENDOR = "Yaesu"
MODEL = "FT-60"
@@ -158,6 +159,7 @@
rf.has_ctone = False
rf.has_bank = False
rf.has_dtcs_polarity = False
+
return rf
def _checksums(self):
@@ -165,7 +167,7 @@
def sync_in(self):
try:
- self._mmap = download(self)
+ self._mmap = _download(self)
except errors.RadioError:
raise
except Exception, e:
@@ -175,14 +177,14 @@
def sync_out(self):
self.update_checksums()
try:
- upload(self)
+ _upload(self)
except errors.RadioError:
raise
except Exception, e:
raise errors.RadioError("Failed to communicate with radio: %s" % e)
def process_mmap(self):
- self._memobj = bitwise.parse(mem_format, self._mmap)
+ self._memobj = bitwise.parse(MEM_FORMAT, self._mmap)
def get_raw_memory(self, number):
return repr(self._memobj.memory[number]) + \
diff -r db82df47f205 -r f805c420592f chirp/ft7800.py
--- a/chirp/ft7800.py Fri Apr 27 14:35:40 2012 -0700
+++ b/chirp/ft7800.py Fri Apr 27 14:35:41 2012 -0700
@@ -15,11 +15,11 @@
import time
from chirp import chirp_common, yaesu_clone, memmap, directory
-from chirp import bitwise, util, errors
+from chirp import bitwise, errors
ACK = chr(0x06)
-mem_format = """
+MEM_FORMAT = """
#seekto 0x04C8;
struct {
u8 used:1,
@@ -89,16 +89,15 @@
chirp_common.PowerLevel("Mid2", watts=10),
chirp_common.PowerLevel("Low", watts=5)]
-def send(s, data):
-
+def _send(ser, data):
for i in data:
- s.write(i)
+ ser.write(i)
time.sleep(0.002)
- echo = s.read(len(data))
+ echo = ser.read(len(data))
if echo != data:
raise errors.RadioError("Error reading echo (Bad cable?)")
-def download(radio):
+def _download(radio):
data = ""
chunk = ""
@@ -111,49 +110,49 @@
raise Exception("Failed to read header (%i)" % len(chunk))
data += chunk
- send(radio.pipe, ACK)
+ _send(radio.pipe, ACK)
for i in range(0, radio._block_lengths[1], 64):
chunk = radio.pipe.read(64)
data += chunk
if len(chunk) != 64:
break
- raise Exception("No block at %i" % i)
time.sleep(0.01)
- send(radio.pipe, ACK)
+ _send(radio.pipe, ACK)
if radio.status_fn:
status = chirp_common.Status()
- status.max = radio._memsize
+ status.max = radio.get_memsize()
status.cur = i+len(chunk)
status.msg = "Cloning from radio"
radio.status_fn(status)
data += radio.pipe.read(1)
- send(radio.pipe, ACK)
+ _send(radio.pipe, ACK)
return memmap.MemoryMap(data)
-def upload(radio):
+def _upload(radio):
cur = 0
for block in radio._block_lengths:
- for i in range(0, block, 64):
+ for _i in range(0, block, 64):
length = min(64, block)
#print "i=%i length=%i range: %i-%i" % (i, length,
# cur, cur+length)
- send(radio.pipe, radio._mmap[cur:cur+length])
+ _send(radio.pipe, radio.get_mmap()[cur:cur+length])
if radio.pipe.read(1) != ACK:
raise errors.RadioError("Radio did not ack block at %i" % cur)
cur += length
time.sleep(0.05)
if radio.status_fn:
- s = chirp_common.Status()
- s.cur = cur
- s.max = radio._memsize
- s.msg = "Cloning to radio"
- radio.status_fn(s)
+ status = chirp_common.Status()
+ status.cur = cur
+ status.max = radio.get_memsize()
+ status.msg = "Cloning to radio"
+ radio.status_fn(status)
def get_freq(rawfreq):
+ """Decode a frequency that may include a fractional step flag"""
# Ugh. The 0x80 and 0x40 indicate values to add to get the
# real frequency. Gross.
if rawfreq > 8000000000:
@@ -165,6 +164,7 @@
return rawfreq
def set_freq(freq, obj, field):
+ """Encode a frequency with any necessary fractional step flags"""
obj[field] = freq / 10000
if (freq % 1000) == 500:
obj[field][0].set_bits(0x40)
@@ -175,6 +175,7 @@
return freq
class FTx800Radio(yaesu_clone.YaesuCloneModeRadio):
+ """Base class for FT-7800,7900,8800,8900 radios"""
BAUD_RATE = 9600
VENDOR = "Yaesu"
@@ -200,30 +201,30 @@
return [ yaesu_clone.YaesuChecksum(0x0000, 0x7B47) ]
def sync_in(self):
- t = time.time()
+ start = time.time()
try:
- self._mmap = download(self)
+ self._mmap = _download(self)
except errors.RadioError:
raise
except Exception, e:
raise errors.RadioError("Failed to communicate with radio: %s" % e)
- print "Download finished in %i seconds" % (time.time() - t)
+ print "Download finished in %i seconds" % (time.time() - start)
self.check_checksums()
self.process_mmap()
def process_mmap(self):
- self._memobj = bitwise.parse(mem_format, self._mmap)
+ self._memobj = bitwise.parse(MEM_FORMAT, self._mmap)
def sync_out(self):
self.update_checksums()
- t = time.time()
+ start = time.time()
try:
- upload(self)
+ _upload(self)
except errors.RadioError:
raise
except Exception, e:
raise errors.RadioError("Failed to communicate with radio: %s" % e)
- print "Upload finished in %i seconds" % (time.time() - t)
+ print "Upload finished in %i seconds" % (time.time() - start)
def get_raw_memory(self, number):
return repr(self._memobj.memory[number-1])
@@ -330,6 +331,7 @@
self._set_mem_skip(mem, _mem)
class FT7800BankModel(chirp_common.BankModel):
+ """Yaesu FT-7800/7900 bank model"""
def get_num_banks(self):
return 20
@@ -353,8 +355,8 @@
_bitmap = self._radio._memobj.bank_channels[bank.index]
ishft = 31 - (index % 32)
if not (_bitmap.bitmap[index / 32] & (1 << ishft)):
- raise Exception(_("Memory {num} is "
- "not in bank {bank}").format(num=memory.number,
+ raise Exception("Memory {num} is " +
+ "not in bank {bank}".format(num=memory.number,
bank=bank))
_bitmap.bitmap[index / 32] &= ~(1 << ishft)
@@ -377,6 +379,7 @@
@directory.register
class FT7800Radio(FTx800Radio):
+ """Yaesu FT-7800"""
MODEL = "FT-7800"
_model = "AH016"
@@ -396,9 +399,10 @@
FTx800Radio.set_memory(self, memory)
class FT7900Radio(FT7800Radio):
+ """Yaesu FT-7900"""
MODEL = "FT-7900"
-mem_format_8800 = """
+MEM_FORMAT_8800 = """
#seekto %s;
struct {
u8 used:1,
@@ -434,6 +438,7 @@
@directory.register
class FT8800Radio(FTx800Radio):
+ """Base class for Yaesu FT-8800"""
MODEL = "FT-8800"
_model = "AH018"
@@ -460,7 +465,7 @@
if not self._memstart:
return
- self._memobj = bitwise.parse(mem_format_8800 % self._memstart,
+ self._memobj = bitwise.parse(MEM_FORMAT_8800 % self._memstart,
self._mmap)
def _get_mem_offset(self, mem, _mem):
@@ -502,14 +507,16 @@
_mem.nameused = bool(mem.name.rstrip())
class FT8800RadioLeft(FT8800Radio):
+ """Yaesu FT-8800 Left VFO subdevice"""
VARIANT = "Left"
_memstart = "0x0948"
class FT8800RadioRight(FT8800Radio):
+ """Yaesu FT-8800 Right VFO subdevice"""
VARIANT = "Right"
_memstart = "0x2948"
-mem_format_8900 = """
+MEM_FORMAT_8900 = """
#seekto 0x0708;
struct {
u8 used:1,
@@ -546,6 +553,7 @@
@directory.register
class FT8900Radio(FT8800Radio):
+ """Yaesu FT-8900"""
MODEL = "FT-8900"
_model = "AH008"
@@ -553,7 +561,7 @@
_block_lengths = [8, 14784, 1]
def process_mmap(self):
- self._memobj = bitwise.parse(mem_format_8900, self._mmap)
+ self._memobj = bitwise.parse(MEM_FORMAT_8900, self._mmap)
def get_features(self):
rf = FT8800Radio.get_features(self)
@@ -595,7 +603,7 @@
# the memory should show up on the sub (right) band
_mem = self._memobj.memory[mem.number - 1]
if mem.freq < 108000000 or mem.freq > 480000000:
- _mem.sub_used = 0;
+ _mem.sub_used = 0
else:
_mem.sub_used = 1
diff -r db82df47f205 -r f805c420592f chirp/ft817.py
--- a/chirp/ft817.py Fri Apr 27 14:35:40 2012 -0700
+++ b/chirp/ft817.py Fri Apr 27 14:35:41 2012 -0700
@@ -20,26 +20,29 @@
CMD_ACK = 0x06
-def ft817_read(pipe, block, blocknum):
- for i in range(0,60):
+def _ft8x7_read(pipe, block, blocknum):
+ for _i in range(0, 60):
data = pipe.read(block+2)
- if data:
+ if data:
break
- time.sleep(0.5)
+ time.sleep(0.5)
if len(data) == block+2 and data[0] == chr(blocknum):
- checksum = yaesu_clone.YaesuChecksum(1, block)
- if checksum.get_existing(data) != \
- checksum.get_calculated(data):
- raise Exception("Checksum Failed [%02X<>%02X] block %02X" % (checksum.get_existing(data), checksum.get_calculated(data), blocknum))
- data = data[1:block+1] # Chew away the block number and the checksum
+ checksum = yaesu_clone.YaesuChecksum(1, block)
+ if checksum.get_existing(data) != \
+ checksum.get_calculated(data):
+ raise Exception("Checksum Failed [%02X<>%02X] block %02X" % \
+ (checksum.get_existing(data),
+ checksum.get_calculated(data), blocknum))
+ data = data[1:block+1] # Chew away the block number and the checksum
else:
- raise Exception("Unable to read block %02X expected %i got %i" % (blocknum, block+2, len(data)))
+ raise Exception("Unable to read block %02X expected %i got %i" % \
+ (blocknum, block+2, len(data)))
if os.getenv("CHIRP_DEBUG"):
print "Read %i" % len(data)
return data
-def clone_in(radio):
+def _ft8x7_clone_in(radio):
pipe = radio.pipe
# Be very patient with the radio
@@ -54,21 +57,21 @@
status.max = len(radio._block_lengths) + 39
for block in radio._block_lengths:
if blocks == 8:
- repeat = 40 # repeated read of 40 block same size (memory area btw)
+ repeat = 40 # repeated read of 40 block same size (memory area)
else:
repeat = 1
- for i in range(0, repeat):
- data += ft817_read(pipe, block, blocks)
- pipe.write(chr(CMD_ACK))
- blocks += 1
- status.cur = blocks
- radio.status_fn(status)
+ for _i in range(0, repeat):
+ data += _ft8x7_read(pipe, block, blocks)
+ pipe.write(chr(CMD_ACK))
+ blocks += 1
+ status.cur = blocks
+ radio.status_fn(status)
print "Clone completed in %i seconds" % (time.time() - start)
return memmap.MemoryMap(data)
-def clone_out(radio):
+def _ft8x7_clone_out(radio):
delay = 0.5
pipe = radio.pipe
@@ -81,21 +84,24 @@
status.max = len(radio._block_lengths) + 39
for block in radio._block_lengths:
if blocks == 8:
- repeat = 40 # repeated read of 40 block same size (memory area btw)
+ repeat = 40 # repeated read of 40 block same size (memory area)
else:
repeat = 1
- for i in range(0, repeat):
+ for _i in range(0, repeat):
time.sleep(0.01)
checksum = yaesu_clone.YaesuChecksum(pos, pos+block-1)
if os.getenv("CHIRP_DEBUG"):
- print "Block %i - will send from %i to %i byte " % (blocks, pos, pos+block)
+ print "Block %i - will send from %i to %i byte " % (blocks,
+ pos,
+ pos+block)
print util.hexprint(chr(blocks))
- print util.hexprint(radio._mmap[pos:pos+block])
- print util.hexprint(chr(checksum.get_calculated(radio._mmap)))
+ print util.hexprint(radio.get_mmap()[pos:pos+block])
+ print util.hexprint(chr(checksum.get_calculated(\
+ radio.get_mmap())))
pipe.write(chr(blocks))
- pipe.write(radio._mmap[pos:pos+block])
- pipe.write(chr(checksum.get_calculated(radio._mmap)))
- buf = pipe.read(1)
+ pipe.write(radio.get_mmap()[pos:pos+block])
+ pipe.write(chr(checksum.get_calculated(radio.get_mmap())))
+ buf = pipe.read(1)
if not buf or buf[0] != chr(CMD_ACK):
time.sleep(delay)
buf = pipe.read(1)
@@ -105,12 +111,12 @@
raise Exception("Radio did not ack block %i" % blocks)
pos += block
blocks += 1
- status.cur = blocks
- radio.status_fn(status)
+ status.cur = blocks
+ radio.status_fn(status)
print "Clone completed in %i seconds" % (time.time() - start)
-mem_format = """
+MEM_FORMAT = """
struct mem_struct {
u8 tag_on_off:1,
tag_default:1,
@@ -167,21 +173,29 @@
@directory.register
class FT817Radio(yaesu_clone.YaesuCloneModeRadio):
+ """Yaesu FT-817"""
BAUD_RATE = 9600
MODEL = "FT-817"
_model = ""
DUPLEX = ["", "-", "+", "split"]
- MODES = ["LSB", "USB", "CW", "CWR", "AM", "FM", "DIG", "PKT", "NCW", "NCWR", "NFM"] # narrow modes has to be at end
+ # narrow modes has to be at end
+ MODES = ["LSB", "USB", "CW", "CWR", "AM", "FM", "DIG", "PKT", "NCW",
+ "NCWR", "NFM"]
TMODES = ["", "Tone", "TSQL", "DTCS"]
STEPSFM = [5.0, 6.25, 10.0, 12.5, 15.0, 20.0, 25.0, 50.0]
STEPSAM = [2.5, 5.0, 9.0, 10.0, 12.5, 25.0]
STEPSSSB = [1.0, 2.5, 5.0]
- VALID_BANDS = [(100000,33000000), (33000000,56000000), (76000000,108000000), (108000000,137000000), (137000000,154000000), (420000000,470000000)] # warning ranges has to be in this exact order
+
+ # warning ranges has to be in this exact order
+ VALID_BANDS = [(100000, 33000000), (33000000, 56000000),
+ (76000000, 108000000), (108000000, 137000000),
+ (137000000, 154000000), (420000000, 470000000)]
CHARSET = [chr(x) for x in range(0, 256)]
- POWER_LEVELS = [chirp_common.PowerLevel("Hi", watts=5.00), # not used in memory
+ # Hi not used in memory
+ POWER_LEVELS = [chirp_common.PowerLevel("Hi", watts=5.00),
chirp_common.PowerLevel("L3", watts=2.50),
chirp_common.PowerLevel("L2", watts=1.00),
chirp_common.PowerLevel("L1", watts=0.5)]
@@ -190,7 +204,8 @@
# block 9 (130 Bytes long) is to be repeted 40 times
_block_lengths = [ 2, 40, 208, 182, 208, 182, 198, 53, 130, 118, 118]
- SPECIAL_MEMORIES = { # WARNING Index are hard wired in memory management code !!!
+ # WARNING Index are hard wired in memory management code !!!
+ SPECIAL_MEMORIES = {
"VFOa-1.8M" : -35,
"VFOa-3.5M" : -34,
"VFOa-7M" : -33,
@@ -232,11 +247,12 @@
FIRST_VFOA_INDEX = -21
LAST_VFOA_INDEX = -35
- SPECIAL_MEMORIES_REV = dict(zip(SPECIAL_MEMORIES.values(), SPECIAL_MEMORIES.keys()))
+ SPECIAL_MEMORIES_REV = dict(zip(SPECIAL_MEMORIES.values(),
+ SPECIAL_MEMORIES.keys()))
def sync_in(self):
try:
- self._mmap = clone_in(self)
+ self._mmap = _ft8x7_clone_in(self)
except errors.RadioError:
raise
except Exception, e:
@@ -245,14 +261,14 @@
def sync_out(self):
try:
- clone_out(self)
+ _ft8x7_clone_out(self)
except errors.RadioError:
raise
except Exception, e:
raise errors.RadioError("Failed to communicate with radio: %s" % e)
def process_mmap(self):
- self._memobj = bitwise.parse(mem_format, self._mmap)
+ self._memobj = bitwise.parse(MEM_FORMAT, self._mmap)
def get_features(self):
rf = chirp_common.RadioFeatures()
@@ -276,27 +292,28 @@
def get_raw_memory(self, number):
return repr(self._memobj.memory[number-1])
- def get_duplex(self, mem, _mem):
+ def _get_duplex(self, mem, _mem):
if _mem.is_duplex == 1:
mem.duplex = self.DUPLEX[_mem.duplex]
else:
mem.duplex = ""
- def get_tmode(self, mem, _mem):
+ def _get_tmode(self, mem, _mem):
mem.tmode = self.TMODES[_mem.tmode]
- def set_duplex(self, mem, _mem):
+ def _set_duplex(self, mem, _mem):
_mem.duplex = self.DUPLEX.index(mem.duplex)
_mem.is_duplex = mem.duplex != ""
- def set_tmode(self, mem, _mem):
+ def _set_tmode(self, mem, _mem):
_mem.tmode = self.TMODES.index(mem.tmode)
def get_memory(self, number):
if isinstance(number, str):
return self._get_special(number)
elif number < 0:
- # I can't stop delete operation from loosing extd_number but I know how to get it back
+ # I can't stop delete operation from loosing extd_number but
+ # I know how to get it back
return self._get_special(self.SPECIAL_MEMORIES_REV[number])
else:
return self._get_normal(number)
@@ -315,27 +332,32 @@
mem.number = self.SPECIAL_MEMORIES[number]
mem.extd_number = number
- if mem.number in range(self.FIRST_VFOA_INDEX, self.LAST_VFOA_INDEX -1, -1):
+ if mem.number in range(self.FIRST_VFOA_INDEX,
+ self.LAST_VFOA_INDEX - 1,
+ -1):
_mem = self._memobj.vfoa[-self.LAST_VFOA_INDEX + mem.number]
- immutable = ["number", "skip", "rtone", "ctone", "extd_number", "name",
- "dtcs_polarity", "power", "comment"]
- elif mem.number in range(self.FIRST_VFOB_INDEX, self.LAST_VFOB_INDEX -1, -1):
+ immutable = ["number", "skip", "rtone", "ctone", "extd_number",
+ "name", "dtcs_polarity", "power", "comment"]
+ elif mem.number in range(self.FIRST_VFOB_INDEX,
+ self.LAST_VFOB_INDEX - 1,
+ -1):
_mem = self._memobj.vfob[-self.LAST_VFOB_INDEX + mem.number]
- immutable = ["number", "skip", "rtone", "ctone", "extd_number", "name",
- "dtcs_polarity", "power", "comment"]
+ immutable = ["number", "skip", "rtone", "ctone", "extd_number",
+ "name", "dtcs_polarity", "power", "comment"]
elif mem.number in range(-2, -6, -1):
_mem = self._memobj.home[5 + mem.number]
immutable = ["number", "skip", "rtone", "ctone", "extd_number",
"dtcs_polarity", "power", "comment"]
elif mem.number == -1:
_mem = self._memobj.qmb
- immutable = ["number", "skip", "rtone", "ctone", "extd_number", "name",
- "dtcs_polarity", "power", "comment"]
- else:
- raise Exception("Sorry, special memory index %i unknown you hit a bug!!" % mem.number)
+ immutable = ["number", "skip", "rtone", "ctone", "extd_number",
+ "name", "dtcs_polarity", "power", "comment"]
+ else:
+ raise Exception("Sorry, special memory index %i " % mem.number +
+ "unknown you hit a bug!!")
mem = self._get_memory(mem, _mem)
- mem.immutable = immutable
+ mem.immutable = immutable
return mem
@@ -352,16 +374,21 @@
"is not supported on this channel")
# TODO add frequency range check for vfo and home memories
- if mem.number in range(self.FIRST_VFOA_INDEX, self.LAST_VFOA_INDEX -1, -1):
+ if mem.number in range(self.FIRST_VFOA_INDEX,
+ self.LAST_VFOA_INDEX -1,
+ -1):
_mem = self._memobj.vfoa[-self.LAST_VFOA_INDEX + mem.number]
- elif mem.number in range(self.FIRST_VFOB_INDEX, self.LAST_VFOB_INDEX -1, -1):
+ elif mem.number in range(self.FIRST_VFOB_INDEX,
+ self.LAST_VFOB_INDEX -1,
+ -1):
_mem = self._memobj.vfob[-self.LAST_VFOB_INDEX + mem.number]
elif mem.number in range(-2, -6, -1):
_mem = self._memobj.home[5 + mem.number]
elif mem.number == -1:
_mem = self._memobj.qmb
- else:
- raise Exception("Sorry, special memory index %i unknown you hit a bug!!" % mem.number)
+ else:
+ raise Exception("Sorry, special memory index %i " % mem.number +
+ "unknown you hit a bug!!")
self._set_memory(mem, _mem)
@@ -382,8 +409,10 @@
def _set_normal(self, mem):
_mem = self._memobj.memory[mem.number-1]
- wasused = (self._memobj.visible[(mem.number-1)/8] >> (mem.number-1)%8) & 0x01
- wasvalid = (self._memobj.filled[(mem.number-1)/8] >> (mem.number-1)%8) & 0x01
+ wasused = (self._memobj.visible[(mem.number - 1) / 8] >> \
+ (mem.number - 1) % 8) & 0x01
+ wasvalid = (self._memobj.filled[(mem.number - 1) / 8] >> \
+ (mem.number - 1) % 8) & 0x01
if mem.empty:
if mem.number == 1:
@@ -391,18 +420,20 @@
# if you ulpoad an empty image you can brick your radio
raise Exception("Sorry, can't delete first memory")
if wasvalid and not wasused:
- self._memobj.filled[(mem.number-1)/8] &= ~ (1 << (mem.number-1)%8)
- self._memobj.visible[(mem.number-1)/8] &= ~ (1 << (mem.number-1)%8)
+ self._memobj.filled[(mem.number-1) / 8] &= \
+ ~(1 << (mem.number - 1) % 8)
+ self._memobj.visible[(mem.number-1) / 8] &= \
+ ~(1 << (mem.number - 1) % 8)
return
- self._memobj.visible[(mem.number-1)/8] |= 1 << (mem.number-1)%8
- self._memobj.filled[(mem.number-1)/8] |= 1 << (mem.number-1)%8
+ self._memobj.visible[(mem.number - 1) / 8] |= 1 << (mem.number - 1) % 8
+ self._memobj.filled[(mem.number - 1) / 8] |= 1 << (mem.number - 1) % 8
self._set_memory(mem, _mem)
def _get_memory(self, mem, _mem):
mem.freq = int(_mem.freq) * 10
mem.offset = int(_mem.offset) * 10
- self.get_duplex(mem, _mem)
+ self._get_duplex(mem, _mem)
mem.mode = self.MODES[_mem.mode]
if mem.mode == "FM":
if _mem.is_fm_narrow == 1:
@@ -420,11 +451,11 @@
except IndexError:
pass
mem.skip = _mem.skip and "S" or ""
- self.get_tmode(mem, _mem)
+ self._get_tmode(mem, _mem)
mem.rtone = mem.ctone = chirp_common.TONES[_mem.tone]
mem.dtcs = chirp_common.DTCS_CODES[_mem.dcs]
- if _mem.tag_on_off == 1:
+ if _mem.tag_on_off == 1:
for i in _mem.name:
if i == "\xFF":
break
@@ -442,31 +473,34 @@
else:
_mem.tag_on_off = 0
_mem.tag_default = 0 # never use default label "CH-nnn"
- self.set_duplex(mem, _mem)
+ self._set_duplex(mem, _mem)
if mem.mode[0] == "N": # is it narrow?
_mem.mode = self.MODES.index(mem.mode[1:])
- _mem.is_fm_narrow = _mem.is_cwdig_narrow = 1 # here I suppose it's safe to set both
+ # here I suppose it's safe to set both
+ _mem.is_fm_narrow = _mem.is_cwdig_narrow = 1
else:
_mem.mode = self.MODES.index(mem.mode)
- _mem.is_fm_narrow = _mem.is_cwdig_narrow = 0 # here I suppose it's safe to set both
- i = 0 # This search can probably be written better but
- for lo, hi in self.VALID_BANDS: # I just don't know python enought
+ # here I suppose it's safe to set both
+ _mem.is_fm_narrow = _mem.is_cwdig_narrow = 0
+ i = 0
+ for lo, hi in self.VALID_BANDS:
if mem.freq > lo and mem.freq < hi:
break
- i+=1
+ i += 1
_mem.freq_range = i
- if mem.duplex == "split": # all this should be safe also when not in split but ...
+ # all this should be safe also when not in split but ...
+ if mem.duplex == "split":
_mem.tx_mode = _mem.mode
- i = 0 # This search can probably be written better but
- for lo, hi in self.VALID_BANDS: # I just don't know python enought
+ i = 0
+ for lo, hi in self.VALID_BANDS:
if mem.offset >= lo and mem.offset < hi:
break
- i+=1
+ i += 1
_mem.tx_freq_range = i
_mem.skip = mem.skip == "S"
_mem.ipo = 0 # not supported in chirp
_mem.att = 0 # not supported in chirp
- self.set_tmode(mem, _mem)
+ self._set_tmode(mem, _mem)
try:
_mem.ssb_step = self.STEPSSSB.index(mem.tuning_step)
except ValueError:
@@ -490,10 +524,11 @@
def validate_memory(self, mem):
msgs = yaesu_clone.YaesuCloneModeRadio.validate_memory(self, mem)
- lo, hi = self.VALID_BANDS[2] # this is fm broadcasting
- if mem.freq >= lo and mem.freq <= hi:
+ lo, hi = self.VALID_BANDS[2] # this is fm broadcasting
+ if mem.freq >= lo and mem.freq <= hi:
if mem.mode != "FM":
- msgs.append(chirp_common.ValidationError("Only FM is supported in this band"))
+ msgs.append(chirp_common.ValidationError(\
+ "Only FM is supported in this band"))
# TODO check that step is valid in current mode
return msgs
@@ -503,6 +538,7 @@
@directory.register
class FT817NDRadio(FT817Radio):
+ """Yaesu FT-817ND"""
MODEL = "FT-817ND"
_model = ""
@@ -512,8 +548,9 @@
@directory.register
class FT817ND_US_Radio(FT817Radio):
- # seems that radios configured for 5MHz operations send one paket more than others
- # so we have to distinguish sub models
+ """Yaesu FT-817ND (US version)"""
+ # seems that radios configured for 5MHz operations send one paket
+ # more than others so we have to distinguish sub models
MODEL = "FT-817ND (US)"
_model = ""
@@ -533,14 +570,16 @@
SPECIAL_MEMORIES = dict(FT817Radio.SPECIAL_MEMORIES)
SPECIAL_MEMORIES.update(SPECIAL_60M)
- SPECIAL_MEMORIES_REV = dict(zip(SPECIAL_MEMORIES.values(), SPECIAL_MEMORIES.keys()))
+ SPECIAL_MEMORIES_REV = dict(zip(SPECIAL_MEMORIES.values(),
+ SPECIAL_MEMORIES.keys()))
def _get_special_60M(self, number):
mem = chirp_common.Memory()
mem.number = self.SPECIAL_60M[number]
mem.extd_number = number
- _mem = self._memobj.sixtymeterchannels[-self.LAST_SPECIAL60M_INDEX + mem.number]
+ _mem = self._memobj.sixtymeterchannels[-self.LAST_SPECIAL60M_INDEX +
+ mem.number]
mem = self._get_memory(mem, _mem)
@@ -564,16 +603,19 @@
"is not supported on M-60x channels")
if mem.mode not in ["USB", "LSB", "CW", "CWR", "NCW", "NCWR", "DIG"]:
- raise errors.RadioError(_("Mode {mode} is not valid "
- "in 60m channels").format(mode=mem.mode))
- _mem = self._memobj.sixtymeterchannels[-self.LAST_SPECIAL60M_INDEX + mem.number]
+ raise errors.RadioError("Mode {mode} is not valid "
+ "in 60m channels".format(mode=mem.mode))
+ _mem = self._memobj.sixtymeterchannels[-self.LAST_SPECIAL60M_INDEX +
+ mem.number]
self._set_memory(mem, _mem)
def get_memory(self, number):
if number in self.SPECIAL_60M.keys():
return self._get_special_60M(number)
- elif number < 0 and self.SPECIAL_MEMORIES_REV[number] in self.SPECIAL_60M.keys():
- # I can't stop delete operation from loosing extd_number but I know how to get it back
+ elif number < 0 and \
+ self.SPECIAL_MEMORIES_REV[number] in self.SPECIAL_60M.keys():
+ # I can't stop delete operation from loosing extd_number but
+ # I know how to get it back
return self._get_special_60M(self.SPECIAL_MEMORIES_REV[number])
else:
return FT817Radio.get_memory(self, number)
diff -r db82df47f205 -r f805c420592f chirp/ft857.py
--- a/chirp/ft857.py Fri Apr 27 14:35:40 2012 -0700
+++ b/chirp/ft857.py Fri Apr 27 14:35:41 2012 -0700
@@ -18,7 +18,7 @@
from chirp import bitwise
import os
-mem_format = """
+MEM_FORMAT = """
struct mem_struct{
u8 tag_on_off:1,
tag_default:1,
@@ -84,6 +84,7 @@
@directory.register
class FT857Radio(ft817.FT817Radio):
+ """Yaesu FT-857/897"""
MODEL = "FT-857/897"
_model = ""
@@ -121,10 +122,15 @@
_memsize = 7341
# block 9 (140 Bytes long) is to be repeted 40 times
# should be 42 times but this way I can use original 817 functions
- _block_lengths = [ 2, 82, 252, 196, 252, 196, 212, 55, 140, 140, 140, 38, 176]
- VALID_BANDS = [(100000,33000000), (33000000,56000000), (76000000,108000000), (108000000,137000000), (137000000,164000000), (420000000,470000000)] # warning ranges has to be in this exact order
+ _block_lengths = [ 2, 82, 252, 196, 252, 196, 212, 55, 140, 140, 140,
+ 38, 176]
+ # warning ranges has to be in this exact order
+ VALID_BANDS = [(100000, 33000000), (33000000, 56000000),
+ (76000000, 108000000), (108000000, 137000000),
+ (137000000, 164000000), (420000000, 470000000)]
- SPECIAL_MEMORIES = { # WARNING Index are hard wired in memory management code !!!
+ # WARNING Index are hard wired in memory management code !!!
+ SPECIAL_MEMORIES = {
"VFOa-1.8M" : -37,
"VFOa-3.5M" : -36,
"VFOa-5M" : -35,
@@ -168,7 +174,8 @@
FIRST_VFOA_INDEX = -22
LAST_VFOA_INDEX = -37
- SPECIAL_PMS = { # WARNING Index are hard wired in memory management code !!!
+ # WARNING Index are hard wired in memory management code !!!
+ SPECIAL_PMS = {
"PMS-1L" : -47,
"PMS-1U" : -46,
"PMS-2L" : -45,
@@ -184,7 +191,8 @@
SPECIAL_MEMORIES = dict(SPECIAL_MEMORIES)
SPECIAL_MEMORIES.update(SPECIAL_PMS)
- SPECIAL_MEMORIES_REV = dict(zip(SPECIAL_MEMORIES.values(), SPECIAL_MEMORIES.keys()))
+ SPECIAL_MEMORIES_REV = dict(zip(SPECIAL_MEMORIES.values(),
+ SPECIAL_MEMORIES.keys()))
def get_features(self):
rf = ft817.FT817Radio.get_features(self)
@@ -193,22 +201,25 @@
rf.valid_cross_modes = self.CROSS_MODES_REV.keys()
return rf
- def get_duplex(self, mem, _mem):
+ def _get_duplex(self, mem, _mem):
# radio set is_duplex only for + and - but not for split
- # at the same time it does not complain if we set it same way 817 does (so no set_duplex here)
+ # at the same time it does not complain if we set it same way 817 does
+ # (so no set_duplex here)
mem.duplex = self.DUPLEX[_mem.duplex]
- def get_tmode(self, mem, _mem):
- # I do not use is_split_tone here because the radio sometimes set it also for standard tone mode
+ def _get_tmode(self, mem, _mem):
+ # I do not use is_split_tone here because the radio sometimes set it
+ # also for standard tone mode
try:
mem.tmode = self.TMODES[int(_mem.tmode)]
except KeyError:
mem.tmode = "Cross"
mem.cross_mode = self.CROSS_MODES[int(_mem.tmode)]
- def set_tmode(self, mem, _mem):
- _mem.unknown_flag = 0 # have to put this bit to 0 otherwise we get strange display in tone frequency (menu 83)
- # see bug #88
+ def _set_tmode(self, mem, _mem):
+ # have to put this bit to 0 otherwise we get strange display in tone
+ # frequency (menu 83). See bug #88
+ _mem.unknown_flag = 0
if mem.tmode != "Cross":
_mem.is_split_tone = 0
_mem.tmode = self.TMODES_REV[mem.tmode]
@@ -217,18 +228,24 @@
_mem.is_split_tone = 1
def process_mmap(self):
- self._memobj = bitwise.parse(mem_format, self._mmap)
+ self._memobj = bitwise.parse(MEM_FORMAT, self._mmap)
def _get_special_pms(self, number):
mem = chirp_common.Memory()
mem.number = self.SPECIAL_PMS[number]
mem.extd_number = number
- bitindex = 47 + mem.number
+ bitindex = 47 + mem.number
used = (self._memobj.pmsvisible >> bitindex) & 0x01
valid = (self._memobj.pmsfilled >> bitindex) & 0x01
if os.getenv("CHIRP_DEBUG"):
- print "mem.number %i bitindex %i pmsvisible %i pmsfilled %i used %i filled %i" % (mem.number, bitindex, self._memobj.pmsvisible, self._memobj.pmsfilled, used, valid)
+ print "mem.number %i bitindex %i pmsvisible %i" % \
+ (mem.number,
+ bitindex,
+ self._memobj.pmsvisible),
+ print "pmsfilled %i used %i filled %i" % (self._memobj.pmsfilled,
+ used,
+ valid)
if not used:
mem.empty = True
if not valid:
@@ -249,7 +266,7 @@
def _set_special_pms(self, mem):
cur_mem = self._get_special_pms(self.SPECIAL_MEMORIES_REV[mem.number])
- bitindex = 47 + mem.number
+ bitindex = 47 + mem.number
wasused = (self._memobj.pmsvisible >> bitindex) & 0x01
wasvalid = (self._memobj.pmsfilled >> bitindex) & 0x01
@@ -273,8 +290,10 @@
def get_memory(self, number):
if number in self.SPECIAL_PMS.keys():
return self._get_special_pms(number)
- elif number < 0 and self.SPECIAL_MEMORIES_REV[number] in self.SPECIAL_PMS.keys():
- # I can't stop delete operation from loosing extd_number but I know how to get it back
+ elif number < 0 and \
+ self.SPECIAL_MEMORIES_REV[number] in self.SPECIAL_PMS.keys():
+ # I can't stop delete operation from loosing extd_number but
+ # I know how to get it back
return self._get_special_pms(self.SPECIAL_MEMORIES_REV[number])
else:
return ft817.FT817Radio.get_memory(self, number)
@@ -287,16 +306,17 @@
@directory.register
class FT857_US_Radio(FT857Radio):
- # seems that radios configured for 5MHz operations send one paket more than others
- # so we have to distinguish sub models
+ """Yaesu FT857/897 (US version)"""
+ # seems that radios configured for 5MHz operations send one paket more
+ # than others so we have to distinguish sub models
MODEL = "FT-857/897 (US)"
_model = ""
_memsize = 7481
# block 9 (140 Bytes long) is to be repeted 40 times
# should be 42 times but this way I can use original 817 functions
- _block_lengths = [ 2, 82, 252, 196, 252, 196, 212, 55, 140, 140, 140, 38, 176, 140]
-
+ _block_lengths = [ 2, 82, 252, 196, 252, 196, 212, 55, 140, 140, 140, 38,
+ 176, 140]
SPECIAL_60M = {
"M-601" : -52,
@@ -310,7 +330,8 @@
SPECIAL_MEMORIES = dict(FT857Radio.SPECIAL_MEMORIES)
SPECIAL_MEMORIES.update(SPECIAL_60M)
- SPECIAL_MEMORIES_REV = dict(zip(SPECIAL_MEMORIES.values(), SPECIAL_MEMORIES.keys()))
+ SPECIAL_MEMORIES_REV = dict(zip(SPECIAL_MEMORIES.values(),
+ SPECIAL_MEMORIES.keys()))
# this is identical to the one in FT817ND_US_Radio but we inherit from 857
def _get_special_60M(self, number):
@@ -318,7 +339,8 @@
mem.number = self.SPECIAL_60M[number]
mem.extd_number = number
- _mem = self._memobj.sixtymeterchannels[-self.LAST_SPECIAL60M_INDEX + mem.number]
+ _mem = self._memobj.sixtymeterchannels[-self.LAST_SPECIAL60M_INDEX +
+ mem.number]
mem = self._get_memory(mem, _mem)
@@ -343,16 +365,19 @@
"is not supported on M-60x channels")
if mem.mode not in ["USB", "LSB", "CW", "CWR", "NCW", "NCWR", "DIG"]:
- raise errors.RadioError(_("Mode {mode} is not valid "
- "in 60m channels").format(mode=mem.mode))
- _mem = self._memobj.sixtymeterchannels[-self.LAST_SPECIAL60M_INDEX + mem.number]
+ raise errors.RadioError("Mode {mode} is not valid "
+ "in 60m channels".format(mode=mem.mode))
+ _mem = self._memobj.sixtymeterchannels[-self.LAST_SPECIAL60M_INDEX +
+ mem.number]
self._set_memory(mem, _mem)
def get_memory(self, number):
if number in self.SPECIAL_60M.keys():
return self._get_special_60M(number)
- elif number < 0 and self.SPECIAL_MEMORIES_REV[number] in self.SPECIAL_60M.keys():
- # I can't stop delete operation from loosing extd_number but I know how to get it back
+ elif number < 0 and \
+ self.SPECIAL_MEMORIES_REV[number] in self.SPECIAL_60M.keys():
+ # I can't stop delete operation from loosing extd_number but
+ # I know how to get it back
return self._get_special_60M(self.SPECIAL_MEMORIES_REV[number])
else:
return FT857Radio.get_memory(self, number)
diff -r db82df47f205 -r f805c420592f chirp/generic_csv.py
--- a/chirp/generic_csv.py Fri Apr 27 14:35:40 2012 -0700
+++ b/chirp/generic_csv.py Fri Apr 27 14:35:41 2012 -0700
@@ -19,10 +19,29 @@
from chirp import chirp_common, errors, directory
class OmittedHeaderError(Exception):
+ """Internal exception to signal that a column has been omitted"""
pass
+def get_datum_by_header(headers, data, header):
+ """Return the column corresponding to @headers[@header] from @data"""
+ if header not in headers:
+ raise OmittedHeaderError("Header %s not provided" % header)
+
+ try:
+ return data[headers.index(header)]
+ except IndexError:
+ raise OmittedHeaderError("Header %s not provided on this line" % \
+ header)
+
+def write_memory(writer, mem):
+ """Write @mem using @writer if not empty"""
+ if mem.empty:
+ return
+ writer.writerow(mem.to_csv())
+
@directory.register
class CSVRadio(chirp_common.FileBackedRadio, chirp_common.IcomDstarSupport):
+ """A driver for Generic CSV files"""
VENDOR = "Generic"
MODEL = "CSV"
FILE_EXTENSION = "csv"
@@ -51,13 +70,14 @@
self.errors = []
self.memories = []
for i in range(0, 1000):
- m = chirp_common.Memory()
- m.number = i
- m.empty = True
- self.memories.append(m)
+ mem = chirp_common.Memory()
+ mem.number = i
+ mem.empty = True
+ self.memories.append(mem)
def __init__(self, pipe):
chirp_common.FileBackedRadio.__init__(self, None)
+ self.memories = []
self._filename = pipe
if self._filename and os.path.exists(self._filename):
@@ -86,34 +106,17 @@
return rf
- def _parse_quoted_line(self, line):
- line = line.replace("\n", "")
- line = line.replace("\r", "")
- line = line.replace('"', "")
-
- return line.split(",")
-
- def _get_datum_by_header(self, headers, data, header):
- if header not in headers:
- raise OmittedHeaderError("Header %s not provided" % header)
-
- try:
- return data[headers.index(header)]
- except IndexError:
- raise OmittedHeaderError("Header %s not provided on this line" %\
- header)
-
def _parse_csv_data_line(self, headers, line):
mem = chirp_common.Memory()
try:
- if self._get_datum_by_header(headers, line, "Mode") == "DV":
+ if get_datum_by_header(headers, line, "Mode") == "DV":
mem = chirp_common.DVMemory()
except OmittedHeaderError:
pass
for header, (typ, attr) in self.ATTR_MAP.items():
try:
- val = self._get_datum_by_header(headers, line, header)
+ val = get_datum_by_header(headers, line, header)
if not val and typ == int:
val = None
else:
@@ -174,12 +177,6 @@
print self.errors
raise errors.InvalidDataError("No channels found")
- def save_memory(self, writer, mem):
- if mem.empty:
- return
-
- writer.writerow(mem.to_csv())
-
def save(self, filename=None):
if filename is None and self._filename is None:
raise errors.RadioError("Need a location to save to")
@@ -192,7 +189,7 @@
writer.writerow(chirp_common.Memory.CSV_FORMAT)
for mem in self.memories:
- self.save_memory(writer, mem)
+ write_memory(writer, mem)
f.close()
@@ -220,20 +217,20 @@
delta += 1
for i in range(len(self.memories), len(self.memories) + delta + 1):
- m = chirp_common.Memory()
- m.empty = True
- m.number = i
- self.memories.append(m)
+ mem = chirp_common.Memory()
+ mem.empty = True
+ mem.number = i
+ self.memories.append(mem)
def set_memory(self, newmem):
self._grow(newmem.number)
self.memories[newmem.number] = newmem
def erase_memory(self, number):
- m = chirp_common.Memory()
- m.number = number
- m.empty = True
- self.memories[number] = m
+ mem = chirp_common.Memory()
+ mem.number = number
+ mem.empty = True
+ self.memories[number] = mem
def get_raw_memory(self, number):
return ",".join(chirp_common.Memory.CSV_FORMAT) + \
@@ -241,5 +238,6 @@
",".join(self.memories[number].to_csv())
@classmethod
- def match_model(cls, filedata, filename):
+ def match_model(cls, _filedata, filename):
+ """Match files ending in .CSV"""
return filename.lower().endswith("." + cls.FILE_EXTENSION)
diff -r db82df47f205 -r f805c420592f chirp/generic_tpe.py
--- a/chirp/generic_tpe.py Fri Apr 27 14:35:40 2012 -0700
+++ b/chirp/generic_tpe.py Fri Apr 27 14:35:41 2012 -0700
@@ -13,12 +13,10 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
-import os
-import csv
-
+import UserDict
from chirp import chirp_common, directory, generic_csv
-class TpeMap:
+class TpeMap(UserDict.UserDict):
"""Pretend we're a dict"""
def items(self):
return [
@@ -27,13 +25,20 @@
("Call Sign" , (str, "name")),
("Output Frequency", (chirp_common.parse_freq, "freq")),
("Input Frequency" , (str, "duplex")),
- ("CTCSS Tones" , (lambda v: "Tone" if float(v) in chirp_common.TONES else "", "tmode")),
- ("CTCSS Tones" , (lambda v: float(v) if float(v) in chirp_common.TONES else 88.5, "rtone")),
- ("CTCSS Tones" , (lambda v: float(v) if float(v) in chirp_common.TONES else 88.5, "ctone")),
+ ("CTCSS Tones" , (lambda v: "Tone"
+ if float(v) in chirp_common.TONES
+ else "", "tmode")),
+ ("CTCSS Tones" , (lambda v: float(v)
+ if float(v) in chirp_common.TONES
+ else 88.5, "rtone")),
+ ("CTCSS Tones" , (lambda v: float(v)
+ if float(v) in chirp_common.TONES
+ else 88.5, "ctone")),
]
@directory.register
class TpeRadio(generic_csv.CSVRadio):
+ """Generic ARRL Travel Plus"""
VENDOR = "ARRL"
MODEL = "Travel Plus"
FILE_EXTENSION = "tpe"
diff -r db82df47f205 -r f805c420592f chirp/generic_xml.py
--- a/chirp/generic_xml.py Fri Apr 27 14:35:40 2012 -0700
+++ b/chirp/generic_xml.py Fri Apr 27 14:35:41 2012 -0700
@@ -19,6 +19,7 @@
from chirp import chirp_common, errors, xml_ll, platform, directory
def validate_doc(doc):
+ """Validate the document"""
basepath = platform.get_platform().executable_path()
path = os.path.abspath(os.path.join(basepath, "chirp.xsd"))
if not os.path.exists(path):
@@ -37,16 +38,16 @@
errs = []
warnings = []
- def err(msg, arg=None):
+ def _err(msg, *_args):
errs.append("ERROR: %s" % msg)
- def wrn(msg, arg=None):
+ def _wrn(msg, *_args):
print "WARNING: %s" % msg
warnings.append("WARNING: %s" % msg)
- validCtx = schema.schemaNewValidCtxt()
- validCtx.setValidityErrorHandler(err, wrn)
- err = validCtx.schemaValidateDoc(doc)
+ validctx = schema.schemaNewValidCtxt()
+ validctx.setValidityErrorHandler(_err, _wrn)
+ err = validctx.schemaValidateDoc(doc)
print os.linesep.join(warnings)
if err:
print "---DOC---\n%s\n------" % doc.serialize(format=1)
@@ -54,6 +55,7 @@
raise errors.RadioError("Schema error")
def default_banks():
+ """Return an empty set of banks"""
banks = []
for i in range(0, 26):
@@ -63,6 +65,7 @@
@directory.register
class XMLRadio(chirp_common.FileBackedRadio, chirp_common.IcomDstarSupport):
+ """Generic XML driver"""
VENDOR = "Generic"
MODEL = "XML"
FILE_EXTENSION = "chirp"
@@ -135,18 +138,6 @@
xml_ll.del_memory(self.doc, number)
@classmethod
- def match_model(cls, filedata, filename):
+ def match_model(cls, _filedata, filename):
+ """Match this driver if the extension matches"""
return filename.lower().endswith("." + cls.FILE_EXTENSION)
-
-if __name__ == "__main__":
- r = XMLRadio("testmem.chirp")
-
- print r.get_memory(3)
-
- m = chirp_common.Memory()
- m.name = "TestMem2"
- m.freq = 123.456
- m.number = 10
-
- #r.set_memory(m)
- #r.erase_memory(10)
diff -r db82df47f205 -r f805c420592f chirp/ic2100.py
--- a/chirp/ic2100.py Fri Apr 27 14:35:40 2012 -0700
+++ b/chirp/ic2100.py Fri Apr 27 14:35:41 2012 -0700
@@ -16,7 +16,7 @@
from chirp import chirp_common, icf, util, directory
from chirp import bitwise, memmap
-mem_format = """
+MEM_FORMAT = """
struct {
bbcd freq[2];
u8 freq_10khz:4,
@@ -82,8 +82,73 @@
DUPLEX = ["", "", "+", "-"]
STEPS = [5.0, 10.0, 12.5, 15.0, 20.0, 25.0, 30.0, 50.0]
+def _get_special():
+ special = { "C": 506 }
+ for i in range(0, 3):
+ ida = "%iA" % (i + 1)
+ idb = "%iB" % (i + 1)
+ num = 500 + (i * 2)
+ special[ida] = num
+ special[idb] = num + 1
+
+ return special
+
+def _get_freq(mem):
+ freq = (int(mem.freq) * 100000) + \
+ (mem.freq_10khz * 10000) + \
+ (mem.freq_1khz * 1000)
+
+ if mem.is_12_5:
+ if chirp_common.is_12_5(freq):
+ pass
+ elif mem.freq_1khz == 2:
+ freq += 500
+ elif mem.freq_1khz == 5:
+ freq += 2500
+ elif mem.freq_1khz == 7:
+ freq += 500
+ else:
+ raise Exception("Unable to resolve 12.5kHz: %i" % freq)
+
+ return freq
+
+def _set_freq(mem, freq):
+ mem.freq = freq / 100000
+ mem.freq_10khz = (freq / 10000) % 10
+ khz = (freq / 1000) % 10
+ mem.freq_1khz = khz
+ mem.is_12_5 = chirp_common.is_12_5(freq)
+
+def _get_offset(mem):
+ raw = memmap.MemoryMap(mem.get_raw())
+ if ord(raw[5]) & 0x0A:
+ raw[5] = ord(raw[5]) & 0xF0
+ mem.set_raw(raw.get_packed())
+ offset = int(mem.offset) * 1000 + 5000
+ raw[5] = ord(raw[5]) | 0x0A
+ mem.set_raw(raw.get_packed())
+ return offset
+ else:
+ return int(mem.offset) * 1000
+
+def _set_offset(mem, offset):
+ if (offset % 10) == 5000:
+ extra = 0x0A
+ offset -= 5000
+ else:
+ extra = 0x00
+
+ mem.offset = offset / 1000
+ raw = memmap.MemoryMap(mem.get_raw())
+ raw[5] = ord(raw[5]) | extra
+ mem.set_raw(raw.get_packed())
+
+def _wipe_memory(mem, char):
+ mem.set_raw(char * (mem.size() / 8))
+
@directory.register
class IC2100Radio(icf.IcomCloneModeRadio):
+ """Icom IC-2100"""
VENDOR = "Icom"
MODEL = "IC-2100H"
@@ -110,81 +175,20 @@
return rf
def process_mmap(self):
- self._memobj = bitwise.parse(mem_format, self._mmap)
-
- def _get_special(self):
- special = { "C": 506 }
- for i in range(0, 3):
- idA = "%iA" % (i+1)
- idB = "%iB" % (i+1)
- num = 500 + (i * 2)
- special[idA] = num
- special[idB] = num + 1
-
- return special
+ self._memobj = bitwise.parse(MEM_FORMAT, self._mmap)
def get_special_locations(self):
- return sorted(self._get_special().keys())
-
- def __get_freq(self, mem):
- freq = (int(mem.freq) * 100000) + \
- (mem.freq_10khz * 10000) + \
- (mem.freq_1khz * 1000)
-
- if mem.is_12_5:
- if chirp_common.is_12_5(freq):
- pass
- elif mem.freq_1khz == 2:
- freq += 500
- elif mem.freq_1khz == 5:
- freq += 2500
- elif mem.freq_1khz == 7:
- freq += 500
- else:
- raise Exception("Unable to resolve 12.5kHz: %i" % freq)
-
- return freq
-
- def __set_freq(self, mem, freq):
- mem.freq = freq / 100000
- mem.freq_10khz = (freq / 10000) % 10
- khz = (freq / 1000) % 10
- mem.freq_1khz = khz
- mem.is_12_5 = chirp_common.is_12_5(freq)
-
- def __get_offset(self, mem):
- raw = memmap.MemoryMap(mem.get_raw())
- if ord(raw[5]) & 0x0A:
- raw[5] = ord(raw[5]) & 0xF0
- mem.set_raw(raw.get_packed())
- offset = int(mem.offset) * 1000 + 5000
- raw[5] = ord(raw[5]) | 0x0A
- mem.set_raw(raw.get_packed())
- return offset
- else:
- return int(mem.offset) * 1000
-
- def __set_offset(self, mem, offset):
- if (offset % 10) == 5000:
- extra = 0x0A
- offset -= 5000
- else:
- extra = 0x00
-
- mem.offset = offset / 1000
- raw = memmap.MemoryMap(mem.get_raw())
- raw[5] = ord(raw[5]) | extra
- mem.set_raw(raw.get_packed())
+ return sorted(_get_special().keys())
def get_memory(self, number):
mem = chirp_common.Memory()
if isinstance(number, str):
if number == "C":
- number = self._get_special()[number]
+ number = _get_special()[number]
_mem = self._memobj.call[0]
else:
- number = self._get_special()[number]
+ number = _get_special()[number]
_mem = self._memobj.special[number - 500]
empty = False
else:
@@ -202,15 +206,15 @@
if number <= 100:
mem.skip = isskip and "S" or ""
else:
- mem.extd_number = util.get_dict_rev(self._get_special(), number)
+ mem.extd_number = util.get_dict_rev(_get_special(), number)
mem.immutable = ["number", "skip", "extd_number"]
if empty:
mem.empty = True
return mem
- mem.freq = self.__get_freq(_mem)
- mem.offset = self.__get_offset(_mem)
+ mem.freq = _get_freq(_mem)
+ mem.offset = _get_offset(_mem)
mem.rtone = chirp_common.TONES[_mem.rtone]
mem.ctone = chirp_common.TONES[_mem.ctone]
mem.tmode = TMODES[_mem.tmode]
@@ -218,14 +222,11 @@
return mem
- def _wipe_memory(self, mem, char):
- mem.set_raw(char * (mem.size() / 8))
-
def set_memory(self, mem):
if mem.number == "C":
_mem = self._memobj.call[0]
elif isinstance(mem.number, str):
- _mem = self._memobj.special[self._get_special[number] - 500]
+ _mem = self._memobj.special[_get_special[mem.number] - 500]
else:
number = mem.number - 1
_mem = self._memobj.memory[number]
@@ -242,8 +243,8 @@
_skp &= ~mask
_mem.name = mem.name.ljust(6)
- self.__set_freq(_mem, mem.freq)
- self.__set_offset(_mem, mem.offset)
+ _set_freq(_mem, mem.freq)
+ _set_offset(_mem, mem.offset)
_mem.rtone = chirp_common.TONES.index(mem.rtone)
_mem.ctone = chirp_common.TONES.index(mem.ctone)
_mem.tmode = TMODES.index(mem.tmode)
diff -r db82df47f205 -r f805c420592f chirp/ic2200.py
--- a/chirp/ic2200.py Fri Apr 27 14:35:40 2012 -0700
+++ b/chirp/ic2200.py Fri Apr 27 14:35:41 2012 -0700
@@ -16,7 +16,7 @@
from chirp import chirp_common, icf, util, directory
from chirp import bitwise
-mem_format = """
+MEM_FORMAT = """
struct {
ul16 freq;
ul16 offset;
@@ -83,8 +83,23 @@
chirp_common.PowerLevel("MidLow", watts=10),
chirp_common.PowerLevel("Low", watts=5)]
+def _get_special():
+ special = { "C" : 206 }
+ for i in range(0, 3):
+ ida = "%iA" % (i+1)
+ idb = "%iB" % (i+1)
+ num = 200 + i * 2
+ special[ida] = num
+ special[idb] = num + 1
+
+ return special
+
+def _wipe_memory(mem, char):
+ mem.set_raw(char * (mem.size() / 8))
+
@directory.register
class IC2200Radio(icf.IcomCloneModeRadio, chirp_common.IcomDstarSupport):
+ """Icom IC-2200"""
VENDOR = "Icom"
MODEL = "IC-2200H"
@@ -145,25 +160,14 @@
return rf
def process_mmap(self):
- self._memobj = bitwise.parse(mem_format, self._mmap)
-
- def _get_special(self):
- special = { "C" : 206 }
- for i in range(0, 3):
- idA = "%iA" % (i+1)
- idB = "%iB" % (i+1)
- num = 200 + i * 2
- special[idA] = num
- special[idB] = num + 1
-
- return special
+ self._memobj = bitwise.parse(MEM_FORMAT, self._mmap)
def get_special_locations(self):
- return sorted(self._get_special().keys())
+ return sorted(_get_special().keys())
def get_memory(self, number):
if isinstance(number, str):
- number = self._get_special()[number]
+ number = _get_special()[number]
_mem = self._memobj.memory[number]
_flag = self._memobj.flags[number]
@@ -183,7 +187,7 @@
if number < 200:
mem.skip = _flag.skip and "S" or ""
else:
- mem.extd_number = util.get_dict_rev(self._get_special(), number)
+ mem.extd_number = util.get_dict_rev(_get_special(), number)
mem.immutable = ["number", "skip", "bank", "bank_index",
"extd_number"]
@@ -214,12 +218,9 @@
return [m for m in self._memories if m.number >= lo and m.number <= hi]
- def _wipe_memory(self, mem, char):
- mem.set_raw(char * (mem.size() / 8))
-
def set_memory(self, mem):
if isinstance(mem.number, str):
- number = self._get_special()[mem.number]
+ number = _get_special()[mem.number]
else:
number = mem.number
@@ -230,11 +231,11 @@
_flag.empty = mem.empty
if mem.empty:
- self._wipe_memory(_mem, "\xFF")
+ _wipe_memory(_mem, "\xFF")
return
if was_empty:
- self._wipe_memory(_mem, "\x00")
+ _wipe_memory(_mem, "\x00")
_mem.unknown8 = 0
_mem.is_625 = chirp_common.is_fractional_step(mem.freq)
diff -r db82df47f205 -r f805c420592f chirp/ic2720.py
--- a/chirp/ic2720.py Fri Apr 27 14:35:40 2012 -0700
+++ b/chirp/ic2720.py Fri Apr 27 14:35:41 2012 -0700
@@ -13,10 +13,10 @@
# 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 chirp_common, icf, util, directory
+from chirp import chirp_common, icf, directory
from chirp import bitwise
-mem_format = """
+MEM_FORMAT = """
struct {
u32 freq;
u32 offset;
@@ -69,6 +69,7 @@
@directory.register
class IC2720Radio(icf.IcomCloneModeRadio):
+ """Icom IC-2720"""
VENDOR = "Icom"
MODEL = "IC-2720H"
@@ -113,7 +114,7 @@
return rf
def process_mmap(self):
- self._memobj = bitwise.parse(mem_format, self._mmap)
+ self._memobj = bitwise.parse(MEM_FORMAT, self._mmap)
def get_raw_memory(self, number):
return repr(self._memobj.memory[number])
diff -r db82df47f205 -r f805c420592f chirp/ic2820.py
--- a/chirp/ic2820.py Fri Apr 27 14:35:40 2012 -0700
+++ b/chirp/ic2820.py Fri Apr 27 14:35:41 2012 -0700
@@ -13,10 +13,10 @@
# 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 chirp_common, icf, errors, util, directory
-from chirp import bitwise;
+from chirp import chirp_common, icf, util, directory
+from chirp import bitwise
-mem_format = """
+MEM_FORMAT = """
struct {
u32 freq;
u32 offset;
@@ -84,7 +84,8 @@
MEM_LOC_SIZE = 48
-class IC2820Bank(icf.IcomBank):
+class IC2820Bank(icf.IcomNamedBank):
+ """An IC2820 bank"""
def get_name(self):
_banks = self._model._radio._memobj.bank_names
return str(_banks[self.index].name).rstrip()
@@ -93,8 +94,30 @@
_banks = self._model._radio._memobj.bank_names
_banks[self.index].name = str(name).ljust(8)[:8]
+def _get_special():
+ special = {"C0" : 500 + 20,
+ "C1" : 500 + 21}
+
+ for i in range(0, 10):
+ ida = "%iA" % i
+ idb = "%iB" % i
+ special[ida] = 500 + i * 2
+ special[idb] = 500 + i * 2 + 1
+
+ return special
+
+def _resolve_memory_number(number):
+ if isinstance(number, str):
+ return _get_special()[number]
+ else:
+ return number
+
+def _wipe_memory(mem, char):
+ mem.set_raw(char * (mem.size() / 8))
+
@directory.register
class IC2820Radio(icf.IcomCloneModeRadio, chirp_common.IcomDstarSupport):
+ """Icom IC-2820"""
VENDOR = "Icom"
MODEL = "IC-2820H"
@@ -156,32 +179,14 @@
rf.valid_name_length = 8
return rf
- def _get_special(self):
- special = {"C0" : 500 + 20,
- "C1" : 500 + 21}
-
- for i in range(0, 10):
- idA = "%iA" % i
- idB = "%iB" % i
- special[idA] = 500 + i * 2
- special[idB] = 500 + i * 2 + 1
-
- return special
-
def get_special_locations(self):
- return sorted(self._get_special().keys())
+ return sorted(_get_special().keys())
def process_mmap(self):
- self._memobj = bitwise.parse(mem_format, self._mmap)
-
- def _resolve_memory_number(self, number):
- if isinstance(number, str):
- return self._get_special()[number]
- else:
- return number
+ self._memobj = bitwise.parse(MEM_FORMAT, self._mmap)
def get_memory(self, number):
- number = self._resolve_memory_number(number)
+ number = _resolve_memory_number(number)
bitpos = (1 << (number % 8))
bytepos = number / 8
@@ -208,7 +213,7 @@
elif _pskip & bitpos:
mem.skip = "P"
else:
- mem.extd_number = util.get_dict_rev(self._get_special(), number)
+ mem.extd_number = util.get_dict_rev(_get_special(), number)
mem.immutable = ["number", "skip", "bank", "bank_index",
"extd_number"]
@@ -233,9 +238,6 @@
return mem
- def _wipe_memory(self, mem, char):
- mem.set_raw(char * (mem.size() / 8))
-
def set_memory(self, mem):
bitpos = (1 << (mem.number % 8))
bytepos = mem.number / 8
@@ -259,13 +261,13 @@
if mem.empty:
_used |= bitpos
- self._wipe_memory(_mem, "\xFF")
+ _wipe_memory(_mem, "\xFF")
self._set_bank(mem.number, None)
return
_used &= ~bitpos
if was_empty:
- self._wipe_memory(_mem, "\x00")
+ _wipe_memory(_mem, "\x00")
_mem.freq = mem.freq
_mem.offset = mem.offset
diff -r db82df47f205 -r f805c420592f chirp/ic9x.py
--- a/chirp/ic9x.py Fri Apr 27 14:35:40 2012 -0700
+++ b/chirp/ic9x.py Fri Apr 27 14:35:41 2012 -0700
@@ -16,13 +16,11 @@
import time
import threading
-from chirp import chirp_common, errors, memmap, ic9x_ll, util, icf, directory
+from chirp import chirp_common, errors, ic9x_ll, icf, util, directory
from chirp import bitwise
-IC9xA_SPECIAL = {}
-IC9xA_SPECIAL_REV = {}
-IC9xB_SPECIAL = {}
-IC9xB_SPECIAL_REV = {}
+IC9XA_SPECIAL = {}
+IC9XB_SPECIAL = {}
for i in range(0, 25):
idA = "%iA" % i
@@ -30,30 +28,18 @@
Anum = 800 + i * 2
Bnum = 400 + i * 2
- IC9xA_SPECIAL[idA] = Anum
- IC9xA_SPECIAL[idB] = Bnum
- IC9xA_SPECIAL_REV[Anum] = idA
- IC9xA_SPECIAL_REV[Bnum] = idB
+ IC9XA_SPECIAL[idA] = Anum
+ IC9XA_SPECIAL[idB] = Bnum
- IC9xB_SPECIAL[idA] = Bnum
- IC9xB_SPECIAL[idB] = Bnum + 1
- IC9xB_SPECIAL_REV[Bnum] = idA
- IC9xB_SPECIAL_REV[Bnum+1] = idB
+ IC9XB_SPECIAL[idA] = Bnum
+ IC9XB_SPECIAL[idB] = Bnum + 1
-IC9xA_SPECIAL["C0"] = IC9xB_SPECIAL["C0"] = -1
-IC9xA_SPECIAL["C1"] = IC9xB_SPECIAL["C1"] = -2
+IC9XA_SPECIAL["C0"] = IC9XB_SPECIAL["C0"] = -1
+IC9XA_SPECIAL["C1"] = IC9XB_SPECIAL["C1"] = -2
-IC9xA_SPECIAL_REV[-1] = IC9xB_SPECIAL_REV[-1] = "C0"
-IC9xA_SPECIAL_REV[-2] = IC9xB_SPECIAL_REV[-2] = "C1"
-
-IC9x_SPECIAL = {
- 1 : IC9xA_SPECIAL,
- 2 : IC9xB_SPECIAL,
-}
-
-IC9x_SPECIAL_REV = {
- 1 : IC9xA_SPECIAL_REV,
- 2 : IC9xB_SPECIAL_REV,
+IC9X_SPECIAL = {
+ 1 : IC9XA_SPECIAL,
+ 2 : IC9XB_SPECIAL,
}
CHARSET = chirp_common.CHARSET_ALPHANUMERIC + \
@@ -61,7 +47,8 @@
LOCK = threading.Lock()
-class IC9xBank(icf.IcomBank):
+class IC9xBank(icf.IcomNamedBank):
+ """Icom 9x Bank"""
def get_name(self):
banks = self._model._radio._ic9x_get_banks()
return banks[self.index]
@@ -73,6 +60,7 @@
@directory.register
class IC9xRadio(icf.IcomLiveRadio):
+ """Base class for Icom IC-9x radios"""
MODEL = "IC-91/92AD"
_model = "ic9x" # Fake model info for detect.py
@@ -102,7 +90,7 @@
self.set_memory(mem)
def __init__(self, *args, **kwargs):
- chirp_common.LiveRadio.__init__(self, *args, **kwargs)
+ icf.IcomLiveRadio.__init__(self, *args, **kwargs)
if self.pipe:
self.pipe.setTimeout(0.1)
@@ -119,35 +107,22 @@
ic9x_ll.send_magic(self.pipe)
self.__last = time.time()
- def get_available_bank_index(self, bank):
- indexes = []
- for mem in self.__memcache.values():
- if mem.bank == bank and mem.bank_index >= 0:
- indexes.append(mem.bank_index)
-
- print "Index list for %i: %s" % (bank, indexes)
-
- for i in range(0, 99):
- if i not in indexes:
- return i
-
- raise errors.RadioError("Out of slots in this bank")
-
def get_special_locations(self):
- return sorted(IC9x_SPECIAL[self.vfo].keys())
+ return sorted(IC9X_SPECIAL[self.vfo].keys())
def get_memory(self, number):
if isinstance(number, str):
try:
- number = IC9x_SPECIAL[self.vfo][number]
+ number = IC9X_SPECIAL[self.vfo][number]
except KeyError:
- raise InvalidMemoryLocation("Unknown channel %s" % number)
+ raise errors.InvalidMemoryLocation("Unknown channel %s" % \
+ number)
if number < -2 or number > 999:
raise errors.InvalidValueError("Number must be between 0 and 999")
if self.__memcache.has_key(number):
- return self.__memcache[number]
+ return self.__memcache[number]
self._lock.acquire()
try:
@@ -165,7 +140,8 @@
self._lock.release()
if number > self._upper or number < 0:
- mem.extd_number = IC9x_SPECIAL_REV[self.vfo][number]
+ mem.extd_number = util.get_dict_rev(IC9X_SPECIAL,
+ [self.vfo][number])
mem.immutable = ["number", "skip", "bank", "bank_index",
"extd_number"]
@@ -184,7 +160,7 @@
self._lock.release()
- return repr(bitwise.parse(ic9x_ll.memory_frame_format, mframe))
+ return repr(bitwise.parse(ic9x_ll.MEMORY_FRAME_FORMAT, mframe))
def get_memories(self, lo=0, hi=None):
if hi is None:
@@ -192,7 +168,7 @@
memories = []
- for i in range(lo, hi+1):
+ for i in range(lo, hi + 1):
try:
print "Getting %i" % i
mem = self.get_memory(i)
@@ -244,7 +220,8 @@
def _ic9x_get_banks(self):
if len(self.__bankcache.keys()) == 26:
- return [self.__bankcache[k] for k in sorted(self.__bankcache.keys())]
+ return [self.__bankcache[k] for k in
+ sorted(self.__bankcache.keys())]
self._lock.acquire()
try:
@@ -302,6 +279,7 @@
return rf
class IC9xRadioA(IC9xRadio):
+ """IC9x Band A subdevice"""
VARIANT = "Band A"
vfo = 1
_upper = 849
@@ -323,6 +301,7 @@
return rf
class IC9xRadioB(IC9xRadio, chirp_common.IcomDstarSupport):
+ """IC9x Band B subdevice"""
VARIANT = "Band B"
vfo = 2
_upper = 399
@@ -362,7 +341,7 @@
calls = []
self._maybe_send_magic()
- for i in range(ulimit-1):
+ for i in range(ulimit - 1):
call = ic9x_ll.get_call(self.pipe, cstype, i+1)
calls.append(call)
@@ -426,15 +405,13 @@
self.RPTCALL_LIMIT[1],
calls)
+def _test():
+ import serial
+ ser = IC9xRadioB(serial.Serial(port="/dev/ttyUSB1",
+ baudrate=38400, timeout=0.1))
+ print ser.get_urcall_list()
+ print "-- FOO --"
+ ser.set_urcall_list(["K7TAY", "FOOBAR", "BAZ"])
+
if __name__ == "__main__":
- def test():
- import serial
- import util
- r = IC9xRadioB(serial.Serial(port="/dev/ttyUSB1",
- baudrate=38400, timeout=0.1))
- print r.get_urcall_list()
- #r.set_urcall_list(["K7TAY", "FOOBAR"])
- print "-- FOO --"
- r.set_urcall_list(["K7TAY", "FOOBAR", "BAZ"])
-
- test()
+ _test()
diff -r db82df47f205 -r f805c420592f chirp/ic9x_icf.py
--- a/chirp/ic9x_icf.py Fri Apr 27 14:35:40 2012 -0700
+++ b/chirp/ic9x_icf.py Fri Apr 27 14:35:41 2012 -0700
@@ -13,7 +13,7 @@
# 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 chirp_common, icf, ic9x_icf_ll, util, directory
+from chirp import chirp_common, icf, ic9x_icf_ll, util, directory, errors
@directory.register
class IC9xICFRadio(chirp_common.CloneModeRadio):
@@ -45,7 +45,7 @@
return ic9x_icf_ll.get_memory(self._mmap, number)
def load_mmap(self, filename):
- mdata, self._mmap = icf.read_file(filename)
+ _mdata, self._mmap = icf.read_file(filename)
def get_sub_devices(self):
return [IC9xICFRadioA(self._mmap),
diff -r db82df47f205 -r f805c420592f chirp/ic9x_icf_ll.py
--- a/chirp/ic9x_icf_ll.py Fri Apr 27 14:35:40 2012 -0700
+++ b/chirp/ic9x_icf_ll.py Fri Apr 27 14:35:41 2012 -0700
@@ -14,7 +14,7 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import struct
-from chirp import chirp_common, util
+from chirp import chirp_common
from chirp.memmap import MemoryMap
MEM_LOC_SIZE_A = 20
@@ -31,12 +31,14 @@
POS_NAME = 12
def get_mem_offset(number):
+ """Get the offset into the memory map for memory @number"""
if number < 850:
return MEM_LOC_SIZE_A * number
else:
return (MEM_LOC_SIZE_A * 850) + (MEM_LOC_SIZE_B * (number - 850))
def get_raw_memory(mmap, number):
+ """Return a raw representation of memory @number"""
offset = get_mem_offset(number)
if number >= 850:
size = MEM_LOC_SIZE_B
@@ -45,6 +47,7 @@
return MemoryMap(mmap[offset:offset+size])
def get_freq(mmap):
+ """Return the memory frequency"""
if ord(mmap[10]) & 0x10:
mult = 6250
else:
@@ -53,22 +56,27 @@
return val * mult
def get_offset(mmap):
+ """Return the memory offset"""
val, = struct.unpack(">H", mmap[POS_OFFSET:POS_OFFSET+2])
return val * 5000
def get_rtone(mmap):
+ """Return the memory rtone"""
val = (ord(mmap[POS_TONE]) & 0xFC) >> 2
return chirp_common.TONES[val]
def get_ctone(mmap):
+ """Return the memory ctone"""
val = (ord(mmap[POS_TONE]) & 0x03) | ((ord(mmap[POS_TONE+1]) & 0xF0) >> 4)
return chirp_common.TONES[val]
def get_dtcs(mmap):
+ """Return the memory dtcs value"""
val = ord(mmap[POS_DTCS]) >> 1
return chirp_common.DTCS_CODES[val]
def get_mode(mmap):
+ """Return the memory mode"""
val = ord(mmap[POS_MODE]) & 0x07
modemap = ["FM", "NFM", "WFM", "AM", "DV", "FM"]
@@ -76,20 +84,22 @@
return modemap[val]
def get_ts(mmap):
+ """Return the memory tuning step"""
val = (ord(mmap[POS_TS]) & 0xF0) >> 4
if val == 14:
return 5.0 # Coerce "Auto" to 5.0
- ICF_TS = list(chirp_common.TUNING_STEPS)
- ICF_TS.insert(2, 8.33)
- ICF_TS.insert(3, 9.00)
- ICF_TS.append(100.0)
- ICF_TS.append(125.0)
- ICF_TS.append(200.0)
+ icf_ts = list(chirp_common.TUNING_STEPS)
+ icf_ts.insert(2, 8.33)
+ icf_ts.insert(3, 9.00)
+ icf_ts.append(100.0)
+ icf_ts.append(125.0)
+ icf_ts.append(200.0)
- return ICF_TS[val]
+ return icf_ts[val]
def get_dtcs_polarity(mmap):
+ """Return the memory dtcs polarity"""
val = (ord(mmap[POS_DTCSPOL]) & 0x03)
pols = ["NN", "NR", "RN", "RR"]
@@ -97,6 +107,7 @@
return pols[val]
def get_duplex(mmap):
+ """Return the memory duplex"""
val = (ord(mmap[POS_DUPLEX]) & 0x0C) >> 2
dup = ["", "-", "+", ""]
@@ -104,9 +115,11 @@
return dup[val]
def get_name(mmap):
+ """Return the memory name"""
return mmap[POS_NAME:POS_NAME+8]
def get_memory(_mmap, number):
+ """Get memory @number from global memory map @_mmap"""
mmap = get_raw_memory(_mmap, number)
mem = chirp_common.Memory()
mem.number = number
diff -r db82df47f205 -r f805c420592f chirp/ic9x_ll.py
--- a/chirp/ic9x_ll.py Fri Apr 27 14:35:40 2012 -0700
+++ b/chirp/ic9x_ll.py Fri Apr 27 14:35:41 2012 -0700
@@ -32,11 +32,13 @@
# Dirty hack until I clean up this IC9x mess
class IC9xMemory(chirp_common.Memory):
+ """A dirty hack to stash bank information in a memory"""
_bank = None
_bank_index = 0
def __init__(self):
chirp_common.Memory.__init__(self)
class IC9xDVMemory(chirp_common.DVMemory):
+ """See above dirty hack"""
_bank = None
_bank_index = 0
def __init__(self):
@@ -89,32 +91,34 @@
return _ic9x_parse_frames(data)
-class IcomFrame:
- pass
-
-class IC92Frame(IcomFrame):
+class IC92Frame:
+ """IC9x frame base class"""
def get_vfo(self):
+ """Return the vfo number"""
return ord(self._map[0])
def set_vfo(self, vfo):
+ """Set the vfo number"""
self._map[0] = chr(vfo)
def from_raw(self, data):
+ """Construct the frame from raw data"""
self._map = MemoryMap(data)
- #self._map.printable()
-
def from_frame(self, frame):
- self._map = frame._map
+ """Construct the frame by copying another frame"""
+ self._map = MemoryMap(frame.get_raw())
def __init__(self, subcmd=0, flen=0, cmd=0x1A):
self._map = MemoryMap("\x00" * (4 + flen))
self._map[0] = "\x01\x80" + chr(cmd) + chr(subcmd)
def get_payload(self):
+ """Return the entire payload (sans header)"""
return self._map[4:]
def get_raw(self):
+ """Return the raw version of the frame"""
return self._map.get_packed()
def __str__(self):
@@ -126,6 +130,7 @@
return string
def send(self, pipe, verbose=False):
+ """Send the frame to the radio via @pipe"""
if verbose:
print "Sending:\n%s" % util.hexprint(self.get_raw())
@@ -146,10 +151,11 @@
return self._map[start+4:end+4]
class IC92GetBankFrame(IC92Frame):
+ """A frame for requesting bank information"""
def __init__(self):
IC92Frame.__init__(self, 0x09)
- def send(self, pipe):
+ def send(self, pipe, verbose=False):
rframes = ic9x_send(pipe, self.get_raw())
if len(rframes) == 0:
@@ -158,27 +164,30 @@
return rframes
class IC92BankFrame(IC92Frame):
+ """A frame for bank information"""
def __init__(self):
# 1 byte for identifier
# 8 bytes for name
IC92Frame.__init__(self, 0x0B, 9)
- def __str__(self):
- return "Bank %s: %s" % (self._data[2], self._data[3:])
-
def get_name(self):
+ """Return the bank name"""
return self[1:]
def get_identifier(self):
+ """Return the letter for the bank (A-Z)"""
return self[0]
def set_name(self, name):
+ """Set the bank name"""
self[1] = name[:8].ljust(8)
def set_identifier(self, ident):
+ """Set the letter for the bank (A-Z)"""
self[0] = ident[0]
class IC92MemClearFrame(IC92Frame):
+ """A frame for clearing (erasing) a memory"""
def __init__(self, loc):
# 2 bytes for location
# 1 byte for 0xFF
@@ -187,24 +196,27 @@
self[0] = struct.pack(">BHB", 1, int("%i" % loc, 16), 0xFF)
class IC92MemGetFrame(IC92Frame):
- def __init__(self, loc, call=False):
+ """A frame for requesting a memory"""
+ def __init__(self, loc, iscall=False):
# 2 bytes for location
IC92Frame.__init__(self, 0x00, 3)
- if call:
- c = 2
+ if iscall:
+ call = 2
else:
- c = 1
+ call = 1
- self[0] = struct.pack(">BH", c, int("%i" % loc, 16))
+ self[0] = struct.pack(">BH", call, int("%i" % loc, 16))
class IC92GetCallsignFrame(IC92Frame):
- def __init__(self, type, number):
- IC92Frame.__init__(self, type, 1, 0x1D)
+ """A frame for getting callsign information"""
+ def __init__(self, calltype, number):
+ IC92Frame.__init__(self, calltype, 1, 0x1D)
self[0] = chr(number)
class IC92CallsignFrame(IC92Frame):
+ """A frame to communicate callsign information"""
command = 0 # Invalid
width = 8
@@ -216,19 +228,23 @@
self[0] = chr(number) + callsign[:self.width].ljust(self.width)
def get_callsign(self):
+ """Return the actual callsign"""
return self[1:self.width+1].rstrip()
class IC92YourCallsignFrame(IC92CallsignFrame):
+ """URCALL frame"""
command = 6 # Your
class IC92RepeaterCallsignFrame(IC92CallsignFrame):
+ """RPTCALL frame"""
command = 7 # Repeater
class IC92MyCallsignFrame(IC92CallsignFrame):
+ """MYCALL frame"""
command = 8 # My
width = 12 # 4 bytes for /STID
-memory_frame_format = """
+MEMORY_FRAME_FORMAT = """
struct {
u8 vfo;
bbcd number[2];
@@ -261,6 +277,7 @@
"""
class IC92MemoryFrame(IC92Frame):
+ """A frame for communicating memory information"""
def __init__(self):
IC92Frame.__init__(self, 0, DV_MEM_LEN)
@@ -284,21 +301,24 @@
self._map.truncate(MEM_LEN + 4)
def set_iscall(self, iscall):
+ """This frame refers to a call channel if @iscall is True"""
if iscall:
self[0] = 2
else:
self[0] = 1
def get_iscall(self):
+ """Return True if this frame refers to a call channel"""
return ord(self[0]) == 2
def set_memory(self, mem):
+ """Take Memory object @mem and configure the frame accordingly"""
if mem.number < 0:
self.set_iscall(True)
mem.number = abs(mem.number) - 1
print "Memory is %i (call %s)" % (mem.number, self.get_iscall())
- _mem = bitwise.parse(memory_frame_format, self).mem
+ _mem = bitwise.parse(MEMORY_FRAME_FORMAT, self).mem
_mem.number = mem.number
@@ -329,7 +349,8 @@
_mem.digital_code = mem.dv_code
def get_memory(self):
- _mem = bitwise.parse(memory_frame_format, self).mem
+ """Return a Memory object based on the contents of the frame"""
+ _mem = bitwise.parse(MEMORY_FRAME_FORMAT, self).mem
if MODES[_mem.mode] == "DV":
mem = IC9xDVMemory()
@@ -372,74 +393,55 @@
return mem
-def print_frames(frames):
- count = 0
- for i in frames:
- print "Frame %i:" % count
- print i
- count += 1
-
def _send_magic_4800(pipe):
cmd = "\x01\x80\x19"
magic = ("\xFE" * 25) + cmd
- for i in [0,1]:
- r = ic9x_send(pipe, magic)
- if r:
- return r[0].get_raw()[0] == "\x80"
- return r and r[0].get_raw()[:3] == rsp
+ for _i in [0, 1]:
+ resp = ic9x_send(pipe, magic)
+ if resp:
+ return resp[0].get_raw()[0] == "\x80"
+ return True
def _send_magic_38400(pipe):
cmd = "\x01\x80\x19"
- rsp = "\x80\x01\x19"
+ #rsp = "\x80\x01\x19"
magic = ("\xFE" * 400) + cmd
- for i in [0,1]:
- r = ic9x_send(pipe, magic)
- if r:
- return r[0].get_raw()[0] == "\x80"
+ for _i in [0, 1]:
+ resp = ic9x_send(pipe, magic)
+ if resp:
+ return resp[0].get_raw()[0] == "\x80"
return False
def send_magic(pipe):
+ """Send the magic incantation to wake up an ic9x radio"""
if pipe.getBaudrate() == 38400:
- r = _send_magic_38400(pipe)
- if r:
+ resp = _send_magic_38400(pipe)
+ if resp:
return
print "Switching from 38400 to 4800"
pipe.setBaudrate(4800)
- r = _send_magic_4800(pipe)
+ resp = _send_magic_4800(pipe)
pipe.setBaudrate(38400)
- if r:
+ if resp:
return
raise errors.RadioError("Radio not responding")
elif pipe.getBaudrate() == 4800:
- r = _send_magic_4800(pipe)
- if r:
+ resp = _send_magic_4800(pipe)
+ if resp:
return
print "Switching from 4800 to 38400"
pipe.setBaudrate(38400)
- r = _send_magic_38400(pipe)
- if r:
+ resp = _send_magic_38400(pipe)
+ if resp:
return
pipe.setBaudrate(4800)
raise errors.RadioError("Radio not responding")
else:
- raise errors.InvalidDataError("Radio in unknown state (%i)" % r.getBaudrate())
-
-def print_banks(pipe):
- frames = send(pipe, "\x01\x80\x1a\x09") # Banks
-
- print "A Banks:"
- for i in range(180, 180+26):
- bf = IC92BankFrame()
- bf.from_frame(frames[i])
- print str(bf)
-
- print "B Banks:"
- for i in range(237, 237+26):
- bf = IC92BankFrame()
- bf.from_frame(frames[i])
- print str(bf)
+ raise errors.InvalidDataError("Radio in unknown state (%i)" % \
+ pipe.getBaudrate())
def get_memory_frame(pipe, vfo, number):
+ """Get the memory frame for @vfo and @number via @pipe"""
if number < 0:
number = abs(number + 1)
call = True
@@ -452,6 +454,7 @@
return frame.send(pipe)
def get_memory(pipe, vfo, number):
+ """Get a memory object for @vfo and @number via @pipe"""
rframe = get_memory_frame(pipe, vfo, number)
if len(rframe.get_payload()) < 1:
@@ -466,6 +469,7 @@
return mf.get_memory()
def set_memory(pipe, vfo, memory):
+ """Set memory @memory on @vfo via @pipe"""
frame = IC92MemoryFrame()
frame.set_memory(memory)
frame.set_vfo(vfo)
@@ -480,6 +484,7 @@
util.hexprint(rframe.get_payload()))
def erase_memory(pipe, vfo, number):
+ """Erase memory @number on @vfo via @pipe"""
frame = IC92MemClearFrame(number)
frame.set_vfo(vfo)
@@ -488,6 +493,7 @@
raise errors.InvalidDataError("Radio reported error")
def get_banks(pipe, vfo):
+ """Get banks for @vfo via @pipe"""
frame = IC92GetBankFrame()
frame.set_vfo(vfo)
@@ -509,6 +515,7 @@
return banks
def set_banks(pipe, vfo, banks):
+ """Set banks for @vfo via @pipe"""
for i in range(0, 26):
bframe = IC92BankFrame()
bframe.set_vfo(vfo)
@@ -520,6 +527,7 @@
raise errors.InvalidDataError("Radio reported error")
def get_call(pipe, cstype, number):
+ """Get @cstype callsign @number via @pipe"""
cframe = IC92GetCallsignFrame(cstype.command, number)
cframe.set_vfo(2)
rframe = cframe.send(pipe)
@@ -530,28 +538,10 @@
return cframe.get_callsign()
def set_call(pipe, cstype, number, call):
+ """Set @cstype @call at position @number via @pipe"""
cframe = cstype(number, call)
cframe.set_vfo(2)
rframe = cframe.send(pipe)
if rframe.get_payload() != "\xfb":
raise errors.RadioError("Radio reported error")
-
-def print_memory(pipe, vfo, number):
- if vfo not in [1, 2]:
- raise errors.InvalidValueError("VFO must be 1 or 2")
-
- if number < 0 or number > 399:
- raise errors.InvalidValueError("Number must be between 0 and 399")
-
- mf = get_memory(pipe, vfo, number)
-
- print "Memory %i from VFO %i: %s" % (number, vfo, str(mf))
-
-if __name__ == "__main__":
- print util.hexprint(util.bcd_encode(1072))
- print util.hexprint(util.bcd_encode(146900000, False))
- print util.hexprint(util.bcd_encode(25, width=4))
- print util.hexprint(util.bcd_encode(5000000, False, 6))
- print util.hexprint(util.bcd_encode(600000, False, 6))
-
diff -r db82df47f205 -r f805c420592f chirp/icf.py
--- a/chirp/icf.py Fri Apr 27 14:35:40 2012 -0700
+++ b/chirp/icf.py Fri Apr 27 14:35:41 2012 -0700
@@ -13,21 +13,20 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
-
import struct
import re
from chirp import chirp_common, errors, util, memmap
-from chirp import ic9x_ll # for magic; may need to move later
CMD_CLONE_OUT = 0xE2
CMD_CLONE_IN = 0xE3
CMD_CLONE_DAT = 0xE4
-CMD_CLONE_END = 0xE5
+CMD_CLONE_END = 0xE5
-save_pipe = None
+SAVE_PIPE = None
class IcfFrame:
+ """A single ICF communication frame"""
src = 0
dst = 0
cmd = 0
@@ -53,6 +52,7 @@
pass
def parse_frame_generic(data):
+ """Parse an ICF frame of unknown type from the beginning of @data"""
frame = IcfFrame()
frame.src = ord(data[2])
@@ -69,6 +69,7 @@
return frame, data[end+1:]
class RadioStream:
+ """A class to make reading a stream of IcfFrames easier"""
def __init__(self, pipe):
self.pipe = pipe
self.data = ""
@@ -105,6 +106,7 @@
return frames
def get_frames(self, nolimit=False):
+ """Read any pending frames from the stream"""
while True:
_data = self.pipe.read(64)
if not _data:
@@ -114,7 +116,7 @@
if not nolimit and len(self.data) > 128 and "\xFD" in self.data:
break # Give us a chance to do some status
- if len(data) > 1024:
+ if len(_data) > 1024:
break # Avoid an endless loop of chewing garbage
if not self.data:
@@ -122,8 +124,9 @@
return self._process_frames()
-def get_model_data(pipe, model="\x00\x00\x00\x00"):
- send_clone_frame(pipe, 0xe0, model, raw=True)
+def get_model_data(pipe, mdata="\x00\x00\x00\x00"):
+ """Query the radio connected to @pipe for its model data"""
+ send_clone_frame(pipe, 0xe0, mdata, raw=True)
stream = RadioStream(pipe)
frames = stream.get_frames()
@@ -134,7 +137,10 @@
return frames[0].payload
def get_clone_resp(pipe, length=None):
+ """Read the response to a clone frame"""
def exit_criteria(buf, length):
+ """Stop reading a clone response if we have enough data or encounter
+ the end of a frame"""
if length is None:
return buf.endswith("\xfd")
else:
@@ -147,6 +153,8 @@
return resp
def send_clone_frame(pipe, cmd, data, raw=False, checksum=False):
+ """Send a clone frame with @cmd and @data to the radio attached
+ to @pipe"""
cs = 0
if raw:
@@ -166,9 +174,9 @@
frame = "\xfe\xfe\xee\xef%s%s%s\xfd" % (chr(cmd), hed, cs)
- if save_pipe:
+ if SAVE_PIPE:
print "Saving data..."
- save_pipe.write(frame)
+ SAVE_PIPE.write(frame)
#print "Sending:\n%s" % util.hexprint(frame)
#print "Sending:\n%s" % util.hexprint(hed[6:])
@@ -182,6 +190,7 @@
return frame
def process_bcd(bcddata):
+ """Convert BCD-encoded data to raw"""
data = ""
i = 0
while i < range(len(bcddata)) and i+1 < len(bcddata):
@@ -195,36 +204,45 @@
return data
-def process_data_frame(frame, mmap):
+def process_data_frame(frame, _mmap):
+ """Process a data frame, adding the payload to @_mmap"""
_data = process_bcd(frame.payload)
- if len(mmap) >= 0x10000:
+ if len(_mmap) >= 0x10000:
saddr, = struct.unpack(">I", _data[0:4])
- bytes, = struct.unpack("B", _data[4])
- data = _data[5:5+bytes]
+ length, = struct.unpack("B", _data[4])
+ data = _data[5:5+length]
else:
saddr, = struct.unpack(">H", _data[0:2])
- bytes, = struct.unpack("B", _data[2])
- data = _data[3:3+bytes]
+ length, = struct.unpack("B", _data[2])
+ data = _data[3:3+length]
try:
- mmap[saddr] = data
+ _mmap[saddr] = data
except IndexError:
- print "Error trying to set %i bytes at %05x (max %05x)" %\
- (bytes, saddr, len(mmap))
- return saddr, saddr + bytes
+ print "Error trying to set %i bytes at %05x (max %05x)" % \
+ (bytes, saddr, len(_mmap))
+ return saddr, saddr + length
def start_hispeed_clone(radio, cmd):
- buf = ("\xFE" * 20) + "\xEE\xEF\xE8" + radio._model + "\x00\x00\x02\x01\xFD"
+ """Send the magic incantation to the radio to go fast"""
+ buf = ("\xFE" * 20) + \
+ "\xEE\xEF\xE8" + \
+ radio.get_model() + \
+ "\x00\x00\x02\x01\xFD"
print "Starting HiSpeed:\n%s" % util.hexprint(buf)
radio.pipe.write(buf)
radio.pipe.flush()
- r = radio.pipe.read(128)
- print "Response:\n%s" % util.hexprint(r)
+ resp = radio.pipe.read(128)
+ print "Response:\n%s" % util.hexprint(resp)
print "Switching to 38400 baud"
radio.pipe.setBaudrate(38400)
- buf = ("\xFE" * 14) + "\xEE\xEF" + chr(cmd) + radio._model[:3] + "\x00\xFD"
+ buf = ("\xFE" * 14) + \
+ "\xEE\xEF" + \
+ chr(cmd) + \
+ radio.get_model()[:3] + \
+ "\x00\xFD"
print "Starting HiSpeed Clone:\n%s" % util.hexprint(buf)
radio.pipe.write(buf)
radio.pipe.flush()
@@ -247,7 +265,7 @@
stream = RadioStream(radio.pipe)
addr = 0
- mmap = memmap.MemoryMap(chr(0x00) * radio._memsize)
+ _mmap = memmap.MemoryMap(chr(0x00) * radio.get_memsize())
last_size = 0
while True:
frames = stream.get_frames()
@@ -256,7 +274,7 @@
for frame in frames:
if frame.cmd == CMD_CLONE_DAT:
- src, dst = process_data_frame(frame, mmap)
+ src, dst = process_data_frame(frame, _mmap)
if last_size != (dst - src):
print "ICF Size change from %i to %i at %04x" % (last_size,
dst - src,
@@ -276,16 +294,18 @@
status.cur = addr
radio.status_fn(status)
- return mmap
+ return _mmap
def clone_from_radio(radio):
+ """Do a full clone out of the radio's memory"""
try:
return _clone_from_radio(radio)
except Exception, e:
raise errors.RadioError("Failed to communicate with the radio: %s" % e)
def send_mem_chunk(radio, start, stop, bs=32):
- mmap = radio.get_mmap()
+ """Send a single chunk of the radio's memory from @start- at stop"""
+ _mmap = radio.get_mmap()
status = chirp_common.Status()
status.msg = "Cloning to radio"
@@ -297,11 +317,11 @@
else:
size = stop - i
- if radio._memsize >= 0x10000:
+ if radio.get_memsize() >= 0x10000:
chunk = struct.pack(">IB", i, size)
else:
chunk = struct.pack(">HB", i, size)
- chunk += mmap[i:i+size]
+ chunk += _mmap[i:i+size]
send_clone_frame(radio.pipe,
CMD_CLONE_DAT,
@@ -315,10 +335,10 @@
return True
def _clone_to_radio(radio):
- global save_pipe
+ global SAVE_PIPE
# Uncomment to save out a capture of what we actually write to the radio
- # save_pipe = file("pipe_capture.log", "w", 0)
+ # SAVE_PIPE = file("pipe_capture.log", "w", 0)
md = get_model_data(radio.pipe)
@@ -347,9 +367,9 @@
send_clone_frame(radio.pipe, CMD_CLONE_END, radio.get_endframe(), raw=True)
frames += stream.get_frames(True)
- if save_pipe:
- save_pipe.close()
- save_pipe = None
+ if SAVE_PIPE:
+ SAVE_PIPE.close()
+ SAVE_PIPE = None
try:
result = frames[-1]
@@ -359,21 +379,24 @@
return result.payload[0] == '\x00'
def clone_to_radio(radio):
+ """Initiate a full memory clone out to @radio"""
try:
return _clone_to_radio(radio)
except Exception, e:
raise errors.RadioError("Failed to communicate with the radio: %s" % e)
def convert_model(mod_str):
+ """Convert an ICF-style model string into what we get from the radio"""
data = ""
for i in range(0, len(mod_str), 2):
- hex = mod_str[i:i+2]
- val = int(hex, 16)
- data += chr(val)
+ hexval = mod_str[i:i+2]
+ intval = int(hexval, 16)
+ data += chr(intval)
return data
def convert_data_line(line):
+ """Convert an ICF data line to raw memory format"""
if line.startswith("#"):
return ""
@@ -381,12 +404,10 @@
if len(line) == 38:
# Small memory (< 0x10000)
- pos = int(line[0:4], 16)
size = int(line[4:6], 16)
data = line[6:]
else:
# Large memory (>= 0x10000)
- pos = int(line[0:8], 16)
size = int(line[8:10], 16)
data = line[10:]
@@ -404,6 +425,7 @@
return _mmap
def read_file(filename):
+ """Read an ICF file and return the model string and memory data"""
f = file(filename)
mod_str = f.readline()
@@ -419,6 +441,7 @@
return model, memmap.MemoryMap(_mmap)
def is_9x_icf(filename):
+ """Returns True if @filename is an IC9x ICF file"""
f = file(filename)
mdata = f.read(8)
f.close()
@@ -426,6 +449,7 @@
return mdata in ["30660000", "28880000"]
def is_icf_file(filename):
+ """Returns True if @filename is an ICF file"""
f = file(filename)
data = f.readline()
data += f.readline()
@@ -436,10 +460,17 @@
return bool(re.match("^[0-9]{8}#", data))
class IcomBank(chirp_common.Bank):
+ """A bank that works for all Icom radios"""
# Integral index of the bank (not to be confused with per-memory
# bank indexes
index = 0
+class IcomNamedBank(IcomBank):
+ """A bank with an adjustable name"""
+ def set_name(self, name):
+ """Set the name of the bank"""
+ pass
+
class IcomBankModel(chirp_common.BankModel):
"""Icom radios all have pretty much the same simple bank model. This
central implementation can, with a few icom-specific radio interfaces
@@ -483,6 +514,7 @@
return [self.get_banks()[index]]
class IcomIndexedBankModel(IcomBankModel, chirp_common.BankIndexInterface):
+ """Generic bank model for Icom radios with indexed banks"""
def get_index_bounds(self):
return self._radio._bank_index_bounds
@@ -512,6 +544,7 @@
class IcomCloneModeRadio(chirp_common.CloneModeRadio):
+ """Base class for Icom clone-mode radios"""
VENDOR = "Icom"
BAUDRATE = 9600
@@ -523,17 +556,25 @@
_bank_class = IcomBank
_can_hispeed = False
- def is_hispeed(self):
- return self._can_hispeed
+ @classmethod
+ def is_hispeed(cls):
+ """Returns True if the radio supports hispeed cloning"""
+ return cls._can_hispeed
- def get_model(self):
- return self._model
+ @classmethod
+ def get_model(cls):
+ """Returns the Icom model data for this radio"""
+ return cls._model
- def get_endframe(self):
- return self._endframe
+ @classmethod
+ def get_endframe(cls):
+ """Returns the magic clone end frame for this radio"""
+ return cls._endframe
- def get_ranges(self):
- return self._ranges
+ @classmethod
+ def get_ranges(cls):
+ """Returns the ranges this radio likes to have in a clone"""
+ return cls._ranges
def sync_in(self):
self._mmap = clone_from_radio(self)
@@ -563,6 +604,7 @@
raise Exception("Not implemented")
class IcomLiveRadio(chirp_common.LiveRadio):
+ """Base class for an Icom Live-mode radio"""
VENDOR = "Icom"
BAUD_RATE = 38400
@@ -579,14 +621,3 @@
return IcomBankModel(self)
else:
return None
-
-if __name__ == "__main__":
- import sys
-
- model, mmap = read_file(sys.argv[1])
-
- print util.hexprint(model)
-
- f = file("out.img", "w")
- f.write(mmap.get_packed())
- f.close()
diff -r db82df47f205 -r f805c420592f chirp/icomciv.py
--- a/chirp/icomciv.py Fri Apr 27 14:35:40 2012 -0700
+++ b/chirp/icomciv.py Fri Apr 27 14:35:41 2012 -0700
@@ -1,18 +1,18 @@
import struct
-from chirp import chirp_common, icf, util, errors, bitwise, ic9x_ll, directory
+from chirp import chirp_common, icf, util, errors, bitwise, directory
from chirp.memmap import MemoryMap
DEBUG = True
-mem_format = """
+MEM_FORMAT = """
bbcd number[2];
u8 unknown1;
lbcd freq[5];
u8 unknown2:5,
mode:3;
"""
-mem_vfo_format = """
+MEM_VFO_FORMAT = """
u8 vfo;
bbcd number[2];
u8 unknown1;
@@ -35,6 +35,7 @@
"""
class Frame:
+ """Base class for an ICF frame"""
_cmd = 0x00
_sub = 0x00
@@ -42,16 +43,20 @@
self._data = ""
def set_command(self, cmd, sub):
+ """Set the command number (and optional subcommand)"""
self._cmd = cmd
self._sub = sub
def get_data(self):
+ """Return the data payload"""
return self._data
def set_data(self, data):
+ """Set the data payload"""
self._data = data
def send(self, src, dst, serial, willecho=True):
+ """Send the frame over @serial, using @src and @dst addresses"""
raw = struct.pack("BBBBBB", 0xFE, 0xFE, src, dst, self._cmd, self._sub)
raw += str(self._data) + chr(0xFD)
@@ -68,13 +73,14 @@
print util.hexprint(echo)
def read(self, serial):
+ """Read the frame from @serial"""
data = ""
while not data.endswith(chr(0xFD)):
- c = serial.read(1)
- if not c:
+ char = serial.read(1)
+ if not char:
print "Read %i bytes total" % len(data)
raise errors.RadioError("Timeout")
- data += c
+ data += char
if data == chr(0xFD):
raise errors.RadioError("Radio reported error")
@@ -90,39 +96,49 @@
return src, dst
class MemFrame(Frame):
+ """A memory frame"""
_cmd = 0x1A
_sub = 0x00
_loc = 0
def set_location(self, loc):
+ """Set the memory location number"""
self._loc = loc
self._data = struct.pack(">H", int("%04i" % loc, 16))
def make_empty(self):
+ """Mark as empty so the radio will erase the memory"""
self._data = struct.pack(">HB", int("%04i" % self._loc, 16), 0xFF)
def is_empty(self):
+ """Return True if memory is marked as empty"""
return len(self._data) < 5
def get_obj(self):
+ """Return a bitwise parsed object"""
self._data = MemoryMap(str(self._data)) # Make sure we're assignable
- return bitwise.parse(mem_format, self._data)
+ return bitwise.parse(MEM_FORMAT, self._data)
def initialize(self):
+ """Initialize to sane values"""
self._data = MemoryMap("".join(["\x00"] * (self.get_obj().size() / 8)))
class MultiVFOMemFrame(MemFrame):
+ """A memory frame for radios with multiple VFOs"""
def set_location(self, loc, vfo=1):
self._loc = loc
self._data = struct.pack(">BH", vfo, int("%04i" % loc, 16))
def get_obj(self):
self._data = MemoryMap(str(self._data)) # Make sure we're assignable
- return bitwise.parse(mem_vfo_format, self._data)
+ return bitwise.parse(MEM_VFO_FORMAT, self._data)
class IcomCIVRadio(icf.IcomLiveRadio):
+ """Base class for ICOM CIV-based radios"""
BAUD_RATE = 19200
MODEL = "CIV Radio"
+ _model = "\x00"
+ _template = 0
def _send_frame(self, frame):
return frame.send(ord(self._model), 0xE0, self.pipe,
@@ -140,9 +156,9 @@
def _detect_echo(self):
echo_test = "\xfe\xfe\xe0\xe0\xfa\xfd"
self.pipe.write(echo_test)
- r = self.pipe.read(6)
- print "Echo:\n%s" % util.hexprint(r)
- return r == echo_test
+ resp = self.pipe.read(6)
+ print "Echo:\n%s" % util.hexprint(resp)
+ return resp == echo_test
def __init__(self, *args, **kwargs):
icf.IcomLiveRadio.__init__(self, *args, **kwargs)
@@ -256,6 +272,7 @@
@directory.register
class Icom7200Radio(IcomCIVRadio):
+ """Icom IC-7200"""
MODEL = "7200"
_model = "\x76"
_template = 201
@@ -277,6 +294,7 @@
@directory.register
class Icom7000Radio(IcomCIVRadio):
+ """Icom IC-7000"""
MODEL = "7000"
_model = "\x70"
_template = 102
@@ -305,14 +323,15 @@
(0x70, 0xE0) : Icom7000Radio,
}
-def probe_model(s):
+def probe_model(ser):
+ """Probe the radio attatched to @ser for its model"""
f = Frame()
f.set_command(0x19, 0x00)
for model, controller in CIV_MODELS.keys():
- f.send(model, controller, s)
+ f.send(model, controller, ser)
try:
- f.read(s)
+ f.read(ser)
except errors.RadioError:
continue
diff -r db82df47f205 -r f805c420592f chirp/icq7.py
--- a/chirp/icq7.py Fri Apr 27 14:35:40 2012 -0700
+++ b/chirp/icq7.py Fri Apr 27 14:35:41 2012 -0700
@@ -13,12 +13,11 @@
# 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 chirp_common, icf, errors, util, directory
+from chirp import chirp_common, icf, directory
from chirp import bitwise
-from chirp.memmap import MemoryMap
from chirp.chirp_common import to_GHz, from_GHz
-mem_format = """
+MEM_FORMAT = """
struct {
bbcd freq[3];
u8 fractional:1,
@@ -49,6 +48,7 @@
@directory.register
class ICQ7Radio(icf.IcomCloneModeRadio):
+ """Icom IC-Q7A"""
VENDOR = "Icom"
MODEL = "IC-Q7A"
@@ -76,7 +76,7 @@
return rf
def process_mmap(self):
- self._memobj = bitwise.parse(mem_format, self._mmap)
+ self._memobj = bitwise.parse(MEM_FORMAT, self._mmap)
def get_raw_memory(self, number):
return repr(self._memobj.memory[number])
diff -r db82df47f205 -r f805c420592f chirp/ict70.py
--- a/chirp/ict70.py Fri Apr 27 14:35:40 2012 -0700
+++ b/chirp/ict70.py Fri Apr 27 14:35:41 2012 -0700
@@ -13,11 +13,10 @@
# 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 chirp_common, icf, errors, util, directory
+from chirp import chirp_common, icf, directory
from chirp import bitwise
-from chirp.memmap import MemoryMap
-mem_format = """
+MEM_FORMAT = """
struct {
u24 freq;
ul16 offset;
@@ -71,6 +70,7 @@
]
class ICT70Bank(icf.IcomBank):
+ """ICT70 bank"""
def get_name(self):
_bank = self._model._radio._memobj.bank_names[self.index]
return str(_bank.name).rstrip()
@@ -81,6 +81,7 @@
@directory.register
class ICT70Radio(icf.IcomCloneModeRadio):
+ """Icom IC-T70"""
VENDOR = "Icom"
MODEL = "IC-T70"
@@ -133,7 +134,7 @@
return rf
def process_mmap(self):
- self._memobj = bitwise.parse(mem_format, self._mmap)
+ self._memobj = bitwise.parse(MEM_FORMAT, self._mmap)
def get_raw_memory(self, number):
return repr(self._memobj.memory[number])
diff -r db82df47f205 -r f805c420592f chirp/icw32.py
--- a/chirp/icw32.py Fri Apr 27 14:35:40 2012 -0700
+++ b/chirp/icw32.py Fri Apr 27 14:35:41 2012 -0700
@@ -13,10 +13,10 @@
# 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 chirp_common, icf, errors, util, directory
+from chirp import chirp_common, icf, util, directory
from chirp import bitwise
-mem_format = """
+MEM_FORMAT = """
#seekto 0x%x;
struct {
bbcd freq[3];
@@ -61,8 +61,16 @@
DUPLEX = ["", "", "-", "+"]
TONE = ["", "", "Tone", "TSQL"]
+def _get_special():
+ special = {}
+ for i in range(0, 5):
+ special["M%iA" % (i+1)] = 100 + i*2
+ special["M%iB" % (i+1)] = 100 + i*2 + 1
+ return special
+
@directory.register
class ICW32ARadio(icf.IcomCloneModeRadio):
+ """Icom IC-W32A"""
VENDOR = "Icom"
MODEL = "IC-W32A"
@@ -97,26 +105,18 @@
return rf
def process_mmap(self):
- format = mem_format % self._mem_positions
- self._memobj = bitwise.parse(format, self._mmap)
+ fmt = MEM_FORMAT % self._mem_positions
+ self._memobj = bitwise.parse(fmt, self._mmap)
def get_raw_memory(self, number):
return repr(self._memobj.memory[number])
- def _get_special(self):
- special = {}
- for i in range(0, 5):
- special["M%iA" % (i+1)] = 100 + i*2
- special["M%iB" % (i+1)] = 100 + i*2 + 1
-
- return special
-
def get_special_locations(self):
- return sorted(self._get_special().keys())
+ return sorted(_get_special().keys())
def get_memory(self, number):
if isinstance(number, str):
- number = self._get_special()[number]
+ number = _get_special()[number]
_mem = self._memobj.memory[number]
_flg = self._memobj.flag[number]
@@ -129,7 +129,7 @@
mem.skip = _flg.skip and "S" or ""
else:
# Special memories
- mem.extd_number = util.get_dict_rev(self._get_special(), number)
+ mem.extd_number = util.get_dict_rev(_get_special(), number)
if _flg.empty:
mem.empty = True
@@ -190,11 +190,13 @@
return filedata[-16:] == "IcomCloneFormat3"
class ICW32ARadioVHF(ICW32ARadio):
+ """ICW32 VHF subdevice"""
VARIANT = "VHF"
_limits = (118000000, 174000000)
_mem_positions = (0x0000, 0x0DC0)
class ICW32ARadioUHF(ICW32ARadio):
+ """ICW32 UHF subdevice"""
VARIANT = "UHF"
_limits = (400000000, 470000000)
_mem_positions = (0x06E0, 0x0E2E)
diff -r db82df47f205 -r f805c420592f chirp/icx8x.py
--- a/chirp/icx8x.py Fri Apr 27 14:35:40 2012 -0700
+++ b/chirp/icx8x.py Fri Apr 27 14:35:41 2012 -0700
@@ -15,7 +15,7 @@
from chirp import chirp_common, icf, icx8x_ll, errors, directory
-def isUHF(pipe):
+def _isuhf(pipe):
try:
md = icf.get_model_data(pipe)
val = ord(md[20])
@@ -29,6 +29,7 @@
@directory.register
class ICx8xRadio(icf.IcomCloneModeRadio, chirp_common.IcomDstarSupport):
+ """Icom IC-V/U82"""
VENDOR = "Icom"
MODEL = "IC-V82/U82"
@@ -69,7 +70,7 @@
rf.valid_duplexes = ["", "-", "+"]
rf.valid_tuning_steps = [x for x in chirp_common.TUNING_STEPS
if x != 6.25]
- if self.isUHF:
+ if self._isuhf:
rf.valid_bands = [(420000000, 470000000)]
else:
rf.valid_bands = [(118000000, 176000000)]
@@ -78,12 +79,12 @@
return rf
def _get_type(self):
- flag = (isUHF(self.pipe) != 0)
+ flag = (_isuhf(self.pipe) != 0)
- if self.isUHF is not None and (self.isUHF != flag):
+ if self._isuhf is not None and (self._isuhf != flag):
raise errors.RadioError("VHF/UHF model mismatch")
- self.isUHF = flag
+ self._isuhf = flag
return flag
@@ -95,15 +96,15 @@
# file, look for the flag. If we're syncing from serial, set
# that flag.
if isinstance(pipe, str):
- self.isUHF = (ord(self._mmap[0x1930]) != 0)
+ self._isuhf = (ord(self._mmap[0x1930]) != 0)
#print "Found %s image" % (self.isUHF and "UHF" or "VHF")
else:
- self.isUHF = None
+ self._isuhf = None
def sync_in(self):
self._get_type()
icf.IcomCloneModeRadio.sync_in(self)
- self._mmap[0x1930] = self.isUHF and 1 or 0
+ self._mmap[0x1930] = self._isuhf and 1 or 0
def sync_out(self):
self._get_type()
@@ -116,7 +117,7 @@
if not self._mmap:
self.sync_in()
- if self.isUHF:
+ if self._isuhf:
base = 400
else:
base = 0
@@ -134,7 +135,7 @@
if not self._mmap:
self.sync_in()
- if self.isUHF:
+ if self._isuhf:
base = 400
else:
base = 0
diff -r db82df47f205 -r f805c420592f chirp/id31.py
--- a/chirp/id31.py Fri Apr 27 14:35:40 2012 -0700
+++ b/chirp/id31.py Fri Apr 27 14:35:41 2012 -0700
@@ -15,7 +15,7 @@
from chirp import directory, icf, bitwise, chirp_common
-mem_format = """
+MEM_FORMAT = """
struct {
u24 freq;
u16 offset;
@@ -111,7 +111,6 @@
def _encode_call(call):
_call = [0x00] * 7
- mask = 0
for i in range(0, 7):
val = ord(call[i]) << (i + 1)
if i > 0:
@@ -121,7 +120,32 @@
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 ID31Bank(icf.IcomBank):
+ """A ID-31 Bank"""
def get_name(self):
_banks = self._model._radio._memobj.bank_names
return str(_banks[self.index].name).rstrip()
@@ -132,6 +156,7 @@
@directory.register
class ID31Radio(icf.IcomCloneModeRadio, chirp_common.IcomDstarSupport):
+ """Icom ID-31"""
MODEL = "ID-31A"
_memsize = 0x15500
@@ -179,35 +204,11 @@
return rf
def process_mmap(self):
- self._memobj = bitwise.parse(mem_format, self._mmap)
+ self._memobj = bitwise.parse(MEM_FORMAT, self._mmap)
def get_raw_memory(self, number):
return repr(self._memobj.memory[number])
- def _get_freq(self, _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(self, _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)
-
def get_memory(self, number):
_mem = self._memobj.memory[number]
_usd = self._memobj.used_flags[number / 8]
@@ -226,7 +227,7 @@
mem.empty = True
return mem
- mem.freq, mem.offset = self._get_freq(_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]
@@ -261,7 +262,7 @@
bit = (1 << (memory.number % 8))
- self._set_freq(_mem, memory.freq, memory.offset)
+ _set_freq(_mem, memory.freq, memory.offset)
_mem.name = memory.name.ljust(12)[:12]
_mem.rtone = chirp_common.TONES.index(memory.rtone)
_mem.ctone = chirp_common.TONES.index(memory.ctone)
@@ -308,10 +309,8 @@
def get_repeater_call_list(self):
calls = []
- i = 0
for rptcall in self._memobj.rptcall:
call = _decode_call(rptcall.call)
- i += 1
if call.rstrip() and not call == "CALLSIGN":
calls.append(call)
for repeater in self._memobj.repeaters:
diff -r db82df47f205 -r f805c420592f chirp/id800.py
--- a/chirp/id800.py Fri Apr 27 14:35:40 2012 -0700
+++ b/chirp/id800.py Fri Apr 27 14:35:41 2012 -0700
@@ -16,7 +16,7 @@
from chirp import chirp_common, icf, errors, directory
from chirp import bitwise
-mem_format = """
+MEM_FORMAT = """
#seekto 0x0020;
struct {
u24 freq;
@@ -104,8 +104,50 @@
ALPHA_CHARSET = " ABCDEFGHIJKLMNOPQRSTUVWXYZ"
NUMERIC_CHARSET = "0123456789+-=*/()|"
+def get_name(_mem):
+ """Decode the name from @_mem"""
+ def _get_char(val):
+ if val == 0:
+ return " "
+ elif val & 0x20:
+ return ALPHA_CHARSET[val & 0x1F]
+ else:
+ return NUMERIC_CHARSET[val & 0x0F]
+
+ name_bytes = [_mem.name1, _mem.name2, _mem.name3,
+ _mem.name4, _mem.name5, _mem.name6]
+ name = ""
+ for val in name_bytes:
+ name += _get_char(val)
+
+ return name.rstrip()
+
+def set_name(_mem, name):
+ """Encode @name in @_mem"""
+ def _get_index(char):
+ if char == " ":
+ return 0
+ elif char.isalpha():
+ return ALPHA_CHARSET.index(char) | 0x20
+ else:
+ return NUMERIC_CHARSET.index(char) | 0x10
+
+ name = name.ljust(6)[:6]
+
+ _mem.usealpha = bool(name.strip())
+
+ # The element override calling convention makes this harder to automate.
+ # It's just six, so do it manually
+ _mem.name1 = _get_index(name[0])
+ _mem.name2 = _get_index(name[1])
+ _mem.name3 = _get_index(name[2])
+ _mem.name4 = _get_index(name[3])
+ _mem.name5 = _get_index(name[4])
+ _mem.name6 = _get_index(name[5])
+
@directory.register
class ID800v2Radio(icf.IcomCloneModeRadio, chirp_common.IcomDstarSupport):
+ """Icom ID800"""
VENDOR = "Icom"
MODEL = "ID-800H"
VARIANT = "v2"
@@ -186,50 +228,11 @@
return rf
def process_mmap(self):
- self._memobj = bitwise.parse(mem_format, self._mmap)
+ self._memobj = bitwise.parse(MEM_FORMAT, self._mmap)
def get_special_locations(self):
return sorted(ID800_SPECIAL.keys())
- def _get_name(self, _mem):
- def get_char(val):
- if val == 0:
- return " "
- elif val & 0x20:
- return ALPHA_CHARSET[val & 0x1F]
- else:
- return NUMERIC_CHARSET[val & 0x0F]
-
- name_bytes = [_mem.name1, _mem.name2, _mem.name3,
- _mem.name4, _mem.name5, _mem.name6]
- name = ""
- for val in name_bytes:
- name += get_char(val)
-
- return name.rstrip()
-
- def _set_name(self, _mem, name):
- def get_index(char):
- if char == " ":
- return 0
- elif char.isalpha():
- return ALPHA_CHARSET.index(char) | 0x20
- else:
- return NUMERIC_CHARSET.index(char) | 0x10
-
- name = name.ljust(6)[:6]
-
- _mem.usealpha = bool(name.strip())
-
- # The element override calling convention makes this harder to automate.
- # It's just six, so do it manually
- _mem.name1 = get_index(name[0])
- _mem.name2 = get_index(name[1])
- _mem.name3 = get_index(name[2])
- _mem.name4 = get_index(name[3])
- _mem.name5 = get_index(name[4])
- _mem.name6 = get_index(name[5])
-
def get_memory(self, number):
if isinstance(number, str):
try:
@@ -268,7 +271,7 @@
mem.dtcs = chirp_common.DTCS_CODES[_mem.dtcs]
mem.dtcs_polarity = DTCS_POL[_mem.dtcs_polarity]
mem.tuning_step = STEPS[_mem.tuning_step]
- mem.name = self._get_name(_mem)
+ mem.name = get_name(_mem)
mem.skip = _flg.pskip and "P" or _flg.skip and "S" or ""
@@ -295,7 +298,7 @@
_mem.dtcs = chirp_common.DTCS_CODES.index(mem.dtcs)
_mem.dtcs_polarity = DTCS_POL.index(mem.dtcs_polarity)
_mem.tuning_step = STEPS.index(mem.tuning_step)
- self._set_name(_mem, mem.name)
+ set_name(_mem, mem.name)
_flg.pskip = mem.skip == "P"
_flg.skip = mem.skip == "S"
diff -r db82df47f205 -r f805c420592f chirp/id880.py
--- a/chirp/id880.py Fri Apr 27 14:35:40 2012 -0700
+++ b/chirp/id880.py Fri Apr 27 14:35:41 2012 -0700
@@ -16,7 +16,7 @@
from chirp import chirp_common, icf, directory
from chirp import bitwise
-mem_format = """
+MEM_FORMAT = """
struct {
u24 freq;
u16 offset;
@@ -86,12 +86,13 @@
100.0, 125.0, 200.0]
def decode_call(sevenbytes):
+ """Decode a callsign from a packed region @sevenbytes"""
if len(sevenbytes) != 7:
raise Exception("%i (!=7) bytes to decode_call" % len(sevenbytes))
i = 0
rem = 0
- str = ""
+ call = ""
for byte in [ord(x) for x in sevenbytes]:
i += 1
@@ -100,7 +101,7 @@
code = (byte >> i) | rem # Code gets the upper bits of remainder
# plus all but the i lower bits of this
# byte
- str += chr(code)
+ call += chr(code)
rem = (byte & mask) << 7 - i # Remainder for next time are the masked
# bits, moved to the high places for the
@@ -108,14 +109,13 @@
# After seven trips gathering overflow bits, we chould have seven
# left, which is the final character
- str += chr(rem)
+ call += chr(rem)
- return str.rstrip()
+ return call.rstrip()
def encode_call(call):
+ """Encode @call into a 7-byte region"""
call = call.ljust(8)
- val = 0
-
buf = []
for i in range(0, 8):
@@ -132,7 +132,33 @@
return "".join([chr(x) for x in buf[:7]])
-class ID880Bank(icf.IcomBank):
+def _get_freq(_mem):
+ val = int(_mem.freq)
+
+ if val & 0x00200000:
+ mult = 6250
+ else:
+ mult = 5000
+
+ val &= 0x0003FFFF
+
+ return (val * mult)
+
+def _set_freq(_mem, freq):
+ if chirp_common.is_fractional_step(freq):
+ mult = 6250
+ flag = 0x00200000
+ else:
+ mult = 5000
+ flag = 0x00000000
+
+ _mem.freq = (freq / mult) | flag
+
+def _wipe_memory(mem, char):
+ mem.set_raw(char * (mem.size() / 8))
+
+class ID880Bank(icf.IcomNamedBank):
+ """ID880 Bank"""
def get_name(self):
_bank = self._model._radio._memobj.bank_names[self.index]
return str(_bank.name).rstrip()
@@ -143,6 +169,7 @@
@directory.register
class ID880Radio(icf.IcomCloneModeRadio, chirp_common.IcomDstarSupport):
+ """Icom ID880"""
VENDOR = "Icom"
MODEL = "ID-880H"
@@ -185,7 +212,7 @@
_bank.index = index
def process_mmap(self):
- self._memobj = bitwise.parse(mem_format, self._mmap)
+ self._memobj = bitwise.parse(MEM_FORMAT, self._mmap)
def get_features(self):
rf = chirp_common.RadioFeatures()
@@ -208,28 +235,6 @@
def get_raw_memory(self, number):
return repr(self._memobj.memory[number])
- def _get_freq(self, _mem):
- val = int(_mem.freq)
-
- if val & 0x00200000:
- mult = 6250
- else:
- mult = 5000
-
- val &= 0x0003FFFF
-
- return (val * mult)
-
- def _set_freq(self, _mem, freq):
- if chirp_common.is_fractional_step(freq):
- mult = 6250
- flag = 0x00200000
- else:
- mult = 5000
- flag = 0x00000000
-
- _mem.freq = (freq / mult) | flag
-
def get_memory(self, number):
bytepos = number / 8
bitpos = 1 << (number % 8)
@@ -263,7 +268,7 @@
mem.empty = True
return mem
- mem.freq = self._get_freq(_mem)
+ mem.freq = _get_freq(_mem)
mem.offset = (_mem.offset * 5) * 1000
mem.rtone = chirp_common.TONES[_mem.rtone]
mem.ctone = chirp_common.TONES[_mem.ctone]
@@ -280,9 +285,6 @@
return mem
- def _wipe_memory(self, mem, char):
- mem.set_raw(char * (mem.size() / 8))
-
def set_memory(self, mem):
bitpos = (1 << (mem.number % 8))
bytepos = mem.number / 8
@@ -295,16 +297,16 @@
if mem.empty:
_used |= bitpos
- self._wipe_memory(_mem, "\xFF")
+ _wipe_memory(_mem, "\xFF")
self._set_bank(mem.number, None)
return
_used &= ~bitpos
if was_empty:
- self._wipe_memory(_mem, "\x00")
+ _wipe_memory(_mem, "\x00")
- self._set_freq(_mem, mem.freq)
+ _set_freq(_mem, mem.freq)
_mem.offset = int((mem.offset / 1000) / 5)
_mem.rtone = chirp_common.TONES.index(mem.rtone)
_mem.ctone = chirp_common.TONES.index(mem.ctone)
@@ -359,7 +361,7 @@
_calls = self._memobj.rptcall
calls = ["*NOTUSE*"]
- for i in range(*self.RPTCALL_LIMIT):
+ for _i in range(*self.RPTCALL_LIMIT):
# FIXME: Not sure where the repeater list actually is
calls.append("UNSUPRTD")
continue
@@ -370,6 +372,7 @@
# the ID-880. So, don't register right now
#@directory.register
class ID80Radio(ID880Radio):
+ """Icom ID80"""
MODEL = "ID-80H"
_model = "\x31\x55\x00\x01"
diff -r db82df47f205 -r f805c420592f chirp/idrp.py
--- a/chirp/idrp.py Fri Apr 27 14:35:40 2012 -0700
+++ b/chirp/idrp.py Fri Apr 27 14:35:41 2012 -0700
@@ -13,16 +13,15 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
-import struct
import serial
from chirp import chirp_common, errors
-from chirp.memmap import MemoryMap
from chirp import util
DEBUG_IDRP = False
def parse_frames(buf):
+ """Parse frames from the radio"""
frames = []
while "\xfe\xfe" in buf:
@@ -38,8 +37,9 @@
return frames
-def send(pipe, buffer):
- pipe.write("\xfe\xfe%s\xfd" % buffer)
+def send(pipe, buf):
+ """Send data in @buf to @pipe"""
+ pipe.write("\xfe\xfe%s\xfd" % buf)
pipe.flush()
data = ""
@@ -55,15 +55,18 @@
return parse_frames(data)
def send_magic(pipe):
+ """Send the magic wakeup call to @pipe"""
send(pipe, ("\xfe" * 15) + "\x01\x7f\x19")
def drain(pipe):
+ """Chew up any data waiting on @pipe"""
while True:
buf = pipe.read(4096)
if not buf:
break
def set_freq(pipe, freq):
+ """Set the frequency of the radio on @pipe to @freq"""
freqbcd = util.bcd_encode(freq, bigendian=False, width=9)
buf = "\x01\x7f\x05" + freqbcd
@@ -78,6 +81,7 @@
raise errors.InvalidDataError("Repeater reported error")
def get_freq(pipe):
+ """Get the frequency of the radio attached to @pipe"""
buf = "\x01\x7f\x1a\x09"
drain(pipe)
@@ -103,10 +107,8 @@
"ctone", "dtcs", "tmode", "dtcs_polarity", "skip", "duplex",
"offset", "mode", "tuning_step", "bank_index"]
-class IcomRepeater(chirp_common.LiveRadio):
- pass
-
-class IDRPx000V(IcomRepeater):
+class IDRPx000V(chirp_common.LiveRadio):
+ """Icom IDRP-*"""
BAUD_RATE = 19200
VENDOR = "Icom"
MODEL = "ID-2000V/4000V/2D/2V"
@@ -154,7 +156,11 @@
set_freq(self.pipe, mem.freq)
+def do_test():
+ """Get the frequency of /dev/icom"""
+ ser = serial.Serial(port="/dev/icom", baudrate=19200, timeout=0.5)
+ #set_freq(pipe, 439.920)
+ get_freq(ser)
+
if __name__ == "__main__":
- pipe = serial.Serial(port="/dev/icom", baudrate=19200, timeout=0.5)
- #set_freq(pipe, 439.920)
- get_freq(pipe)
+ do_test()
diff -r db82df47f205 -r f805c420592f chirp/import_logic.py
--- a/chirp/import_logic.py Fri Apr 27 14:35:40 2012 -0700
+++ b/chirp/import_logic.py Fri Apr 27 14:35:41 2012 -0700
@@ -16,12 +16,15 @@
from chirp import chirp_common, errors
class ImportError(Exception):
+ """An import error"""
pass
class DestNotCompatible(ImportError):
+ """Memory is not compatible with the destination radio"""
pass
def ensure_has_calls(radio, memory):
+ """Make sure @radio has the necessary D-STAR callsigns for @memory"""
ulist_changed = rlist_changed = False
ulist = radio.get_urcall_list()
@@ -59,10 +62,10 @@
radio.set_repeater_cal_list(rlist)
# Filter the name according to the destination's rules
-def _import_name(dst_radio, srcrf, mem):
+def _import_name(dst_radio, _srcrf, mem):
mem.name = dst_radio.filter_name(mem.name)
-def _import_power(dst_radio, srcrf, mem):
+def _import_power(dst_radio, _srcrf, mem):
levels = dst_radio.get_features().valid_power_levels
if not levels:
mem.power = None
@@ -101,6 +104,8 @@
mem.ctone = mem.rtone
def import_mem(dst_radio, src_features, src_mem, overrides={}):
+ """Perform import logic to create a destination memory from
+ src_mem that will be compatible with @dst_radio"""
dst_rf = dst_radio.get_features()
if isinstance(src_mem, chirp_common.DVMemory):
@@ -123,10 +128,10 @@
dst_mem.__dict__[k] = v
msgs = dst_radio.validate_memory(dst_mem)
- errors = [x for x in msgs if isinstance(x, chirp_common.ValidationError)]
- if errors:
+ errs = [x for x in msgs if isinstance(x, chirp_common.ValidationError)]
+ if errs:
raise DestNotCompatible("Unable to create import memory: %s" %\
- ", ".join(errors))
+ ", ".join(errs))
return dst_mem
diff -r db82df47f205 -r f805c420592f chirp/kenwood_hmk.py
--- a/chirp/kenwood_hmk.py Fri Apr 27 14:35:40 2012 -0700
+++ b/chirp/kenwood_hmk.py Fri Apr 27 14:35:41 2012 -0700
@@ -14,16 +14,17 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
-import os
import csv
from chirp import chirp_common, errors, directory, generic_csv
class OmittedHeaderError(Exception):
+ """An internal exception to indicate that a header was omitted"""
pass
@directory.register
class HMKRadio(generic_csv.CSVRadio):
+ """Kenwood HMK format"""
VENDOR = "Kenwood"
MODEL = "HMK"
FILE_EXTENSION = "hmk"
diff -r db82df47f205 -r f805c420592f chirp/kenwood_live.py
--- a/chirp/kenwood_live.py Fri Apr 27 14:35:40 2012 -0700
+++ b/chirp/kenwood_live.py Fri Apr 27 14:35:41 2012 -0700
@@ -23,8 +23,10 @@
import sys
sys.path.insert(0, "..")
-from chirp import chirp_common, errors, directory
-from chirp.settings import *
+from chirp import chirp_common, errors, directory, util
+from chirp.settings import RadioSetting, RadioSettingGroup, \
+ RadioSettingValueInteger, RadioSettingValueBoolean, \
+ RadioSettingValueString, RadioSettingValueList
DEBUG = True
@@ -35,31 +37,24 @@
THF6_MODES = ["FM", "WFM", "AM", "LSB", "USB", "CW"]
-def rev(hash, value):
- reverse = {}
- for k, v in hash.items():
- reverse[v] = k
-
- return reverse[value]
-
LOCK = threading.Lock()
-def command(s, command, *args):
+def command(ser, cmd, *args):
+ """Send @cmd to radio via @ser"""
global LOCK
start = time.time()
LOCK.acquire()
- cmd = command
if args:
cmd += " " + " ".join(args)
if DEBUG:
print "PC->RADIO: %s" % cmd
- s.write(cmd + "\r")
+ ser.write(cmd + "\r")
result = ""
while not result.endswith("\r"):
- result += s.read(8)
+ result += ser.read(8)
if (time.time() - start) > 0.5:
print "Timeout waiting for data"
break
@@ -72,7 +67,8 @@
return result.strip()
LAST_BAUD = 9600
-def get_id(s):
+def get_id(ser):
+ """Get the ID of the radio attached to @ser"""
global LAST_BAUD
bauds = [9600, 19200, 38400, 57600]
bauds.remove(LAST_BAUD)
@@ -80,17 +76,18 @@
for i in bauds:
print "Trying ID at baud %i" % i
- s.setBaudrate(i)
- s.write("\r")
- s.read(25)
- r = command(s, "ID")
- if " " in r:
+ ser.setBaudrate(i)
+ ser.write("\r")
+ ser.read(25)
+ resp = command(ser, "ID")
+ if " " in resp:
LAST_BAUD = i
- return r.split(" ")[1]
+ return resp.split(" ")[1]
raise errors.RadioError("No response from radio")
def get_tmode(tone, ctcss, dcs):
+ """Get the tone mode based on the values of the tone, ctcss, dcs"""
if dcs and int(dcs) == 1:
return "DTCS"
elif int(ctcss):
@@ -101,9 +98,11 @@
return ""
def iserr(result):
+ """Returns True if the @result from a radio is an error"""
return result in ["N", "?"]
class KenwoodLiveRadio(chirp_common.LiveRadio):
+ """Base class for all live-mode kenwood radios"""
BAUD_RATE = 9600
VENDOR = "Kenwood"
MODEL = ""
@@ -178,9 +177,9 @@
if " " in result:
value = result.split(" ", 1)[1]
if value.count(",") == 2:
- zero, loc, mem.name = value.split(",")
+ _zero, _loc, mem.name = value.split(",")
else:
- loc, mem.name = value.split(",")
+ _loc, mem.name = value.split(",")
if mem.duplex == "" and self._kenwood_split:
result = command(self.pipe, *self._cmd_get_split(number))
@@ -212,7 +211,6 @@
spec = ",".join(spec)
r1 = command(self.pipe, *self._cmd_set_memory(memory.number, spec))
if not iserr(r1):
- import time
time.sleep(0.5)
r2 = command(self.pipe, *self._cmd_set_memory_name(memory.number,
memory.name))
@@ -238,8 +236,8 @@
if not self.__memcache.has_key(number):
return
- r = command(self.pipe, *self._cmd_set_memory(number, ""))
- if iserr(r):
+ resp = command(self.pipe, *self._cmd_set_memory(number, ""))
+ if iserr(resp):
raise errors.RadioError("Radio refused delete of %i" % number)
del self.__memcache[number]
@@ -271,6 +269,7 @@
@directory.register
class THD7Radio(KenwoodLiveRadio):
+ """Kenwood TH-D7"""
MODEL = "TH-D7"
_kenwood_split = True
@@ -294,7 +293,7 @@
def _make_mem_spec(self, mem):
if mem.duplex in " -+":
- duplex = rev(DUPLEX, mem.duplex)
+ duplex = util.get_dict_rev(DUPLEX, mem.duplex)
offset = mem.offset
else:
duplex = 0
@@ -312,7 +311,7 @@
"", # DCS Code
"%02i" % (self._kenwood_valid_tones.index(mem.ctone) + 1),
"%09i" % offset,
- "%i" % rev(MODES, mem.mode),
+ "%i" % util.get_dict_rev(MODES, mem.mode),
"%i" % ((mem.skip == "S") and 1 or 0))
return spec
@@ -341,15 +340,15 @@
return mem
def _kenwood_get(self, cmd):
- r = command(self.pipe, cmd)
- if " " in r:
- return r.split(" ", 1)
+ resp = command(self.pipe, cmd)
+ if " " in resp:
+ return resp.split(" ", 1)
else:
raise errors.RadioError("Radio refused to return %s" % cmd)
def _kenwood_set(self, cmd, value):
- r = command(self.pipe, cmd, value)
- if " " in r:
+ resp = command(self.pipe, cmd, value)
+ if " " in resp:
return
raise errors.RadioError("Radio refused to set %s" % cmd)
@@ -377,7 +376,7 @@
aux, tnc, save, display, dtmf)
sky = RadioSettingGroup("sky", "SkyCommand")
aprs = RadioSettingGroup("aprs", "APRS")
- all = RadioSettingGroup("top", "All Settings", radio, aprs, sky)
+ top = RadioSettingGroup("top", "All Settings", radio, aprs, sky)
bools = [("AMR", aprs, "APRS Message Auto-Reply"),
("AIP", aux, "Advanced Intercept Point"),
@@ -394,9 +393,9 @@
for setting, group, name in bools:
value = self._kenwood_get_bool(setting)
- s = RadioSetting(setting, name,
- RadioSettingValueBoolean(value))
- group.append(s)
+ rs = RadioSetting(setting, name,
+ RadioSettingValueBoolean(value))
+ group.append(rs)
lists = [("BAL", all, "Balance"),
("BEP", aux, "Beep"),
@@ -420,18 +419,18 @@
for setting, group, name in lists:
value = self._kenwood_get_int(setting)
options = TH_D7_SETTINGS[setting]
- s = RadioSetting(setting, name,
- RadioSettingValueList(options,
- options[value]))
- group.append(s)
+ rs = RadioSetting(setting, name,
+ RadioSettingValueList(options,
+ options[value]))
+ group.append(rs)
ints = [("CNT", display, "Contrast", 1, 16),
]
- for setting, group, name, min, max in ints:
+ for setting, group, name, minv, maxv in ints:
value = self._kenwood_get_int(setting)
- s = RadioSetting(setting, name,
- RadioSettingValueInteger(min, max, value))
- group.append(s)
+ rs = RadioSetting(setting, name,
+ RadioSettingValueInteger(minv, maxv, value))
+ group.append(rs)
strings = [("MES", display, "Power-on Message", 8),
("MYC", aprs, "APRS Callsign", 8),
@@ -442,11 +441,11 @@
]
for setting, group, name, length in strings:
_cmd, value = self._kenwood_get(setting)
- s = RadioSetting(setting, name,
- RadioSettingValueString(0, length, value))
- group.append(s)
+ rs = RadioSetting(setting, name,
+ RadioSettingValueString(0, length, value))
+ group.append(rs)
- return all
+ return top
def set_settings(self, settings):
for element in settings:
@@ -471,10 +470,12 @@
@directory.register
class THD7GRadio(THD7Radio):
+ """Kenwood TH-D7G"""
MODEL = "TH-D7G"
@directory.register
class TMD700Radio(KenwoodLiveRadio):
+ """Kenwood TH-D700"""
MODEL = "TM-D700"
_kenwood_split = True
@@ -497,7 +498,7 @@
def _make_mem_spec(self, mem):
if mem.duplex in " -+":
- duplex = rev(DUPLEX, mem.duplex)
+ duplex = util.get_dict_rev(DUPLEX, mem.duplex)
else:
duplex = 0
spec = ( \
@@ -512,7 +513,7 @@
"%03i0" % (chirp_common.DTCS_CODES.index(mem.dtcs) + 1),
"%02i" % (self._kenwood_valid_tones.index(mem.ctone) + 1),
"%09i" % mem.offset,
- "%i" % rev(MODES, mem.mode),
+ "%i" % util.get_dict_rev(MODES, mem.mode),
"%i" % ((mem.skip == "S") and 1 or 0))
return spec
@@ -555,6 +556,7 @@
@directory.register
class TMV7Radio(KenwoodLiveRadio):
+ """Kenwood TM-V7"""
MODEL = "TM-V7"
mem_upper_limit = 200 # Will be updated
@@ -592,7 +594,7 @@
spec = ( \
"%011i" % mem.freq,
"%X" % STEPS.index(mem.tuning_step),
- "%i" % rev(DUPLEX, mem.duplex),
+ "%i" % util.get_dict_rev(DUPLEX, mem.duplex),
"0",
"%i" % (mem.tmode == "Tone"),
"%i" % (mem.tmode == "TSQL"),
@@ -637,14 +639,14 @@
mem.empty = False
try:
self.set_memory(mem)
- except:
+ except Exception:
# Failed, so we're past the limit
return False
# Erase what we did
try:
self.erase_memory(loc)
- except:
+ except Exception:
pass # V7A Can't delete just yet
return True
@@ -653,20 +655,24 @@
return 50
class TMV7RadioSub(TMV7Radio):
+ """Base class for the TM-V7 sub devices"""
def __init__(self, pipe):
- KenwoodLiveRadio.__init__(self, pipe)
+ TMV7Radio.__init__(self, pipe)
self._detect_split()
class TMV7RadioVHF(TMV7RadioSub):
+ """TM-V7 VHF subdevice"""
VARIANT = "VHF"
_vfo = 0
class TMV7RadioUHF(TMV7RadioSub):
+ """TM-V7 UHF subdevice"""
VARIANT = "UHF"
_vfo = 1
@directory.register
class TMG707Radio(TMV7Radio):
+ """Kenwood TM-G707"""
MODEL = "TM-G707"
def get_features(self):
@@ -677,13 +683,15 @@
(430000000, 450000000)]
return rf
-THF6A_STEPS = [5.0, 6.25, 8.33, 9.0, 10.0, 12.5, 15.0, 20.0, 25.0, 30.0, 50.0, 100.0]
+THF6A_STEPS = [5.0, 6.25, 8.33, 9.0, 10.0, 12.5, 15.0, 20.0, 25.0, 30.0, 50.0,
+ 100.0]
THF6A_DUPLEX = dict(DUPLEX)
THF6A_DUPLEX[3] = "split"
@directory.register
class THF6ARadio(KenwoodLiveRadio):
+ """Kenwood TH-F6"""
MODEL = "TH-F6"
_upper = 399
@@ -751,7 +759,7 @@
def _make_mem_spec(self, mem):
if mem.duplex in " +-":
- duplex = rev(THF6A_DUPLEX, mem.duplex)
+ duplex = util.get_dict_rev(THF6A_DUPLEX, mem.duplex)
offset = mem.offset
elif mem.duplex == "split":
duplex = 0
@@ -777,6 +785,7 @@
@directory.register
class THF7ERadio(THF6ARadio):
+ """Kenwood TH-F7"""
MODEL = "TH-F7"
D710_DUPLEX = ["", "+", "-", "split"]
@@ -786,6 +795,7 @@
@directory.register
class TMD710Radio(KenwoodLiveRadio):
+ """Kenwood TM-D710"""
MODEL = "TM-D710"
_upper = 999
@@ -846,11 +856,11 @@
return mem
def _make_mem_spec(self, mem):
- print "Index %i for step %.2f" % (chirp_common.TUNING_STEPS.index(mem.tuning_step), mem.tuning_step)
spec = ( \
"%010i" % mem.freq,
"%X" % D710_STEPS.index(mem.tuning_step),
- "%i" % (0 if mem.duplex == "split" else D710_DUPLEX.index(mem.duplex)),
+ "%i" % (0 if mem.duplex == "split" else \
+ D710_DUPLEX.index(mem.duplex)),
"0", # Reverse
"%i" % (mem.tmode == "Tone" and 1 or 0),
"%i" % (mem.tmode == "TSQL" and 1 or 0),
@@ -860,7 +870,7 @@
"%03i" % (chirp_common.DTCS_CODES.index(mem.dtcs)),
"%08i" % (0 if mem.duplex == "split" else mem.offset), # Offset
"%i" % D710_MODES.index(mem.mode),
- "%010i" % (mem.offset if mem.duplex == "split" else 0), # TX Frequency
+ "%010i" % (mem.offset if mem.duplex == "split" else 0), # TX Freq
"0", # Unknown
"%i" % D710_SKIP.index(mem.skip), # Memory Lockout
)
@@ -869,6 +879,7 @@
@directory.register
class THD72Radio(TMD710Radio):
+ """Kenwood TH-D72"""
MODEL = "TH-D72"
HARDWARE_FLOW = True
@@ -901,11 +912,11 @@
return mem
def _make_mem_spec(self, mem):
- print "Index %i for step %.2f" % (chirp_common.TUNING_STEPS.index(mem.tuning_step), mem.tuning_step)
spec = ( \
"%010i" % mem.freq,
"%X" % D710_STEPS.index(mem.tuning_step),
- "%i" % (0 if mem.duplex == "split" else D710_DUPLEX.index(mem.duplex)),
+ "%i" % (0 if mem.duplex == "split" else \
+ D710_DUPLEX.index(mem.duplex)),
"0", # Reverse
"%i" % (mem.tmode == "Tone" and 1 or 0),
"%i" % (mem.tmode == "TSQL" and 1 or 0),
@@ -917,7 +928,7 @@
"0",
"%08i" % (0 if mem.duplex == "split" else mem.offset), # Offset
"%i" % D710_MODES.index(mem.mode),
- "%010i" % (mem.offset if mem.duplex == "split" else 0), # TX Frequency
+ "%010i" % (mem.offset if mem.duplex == "split" else 0), # TX Freq
"0", # Unknown
"%i" % D710_SKIP.index(mem.skip), # Memory Lockout
)
@@ -926,7 +937,8 @@
@directory.register
class TMV71Radio(TMD710Radio):
- MODEL = "TM-V71"
+ """Kenwood TM-V71"""
+ MODEL = "TM-V71"
THK2_DUPLEX = ["", "+", "-"]
THK2_MODES = ["FM", "NFM"]
@@ -944,6 +956,7 @@
@directory.register
class THK2Radio(KenwoodLiveRadio):
+ """Kenwood TH-K2"""
MODEL = "TH-K2"
_kenwood_valid_tones = list(THK2_TONES)
@@ -1028,6 +1041,7 @@
@directory.register
class TM271Radio(THK2Radio):
+ """Kenwood TM-271"""
MODEL = "TM-271"
def get_features(self):
@@ -1059,26 +1073,35 @@
def _cmd_set_memory_name(self, number, name):
return "MN", "%03i,%s" % (number, name)
-if __name__ == "__main__":
- m = chirp_common.Memory()
- m.number = 1
- m.freq = 144000000
- m.duplex = "split"
- m.offset = 146000000
+def do_test():
+ """Dev test"""
+ mem = chirp_common.Memory()
+ mem.number = 1
+ mem.freq = 144000000
+ mem.duplex = "split"
+ mem.offset = 146000000
- TestClass = THF6ARadio
+ tc = THF6ARadio
class FakeSerial:
+ """Faked serial line"""
buf = ""
def write(self, buf):
+ """Write"""
self.buf = buf
def read(self, count):
+ """Read"""
if self.buf[:2] == "ID":
return "ID %s\r" % TestClass.MODEL
return self.buf
def setTimeout(self, foo):
+ """Set Timeout"""
pass
def setBaudrate(self, foo):
+ """Set Baudrate"""
pass
- r = TestClass(FakeSerial())
- r.set_memory(m)
+ radio = tc(FakeSerial())
+ radio.set_memory(mem)
+
+if __name__ == "__main__":
+ do_test()
diff -r db82df47f205 -r f805c420592f chirp/memmap.py
--- a/chirp/memmap.py Fri Apr 27 14:35:40 2012 -0700
+++ b/chirp/memmap.py Fri Apr 27 14:35:41 2012 -0700
@@ -24,6 +24,7 @@
self._data = list(data)
def printable(self, start=None, end=None, printit=True):
+ """Return a printable representation of the memory map"""
if not start:
start = 0
@@ -38,12 +39,14 @@
return string
def get(self, start, length=1):
+ """Return a chunk of memory of @length bytes from @start"""
if start == -1:
return "".join(self._data[start:])
else:
return "".join(self._data[start:start+length])
def set(self, pos, value):
+ """Set a chunk of memory at @pos to @value"""
if isinstance(value, int):
self._data[pos] = chr(value)
elif isinstance(value, str):
@@ -55,6 +58,7 @@
type(value).__name__)
def get_packed(self):
+ """Return the entire memory map as raw data"""
return "".join(self._data)
def __len__(self):
@@ -80,4 +84,5 @@
return self.printable(printit=False)
def truncate(self, size):
+ """Truncate the memory map to @size"""
self._data = self._data[:size]
diff -r db82df47f205 -r f805c420592f chirp/platform.py
--- a/chirp/platform.py Fri Apr 27 14:35:40 2012 -0700
+++ b/chirp/platform.py Fri Apr 27 14:35:41 2012 -0700
@@ -1,19 +1,3 @@
-# Copyright 2008 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/>.
-
-#
# Copyright 2008 Dan Smith <dsmith at danplanet.com>
#
# This program is free software: you can redistribute it and/or modify
@@ -34,26 +18,30 @@
import glob
from subprocess import Popen
-def find_me():
+def _find_me():
return sys.modules["chirp.platform"].__file__
class Platform:
- # pylint: disable-msg=R0201
+ """Base class for platform-specific functions"""
def __init__(self, basepath):
self._base = basepath
self._last_dir = self.default_dir()
def get_last_dir(self):
+ """Return the last directory used"""
return self._last_dir
def set_last_dir(self, last_dir):
+ """Set the last directory used"""
self._last_dir = last_dir
def config_dir(self):
+ """Return the preferred configuration file directory"""
return self._base
def log_dir(self):
+ """Return the preferred log file directory"""
logdir = os.path.join(self.config_dir(), "logs")
if not os.path.isdir(logdir):
os.mkdir(logdir)
@@ -61,29 +49,37 @@
return logdir
def filter_filename(self, filename):
+ """Filter @filename for platform-forbidden characters"""
return filename
def log_file(self, filename):
+ """Return the full path to a log file with @filename"""
filename = self.filter_filename(filename + ".txt").replace(" ", "_")
return os.path.join(self.log_dir(), filename)
def config_file(self, filename):
+ """Return the full path to a config file with @filename"""
return os.path.join(self.config_dir(),
self.filter_filename(filename))
def open_text_file(self, path):
+ """Spawn the necessary program to open a text file at @path"""
raise NotImplementedError("The base class can't do that")
def open_html_file(self, path):
+ """Spawn the necessary program to open an HTML file at @path"""
raise NotImplementedError("The base class can't do that")
def list_serial_ports(self):
+ """Return a list of valid serial ports"""
return []
def default_dir(self):
+ """Return the default directory for this platform"""
return "."
def gui_open_file(self, start_dir=None, types=[]):
+ """Prompt the user to pick a file to open"""
import gtk
if not start_dir:
@@ -114,6 +110,7 @@
return None
def gui_save_file(self, start_dir=None, default_name=None, types=[]):
+ """Prompt the user to pick a filename to save"""
import gtk
if not start_dir:
@@ -154,6 +151,7 @@
return None
def gui_select_dir(self, start_dir=None):
+ """Prompt the user to pick a directory"""
import gtk
if not start_dir:
@@ -178,9 +176,11 @@
return None
def os_version_string(self):
+ """Return a string that describes the OS/platform version"""
return "Unknown Operating System"
def executable_path(self):
+ """Return a full path to the program executable"""
def we_are_frozen():
return hasattr(sys, "frozen")
@@ -190,7 +190,8 @@
sys.getfilesystemencoding()))
else:
# UNIX: Find the parent directory of this module
- return os.path.dirname(os.path.abspath(os.path.join(find_me(), "..")))
+ return os.path.dirname(os.path.abspath(os.path.join(_find_me(),
+ "..")))
def _unix_editor():
macos_textedit = "/Applications/TextEdit.app/Contents/MacOS/TextEdit"
@@ -201,6 +202,7 @@
return "gedit"
class UnixPlatform(Platform):
+ """A platform module suitable for UNIX systems"""
def __init__(self, basepath):
if not basepath:
basepath = os.path.abspath(os.path.join(self.default_dir(),
@@ -214,7 +216,7 @@
# This is a hack that needs to be properly fixed by importing the
# latest changes to this module from d-rats. In the interest of
# time, however, I'll throw it here
- if sys.platform == "darwin":
+ if sys.platform == "darwin":
if not os.environ.has_key("DISPLAY"):
print "Forcing DISPLAY for MacOS"
os.environ["DISPLAY"] = ":0"
@@ -252,7 +254,6 @@
glob.glob("/dev/tty.KeySerial*"))
def os_version_string(self):
- # pylint: disable-msg=W0703
try:
issue = file("/etc/issue.net", "r")
ver = issue.read().strip().replace("\r", "").replace("\n", "")[:64]
@@ -264,6 +265,7 @@
return ver
class Win32Platform(Platform):
+ """A platform module suitable for Windows systems"""
def __init__(self, basepath=None):
if not basepath:
appdata = os.getenv("APPDATA")
@@ -319,7 +321,6 @@
return ports
def gui_open_file(self, start_dir=None, types=[]):
- # pylint: disable-msg=W0703,W0613
import win32gui
typestrs = ""
@@ -337,11 +338,10 @@
return str(fname)
def gui_save_file(self, start_dir=None, default_name=None, types=[]):
- # pylint: disable-msg=W0703,W0613
import win32gui
import win32api
- (pform, _, build, _, _) = win32api.GetVersionEx()
+ (pform, _, _, _, _) = win32api.GetVersionEx()
typestrs = ""
custom = "%s\0*.%s\0" % (types[0][0], types[0][1])
@@ -358,10 +358,10 @@
def_ext = "*.%s" % types[0][1]
try:
- fname, filter, _ = win32gui.GetSaveFileNameW(File=default_name,
- CustomFilter=custom,
- DefExt=def_ext,
- Filter=typestrs)
+ fname, _, _ = win32gui.GetSaveFileNameW(File=default_name,
+ CustomFilter=custom,
+ DefExt=def_ext,
+ Filter=typestrs)
except Exception, e:
print "Failed to get filename: %s" % e
return None
@@ -369,7 +369,6 @@
return str(fname)
def gui_select_dir(self, start_dir=None):
- # pylint: disable-msg=W0703,W0613
from win32com.shell import shell
try:
@@ -401,8 +400,7 @@
PLATFORM = None
def get_platform(basepath=None):
- #pylint: disable-msg=W0602
-
+ """Return the platform singleton"""
global PLATFORM
if not PLATFORM:
@@ -410,19 +408,19 @@
return PLATFORM
+def _do_test():
+ __pform = get_platform()
+
+ print "Config dir: %s" % __pform.config_dir()
+ print "Default dir: %s" % __pform.default_dir()
+ print "Log file (foo): %s" % __pform.log_file("foo")
+ print "Serial ports: %s" % __pform.list_serial_ports()
+ print "OS Version: %s" % __pform.os_version_string()
+ #__pform.open_text_file("d-rats.py")
+
+ #print "Open file: %s" % __pform.gui_open_file()
+ #print "Save file: %s" % __pform.gui_save_file(default_name="Foo.txt")
+ print "Open folder: %s" % __pform.gui_select_dir("/tmp")
+
if __name__ == "__main__":
- def do_test():
- __pform = get_platform()
-
- print "Config dir: %s" % __pform.config_dir()
- print "Default dir: %s" % __pform.default_dir()
- print "Log file (foo): %s" % __pform.log_file("foo")
- print "Serial ports: %s" % __pform.list_serial_ports()
- print "OS Version: %s" % __pform.os_version_string()
- #__pform.open_text_file("d-rats.py")
-
- #print "Open file: %s" % __pform.gui_open_file()
- #print "Save file: %s" % __pform.gui_save_file(default_name="Foo.txt")
- print "Open folder: %s" % __pform.gui_select_dir("/tmp")
-
- do_test()
+ _do_test()
diff -r db82df47f205 -r f805c420592f chirp/radioreference.py
--- a/chirp/radioreference.py Fri Apr 27 14:35:40 2012 -0700
+++ b/chirp/radioreference.py Fri Apr 27 14:35:41 2012 -0700
@@ -13,7 +13,7 @@
# 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 chirp_common, CHIRP_VERSION, errors
+from chirp import chirp_common, errors
try:
from suds.client import Client
HAVE_SUDS = True
@@ -31,6 +31,7 @@
}
class RadioReferenceRadio(chirp_common.NetworkSourceRadio):
+ """RadioReference.com data source"""
VENDOR = "Radio Reference LLC"
MODEL = "RadioReference.com"
@@ -38,7 +39,7 @@
APPKEY = "46785108"
def __init__(self, *args, **kwargs):
- chirp_common.Radio.__init__(self, *args, **kwargs)
+ chirp_common.NetworkSourceRadio.__init__(self, *args, **kwargs)
if not HAVE_SUDS:
raise errors.RadioError(
@@ -49,9 +50,11 @@
self._client = Client(self.URL)
self._freqs = None
self._modes = None
+ self._zip = None
- def set_params(self, zip, username, password):
- self._zip = zip
+ def set_params(self, zipcode, username, password):
+ """Set the parameters to be used for a query"""
+ self._zip = zipcode
self._auth["username"] = username
self._auth["password"] = password
@@ -72,7 +75,8 @@
print "Fetching category:", cat.cName
for subcat in cat.subcats:
print "\t", subcat.scName
- result = self._client.service.getSubcatFreqs(subcat.scid, self._auth)
+ result = self._client.service.getSubcatFreqs(subcat.scid,
+ self._auth)
self._freqs += result
status.cur += 1
self.status_fn(status)
@@ -85,7 +89,8 @@
print "Fetching category:", cat.cName
for subcat in cat.subcats:
print "\t", subcat.scName
- result = self._client.service.getSubcatFreqs(subcat.scid, self._auth)
+ result = self._client.service.getSubcatFreqs(subcat.scid,
+ self._auth)
self._freqs += result
status.cur += 1
self.status_fn(status)
@@ -126,7 +131,7 @@
else:
try:
tone, tmode = freq.tone.split(" ")
- except:
+ except Exception:
tone, tmode = None, None
if tmode == "PL":
mem.tmode = "TSQL"
@@ -164,7 +169,9 @@
"""
import sys
rrr = RadioReferenceRadio(None)
- rrr.set_params(zip=sys.argv[1], username=sys.argv[2], password=sys.argv[3])
+ rrr.set_params(zipcode=sys.argv[1],
+ username=sys.argv[2],
+ password=sys.argv[3])
rrr.do_fetch()
print rrr.get_raw_memory(0)
print rrr.get_memory(0)
diff -r db82df47f205 -r f805c420592f chirp/rfinder.py
--- a/chirp/rfinder.py Fri Apr 27 14:35:40 2012 -0700
+++ b/chirp/rfinder.py Fri Apr 27 14:35:41 2012 -0700
@@ -17,7 +17,7 @@
import hashlib
import re
-from math import pi,cos,acos,sin,atan2
+from math import pi, cos, acos, sin, atan2
from chirp import chirp_common, CHIRP_VERSION
@@ -48,46 +48,55 @@
]
def deg2rad(deg):
+ """Convert degrees to radians"""
return deg * (pi / 180)
def rad2deg(rad):
+ """Convert radians to degrees"""
return rad / (pi / 180)
-def dm2deg(deg, min):
- return deg + (min / 60.0)
+def dm2deg(degrees, minutes):
+ """Convert degrees and minutes to decimal degrees"""
+ return degrees + (minutes / 60.0)
def deg2dm(decdeg):
- deg = int(decdeg)
- min = (decdeg - deg) * 60.0
+ """Convert decimal degrees to degrees and minutes"""
+ degrees = int(decdeg)
+ minutes = (decdeg - degrees) * 60.0
- return deg, min
+ return degrees, minutes
-def nmea2deg(nmea, dir="N"):
+def nmea2deg(nmea, direction="N"):
+ """Convert NMEA-encoded value to float"""
deg = int(nmea) / 100
try:
- min = nmea % (deg * 100)
- except ZeroDivisionError, e:
- min = int(nmea)
+ minutes = nmea % (deg * 100)
+ except ZeroDivisionError:
+ minutes = int(nmea)
- if dir == "S" or dir == "W":
- m = -1
+ if direction == "S" or direction == "W":
+ sign = -1
else:
- m = 1
+ sign = 1
- return dm2deg(deg, min) * m
+ return dm2deg(deg, minutes) * sign
def deg2nmea(deg):
- deg, min = deg2dm(deg)
+ """Convert degrees to a NMEA-encoded value"""
+ degrees, minutes = deg2dm(deg)
- return (deg * 100) + min
+ return (degrees * 100) + minutes
def meters2feet(meters):
+ """Convert meters to feet"""
return meters * 3.2808399
def feet2meters(feet):
+ """Convert feet to meters"""
return feet * 0.3048
def distance(lat_a, lon_a, lat_b, lon_b):
+ """Calculate the distance between two points"""
lat_a = deg2rad(lat_a)
lon_a = deg2rad(lon_a)
@@ -108,30 +117,27 @@
elif tmp < -1:
tmp = -1
- distance = acos(tmp)
+ dist = acos(tmp)
- return distance * earth_radius
+ return dist * earth_radius
def bearing(lat_a, lon_a, lat_b, lon_b):
+ """Calculate the bearing between two points"""
lat_me = deg2rad(lat_a)
- lon_me = deg2rad(lon_a)
-
lat_u = deg2rad(lat_b)
- lon_u = deg2rad(lon_b)
-
- lat_d = deg2rad(lat_b - lat_a)
lon_d = deg2rad(lon_b - lon_a)
- y = sin(lon_d) * cos(lat_u)
- x = cos(lat_me) * sin(lat_u) - \
+ posy = sin(lon_d) * cos(lat_u)
+ posx = cos(lat_me) * sin(lat_u) - \
sin(lat_me) * cos(lat_u) * cos(lon_d)
- bearing = rad2deg(atan2(y, x))
+ bear = rad2deg(atan2(posy, posx))
- return (bearing + 360) % 360
+ return (bear + 360) % 360
def fuzzy_to(lat_a, lon_a, lat_b, lon_b):
- dir = bearing(lat_a, lon_a, lat_b, lon_b)
+ """Calculate a fuzzy distance to a point"""
+ bear = bearing(lat_a, lon_a, lat_b, lon_b)
dirs = ["N", "NNE", "NE", "ENE", "E",
"ESE", "SE", "SSE", "S",
@@ -143,27 +149,29 @@
direction = "?"
for i in dirs:
- if dir > angle and dir < (angle + delta):
+ if bear > angle and bear < (angle + delta):
direction = i
angle += delta
return direction
class RFinderParser:
+ """Parser for RFinder's data format"""
def __init__(self, lat, lon):
self.__memories = []
self.__cheat = {}
self.__lat = lat
self.__lon = lon
- def fetch_data(self, user, pw, lat, lon, radius):
+ def fetch_data(self, user, pw, coords, radius):
+ """Fetches the data for a set of parameters"""
print user
print pw
args = {
"email" : urllib.quote_plus(user),
"pass" : hashlib.md5(pw).hexdigest(),
- "lat" : "%7.5f" % lat,
- "lon" : "%8.5f" % lon,
+ "lat" : "%7.5f" % coords[0],
+ "lon" : "%8.5f" % coords[1],
"radius": "%i" % radius,
"vers" : "CH%s" % CHIRP_VERSION,
}
@@ -183,7 +191,7 @@
return data
- def parse_line(self, line):
+ def _parse_line(self, line):
mem = chirp_common.Memory()
_vals = line.split("|")
@@ -217,15 +225,16 @@
try:
lat = float(vals["LATITUDE"])
lon = float(vals["LONGITUDE"])
- d = distance(self.__lat, self.__lon, lat, lon)
- b = fuzzy_to(self.__lat, self.__lon, lat, lon)
- mem.comment = "(%imi %s) %s" % (d, b, mem.comment)
+ dist = distance(self.__lat, self.__lon, lat, lon)
+ bear = fuzzy_to(self.__lat, self.__lon, lat, lon)
+ mem.comment = "(%imi %s) %s" % (dist, bear, mem.comment)
except Exception, e:
print "Failed to calculate distance: %s" % e
return mem
def parse_data(self, data):
+ """Parse the fetched data"""
number = 1
for line in data.split("\n"):
if line.startswith("<"):
@@ -233,7 +242,7 @@
elif not line.strip():
continue
try:
- mem = self.parse_line(line)
+ mem = self._parse_line(line)
mem.number = number
number += 1
self.__memories.append(mem)
@@ -247,23 +256,27 @@
print "\n\n"
def get_memories(self):
+ """Return the Memory objects associated with the fetched data"""
return self.__memories
class RFinderRadio(chirp_common.NetworkSourceRadio):
+ """A network source radio that supports the RFinder repeater directory"""
VENDOR = "ITWeRKS"
MODEL = "RFinder"
def __init__(self, *args, **kwargs):
- chirp_common.Radio.__init__(self, *args, **kwargs)
+ chirp_common.NetworkSourceRadio.__init__(self, *args, **kwargs)
self._lat = 0
self._lon = 0
self._user = ""
self._pass = ""
+ self._miles = 25
self._rfp = None
- def set_params(self, lat, lon, miles, email, password):
+ def set_params(self, (lat, lon), miles, email, password):
+ """Sets the parameters to use for the query"""
self._lat = lat
self._lon = lon
self._miles = miles
@@ -275,8 +288,7 @@
self._rfp.parse_data(self._rfp.fetch_data(self._user,
self._pass,
- self._lat,
- self._lon,
+ (self._lat, self._lon),
self._miles))
def get_features(self):
@@ -297,12 +309,14 @@
return self._rfp.get_memories()[number-1]
-if __name__ == "__main__":
- import sys
-
+def _test():
rfp = RFinderParser()
- data = rfp.fetch_data(45.525, -122.9164, "KK7DS", "dsmith at danplanet.com")
+ data = rfp.fetch_data("KK7DS", "dsmith at danplanet.com",
+ (45.5, -122.91), 25)
rfp.parse_data(data)
- for m in rfp.get_memories():
- print m
+ for mem in rfp.get_memories():
+ print mem
+
+if __name__ == "__main__":
+ _test()
diff -r db82df47f205 -r f805c420592f chirp/settings.py
--- a/chirp/settings.py Fri Apr 27 14:35:40 2012 -0700
+++ b/chirp/settings.py Fri Apr 27 14:35:41 2012 -0700
@@ -16,25 +16,31 @@
from chirp import chirp_common
class InvalidValueError(Exception):
+ """An invalid value was specified for a given setting"""
pass
class InternalError(Exception):
+ """A driver provided an invalid settings object structure"""
pass
class RadioSettingValue:
+ """Base class for a single radio setting"""
def __init__(self):
self._current = None
self._has_changed = False
def changed(self):
+ """Returns True if the setting has been changed since init"""
return self._has_changed
def set_value(self, value):
+ """Sets the current value, triggers changed"""
if self._current != None and value != self._current:
self._has_changed = True
self._current = value
def get_value(self):
+ """Gets the current value"""
return self._current
def __trunc__(self):
@@ -44,10 +50,11 @@
return str(self.get_value())
class RadioSettingValueInteger(RadioSettingValue):
- def __init__(self, min, max, current, step=1):
+ """An integer setting"""
+ def __init__(self, minval, maxval, current, step=1):
RadioSettingValue.__init__(self)
- self._min = min
- self._max = max
+ self._min = minval
+ self._max = maxval
self._step = step
self.set_value(current)
@@ -63,15 +70,19 @@
RadioSettingValue.set_value(self, value)
def get_min(self):
+ """Returns the minimum allowed value"""
return self._min
def get_max(self):
+ """Returns the maximum allowed value"""
return self._max
def get_step(self):
+ """Returns the step increment"""
return self._step
class RadioSettingValueBoolean(RadioSettingValue):
+ """A boolean setting"""
def __init__(self, current):
RadioSettingValue.__init__(self)
self.set_value(current)
@@ -83,6 +94,7 @@
return str(bool(self.get_value()))
class RadioSettingValueList(RadioSettingValue):
+ """A list-of-strings setting"""
def __init__(self, options, current):
RadioSettingValue.__init__(self)
self._options = options
@@ -94,12 +106,14 @@
RadioSettingValue.set_value(self, value)
def get_options(self):
+ """Returns the list of valid option values"""
return self._options
def __trunc__(self):
return self._options.index(self._current)
class RadioSettingValueString(RadioSettingValue):
+ """A string setting"""
def __init__(self, minlength, maxlength, current,
autopad=True):
RadioSettingValue.__init__(self)
@@ -110,6 +124,7 @@
self.set_value(current)
def set_charset(self, charset):
+ """Sets the set of allowed characters"""
self._charset = charset
def set_value(self, value):
@@ -128,6 +143,7 @@
return self._current.rstrip()
class RadioSettingGroup(object):
+ """A group of settings"""
def _validate(self, element):
# RadioSettingGroup can only contain RadioSettingGroup objects
if not isinstance(element, RadioSettingGroup):
@@ -146,37 +162,43 @@
self.append(element)
def get_name(self):
+ """Returns the group name"""
return self._name
def get_shortname(self):
+ """Returns the short group identifier"""
return self._shortname
def set_doc(self, doc):
+ """Sets the docstring for the group"""
self.__doc__ = doc
def __str__(self):
- s = "{Settings Group %s:\n" % self._name
+ string = "{Settings Group %s:\n" % self._name
for element in self._elements.values():
- s += str(element) + "\n"
- s += "}"
- return s
+ string += str(element) + "\n"
+ string += "}"
+ return string
# Kinda list interface
def append(self, element):
+ """Adds an element to the group"""
self[element.get_name()] = element
def __iter__(self):
class RSGIterator:
+ """Iterator for a RadioSettingsGroup"""
def __init__(self, rsg):
self.__rsg = rsg
self.__i = 0
def __iter__(self):
return self
def next(self):
- if self.__i >= len(self.__rsg._element_order):
+ """Next Iterator Interface"""
+ if self.__i >= len(self.__rsg.keys()):
raise StopIteration()
- e = self.__rsg._elements[self.__rsg._element_order[self.__i]]
+ e = self.__rsg[self.__rsg.keys()[self.__i]]
self.__i += 1
return e
return RSGIterator(self)
@@ -196,21 +218,26 @@
self._element_order.append(name)
def items(self):
+ """Returns a key=>value set of elements, like a dict"""
return [(name, self._elements[name]) for name in self._element_order]
def keys(self):
+ """Returns a list of string element names"""
return self._element_order
def values(self):
- return [self.elements[name] for name in self._element_order]
+ """Returns the list of elements"""
+ return [self._elements[name] for name in self._element_order]
class RadioSetting(RadioSettingGroup):
+ """A single setting, which could be an array of items like a group"""
def _validate(self, value):
# RadioSetting can only contain RadioSettingValue objects
if not isinstance(value, RadioSettingValue):
raise InternalError("Incorrect type")
def changed(self):
+ """Returns True if any of the elements in the group have been changed"""
for element in self._elements.values():
if element.changed():
return True
diff -r db82df47f205 -r f805c420592f chirp/template.py
--- a/chirp/template.py Fri Apr 27 14:35:40 2012 -0700
+++ b/chirp/template.py Fri Apr 27 14:35:41 2012 -0700
@@ -13,7 +13,7 @@
# 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 chirp_common, yaesu_clone, util, directory, memmap
+from chirp import chirp_common, directory, memmap
from chirp import bitwise
# Here is where we define the memory map for the radio. Since
@@ -24,7 +24,7 @@
# With some very basic settings, a 32-bit unsigned integer for the
# frequency (in Hertz) and an eight-character alpha tag
#
-mem_format = """
+MEM_FORMAT = """
#seekto 0x0000;
struct {
u32 freq;
@@ -33,6 +33,7 @@
"""
def do_download(radio):
+ """This is your download function"""
# NOTE: Remove this in your real implementation!
return memmap.MemoryMap("\x00" * 1000)
@@ -43,12 +44,13 @@
# from the serial port. Do that one byte at a time and
# store them in the memory map
data = ""
- for i in range(0, 1000):
+ for _i in range(0, 1000):
data = serial.read(1)
return memmap.MemoryMap(data)
def do_upload(radio):
+ """This is your upload function"""
# NOTE: Remove this in your real implementation!
raise Exception("This template driver does not really work!")
@@ -59,11 +61,12 @@
# to the serial port. Do that one byte at a time, reading
# from our memory map
for i in range(0, 1000):
- serial.write(radio._mmap[i])
+ serial.write(radio.get_mmap()[i])
# Uncomment this to actually register this radio in CHIRP
# @directory.register
class TemplateRadio(chirp_common.CloneModeRadio):
+ """Acme Template"""
VENDOR = "Acme" # Replace this with your vendor
MODEL = "Template" # Replace this with your model
BAUD_RATE = 9600 # Replace this with your baud rate
@@ -82,7 +85,7 @@
# Do a download of the radio from the serial port
def sync_in(self):
self._mmap = do_download(self)
- self._memobj = bitwise.parse(mem_format, self._mmap)
+ self._memobj = bitwise.parse(MEM_FORMAT, self._mmap)
# Do an upload of the radio to the serial port
def sync_out(self):
diff -r db82df47f205 -r f805c420592f chirp/util.py
--- a/chirp/util.py Fri Apr 27 14:35:40 2012 -0700
+++ b/chirp/util.py Fri Apr 27 14:35:41 2012 -0700
@@ -16,6 +16,7 @@
import struct
def hexprint(data):
+ """Return a hexdump-like encoding of @data"""
line_sz = 8
lines = len(data) / line_sz
@@ -52,10 +53,8 @@
return out
-def write_in_place(mem, start, data):
- return mem[:start] + data + mem[start+len(data):]
-
def bcd_encode(val, bigendian=True, width=None):
+ """This is really old and shouldn't be used anymore"""
digits = []
while val != 0:
digits.append(val % 10)
@@ -78,8 +77,9 @@
return result
-def get_dict_rev(dict, key):
+def get_dict_rev(thedict, value):
+ """Return the first matching key for a given @value in @dict"""
_dict = {}
- for k,v in dict.items():
+ for k, v in thedict.items():
_dict[v] = k
- return _dict[key]
+ return _dict[value]
diff -r db82df47f205 -r f805c420592f chirp/uv5r.py
--- a/chirp/uv5r.py Fri Apr 27 14:35:40 2012 -0700
+++ b/chirp/uv5r.py Fri Apr 27 14:35:41 2012 -0700
@@ -15,11 +15,13 @@
import struct
-from chirp import chirp_common, errors, util, directory, memmap, settings
+from chirp import chirp_common, errors, util, directory, memmap
from chirp import bitwise
-from chirp.settings import *
+from chirp.settings import RadioSetting, RadioSettingGroup, \
+ RadioSettingValueInteger, RadioSettingValueList, \
+ RadioSettingValueList, RadioSettingValueBoolean
-mem_format = """
+MEM_FORMAT = """
#seekto 0x0008;
struct {
lbcd rxfreq[4];
@@ -83,31 +85,31 @@
"""
STEPS = [2.5, 5.0, 6.25, 10.0, 12.5, 25.0]
-step_list = [str(x) for x in STEPS]
-timeout_list = ["%s sec" % x for x in range(15, 615, 15)]
-resume_list = ["TO", "CO", "SE"]
-mode_list = ["Channel", "Name", "Frequency"]
-color_list = ["Off", "Blue", "Orange", "Purple"]
+STEP_LIST = [str(x) for x in STEPS]
+TIMEOUT_LIST = ["%s sec" % x for x in range(15, 615, 15)]
+RESUME_LIST = ["TO", "CO", "SE"]
+MODE_LIST = ["Channel", "Name", "Frequency"]
+COLOR_LIST = ["Off", "Blue", "Orange", "Purple"]
SETTING_LISTS = {
- "step" : step_list,
- "timeout" : timeout_list,
- "screv" : resume_list,
- "mdfa" : mode_list,
- "mdfb" : mode_list,
- "wtled" : color_list,
- "rxled" : color_list,
- "txled" : color_list,
+ "step" : STEP_LIST,
+ "timeout" : TIMEOUT_LIST,
+ "screv" : RESUME_LIST,
+ "mdfa" : MODE_LIST,
+ "mdfb" : MODE_LIST,
+ "wtled" : COLOR_LIST,
+ "rxled" : COLOR_LIST,
+ "txled" : COLOR_LIST,
}
-def do_status(radio, block):
- s = chirp_common.Status()
- s.msg = "Cloning"
- s.cur = block
- s.max = radio._memsize
- radio.status_fn(s)
+def _do_status(radio, block):
+ status = chirp_common.Status()
+ status.msg = "Cloning"
+ status.cur = block
+ status.max = radio.get_memsize()
+ radio.status_fn(status)
-def do_ident(radio):
+def _do_ident(radio):
serial = radio.pipe
serial.setTimeout(1)
@@ -130,12 +132,12 @@
return ident
-def do_download(radio):
+def _do_download(radio):
serial = radio.pipe
- data = do_ident(radio)
+ data = _do_ident(radio)
- for i in range(0, radio._memsize - 0x08, 0x40):
+ for i in range(0, radio.get_memsize() - 0x08, 0x40):
msg = struct.pack(">BHB", ord("S"), i, 0x40)
serial.write(msg)
@@ -162,23 +164,23 @@
if ack != "\x06":
raise errors.RadioError("Radio refused to send block 0x%04x" % i)
- do_status(radio, i)
+ _do_status(radio, i)
return memmap.MemoryMap(data)
-def do_upload(radio):
+def _do_upload(radio):
serial = radio.pipe
- do_ident(radio)
+ _do_ident(radio)
- for i in range(0x08, radio._memsize, 0x10):
+ for i in range(0x08, radio.get_memsize(), 0x10):
msg = struct.pack(">BHB", ord("X"), i - 0x08, 0x10)
- serial.write(msg + radio._mmap[i:i+0x10])
+ serial.write(msg + radio.get_mmap()[i:i+0x10])
ack = serial.read(1)
if ack != "\x06":
raise errors.RadioError("Radio refused to accept block 0x%04x" % i)
- do_status(radio, i)
+ _do_status(radio, i)
UV5R_POWER_LEVELS = [chirp_common.PowerLevel("High", watts=4.00),
chirp_common.PowerLevel("Low", watts=1.00)]
@@ -186,6 +188,7 @@
# Uncomment this to actually register this radio in CHIRP
@directory.register
class BaofengUV5R(chirp_common.CloneModeRadio):
+ """Baofeng UV-5R"""
VENDOR = "Baofeng"
MODEL = "UV-5R"
BAUD_RATE = 9600
@@ -212,12 +215,12 @@
return rf
def process_mmap(self):
- self._memobj = bitwise.parse(mem_format, self._mmap)
+ self._memobj = bitwise.parse(MEM_FORMAT, self._mmap)
print self.get_settings()
def sync_in(self):
try:
- self._mmap = do_download(self)
+ self._mmap = _do_download(self)
except errors.RadioError:
raise
except Exception, e:
@@ -226,7 +229,7 @@
def sync_out(self):
try:
- do_upload(self)
+ _do_upload(self)
except errors.RadioError:
raise
except Exception, e:
@@ -387,81 +390,81 @@
advanced = RadioSettingGroup("advanced", "Advanced Settings")
group = RadioSettingGroup("top", "All Settings", basic, advanced)
- s = RadioSetting("squelch", "Carrier Squelch Level",
- RadioSettingValueInteger(0, 9, _settings.squelch))
- basic.append(s)
+ rs = RadioSetting("squelch", "Carrier Squelch Level",
+ RadioSettingValueInteger(0, 9, _settings.squelch))
+ basic.append(rs)
- s = RadioSetting("step", "Tuning Step",
- RadioSettingValueList(step_list,
- step_list[_settings.step]))
- advanced.append(s)
+ rs = RadioSetting("step", "Tuning Step",
+ RadioSettingValueList(STEP_LIST,
+ STEP_LIST[_settings.step]))
+ advanced.append(rs)
- s = RadioSetting("save", "Battery Saver",
- RadioSettingValueInteger(0, 4, _settings.save))
- basic.append(s)
+ rs = RadioSetting("save", "Battery Saver",
+ RadioSettingValueInteger(0, 4, _settings.save))
+ basic.append(rs)
- s = RadioSetting("vox", "VOX Sensitivity",
- RadioSettingValueInteger(0, 10, _settings.vox))
- advanced.append(s)
+ rs = RadioSetting("vox", "VOX Sensitivity",
+ RadioSettingValueInteger(0, 10, _settings.vox))
+ advanced.append(rs)
- s = RadioSetting("abr", "Backlight Timeout",
- RadioSettingValueInteger(0, 5, _settings.abr))
- basic.append(s)
+ rs = RadioSetting("abr", "Backlight Timeout",
+ RadioSettingValueInteger(0, 5, _settings.abr))
+ basic.append(rs)
- s = RadioSetting("tdr", "Dual Watch",
- RadioSettingValueBoolean(_settings.tdr))
- advanced.append(s)
+ rs = RadioSetting("tdr", "Dual Watch",
+ RadioSettingValueBoolean(_settings.tdr))
+ advanced.append(rs)
- s = RadioSetting("beep", "Beep",
- RadioSettingValueBoolean(_settings.beep))
- basic.append(s)
+ rs = RadioSetting("beep", "Beep",
+ RadioSettingValueBoolean(_settings.beep))
+ basic.append(rs)
- s = RadioSetting("timeout", "Timeout Timer",
- RadioSettingValueList(timeout_list,
- timeout_list[_settings.tdr]))
- basic.append(s)
+ rs = RadioSetting("timeout", "Timeout Timer",
+ RadioSettingValueList(TIMEOUT_LIST,
+ TIMEOUT_LIST[_settings.tdr]))
+ basic.append(rs)
- s = RadioSetting("voice", "Voice",
- RadioSettingValueBoolean(_settings.voice))
- advanced.append(s)
+ rs = RadioSetting("voice", "Voice",
+ RadioSettingValueBoolean(_settings.voice))
+ advanced.append(rs)
- s = RadioSetting("screv", "Scan Resume",
- RadioSettingValueList(resume_list,
- resume_list[_settings.screv]))
- advanced.append(s)
+ rs = RadioSetting("screv", "Scan Resume",
+ RadioSettingValueList(RESUME_LIST,
+ RESUME_LIST[_settings.screv]))
+ advanced.append(rs)
- s = RadioSetting("mdfa", "Display Mode (A)",
- RadioSettingValueList(mode_list,
- mode_list[_settings.mdfa]))
- basic.append(s)
+ rs = RadioSetting("mdfa", "Display Mode (A)",
+ RadioSettingValueList(MODE_LIST,
+ MODE_LIST[_settings.mdfa]))
+ basic.append(rs)
- s = RadioSetting("mdfb", "Display Mode (B)",
- RadioSettingValueList(mode_list,
- mode_list[_settings.mdfb]))
- basic.append(s)
+ rs = RadioSetting("mdfb", "Display Mode (B)",
+ RadioSettingValueList(MODE_LIST,
+ MODE_LIST[_settings.mdfb]))
+ basic.append(rs)
- s = RadioSetting("bcl", "Busy Channel Lockout",
- RadioSettingValueBoolean(_settings.bcl))
- advanced.append(s)
+ rs = RadioSetting("bcl", "Busy Channel Lockout",
+ RadioSettingValueBoolean(_settings.bcl))
+ advanced.append(rs)
- s = RadioSetting("autolk", "Automatic Key Lock",
- RadioSettingValueBoolean(_settings.autolk))
- advanced.append(s)
+ rs = RadioSetting("autolk", "Automatic Key Lock",
+ RadioSettingValueBoolean(_settings.autolk))
+ advanced.append(rs)
- s = RadioSetting("wtled", "Standby LED Color",
- RadioSettingValueList(color_list,
- color_list[_settings.wtled]))
- basic.append(s)
+ rs = RadioSetting("wtled", "Standby LED Color",
+ RadioSettingValueList(COLOR_LIST,
+ COLOR_LIST[_settings.wtled]))
+ basic.append(rs)
- s = RadioSetting("rxled", "RX LED Color",
- RadioSettingValueList(color_list,
- color_list[_settings.rxled]))
- basic.append(s)
+ rs = RadioSetting("rxled", "RX LED Color",
+ RadioSettingValueList(COLOR_LIST,
+ COLOR_LIST[_settings.rxled]))
+ basic.append(rs)
- s = RadioSetting("txled", "TX LED Color",
- RadioSettingValueList(color_list,
- color_list[_settings.txled]))
- basic.append(s)
+ rs = RadioSetting("txled", "TX LED Color",
+ RadioSettingValueList(COLOR_LIST,
+ COLOR_LIST[_settings.txled]))
+ basic.append(rs)
return group
@@ -471,9 +474,6 @@
if not isinstance(element, RadioSetting):
self.set_settings(element)
continue
-
- if element.get_name() in SETTING_LISTS.keys():
- value = SETTING_LISTS[element.get_name()].index(str(element.value))
try:
setattr(_settings, element.get_name(), element.value)
except Exception, e:
diff -r db82df47f205 -r f805c420592f chirp/vx3.py
--- a/chirp/vx3.py Fri Apr 27 14:35:40 2012 -0700
+++ b/chirp/vx3.py Fri Apr 27 14:35:41 2012 -0700
@@ -14,7 +14,7 @@
# 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 chirp_common, yaesu_clone, util, directory
+from chirp import chirp_common, yaesu_clone, directory
from chirp import bitwise
#interesting offsets which may be checksums needed later
@@ -23,7 +23,7 @@
#0x0409 checksum2?
#0x04C9 checksum2a?
-mem_format = """
+MEM_FORMAT = """
#seekto 0x7F4A;
u8 checksum;
@@ -93,6 +93,7 @@
chirp_common.PowerLevel("Low", watts=0.10)]
class VX3Bank(chirp_common.NamedBank):
+ """A VX3 Bank"""
def get_name(self):
_bank = self._model._radio._memobj.bank_names[self.index]
name = ""
@@ -108,6 +109,7 @@
_bank.name = [CHARSET.index(x) for x in name.ljust(6)[:6]]
class VX3BankModel(chirp_common.BankModel):
+ """A VX-3 bank model"""
def get_num_banks(self):
return 24
@@ -121,8 +123,18 @@
banks.append(bank)
return banks
+def _wipe_memory(mem):
+ mem.set_raw("\x00" * (mem.size() / 8))
+ #the following settings are set to match the defaults
+ #on the radio, some of these fields are unknown
+ mem.name = [0xFF for _i in range(0, 6)]
+ mem.unknown5 = 0x0D #not sure what this is
+ mem.unknown7 = 0x01 #this likely is part of autostep
+ mem.automode = 0x01 #autoselect mode
+
@directory.register
class VX3Radio(yaesu_clone.YaesuCloneModeRadio):
+ """Yaesu VX-3"""
BAUD_RATE = 19200
VENDOR = "Yaesu"
MODEL = "VX-3"
@@ -139,7 +151,7 @@
return [ yaesu_clone.YaesuChecksum(0x0000, 0x7F49) ]
def process_mmap(self):
- self._memobj = bitwise.parse(mem_format, self._mmap)
+ self._memobj = bitwise.parse(MEM_FORMAT, self._mmap)
def get_features(self):
rf = chirp_common.RadioFeatures()
@@ -169,7 +181,7 @@
nibble = ((number-1) % 2) and "even" or "odd"
used = _flag["%s_masked" % nibble]
- valid =_flag["%s_valid" % nibble]
+ valid = _flag["%s_valid" % nibble]
pskip = _flag["%s_pskip" % nibble]
skip = _flag["%s_skip" % nibble]
@@ -203,16 +215,6 @@
mem.name = mem.name.rstrip()
return mem
- def _wipe_memory(self, mem):
- mem.set_raw("\x00" * (mem.size() / 8))
- #the following settings are set to match the defaults
- #on the radio, some of these fields are unknown
- mem.name = [0xFF for i in range(0, 6)]
- mem.unknown5 = 0x0D #not sure what this is
- mem.unknown7 = 0x01 #this likely is part of autostep
- mem.automode = 0x01 #autoselect mode
-
-
def set_memory(self, mem):
_mem = self._memobj.memory[mem.number-1]
_flag = self._memobj.flags[(mem.number-1)/2]
@@ -223,7 +225,7 @@
valid = _flag["%s_valid" % nibble]
if not mem.empty and not valid:
- self._wipe_memory(_mem)
+ _wipe_memory(_mem)
if mem.empty and valid and not used:
_flag["%s_valid" % nibble] = False
@@ -251,7 +253,8 @@
for i in range(0, 6):
_mem.name[i] = CHARSET.index(mem.name.ljust(6)[i])
- if mem.name.strip(): _mem.name[0] |= 0x80
+ if mem.name.strip():
+ _mem.name[0] |= 0x80
def validate_memory(self, mem):
msgs = yaesu_clone.YaesuCloneModeRadio.validate_memory(self, mem)
diff -r db82df47f205 -r f805c420592f chirp/vx5.py
--- a/chirp/vx5.py Fri Apr 27 14:35:40 2012 -0700
+++ b/chirp/vx5.py Fri Apr 27 14:35:41 2012 -0700
@@ -14,10 +14,10 @@
# 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 chirp_common, yaesu_clone, util, directory
+from chirp import chirp_common, yaesu_clone, directory
from chirp import bitwise
-mem_format = """
+MEM_FORMAT = """
#seekto 0x012A;
struct {
u8 zeros:4,
@@ -67,6 +67,7 @@
@directory.register
class VX5Radio(yaesu_clone.YaesuCloneModeRadio):
+ """Yaesu VX-5"""
BAUD_RATE = 9600
VENDOR = "Yaesu"
MODEL = "VX-5"
@@ -97,7 +98,7 @@
return rf
def process_mmap(self):
- self._memobj = bitwise.parse(mem_format, self._mmap)
+ self._memobj = bitwise.parse(MEM_FORMAT, self._mmap)
def get_raw_memory(self, number):
return repr(self._memobj.memory[number-1])
diff -r db82df47f205 -r f805c420592f chirp/vx6.py
--- a/chirp/vx6.py Fri Apr 27 14:35:40 2012 -0700
+++ b/chirp/vx6.py Fri Apr 27 14:35:41 2012 -0700
@@ -27,14 +27,15 @@
# cpu_shifted: CPU freq has been shifted (to move a birdie out of channel)
# power: 0-3: ["L1", "L2", "L3", "Hi"]
# pager: Set if this is a paging memory
-# tmodes: 0-7: ["", "Tone", "TSQL", "DTCS", "Rv Tn", "D Code", "T DCS", "D Tone"]
+# tmodes: 0-7: ["", "Tone", "TSQL", "DTCS", "Rv Tn", "D Code",
+# "T DCS", "D Tone"]
# Rv Tn: Reverse CTCSS - mutes receiver on tone
# The final 3 are for split:
# D Code: DCS Encode only
# T DCS: Encodes tone, decodes DCS code
# D Tone: Encodes DCS code, decodes tone
# }
-mem_format = """
+MEM_FORMAT = """
#seekto 0x018A;
u16 bank_sizes[24];
@@ -110,6 +111,7 @@
@directory.register
class VX6Radio(yaesu_clone.YaesuCloneModeRadio):
+ """Yaesu VX-6"""
BAUD_RATE = 19200
VENDOR = "Yaesu"
MODEL = "VX-6"
@@ -123,7 +125,7 @@
return [ yaesu_clone.YaesuChecksum(0x0000, 0x7F49) ]
def process_mmap(self):
- self._memobj = bitwise.parse(mem_format, self._mmap)
+ self._memobj = bitwise.parse(MEM_FORMAT, self._mmap)
def get_features(self):
rf = chirp_common.RadioFeatures()
@@ -225,35 +227,35 @@
_flag["%s_pskip" % nibble] = mem.skip == "P"
_flag["%s_skip" % nibble] = mem.skip == "S"
- _mem.name == ("\xFF" * 6)
+ _mem.name = [0xFF] * 6
for i in range(0, 6):
_mem.name[i] = CHARSET.index(mem.name.ljust(6)[i])
if mem.name.strip():
_mem.name[0] |= 0x80
- def get_banks(self):
- _banks = self._memobj.bank_names
+# def get_banks(self):
+# _banks = self._memobj.bank_names
+#
+# banks = []
+# for bank in _banks:
+# name = ""
+# for i in bank.name:
+# name += CHARSET[i & 0x7F]
+# banks.append(name.rstrip())
+#
+# return banks
+#
+# # Return channels for a bank. Bank given as number
+# def get_bank_channels(self, bank):
+# nchannels = 0
+# size = self._memobj.bank_sizes[bank]
+# if size <= 198:
+# nchannels = 1 + size/2
+# _channels = self._memobj.bank_channels[bank]
+# channels = []
+# for i in range(0, nchannels):
+# channels.append(int(_channels.channel[i]))
+#
+# return channels
- banks = []
- for bank in _banks:
- name = ""
- for i in bank.name:
- name += CHARSET[i & 0x7F]
- banks.append(name.rstrip())
-
- return banks
-
- # Return channels for a bank. Bank given as number
- def get_bank_channels(self, bank):
- nchannels = 0
- size = self._memobj.bank_sizes[bank]
- if size <= 198:
- nchannels = 1 + size/2
- _channels = self._memobj.bank_channels[bank]
- channels = []
- for i in range(0, nchannels):
- channels.append(int(_channels.channel[i]))
-
- return channels
-
diff -r db82df47f205 -r f805c420592f chirp/vx7.py
--- a/chirp/vx7.py Fri Apr 27 14:35:40 2012 -0700
+++ b/chirp/vx7.py Fri Apr 27 14:35:41 2012 -0700
@@ -13,10 +13,10 @@
# 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 chirp_common, yaesu_clone, util, directory
+from chirp import chirp_common, yaesu_clone, directory
from chirp import bitwise
-mem_format = """
+MEM_FORMAT = """
#seekto 0x0611;
u8 checksum1;
@@ -96,6 +96,7 @@
chirp_common.PowerLevel("L1", watts=0.05)]
class VX7BankModel(chirp_common.BankModel):
+ """A VX-7 Bank model"""
def get_num_banks(self):
return 9
@@ -130,8 +131,8 @@
remaining_members += 1
if not found:
- raise Exception(_("Memory {num} not in "
- "bank {bank}").format(num=memory.number,
+ raise Exception("Memory {num} not in " +
+ "bank {bank}".format(num=memory.number,
bank=bank))
if not remaining_members:
_bank_used.in_use = 0xFFFF
@@ -154,12 +155,19 @@
def get_memory_banks(self, memory):
banks = []
for bank in self.get_banks():
- if memory.number in [x.number for x in self.get_bank_memories(bank)]:
- banks.append(bank)
+ if memory.number in [x.number for x in
+ self.get_bank_memories(bank)]:
+ banks.append(bank)
return banks
+def _wipe_memory(mem):
+ mem.set_raw("\x00" * (mem.size() / 8))
+ mem.unknown1 = 0x05
+ mem.ones = 0x03
+
@directory.register
class VX7Radio(yaesu_clone.YaesuCloneModeRadio):
+ """Yaesu VX-7"""
BAUD_RATE = 19200
VENDOR = "Yaesu"
MODEL = "VX-7"
@@ -176,7 +184,7 @@
]
def process_mmap(self):
- self._memobj = bitwise.parse(mem_format, self._mmap)
+ self._memobj = bitwise.parse(MEM_FORMAT, self._mmap)
def get_features(self):
rf = chirp_common.RadioFeatures()
@@ -243,11 +251,6 @@
return mem
- def _wipe_memory(self, mem):
- mem.set_raw("\x00" * (mem.size() / 8))
- mem.unknown1 = 0x05
- mem.ones = 0x03
-
def set_memory(self, mem):
_mem = self._memobj.memory[mem.number-1]
_flag = self._memobj.flags[(mem.number-1)/2]
@@ -258,7 +261,7 @@
used = _flag["%s_masked" % nibble]
if not mem.empty and not valid:
- self._wipe_memory(_mem)
+ _wipe_memory(_mem)
self._wipe_memory_banks(mem)
if mem.empty and valid and not used:
@@ -294,7 +297,8 @@
if mem.freq >= 222000000 and mem.freq <= 225000000:
if mem.power not in POWER_LEVELS_220:
msgs.append(chirp_common.ValidationError(\
- "Power level %s not supported on 220MHz band" % mem.power))
+ "Power level %s not supported on 220MHz band" % \
+ mem.power))
return msgs
diff -r db82df47f205 -r f805c420592f chirp/vx8.py
--- a/chirp/vx8.py Fri Apr 27 14:35:40 2012 -0700
+++ b/chirp/vx8.py Fri Apr 27 14:35:41 2012 -0700
@@ -16,7 +16,7 @@
from chirp import chirp_common, yaesu_clone, directory
from chirp import bitwise
-mem_format = """
+MEM_FORMAT = """
#seekto 0x54a;
struct {
u16 in_use;
@@ -88,6 +88,8 @@
chirp_common.PowerLevel("L1", watts=0.05)]
class VX8Bank(chirp_common.NamedBank):
+ """A VX-8 bank"""
+
def get_name(self):
_bank = self._model._radio._memobj.bank_info[self.index]
_bank_used = self._model._radio._memobj.bank_used[self.index]
@@ -104,6 +106,7 @@
_bank.name = [CHARSET.index(x) for x in name.ljust(16)[:16]]
class VX8BankModel(chirp_common.BankModel):
+ """A VX-8 bank model"""
def get_num_banks(self):
return 24
@@ -172,8 +175,13 @@
return banks
+def _wipe_memory(mem):
+ mem.set_raw("\x00" * (mem.size() / 8))
+ mem.unknown1 = 0x05
+
@directory.register
class VX8Radio(yaesu_clone.YaesuCloneModeRadio):
+ """Yaesu VX-8"""
BAUD_RATE = 38400
VENDOR = "Yaesu"
MODEL = "VX-8"
@@ -185,7 +193,7 @@
_block_size = 32
def process_mmap(self):
- self._memobj = bitwise.parse(mem_format, self._mmap)
+ self._memobj = bitwise.parse(MEM_FORMAT, self._mmap)
def get_features(self):
rf = chirp_common.RadioFeatures()
@@ -242,10 +250,6 @@
return mem
- def _wipe_memory(self, mem):
- mem.set_raw("\x00" * (mem.size() / 8))
- mem.unknown1 = 0x05
-
def _debank(self, mem):
bm = self.get_bank_model()
for bank in bm.get_memory_banks(mem):
@@ -256,7 +260,7 @@
flag = self._memobj.flag[mem.number-1]
if not mem.empty and not flag.valid:
- self._wipe_memory(_mem)
+ _wipe_memory(_mem)
if mem.empty and flag.valid and not flag.used:
flag.valid = False
@@ -300,5 +304,6 @@
@directory.register
class VX8DRadio(VX8Radio):
+ """Yaesu VX-8DR"""
_model = "AH29D"
VARIANT = "DR"
diff -r db82df47f205 -r f805c420592f chirp/vxa700.py
--- a/chirp/vxa700.py Fri Apr 27 14:35:40 2012 -0700
+++ b/chirp/vxa700.py Fri Apr 27 14:35:41 2012 -0700
@@ -19,21 +19,21 @@
import time
import struct
-def debug(string):
+def _debug(string):
pass
print string
-def send(radio, data):
- debug("Sending %s" % repr(data))
+def _send(radio, data):
+ _debug("Sending %s" % repr(data))
radio.pipe.write(data)
radio.pipe.flush()
echo = radio.pipe.read(len(data))
if len(echo) != len(data):
raise errors.RadioError("Invalid echo")
-def spoonfeed(radio, data):
- count = 0
- debug("Writing %i:\n%s" % (len(data), util.hexprint(data)))
+def _spoonfeed(radio, data):
+ #count = 0
+ _debug("Writing %i:\n%s" % (len(data), util.hexprint(data)))
for byte in data:
radio.pipe.write(byte)
radio.pipe.flush()
@@ -45,12 +45,12 @@
if echo != byte:
print "%02x != %02x" % (ord(echo), ord(byte))
raise errors.RadioError("No echo?")
- count += 1
+ #count += 1
-def download(radio):
+def _download(radio):
count = 0
data = ""
- while len(data) < radio._memsize:
+ while len(data) < radio.get_memsize():
count += 1
chunk = radio.pipe.read(133)
if len(chunk) == 0 and len(data) == 0 and count < 30:
@@ -58,10 +58,9 @@
if len(chunk) != 132:
raise errors.RadioError("Got short block (length %i)" % len(chunk))
- flag, length, block = struct.unpack("BBB", chunk[:3])
checksum = ord(chunk[-1])
-
- flag, length, block, _data, checksum = struct.unpack("BBB128sB", chunk)
+ _flag, _length, _block, _data, checksum = \
+ struct.unpack("BBB128sB", chunk)
cs = 0
for byte in chunk[:-1]:
@@ -70,32 +69,31 @@
raise errors.RadioError("Invalid checksum at 0x%02x" % len(data))
data += _data
- send(radio, "\x06")
+ _send(radio, "\x06")
if radio.status_fn:
status = chirp_common.Status()
status.msg = "Cloning from radio"
status.cur = len(data)
- status.max = radio._memsize
+ status.max = radio.get_memsize()
radio.status_fn(status)
return memmap.MemoryMap(data)
-def upload(radio):
- for i in range(0, radio._memsize, 128):
- chunk = radio._mmap[i:i+128]
+def _upload(radio):
+ for i in range(0, radio.get_memsize(), 128):
+ chunk = radio.get_mmap()[i:i+128]
cs = 0x20 + 130 + (i / 128)
for byte in chunk:
cs += ord(byte)
- spoonfeed(radio,
- struct.pack("BBB128sB",
- 0x20,
- 130,
- i / 128,
- chunk,
- cs % 256))
+ _spoonfeed(radio,
+ struct.pack("BBB128sB",
+ 0x20,
+ 130,
+ i / 128,
+ chunk,
+ cs % 256))
radio.pipe.write("")
- start = time.time()
# This is really unreliable for some reason, so just
# blindly proceed
# ack = radio.pipe.read(1)
@@ -109,10 +107,10 @@
status = chirp_common.Status()
status.msg = "Cloning to radio"
status.cur = i
- status.max = radio._memsize
+ status.max = radio.get_memsize()
radio.status_fn(status)
-mem_format = """
+MEM_FORMAT = """
struct memory_struct {
u8 unknown1;
u8 unknown2:2,
@@ -158,19 +156,24 @@
chirp_common.PowerLevel("Low3", watts=2.500),
chirp_common.PowerLevel("High", watts=5.000)]
+def _wipe_memory(_mem):
+ _mem.set_raw("\x00" * (_mem.size() / 8))
+
@directory.register
class VXA700Radio(chirp_common.CloneModeRadio):
+ """Vertex Standard VXA-700"""
VENDOR = "Vertex Standard"
MODEL = "VXA-700"
_memsize = 4096
def sync_in(self):
try:
- self._mmap = download(self)
+ self._mmap = _download(self)
except errors.RadioError:
raise
except Exception, e:
- raise errors.RadioError("Failed to communicate with the radio: %s" % e)
+ raise errors.RadioError("Failed to communicate " +
+ "with the radio: %s" % e)
self.process_mmap()
def sync_out(self):
@@ -180,14 +183,15 @@
# 0x02 <- air band only
try:
self.pipe.setTimeout(2)
- upload(self)
+ _upload(self)
except errors.RadioError:
raise
except Exception, e:
- raise errors.RadioError("Failed to communicate with the radio: %s" % e)
+ raise errors.RadioError("Failed to communicate " +
+ "with the radio: %s" % e)
def process_mmap(self):
- self._memobj = bitwise.parse(mem_format, self._mmap)
+ self._memobj = bitwise.parse(MEM_FORMAT, self._mmap)
def get_features(self):
rf = chirp_common.RadioFeatures()
@@ -203,7 +207,7 @@
rf.valid_tuning_steps = [5.0, 10.0, 12.5, 15.0, 20.0, 25.0, 50.0, 100.0]
rf.valid_modes = ["AM", "FM"]
rf.valid_power_levels = POWER
- rf.memory_bounds = (1,100)
+ rf.memory_bounds = (1, 100)
return rf
def _get_mem(self, number):
@@ -215,8 +219,8 @@
def get_memory(self, number):
_mem = self._get_mem(number)
- byte = (number - 1) / 8;
- bit = 1 << ((number - 1) % 8);
+ byte = (number - 1) / 8
+ bit = 1 << ((number - 1) % 8)
mem = chirp_common.Memory()
mem.number = number
@@ -251,13 +255,10 @@
return mem
- def _wipe_memory(self, _mem):
- _mem.set_raw("\x00" * (_mem.size() / 8))
-
def set_memory(self, mem):
_mem = self._get_mem(mem.number)
- byte = (mem.number - 1) / 8;
- bit = 1 << ((mem.number - 1) % 8);
+ byte = (mem.number - 1) / 8
+ bit = 1 << ((mem.number - 1) % 8)
if mem.empty and self._memobj.invisible_bits[byte] & bit:
self._memobj.invalid_bits[byte] |= bit
@@ -267,7 +268,7 @@
return
if self._memobj.invalid_bits[byte] & bit:
- self._wipe_memory(_mem)
+ _wipe_memory(_mem)
self._memobj.invisible_bits[byte] &= ~bit
self._memobj.invalid_bits[byte] &= ~bit
@@ -293,7 +294,7 @@
_mem.skip = mem.skip == "S"
try:
_mem.power = POWER.index(mem.power)
- except:
+ except ValueError:
_mem.power = 3 # High
for i in range(0, 8):
diff -r db82df47f205 -r f805c420592f chirp/wouxun.py
--- a/chirp/wouxun.py Fri Apr 27 14:35:40 2012 -0700
+++ b/chirp/wouxun.py Fri Apr 27 14:35:41 2012 -0700
@@ -23,7 +23,7 @@
else:
DEBUG = False
-wouxun_mem_format = """
+WOUXUN_MEM_FORMAT = """
#seekto 0x0010;
struct {
lbcd rx_freq[4];
@@ -50,22 +50,24 @@
"""
def wouxun_identify(radio):
- for i in range(0, 5):
+ """Do the original wouxun identification dance"""
+ for _i in range(0, 5):
radio.pipe.write("HiWOUXUN\x02")
- r = radio.pipe.read(9)
- if len(r) != 9:
+ resp = radio.pipe.read(9)
+ if len(resp) != 9:
print "Retrying identification..."
time.sleep(1)
continue
- if r[2:8] != radio._model:
+ if resp[2:8] != radio._model:
raise Exception("I can't talk to this model")
return
- if len(r) == 0:
+ if len(resp) == 0:
raise Exception("Radio not responding")
else:
raise Exception("Unable to identify radio")
def wouxun_start_transfer(radio):
+ """Tell the radio to go into transfer mode"""
radio.pipe.write("\x02\x06")
time.sleep(0.05)
ack = radio.pipe.read(1)
@@ -73,6 +75,7 @@
raise Exception("Radio refused transfer mode")
def do_download(radio, start, end, blocksize):
+ """Initiate a download of @radio between @start and @end"""
image = ""
for i in range(start, end, blocksize):
cmd = struct.pack(">cHb", "R", i, blocksize)
@@ -80,30 +83,32 @@
print util.hexprint(cmd)
radio.pipe.write(cmd)
length = len(cmd) + blocksize
- r = radio.pipe.read(length)
- if len(r) != (len(cmd) + blocksize):
- print util.hexprint(r)
- raise Exception("Failed to read full block (%i!=%i)" % (len(r),
- len(cmd)+blocksize))
+ resp = radio.pipe.read(length)
+ if len(resp) != (len(cmd) + blocksize):
+ print util.hexprint(resp)
+ raise Exception("Failed to read full block (%i!=%i)" % \
+ (len(resp),
+ len(cmd) + blocksize))
radio.pipe.write("\x06")
radio.pipe.read(1)
- image += r[4:]
+ image += resp[4:]
if radio.status_fn:
- s = chirp_common.Status()
- s.cur = i
- s.max = end
- s.msg = "Cloning from radio"
- radio.status_fn(s)
+ status = chirp_common.Status()
+ status.cur = i
+ status.max = end
+ status.msg = "Cloning from radio"
+ radio.status_fn(status)
return memmap.MemoryMap(image)
def do_upload(radio, start, end, blocksize):
+ """Initiate an upload of @radio between @start and @end"""
ptr = start
for i in range(start, end, blocksize):
cmd = struct.pack(">cHb", "W", i, blocksize)
- chunk = radio._mmap[ptr:ptr+blocksize]
+ chunk = radio.get_mmap()[ptr:ptr+blocksize]
ptr += blocksize
radio.pipe.write(cmd + chunk)
if DEBUG:
@@ -115,13 +120,14 @@
#radio.pipe.write(ack)
if radio.status_fn:
- s = chirp_common.Status()
- s.cur = i
- s.max = end
- s.msg = "Cloning to radio"
- radio.status_fn(s)
+ status = chirp_common.Status()
+ status.cur = i
+ status.max = end
+ status.msg = "Cloning to radio"
+ radio.status_fn(status)
def wouxun_download(radio):
+ """Talk to an original wouxun and do a download"""
try:
wouxun_identify(radio)
wouxun_start_transfer(radio)
@@ -132,6 +138,7 @@
raise errors.RadioError("Failed to communicate with radio: %s" % e)
def wouxun_upload(radio):
+ """Talk to an original wouxun and do an upload"""
try:
wouxun_identify(radio)
wouxun_start_transfer(radio)
@@ -147,8 +154,12 @@
POWER_LEVELS = [chirp_common.PowerLevel("High", watts=5.00),
chirp_common.PowerLevel("Low", watts=1.00)]
+def wipe_memory(_mem, byte):
+ _mem.set_raw(byte * (_mem.size() / 8))
+
@directory.register
class KGUVD1PRadio(chirp_common.CloneModeRadio):
+ """Wouxun KG-UVD1P,UV2,UV3"""
VENDOR = "Wouxun"
MODEL = "KG-UVD1P"
_model = "KG669V"
@@ -172,7 +183,7 @@
# format, padding 16 bytes of 0xFF in front.
self._mmap = memmap.MemoryMap(("\xFF" * 16) + \
self._mmap.get_packed()[8:8184])
- self._memobj = bitwise.parse(wouxun_mem_format, self._mmap)
+ self._memobj = bitwise.parse(WOUXUN_MEM_FORMAT, self._mmap)
def get_features(self):
rf = chirp_common.RadioFeatures()
@@ -194,14 +205,14 @@
def get_raw_memory(self, number):
return repr(self._memobj.memory[number - 1])
- def get_tone(self, _mem, mem):
- def get_dcs(val):
+ def _get_tone(self, _mem, mem):
+ def _get_dcs(val):
code = int("%03o" % (val & 0x07FF))
pol = (val & 0x8000) and "R" or "N"
return code, pol
if _mem.tx_tone != 0xFFFF and _mem.tx_tone > 0x2800:
- tcode, tpol = get_dcs(_mem.tx_tone)
+ tcode, tpol = _get_dcs(_mem.tx_tone)
mem.dtcs = tcode
txmode = "DTCS"
elif _mem.tx_tone != 0xFFFF:
@@ -211,7 +222,7 @@
txmode = ""
if _mem.rx_tone != 0xFFFF and _mem.rx_tone > 0x2800:
- rcode, rpol = get_dcs(_mem.rx_tone)
+ rcode, rpol = _get_dcs(_mem.rx_tone)
mem.dtcs = rcode
rxmode = "DTCS"
elif _mem.rx_tone != 0xFFFF:
@@ -268,7 +279,7 @@
if not _mem.iswide:
mem.mode = "NFM"
- self.get_tone(_mem, mem)
+ self._get_tone(_mem, mem)
mem.power = POWER_LEVELS[not _mem.power_high]
@@ -279,11 +290,8 @@
return mem
- def wipe_memory(self, _mem, byte):
- _mem.set_raw(byte * (_mem.size() / 8))
-
- def set_tone(self, mem, _mem):
- def set_dcs(code, pol):
+ def _set_tone(self, mem, _mem):
+ def _set_dcs(code, pol):
val = int("%i" % code, 8) + 0x2800
if pol == "R":
val += 0xA000
@@ -299,7 +307,7 @@
if tx_mode == "DTCS":
- _mem.tx_tone = set_dcs(mem.dtcs, mem.dtcs_polarity[0])
+ _mem.tx_tone = _set_dcs(mem.dtcs, mem.dtcs_polarity[0])
elif tx_mode:
_mem.tx_tone = tx_mode == "Tone" and \
int(mem.rtone * 10) or int(mem.ctone * 10)
@@ -307,7 +315,7 @@
_mem.tx_tone = 0xFFFF
if rx_mode == "DTCS":
- _mem.rx_tone = set_dcs(mem.dtcs, mem.dtcs_polarity[1])
+ _mem.rx_tone = _set_dcs(mem.dtcs, mem.dtcs_polarity[1])
elif rx_mode:
_mem.rx_tone = int(mem.ctone * 10)
else:
@@ -322,11 +330,11 @@
_nam = self._memobj.names[mem.number - 1]
if mem.empty:
- self.wipe_memory(_mem, "\xFF")
+ wipe_memory(_mem, "\xFF")
return
if _mem.get_raw() == ("\xFF" * 16):
- self.wipe_memory(_mem, "\x00")
+ wipe_memory(_mem, "\x00")
_mem.rx_freq = int(mem.freq / 10)
if mem.duplex == "split":
@@ -341,7 +349,7 @@
_mem.skip = mem.skip != "S"
_mem.iswide = mem.mode != "NFM"
- self.set_tone(mem, _mem)
+ self._set_tone(mem, _mem)
if mem.power:
_mem.power_high = not POWER_LEVELS.index(mem.power)
@@ -386,7 +394,8 @@
raise Exception("Radio did not ACK ident")
def puxing_prep(radio):
- for i in range(0, 10):
+ """Do the Puxing PX-777 identification dance"""
+ for _i in range(0, 10):
try:
return _puxing_prep(radio)
except Exception, e:
@@ -395,6 +404,7 @@
raise e
def puxing_download(radio):
+ """Talk to a Puxing PX-777 and do a download"""
try:
puxing_prep(radio)
return do_download(radio, 0x0000, 0x0C60, 0x0008)
@@ -404,6 +414,7 @@
raise errors.RadioError("Failed to communicate with radio: %s" % e)
def puxing_upload(radio):
+ """Talk to a Puxing PX-777 and do an upload"""
try:
puxing_prep(radio)
return do_upload(radio, 0x0000, 0x0C40, 0x0008)
@@ -412,7 +423,7 @@
except Exception, e:
raise errors.RadioError("Failed to communicate with radio: %s" % e)
-puxing_mem_format = """
+PUXING_MEM_FORMAT = """
#seekto 0x0000;
struct {
lbcd rx_freq[4];
@@ -477,6 +488,7 @@
@directory.register
class Puxing777Radio(KGUVD1PRadio):
+ """Puxing PX-777"""
VENDOR = "Puxing"
MODEL = "PX-777"
@@ -513,7 +525,7 @@
return rf
def process_mmap(self):
- self._memobj = bitwise.parse(puxing_mem_format, self._mmap)
+ self._memobj = bitwise.parse(PUXING_MEM_FORMAT, self._mmap)
@classmethod
def match_model(cls, filedata, filename):
@@ -526,16 +538,16 @@
_mem = self._memobj.memory[number - 1]
_nam = self._memobj.names[number - 1]
- def is_empty():
- for i in range(0,4):
+ def _is_empty():
+ for i in range(0, 4):
if _mem.rx_freq[i].get_raw() != "\xFF":
return False
return True
- def is_no_tone(field):
+ def _is_no_tone(field):
return field[0].get_raw() == "\xFF"
- def get_dtcs(value):
+ def _get_dtcs(value):
# Upper nibble 0x80 -> DCS, 0xC0 -> Inv. DCS
if value > 12000:
return "R", value - 12000
@@ -544,19 +556,19 @@
else:
raise Exception("Unable to convert DCS value")
- def do_dtcs(mem, txfield, rxfield):
+ def _do_dtcs(mem, txfield, rxfield):
if int(txfield) < 8000 or int(rxfield) < 8000:
raise Exception("Split tone not supported")
if txfield[0].get_raw() == "\xFF":
tp, tx = "N", None
else:
- tp, tx = get_dtcs(int(txfield))
+ tp, tx = _get_dtcs(int(txfield))
if rxfield[0].get_raw() == "\xFF":
rp, rx = "N", None
else:
- rp, rx = get_dtcs(int(rxfield))
+ rp, rx = _get_dtcs(int(rxfield))
if not rx:
rx = tx
@@ -572,7 +584,7 @@
mem = chirp_common.Memory()
mem.number = number
- if is_empty():
+ if _is_empty():
mem.empty = True
return mem
@@ -588,15 +600,15 @@
if not _mem.iswide:
mem.mode = "NFM"
- if is_no_tone(_mem.tx_tone):
+ if _is_no_tone(_mem.tx_tone):
pass # No tone
elif int(_mem.tx_tone) > 8000 or \
- (not is_no_tone(_mem.rx_tone) and int(_mem.rx_tone) > 8000):
+ (not _is_no_tone(_mem.rx_tone) and int(_mem.rx_tone) > 8000):
mem.tmode = "DTCS"
- do_dtcs(mem, _mem.tx_tone, _mem.rx_tone)
+ _do_dtcs(mem, _mem.tx_tone, _mem.rx_tone)
else:
mem.rtone = int(_mem.tx_tone) / 10.0
- mem.tmode = is_no_tone(_mem.rx_tone) and "Tone" or "TSQL"
+ mem.tmode = _is_no_tone(_mem.rx_tone) and "Tone" or "TSQL"
mem.power = POWER_LEVELS[not _mem.power_high]
@@ -612,7 +624,7 @@
_nam = self._memobj.names[mem.number - 1]
if mem.empty:
- self.wipe_memory(_mem, "\xFF")
+ wipe_memory(_mem, "\xFF")
return
_mem.rx_freq = mem.freq / 10
@@ -666,6 +678,7 @@
raise Exception("Character `%s' not supported")
def puxing_2r_prep(radio):
+ """Do the Puxing 2R identification dance"""
radio.pipe.setTimeout(0.2)
radio.pipe.write("PROGRAM\x02")
ack = radio.pipe.read(1)
@@ -677,6 +690,7 @@
print "Radio ident: %s (%i)" % (repr(ident), len(ident))
def puxing_2r_download(radio):
+ """Talk to a Puxing 2R and do a download"""
try:
puxing_2r_prep(radio)
return do_download(radio, 0x0000, 0x0FE0, 0x0010)
@@ -686,6 +700,7 @@
raise errors.RadioError("Failed to communicate with radio: %s" % e)
def puxing_2r_upload(radio):
+ """Talk to a Puxing 2R and do an upload"""
try:
puxing_2r_prep(radio)
return do_upload(radio, 0x0000, 0x0FE0, 0x0010)
@@ -694,7 +709,7 @@
except Exception, e:
raise errors.RadioError("Failed to communicate with radio: %s" % e)
-puxing_2r_mem_format = """
+PUXING_2R_MEM_FORMAT = """
#seekto 0x0010;
struct {
lbcd freq[4];
@@ -719,6 +734,7 @@
@directory.register
class Puxing2RRadio(KGUVD1PRadio):
+ """Puxing PX-2R"""
VENDOR = "Puxing"
MODEL = "PX-2R"
_memsize = 0x0FE0
@@ -753,7 +769,7 @@
puxing_2r_upload(self)
def process_mmap(self):
- self._memobj = bitwise.parse(puxing_2r_mem_format, self._mmap)
+ self._memobj = bitwise.parse(PUXING_2R_MEM_FORMAT, self._mmap)
def get_memory(self, number):
_mem = self._memobj.memory[number-1]
@@ -780,16 +796,17 @@
mem.rtone = chirp_common.TONES[_mem.tx_tone - 1]
mem.tmode = _mem.rx_tone and "TSQL" or "Tone"
- c = 0
+ count = 0
for i in _mem.name:
if i == 0xFF:
break
try:
mem.name += PX2R_CHARSET[i]
- except:
- print "Unknown name char %i: 0x%02x (mem %i)" % (c, i, number)
+ except Exception:
+ print "Unknown name char %i: 0x%02x (mem %i)" % (count,
+ i, number)
mem.name += " "
- c += 1
+ count += 1
mem.name = mem.name.rstrip()
return mem
@@ -845,7 +862,8 @@
raise errors.RadioError("Radio did not ACK ident")
def uv3r_prep(radio):
- for i in range(0, 10):
+ """Do the UV3R identification dance"""
+ for _i in range(0, 10):
try:
return _uv3r_prep(radio)
except errors.RadioError, e:
@@ -854,6 +872,7 @@
raise e
def uv3r_download(radio):
+ """Talk to a UV3R and do a download"""
try:
uv3r_prep(radio)
return do_download(radio, 0x0000, 0x0E40, 0x0010)
@@ -863,6 +882,7 @@
raise errors.RadioError("Failed to communicate with radio: %s" % e)
def uv3r_upload(radio):
+ """Talk to a UV3R and do an upload"""
try:
uv3r_prep(radio)
return do_upload(radio, 0x0000, 0x0E40, 0x0010)
@@ -871,7 +891,7 @@
except Exception, e:
raise errors.RadioError("Failed to communicate with radio: %s" % e)
-uv3r_mem_format = """
+UV3R_MEM_FORMAT = """
#seekto 0x0010;
struct {
lbcd rx_freq[4];
@@ -920,6 +940,7 @@
@directory.register
class UV3RRadio(KGUVD1PRadio):
+ """Baofeng UV-3R"""
VENDOR = "Baofeng"
MODEL = "UV-3R"
@@ -950,7 +971,7 @@
uv3r_upload(self)
def process_mmap(self):
- self._memobj = bitwise.parse(uv3r_mem_format, self._mmap)
+ self._memobj = bitwise.parse(UV3R_MEM_FORMAT, self._mmap)
def get_memory(self, number):
_mem = self._memobj.rx_memory[number - 1]
@@ -962,7 +983,7 @@
return mem
mem.freq = int(_mem.rx_freq) * 10
- mem.offset = int(_mem.offset) * 10;
+ mem.offset = int(_mem.offset) * 10
mem.duplex = UV3R_DUPLEX[_mem.duplex]
if mem.offset > 60000000:
if mem.duplex == "+":
diff -r db82df47f205 -r f805c420592f chirp/xml_ll.py
--- a/chirp/xml_ll.py Fri Apr 27 14:35:40 2012 -0700
+++ b/chirp/xml_ll.py Fri Apr 27 14:35:41 2012 -0700
@@ -13,12 +13,12 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
-import errors
import re
-from chirp import chirp_common
+from chirp import chirp_common, errors
def get_memory(doc, number):
+ """Extract a Memory object from @doc"""
ctx = doc.xpathNewContext()
base = "//radio/memories/memory[@location=%i]" % number
@@ -98,6 +98,7 @@
return mem
def set_memory(doc, mem):
+ """Set @mem in @doc"""
ctx = doc.xpathNewContext()
base = "//radio/memories/memory[@location=%i]" % mem.number
@@ -105,7 +106,7 @@
fields = ctx.xpathEval(base)
if len(fields) > 1:
raise errors.RadioError("%i memories claiming to be %i" % (len(fields),
- number))
+ mem.number))
elif len(fields) == 1:
fields[0].unlinkNode()
@@ -197,6 +198,7 @@
dc.addContent(str(mem.dv_code))
def del_memory(doc, number):
+ """Remove memory @number from @doc"""
path = "//radio/memories/memory[@location=%i]" % number
ctx = doc.xpathNewContext()
fields = ctx.xpathEval(path)
@@ -206,11 +208,12 @@
def _get_bank(node):
bank = chirp_common.Bank(node.prop("label"))
- id = int(node.prop("id"))
+ ident = int(node.prop("id"))
- return id, bank
+ return ident, bank
def get_banks(doc):
+ """Return a list of banks from @doc"""
path = "//radio/banks/bank"
ctx = doc.xpathNewContext()
fields = ctx.xpathEval(path)
@@ -219,14 +222,15 @@
for field in fields:
banks.append(_get_bank(field))
- def cmp(x, y):
- return x[0] - y[0]
+ def _cmp(itema, itemb):
+ return itema[0] - itemb[0]
- banks.sort(cmp=cmp)
+ banks.sort(cmp=_cmp)
return [x[1] for x in banks]
def set_banks(doc, banklist):
+ """Set the list of banks in @doc"""
path = "//radio/banks/bank"
ctx = doc.xpathNewContext()
fields = ctx.xpathEval(path)
diff -r db82df47f205 -r f805c420592f chirp/yaesu_clone.py
--- a/chirp/yaesu_clone.py Fri Apr 27 14:35:40 2012 -0700
+++ b/chirp/yaesu_clone.py Fri Apr 27 14:35:41 2012 -0700
@@ -18,10 +18,10 @@
from chirp import chirp_common, util, memmap, errors
import time, os
-def safe_read(pipe, count, times=60):
+def _safe_read(pipe, count):
buf = ""
first = True
- for i in range(0, 60):
+ for _i in range(0, 60):
buf += pipe.read(count - len(buf))
#print "safe_read: %i/%i\n" % (len(buf), count)
if buf:
@@ -34,17 +34,15 @@
print util.hexprint(buf)
return buf
-def chunk_read(pipe, count, status_fn):
+def _chunk_read(pipe, count, status_fn):
block = 32
data = ""
- first = True
- for i in range(0, count, block):
+ for _i in range(0, count, block):
data += pipe.read(block)
if data:
if data[0] == chr(CMD_ACK):
data = data[1:] # Chew an echo'd ack if using a 2-pin cable
#print "Chewed an ack"
- first = False
status = chirp_common.Status()
status.msg = "Cloning from radio"
status.max = count
@@ -54,7 +52,7 @@
print "Read %i/%i" % (len(data), count)
return data
-def _clone_in(radio):
+def __clone_in(radio):
pipe = radio.pipe
start = time.time()
@@ -64,28 +62,28 @@
for block in radio._block_lengths:
blocks += 1
if blocks == len(radio._block_lengths):
- chunk = chunk_read(pipe, block, radio.status_fn)
+ chunk = _chunk_read(pipe, block, radio.status_fn)
else:
- chunk = safe_read(pipe, block)
+ chunk = _safe_read(pipe, block)
pipe.write(chr(CMD_ACK))
if not chunk:
raise errors.RadioError("No response from radio")
data += chunk
- if len(data) != radio._memsize:
+ if len(data) != radio.get_memsize():
raise errors.RadioError("Received incomplete image from radio")
print "Clone completed in %i seconds" % (time.time() - start)
return memmap.MemoryMap(data)
-def clone_in(radio):
+def _clone_in(radio):
try:
- return _clone_in(radio)
+ return __clone_in(radio)
except Exception, e:
raise errors.RadioError("Failed to communicate with the radio: %s" % e)
-def chunk_write(pipe, data, status_fn, block):
+def _chunk_write(pipe, data, status_fn, block):
delay = 0.03
count = 0
for i in range(0, len(data), block):
@@ -101,15 +99,15 @@
status.cur = count
status_fn(status)
-def _clone_out(radio):
+def __clone_out(radio):
pipe = radio.pipe
- l = radio._block_lengths
+ block_lengths = radio._block_lengths
total_written = 0
- def status():
+ def _status():
status = chirp_common.Status()
status.msg = "Cloning to radio"
- status.max = l[0] + l[1] + l[2]
+ status.max = block_lengths[0] + block_lengths[1] + block_lengths[2]
status.cur = total_written
radio.status_fn(status)
@@ -121,28 +119,29 @@
blocks += 1
if blocks != len(radio._block_lengths):
#print "Sending %i-%i" % (pos, pos+block)
- pipe.write(radio._mmap[pos:pos+block])
+ pipe.write(radio.get_mmap()[pos:pos+block])
buf = pipe.read(1)
if buf and buf[0] != chr(CMD_ACK):
buf = pipe.read(block)
if not buf or buf[-1] != chr(CMD_ACK):
raise Exception("Radio did not ack block %i" % blocks)
else:
- chunk_write(pipe, radio._mmap[pos:],
- radio.status_fn, radio._block_size)
+ _chunk_write(pipe, radio.get_mmap()[pos:],
+ radio.status_fn, radio._block_size)
pos += block
pipe.read(pos) # Chew the echo if using a 2-pin cable
print "Clone completed in %i seconds" % (time.time() - start)
-def clone_out(radio):
+def _clone_out(radio):
try:
- return _clone_out(radio)
+ return __clone_out(radio)
except Exception, e:
raise errors.RadioError("Failed to communicate with the radio: %s" % e)
class YaesuChecksum:
+ """A Yaesu Checksum Object"""
def __init__(self, start, stop, address=None):
self._start = start
self._stop = stop
@@ -156,12 +155,14 @@
return ord(mmap[self._address])
def get_calculated(self, mmap):
+ """Return the calculated value of the checksum"""
cs = 0
for i in range(self._start, self._stop+1):
cs += ord(mmap[i])
return cs % 256
def update(self, mmap):
+ """Update the checksum with the data in @mmap"""
mmap[self._address] = self.get_calculated(mmap)
def __str__(self):
@@ -170,6 +171,7 @@
self._address)
class YaesuCloneModeRadio(chirp_common.CloneModeRadio):
+ """Base class for all Yaesu clone-mode radios"""
_block_lengths = [8, 65536]
_block_size = 8
@@ -181,10 +183,12 @@
return []
def update_checksums(self):
+ """Update the radio's checksums from the current memory map"""
for checksum in self._checksums():
checksum.update(self._mmap)
def check_checksums(self):
+ """Validate the checksums stored in the memory map"""
for checksum in self._checksums():
if checksum.get_existing(self._mmap) != \
checksum.get_calculated(self._mmap):
@@ -192,13 +196,13 @@
print "Checksum %s: OK" % checksum
def sync_in(self):
- self._mmap = clone_in(self)
+ self._mmap = _clone_in(self)
self.check_checksums()
self.process_mmap()
def sync_out(self):
self.update_checksums()
- clone_out(self)
+ _clone_out(self)
@classmethod
def match_model(cls, filedata, filename):
@@ -209,24 +213,3 @@
bm = self.get_bank_model()
for bank in bm.get_memory_banks(mem):
bm.remove_memory_from_bank(mem, bank)
-
-
-if __name__ == "__main__":
- import sys, serial
- s = serial.Serial(port=sys.argv[1], baudrate=19200, timeout=5)
-
- d = s.read(20)
- print util.hexprint(d)
-
- s.write(chr(0x06))
-
- d = ""
- while True:
- c = s.read(32)
- if not c:
- break
- d += c
-
- print len(d)
-
-
diff -r db82df47f205 -r f805c420592f chirpui/clone.py
--- a/chirpui/clone.py Fri Apr 27 14:35:40 2012 -0700
+++ b/chirpui/clone.py Fri Apr 27 14:35:41 2012 -0700
@@ -191,7 +191,7 @@
class CloneCancelledException(Exception):
pass
-class CloneThread(chirp_common.KillableThread):
+class CloneThread(threading.Thread):
def __status(self, status):
gobject.idle_add(self.__progw.status, status)
diff -r db82df47f205 -r f805c420592f chirpui/mainapp.py
--- a/chirpui/mainapp.py Fri Apr 27 14:35:40 2012 -0700
+++ b/chirpui/mainapp.py Fri Apr 27 14:35:41 2012 -0700
@@ -887,7 +887,7 @@
else:
from chirp import rfinder
radio = rfinder.RFinderRadio(None)
- radio.set_params(lat, lon, miles, email, passwd)
+ radio.set_params((lat, lon), miles, email, passwd)
self.do_open_live(radio, read_only=True)
self.window.set_cursor(None)
More information about the chirp_devel
mailing list