Skip to content

Commit

Permalink
Merge #139
Browse files Browse the repository at this point in the history
139: Add missing operations to highlevel.py r=MatthieuDartiailh a=aholtzma

This change plumbs in the missing read_stb() from tcpip.py to highlevel.py.

Co-authored-by: Aaron Holtzman <aaron@appliedmind.ca>
Co-authored-by: Matthieu Dartiailh <marul@laposte.net>
  • Loading branch information
3 people committed Jul 4, 2018
2 parents e6c65bb + 6d563d6 commit 985e470
Show file tree
Hide file tree
Showing 4 changed files with 153 additions and 37 deletions.
2 changes: 1 addition & 1 deletion pyvisa-py/gpib.py
Expand Up @@ -186,7 +186,7 @@ def clear(self):
try:
self.interface.clear()
return 0, StatusCode.success
except:
except Exception:
return 0, StatusCode.error_system_error

def gpib_command(self, command_byte):
Expand Down
79 changes: 71 additions & 8 deletions pyvisa-py/highlevel.py
Expand Up @@ -24,6 +24,7 @@

StatusCode = constants.StatusCode


class PyVisaLibrary(highlevel.VisaLibraryBase):
"""A pure Python backend for PyVISA.
Expand Down Expand Up @@ -194,6 +195,22 @@ def open(self, session, resource_name,

return self._register(sess), StatusCode.success

def assert_trigger(self, session, protocol):
"""Asserts software or hardware trigger.
Corresponds to viAssertTrigger function of the VISA library.
:param session: Unique logical identifier to a session.
:param protocol: Trigger protocol to use during assertion. (Constants.PROT*)
:return: return value of the library call.
:rtype: :class:`pyvisa.constants.StatusCode`
"""
try:
sess = self.sessions[session]
except KeyError:
return 0, constants.StatusCode.error_invalid_object
return sess.assert_trigger(protocol)

def clear(self, session):
"""Clears a device.
Expand All @@ -204,11 +221,10 @@ def clear(self, session):
:rtype: :class:`pyvisa.constants.StatusCode`
"""
try:
self.sessions[session].clear()
return constants.StatusCode.success

sess = self.sessions[session]
except KeyError:
return constants.StatusCode.error_invalid_object
return 0, constants.StatusCode.error_invalid_object
return sess.clear()

def gpib_command(self, session, command_byte):
"""Write GPIB command byte on the bus.
Expand Down Expand Up @@ -253,11 +269,23 @@ def gpib_send_ifc(self, session):
:rtype: :class:`pyvisa.constants.StatusCode`
"""
try:
self.sessions[session].gpib_send_ifc()
return constants.StatusCode.success
sess = self.sessions[session]
except KeyError:
return 0, constants.StatusCode.error_invalid_object
return sess.gpib_send_ifc()

def read_stb(self, session):
"""Reads a status byte of the service request.
Corresponds to viReadSTB function of the VISA library.
:param session: Unique logical identifier to a session.
:return: Service request status byte, return value of the library call.
:rtype: int, :class:`pyvisa.constants.StatusCode`
"""
try:
sess = self.sessions[session]
except KeyError:
return constants.StatusCode.error_invalid_object
return 0, constants.StatusCode.error_invalid_object
return sess.read_stb()

def close(self, session):
"""Closes the specified session, event, or find list.
Expand Down Expand Up @@ -301,7 +329,6 @@ def list_resources(self, session, query='?*::INSTR'):

return resources


