r4638 - developers/werner/ahrt/host/tmc/lib
werner at docs.openmoko.org
werner at docs.openmoko.org
Wed Sep 10 01:15:53 CEST 2008
Author: werner
Date: 2008-09-10 01:15:52 +0200 (Wed, 10 Sep 2008)
New Revision: 4638
Modified:
developers/werner/ahrt/host/tmc/lib/function.py
developers/werner/ahrt/host/tmc/lib/instrument.py
developers/werner/ahrt/host/tmc/lib/meter.py
developers/werner/ahrt/host/tmc/lib/power.py
developers/werner/ahrt/host/tmc/lib/scope.py
developers/werner/ahrt/host/tmc/lib/shape.py
developers/werner/ahrt/host/tmc/lib/trigger.py
developers/werner/ahrt/host/tmc/lib/wave.py
Log:
Highlights:
- debugged the trigger/horizontal system setup (many small bugs)
- classes with settable attributes can now be locked, so that typos like
"s.hor.pod = 0" don't cause silent failure
Details:
- lib/instrument.py (settable), lib/*.py all classes derived from "settable":
added ability to lock the attributes of a "settable" class, such that new
attributes can't be added by accident
- lib/scope.py (channel.name): name was incorrectly set to CHn instead of
CHANn, causing setting the trigger source to fail
- lib/scope.py (horizontal.state_map): has to be a list to have an "index"
method
- lib/scope.py (horizontal): new experimental methods "run" and "stop" to
run/stop the scope
- lib/scope.py (wave): call self.wave, not self.download
- lib/shape.py (__shape_with_duty): seems that a class name can't begin with
two underscores. Renamed to shape_with_duty.
- lib/wave.py (analog.digitize): reject inverted thresholds
- lib/trigger.py: the logic for updating settings after attaching a trigger was
busted. Need to explicitly clear and re-set the attributes.
- lib/trigger.py (trigger.set_sweep): don't try to set if we don't have a value
- lib/trigger.py (trigger.get_sweep): query needs a question mark
- lib/wave.py: use iter(obj), not obj.__iter__()
Modified: developers/werner/ahrt/host/tmc/lib/function.py
===================================================================
--- developers/werner/ahrt/host/tmc/lib/function.py 2008-09-08 22:40:16 UTC (rev 4637)
+++ developers/werner/ahrt/host/tmc/lib/function.py 2008-09-09 23:15:52 UTC (rev 4638)
@@ -16,6 +16,7 @@
class function(instrument):
+ # Warning: "function" doesn't lock itself !
pass
@@ -27,6 +28,7 @@
"vendor=0x164e", "product=0x13ec")
else:
function.__init__(self, "telnet", "tries=3", "nl", name, "5025")
+ self.lock_attr()
def read(self):
return function.read(self).rstrip('\n')
Modified: developers/werner/ahrt/host/tmc/lib/instrument.py
===================================================================
--- developers/werner/ahrt/host/tmc/lib/instrument.py 2008-09-08 22:40:16 UTC (rev 4637)
+++ developers/werner/ahrt/host/tmc/lib/instrument.py 2008-09-09 23:15:52 UTC (rev 4638)
@@ -81,12 +81,39 @@
" "+self.args+str(value))
+#
+# The attributes of a "settable" object can be locked. This means that any
+# attempt to create a new attribute will cause an AttributeError. This is to
+# protect against accidently adding new attributes, which would otherwise cause
+# a silent failure.
+#
+# In order to avoid having to call settable.__init__ in the __init__ methods of
+# all subclasses, attr_is_locked also considers the absence of the
+# "attr_locked" attribute to mean that the class is not (yet) locked.
+#
+
class settable(object):
def set(self, **list):
for key in list.keys():
self.__setattr__(key, list[key])
+ def attr_is_locked(self):
+ try:
+ return super(settable, self).__getattribute__("attr_locked")
+ except AttributeError:
+ return False
+
+ def lock_attr(self):
+ if self.attr_is_locked():
+ raise hell
+ object.__setattr__(self, "attr_locked", True)
+
+ def unlock_attr(self):
+ if not self.attr_is_locked():
+ raise hell
+ object.__setattr__(self, "attr_locked", False)
+
def __getattribute__(self, name):
ret = super(settable, self).__getattribute__(name)
if isinstance(ret, settings):
@@ -97,6 +124,8 @@
attr = self.__dict__.get(name)
if isinstance(attr, settings):
return attr.set(value)
+ if self.attr_is_locked():
+ super(settable, self).__getattribute__(name)
return super(settable, self).__setattr__(name, value)
@@ -109,6 +138,7 @@
def __init__(self, *args):
self.__tmc = _tmc.Instr(*args)
+ # Warning: "instrument" doesn't lock itself !
def send(self, s):
print "SEND", s
Modified: developers/werner/ahrt/host/tmc/lib/meter.py
===================================================================
--- developers/werner/ahrt/host/tmc/lib/meter.py 2008-09-08 22:40:16 UTC (rev 4637)
+++ developers/werner/ahrt/host/tmc/lib/meter.py 2008-09-09 23:15:52 UTC (rev 4638)
@@ -16,6 +16,7 @@
class meter(instrument):
+ # Warning: "meter" doesn't lock itself !
pass
@@ -23,6 +24,7 @@
def __init__(self, name):
meter.__init__(self, "telnet", "tries=3", name)
+ self.lock_attr()
class picotest_m3500a(meter):
@@ -30,3 +32,4 @@
def __init__(self):
meter.__init__(self, "usbtmc", "timeout=2", "retry", "vendor=0x164e",
"product=0x0dad")
+ self.lock_attr()
Modified: developers/werner/ahrt/host/tmc/lib/power.py
===================================================================
--- developers/werner/ahrt/host/tmc/lib/power.py 2008-09-08 22:40:16 UTC (rev 4637)
+++ developers/werner/ahrt/host/tmc/lib/power.py 2008-09-09 23:15:52 UTC (rev 4638)
@@ -17,10 +17,12 @@
#
#
-from tmc.instrument import settable, setting, instrument
+from tmc.instrument import setting, instrument
+
class power(instrument):
- pass
+ # Warning: "power" doesn't lock itself !
+ pass
#
@@ -67,6 +69,8 @@
self.mode = setting(self, ":SYS:STATUS",
lambda s: self.mode_map.get(s, None))
+ self.lock_attr()
+
def send(self, s):
power.send(self, s)
last_read = power.read(self)
Modified: developers/werner/ahrt/host/tmc/lib/scope.py
===================================================================
--- developers/werner/ahrt/host/tmc/lib/scope.py 2008-09-08 22:40:16 UTC (rev 4637)
+++ developers/werner/ahrt/host/tmc/lib/scope.py 2008-09-09 23:15:52 UTC (rev 4638)
@@ -87,7 +87,7 @@
self.scope = scope
self.number = number
- self.name = "CH"+str(number)
+ self.name = "CHAN"+str(number)
self.on = setting(scope, ":CHAN"+str(number)+":DISP",
lambda on: on == "ON",
@@ -108,6 +108,7 @@
self.bwlimit = setting(scope, ":CHAN"+str(self.number)+":BWL",
out_convert = self.scope.bwlimit_translate)
+ self.lock_attr()
self.forget()
def forget(self):
@@ -158,7 +159,7 @@
class horizontal(settable):
- state_map = ( "RUN", "STOP", "T'D", "WAIT", "SCAN", "AUTO" )
+ state_map = [ "RUN", "STOP", "T'D", "WAIT", "SCAN", "AUTO" ]
def __init__(self, scope):
self.scope = scope
@@ -170,6 +171,7 @@
lambda x: "%.9f" % x)
self.sweep = horizontal_trigger_setting(scope,
trigger.set_sweep, trigger.get_sweep)
+ self.lock_attr()
self.forget()
def forget(self):
@@ -177,6 +179,16 @@
self.scale = None
self.sweep = None
+ # "run" and "stop" are experimental: should we instead just have a common
+ # attribute "state" that then automatically determines what to do ? Also,
+ # should "run" send a ":STOP" first ?
+
+ def run(self):
+ self.scope.send(":RUN")
+
+ def stop(self):
+ self.scope.send(":STOP")
+
def force(self):
self.scope.send(":FORC")
@@ -188,6 +200,7 @@
class scope(instrument):
+ # Warning: "scope" doesn't lock itself !
pass
@@ -308,6 +321,7 @@
self.ch.append(channel(self, n))
self.trigger = None
self.hor = horizontal(self)
+ self.lock_attr()
def forget(self):
for ch in self.ch:
@@ -353,7 +367,7 @@
def wave(self, channels, start = None, end = None, step = None):
if not isinstance(channels, list):
- return self.download([channels], start, end, step)[0]
+ return self.wave([channels], start, end, step)[0]
la = None
res = waves()
for ch in channels:
Modified: developers/werner/ahrt/host/tmc/lib/shape.py
===================================================================
--- developers/werner/ahrt/host/tmc/lib/shape.py 2008-09-08 22:40:16 UTC (rev 4637)
+++ developers/werner/ahrt/host/tmc/lib/shape.py 2008-09-09 23:15:52 UTC (rev 4638)
@@ -54,6 +54,7 @@
self.freq = shape_setting(self, 0, self.__set_freq)
self.period = shape_setting(self, None, self.__set_period)
+ self.lock_attr()
self.set(**list)
def __set_low(self, y):
@@ -106,7 +107,7 @@
return sin(2*pi*t*self.freq)*self.peak/2.0+self.offset
-class __shape_with_duty(shape):
+class shape_with_duty(shape):
def __init__(self, init, **list):
self.duty = shape_setting(self, init, self.__set_duty)
@@ -122,20 +123,20 @@
self.duty = self.freq*n
-class square(__shape_with_duty):
+class square(shape_with_duty):
def __init__(self, **list):
- __shape_with_duty(self, 0.5, **list)
+ shape_with_duty.__init__(self, 0.5, **list)
def get(self, t):
p = t*self.freq
return (self.low, self.high)[p-floor(p) < self.duty]
-class ramp(__shape_with_duty):
+class ramp(shape_with_duty):
def __init__(self, **list):
- __shape_with_duty(self, 1, **list)
+ shape_with_duty.__init__(self, 1, **list)
def get(self, t):
p = t*self.freq
Modified: developers/werner/ahrt/host/tmc/lib/trigger.py
===================================================================
--- developers/werner/ahrt/host/tmc/lib/trigger.py 2008-09-08 22:40:16 UTC (rev 4637)
+++ developers/werner/ahrt/host/tmc/lib/trigger.py 2008-09-09 23:15:52 UTC (rev 4638)
@@ -31,6 +31,7 @@
def __init__(self):
self.channel = None
self.scope = None
+ # Warning: "trigger" doesn't lock itself !
def source(self, channel, coupling = None):
if self.scope is not None:
@@ -46,7 +47,9 @@
if coupling is not None:
self.scope.send(
":TRIG:"+self.mode+":COUP "+self.coupling_map[coupling])
- self.scope.send(":TRIG:"+self.mode+":SWE "+scope.sweep)
+ old = self.scope.hor.sweep
+ self.scope.hor.sweep = None
+ self.scope.hor.sweep = old
self.update()
def send(self, *args):
@@ -59,11 +62,14 @@
return self.scope.query(*args)
def set_sweep(self, value):
- self.scope.send(":TRIG:"+self.mode+":SWE "+self.sweep_map[value])
+ if value is not None:
+ self.scope.send(":TRIG:"+self.mode+":SWE "+self.sweep_map[value])
def get_sweep(self):
- return self.sweep_map.index(self.scope.query(":TRIG:"+self.mode+":SWE"))
+ return self.sweep_map.index(
+ self.scope.query(":TRIG:"+self.mode+":SWE?"))
+
class slope:
Rising, Falling, Both = range(3)
@@ -81,6 +87,7 @@
lambda x: self.slope_map.index(x),
lambda x: self.slope_map[x])
self.forget()
+ self.lock_attr()
self.set(**list)
def forget(self):
@@ -88,8 +95,12 @@
self.slope = None
def update(self):
- self.level = self.level
- self.slope = self.slope
+ old = self.level
+ self.level = None
+ self.level = old
+ old = self.slope
+ self.slope = None
+ self.slope = old
def apply(self, wave):
# @@@ only digital waves for now
Modified: developers/werner/ahrt/host/tmc/lib/wave.py
===================================================================
--- developers/werner/ahrt/host/tmc/lib/wave.py 2008-09-08 22:40:16 UTC (rev 4637)
+++ developers/werner/ahrt/host/tmc/lib/wave.py 2008-09-09 23:15:52 UTC (rev 4638)
@@ -184,7 +184,7 @@
self.nxt = []
self.t = None
for w in waves:
- i = w.__iter__()
+ i = iter(w)
v = next_or_none(i)
self.iter.append(i)
self.nxt.append(v)
@@ -358,6 +358,8 @@
def digitize(self, low, high = None):
if high is None:
high = low
+ if high < low:
+ raise hell
res = digital()
state = None
for p in self.data:
More information about the commitlog
mailing list