aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWolfgang Draxinger <Wolfgang.Draxinger@draxit.de>2011-10-27 17:19:16 +0200
committerWolfgang Draxinger <Wolfgang.Draxinger@draxit.de>2011-10-27 17:19:16 +0200
commit3a9ad7c595d2b7e892d2eb6e1e39d789e3e0f575 (patch)
tree5b7e2c7bd20e0b1b69f775b8c3fca3e72b4569a3
parentc15a19b6614c358780a7641a06ac0316924df055 (diff)
downloadPyPhytron-3a9ad7c595d2b7e892d2eb6e1e39d789e3e0f575.tar.gz
PyPhytron-3a9ad7c595d2b7e892d2eb6e1e39d789e3e0f575.tar.bz2
extended status class, exception classes, extendedstatusquery
-rw-r--r--Phytron.py152
1 files changed, 143 insertions, 9 deletions
diff --git a/Phytron.py b/Phytron.py
index c00d079..406913b 100644
--- a/Phytron.py
+++ b/Phytron.py
@@ -9,6 +9,21 @@ class ReceiveChecksumError(exceptions.Exception):
self.received = received
self.message = "Checksum Error: expected %x, got %x" % (expected, received)
+class OverrunError(exceptions.EnvironmentError):
+ pass
+
+class NotNowWarning(exceptions.UserWarning):
+ pass
+
+class UnknownCommand(exceptions.Exception):
+ pass
+
+class BadValueError(exceptions.Exception):
+ pass
+
+class ParameterLimitsError(exceptions.ValueError):
+ pass
+
class Axis:
def __init__(self, ipcomm, ID):
self.ipcomm = ipcomm
@@ -16,8 +31,7 @@ class Axis:
def execute(self, cmd):
result = self.ipcomm.execute(self.ID, cmd)
- assert result['ID'] == self.ID
- del result['ID']
+ assert result.ID == self.ID
return result
def goToAbs(self, position):
@@ -46,6 +60,14 @@ def checksum(data):
return chksm
class Status:
+ COLDBOOT = (1<<7)
+ ANY_ERROR = (1<<6)
+ RX_ERROR = (1<<5)
+ SFI_ERROR = (1<<4)
+ OUTPUTSTAGE_ERROR = (1<<3)
+ INITIATOR_M = (1<<2)
+ INITIATOR_P = (1<<1)
+ RUNNING = (1<<0)
def __init__(self, bitvector):
self.coldboot = not not (bitvector & (1<<7))
self.any_error = not not (bitvector & (1<<6))
@@ -76,6 +98,60 @@ class Status:
status += ['Running']
return '{'+ ('|'.join(status)) + '}'
+class ExtendedStatus:
+ CHECKSUM_ERROR = (1<<23)
+ # (1<<22)
+ RXBUFFER_OVERRUN = (1<<21)
+ NOT_NOW = (1<<20)
+ UNKNOWN_COMMAND = (1<<19)
+ BAD_VALUE = (1<<18)
+ PARAMETER_LIMITS = (1<<17)
+ # (1<<16)
+ NO_SYSTEM = (1<<15)
+ NO_RAMPS = (1<<14)
+ PARAMETER_CHANGED = (1<<13)
+ BUSY = (1<<12)
+ PROGRAMING_ERROR = (1<<11)
+ HIGH_TEMPERATURE = (1<<10)
+ INITIATOR_ERROR = (1<< 9)
+ INTERNAL_ERROR = (1<< 8)
+ DRIVER_ERROR = (1<< 7)
+ # (1<< 6)
+ WAIT_FOR_SYNC = (1<< 5)
+ LINEAR_AXIS = (1<< 4)
+ FREE_RUNNING = (1<< 3)
+ INITIALIZED = (1<< 2)
+ HW_DISABLE = (1<< 1)
+ INITIALIZING = (1<< 0)
+ def __init__(self, bitvector):
+ self.checksum_error = not not (bitvector & ExtendedStatus.CHECKSUM_ERROR)
+ self.rxbuffer_overrun = not not (bitvector & ExtendedStatus.RXBUFFER_OVERRUN)
+ self.not_now = not not (bitvector & ExtendedStatus.NOT_NOW)
+ self.unknown_command = not not (bitvector & ExtendedStatus.UNKNOWN_COMMAND)
+ self.bad_value = not not (bitvector & ExtendedStatus.BAD_VALUE)
+ self.parameter_limits = not not (bitvector & ExtendedStatus.PARAMETER_LIMITS)
+ self.no_system = not not (bitvector & ExtendedStatus.NO_SYSTEM)
+ self.no_ramps = not not (bitvector & ExtendedStatus.NO_RAMPS)
+ self.parameter_changed = not not (bitvector & ExtendedStatus.PARAMETER_CHANGED)
+ self.busy = not not (bitvector & ExtendedStatus.BUSY)
+ self.programing_error = not not (bitvector & ExtendedStatus.PROGRAMING_ERROR)
+ self.high_temperature = not not (bitvector & ExtendedStatus.HIGH_TEMPERATURE)
+ self.initiator_error = not not (bitvector & ExtendedStatus,INITIATOR_ERROR)
+ self.internal_error = not not (bitvector & ExtendedStatus.INTERNAL_ERROR)
+ self.driver_error = not not (bitvector & ExtendedStatus.DRIVER_ERROR)
+ self.wait_for_sync = not not (bitvector & ExtendedStatus.WAIT_FOR_SYNC)
+ self.linear_axis = not not (bitvector & ExtendedStatus.LINEAR_AXIS)
+ self.free_running = not not (bitvector & ExtendedStatus.FREE_RUNNING)
+ self.initialized = not not (bitvector & ExtendedStatus.INITIALIZED)
+ self.hw_disable = not not (bitvector & ExtendedStatus.HW_DISABLE)
+ self.initializing = not not (bitvector & ExtendedStatus.INITIALIZING)
+
+class ReceiveData:
+ def __init__(self, ID, status, data):
+ self.ID = ID
+ self.status = status
+ self.data = data
+
class IPCOMM:
def __init__(self, url, baudrate = 38400, axisnames = None):
self.conn = serial.serial_for_url(url)
@@ -99,7 +175,7 @@ class IPCOMM:
self.axisByName.clear()
for ID in range(0x10):
try:
- assert self.execute(ID, 'IS?')['ID'] == ID
+ assert self.execute(ID, 'IS?').ID == ID
axis = Axis(self, ID)
self.axisByID[ID] = axis
@@ -122,13 +198,13 @@ class IPCOMM:
while c != '\x02':
c = self.conn.read(1)
if not c:
- raise ReceiveTimeout
+ raise ReceiveTimeout()
c = None
while c != '\x03':
c = self.conn.read(1)
if not c:
- raise ReceiveTimeout
+ raise ReceiveTimeout()
buf += c
status, data, chksm = buf[:-1].split(':')
@@ -137,15 +213,18 @@ class IPCOMM:
if expected_chksm != chksm:
raise ReceiveChecksumError(expected_chksm, chksm)
- return {'ID': string.atoi(status[0], 0x10),
- 'status': Status(string.atoi(status[1:], 0x10)),
- 'data': data}
+ return ReceiveData( ID = string.atoi(status[0], 0x10),
+ status = Status(string.atoi(status[1:], 0x10)),
+ data = data )
def broadcast(self, cmd):
self.conn.flushInput()
self.send( '@' + cmd )
def execute(self, ID, cmd):
+ if cmd == 'IS?':
+ return self.queryextendedstatus(ID)
+
self.conn.flushInput()
self.send( ('%X' % ID) + cmd )
@@ -155,7 +234,62 @@ class IPCOMM:
recv_data = self.recv()
except ReceiveChecksumError:
self.send( ('%X' % ID) + 'R')
- # self.parseStatus(recv_status)
+
+ if recv_data.status.rx_error:
+ extended_status = self.queryextendedstatus(ID)
+
+ if extended_status.checksum_error:
+ self.conn.flushInput()
+ self.send( ('%X' % ID) + cmd )
+ recv_data = None
+ continue
+
+ if extended_status.overrun:
+ raise OverrunError()
+
+ if extended_status.not_now:
+ raise NotNowWarning()
+
+ if extended_status.unknown():
+ raise UnknownCommand()
+
+ if extended_status.bad_value:
+ raise BadValueError()
+
+ if extended_status.parameter_limits():
+ raise ParameterLimitsError()
+
+
+ return recv_data
+
+ def queryextendedstatus(self, ID):
+ """
+ Special function for querying the extended status.
+ Same basic structure like execute, with the following exceptions:
+ * does not take a command (always issued a IS?)
+ * will not resend query if status rx_error is reported
+ * will not request reply retransmission
+ * will not raise status related exceptions
+
+ Since regular execute will raise exceptions based on IS? status
+ to query the status for further processing, this method must be used.
+
+ If the extended status can not be requested, None is returned.
+ """
+ self.conn.flushInput()
+ self.send( ('%X' % ID) + 'IS?' )
+
+ recv_data = None
+ try:
+ recv_data = self.recv()
+ except ReceiveChecksumError:
+ return None
+
+ if recv_data:
+ recv_data.data = ExtendedStatus(string.atoi(recv_data.data, 0x10))
+ else:
+ recv_data = None
+
return recv_data
def goToAbs(self, positions):