def read(self, session, count):
"""Reads data from device or interface synchronously.
Expand Down Expand Up @@ -383,6 +410,42 @@ def set_attribute(self, session, attribute, attribute_state):

return sess.set_attribute(attribute, attribute_state)

def lock(self, session, lock_type, timeout, requested_key=None):
"""Establishes an access mode to the specified resources.
Corresponds to viLock function of the VISA library.
:param session: Unique logical identifier to a session.
:param lock_type: Specifies the type of lock requested, either Constants.EXCLUSIVE_LOCK or Constants.SHARED_LOCK.
:param timeout: Absolute time period (in milliseconds) that a resource waits to get unlocked by the
locking session before returning an error.
:param requested_key: This parameter is not used and should be set to VI_NULL when lockType is VI_EXCLUSIVE_LOCK.
:return: access_key that can then be passed to other sessions to share the lock, return value of the library call.
:rtype: str, :class:`pyvisa.constants.StatusCode`
"""
try:
sess = self.sessions[session]
except KeyError:
return StatusCode.error_invalid_object

return sess.lock(lock_type, timeout, requested_key)

def unlock(self, session):
"""Relinquishes a lock for the specified resource.
Corresponds to viUnlock function of the VISA library.
:param session: Unique logical identifier to a session.
:return: return value of the library call.
:rtype: :class:`pyvisa.constants.StatusCode`
"""
try:
sess = self.sessions[session]
except KeyError:
return StatusCode.error_invalid_object

return sess.unlock()

def disable_event(self, session, event_type, mechanism):
# TODO: implement this for GPIB finalization
pass
Expand Down
36 changes: 36 additions & 0 deletions pyvisa-py/sessions.py
Expand Up @@ -293,6 +293,42 @@ def clear(self):
"""
return StatusCode.error_nonsupported_operation

def read_stb(self):
"""Reads a status byte of the service request.
Corresponds to viReadSTB function of the VISA library.
:return: Service request status byte, return value of the library call.
:rtype: int, :class:`pyvisa.constants.StatusCode`
"""
return 0, StatusCode.error_nonsupported_operation

def lock(self, session, lock_type, timeout, requested_key=None):
"""Establishes an access mode to the specified resources.
Corresponds to viLock function of the VISA library.
:param session: Unique logical identifier to a session.
:param lock_type: Specifies the type of lock requested, either Constants.EXCLUSIVE_LOCK or Constants.SHARED_LOCK.
:param timeout: Absolute time period (in milliseconds) that a resource waits to get unlocked by the
locking session before returning an error.
:param requested_key: This parameter is not used and should be set to VI_NULL when lockType is VI_EXCLUSIVE_LOCK.
:return: access_key that can then be passed to other sessions to share the lock, return value of the library call.
:rtype: str, :class:`pyvisa.constants.StatusCode`
"""
return '', StatusCode.error_nonsupported_operation

def unlock(self, session):
"""Relinquishes a lock for the specified resource.
Corresponds to viUnlock function of the VISA library.
:param session: Unique logical identifier to a session.
:return: return value of the library call.
:rtype: :class:`pyvisa.constants.StatusCode`
"""
return StatusCode.error_nonsupported_operation

def get_attribute(self, attribute):
"""Get the value for a given VISA attribute for this session.
Expand Down
73 changes: 45 additions & 28 deletions pyvisa-py/tcpip.py
Expand Up @@ -24,6 +24,25 @@

StatusCode = constants.StatusCode

# Conversion between VXI11 error codes and VISA status
# TODO this is so far a best guess, in particular 6 and 29 are likely wrong
VXI11_ERRORS_TO_VISA =\
{0: StatusCode.success, # no_error
1: StatusCode.error_invalid_format, # syntax_error
3: StatusCode.error_connection_lost, # device_no_accessible
4: StatusCode.error_invalid_access_key, # invalid_link_identifier
5: StatusCode.error_invalid_parameter, # parameter_error
6: StatusCode.error_handler_not_installed, # channel_not_established
8: StatusCode.error_nonsupported_operation, # operation_not_supported
9: StatusCode.error_allocation, # out_of_resources
11: StatusCode.error_resource_locked, # device_locked_by_another_link
12: StatusCode.error_session_not_locked, # no_lock_held_by_this_link
15: StatusCode.error_timeout, # io_timeout
17: StatusCode.error_io, # io_error
23: StatusCode.error_abort, # abort
29: StatusCode.error_window_already_mapped, # channel_already_established
}


@Session.register(constants.InterfaceType.tcpip, 'INSTR')
class TCPIPInstrSession(Session):
Expand Down Expand Up @@ -101,7 +120,7 @@ def read(self, count):
read_fun = self.interface.device_read
status = StatusCode.success

timeout = int(self.timeout*1000) if self.timeout else 2**32-1
timeout = self._io_timeout
start_time = time.time()
while reason & end_reason == 0:
# Decrease timeout so that the total timeout does not get larger
Expand Down Expand Up @@ -152,15 +171,14 @@ def write(self, data):
num = len(data)
offset = 0

timeout = int(self.timeout*1000) if self.timeout else 2**32-1
while num > 0:
if num <= chunk_size:
flags |= vxi11.OP_FLAG_END

block = data[offset:offset + self.max_recv_size]

error, size = self.interface.device_write(
self.link, timeout, self.lock_timeout,
self.link, self._io_timeout, self.lock_timeout,
flags, block)

if error == vxi11.ErrorCodes.io_timeout:
Expand Down Expand Up @@ -238,13 +256,9 @@ def assert_trigger(self, protocol):
"""

error = self.interface.device_trigger(self.link, 0, self.lock_timeout,
self.io_timeout)
self._io_timeout)

if error:
# TODO: Which status to return
raise Exception("error triggering: %d" % error)

return StatusCode.success
return VXI11_ERRORS_TO_VISA[error]

def clear(self):
"""Clears a device.
Expand All @@ -256,32 +270,24 @@ def clear(self):
"""

error = self.interface.device_clear(self.link, 0, self.lock_timeout,
self.io_timeout)
self._io_timeout)

if error:
# TODO: Which status to return
raise Exception("error clearing: %d" % error)

return StatusCode.success
return VXI11_ERRORS_TO_VISA[error]

def read_stb(self):
"""Reads a status byte of the service request.
Corresponds to viReadSTB function of the VISA library.
:return: Service request status byte, return value of the library call.
:rtype: int, VISAStatus
:rtype: int, :class:`pyvisa.constants.StatusCode`
"""

error, stb = self.interface.device_read_stb(self.link, 0,
self.lock_timeout,
self.io_timeout)
self._io_timeout)

if error:
# TODO: Which status to return
raise Exception("error reading status: %d" % error)

return stb, StatusCode.success
return stb, VXI11_ERRORS_TO_VISA[error]

def lock(self, lock_type, timeout, requested_key=None):
"""Establishes an access mode to the specified resources.
Expand All @@ -305,9 +311,7 @@ def lock(self, lock_type, timeout, requested_key=None):

error = self.interface.device_lock(self.link, flags, self.lock_timeout)

if error:
# TODO: Which status to return
raise Exception("error locking: %d" % error)
return VXI11_ERRORS_TO_VISA[error]

def unlock(self):
"""Relinquishes a lock for the specified resource.
Expand All @@ -319,9 +323,22 @@ def unlock(self):
"""
error = self.interface.device_unlock(self.link)

if error:
# TODO: Which message to return
raise Exception("error unlocking: %d" % error)
return VXI11_ERRORS_TO_VISA[error]

def _set_timeout(self, attribute, value):
""" Sets timeout calculated value from python way to VI_ way
"""
if value == constants.VI_TMO_INFINITE:
self.timeout = None
self._io_timeout = 2**32-1
elif value == constants.VI_TMO_IMMEDIATE:
self.timeout = 0
self._io_timeout = 0
else:
self.timeout = value / 1000.0
self._io_timeout = int(self.timeout*1000)
return StatusCode.success


@Session.register(constants.InterfaceType.tcpip, 'SOCKET')
Expand Down

0 comments on commit 985e470

Please sign in to comment.