| #!/usr/bin/env python |
| # Copyright 2016 The Chromium OS Authors. All rights reserved. |
| # Use of this source code is governed by a BSD-style license that can be |
| # found in the LICENSE file. |
| |
| """Implementation of GPIB interface wrapper. |
| |
| This module depends on PyVISA and PyVISA-py python module, and the linux-gpib |
| backend driver. |
| """ |
| |
| import time |
| import visa |
| |
| from .. import link |
| from ..default_setting import logger |
| |
| |
| class GPIBLink(link.DeviceLink): |
| """A DUT target that is connected via GPIB interface. |
| |
| link_options example: |
| { |
| 'link_class': 'GPIBLink', |
| 'minor': 0, |
| 'primary': 0 |
| } |
| """ |
| |
| def __init__(self, minor=0, primary=0, timeout=3, query_delay=0.0): |
| """Create the GPIB resource with pyvisa. |
| |
| Args: |
| minor: specify which device file to be used. 0 correspondes to /dev/gpib0 |
| primary: the primary GPIB address. Valid address are 0 to 30. |
| timeout: the timeout for each call, unit in seconds. |
| query_delay: the delay between write and read command, unit in seconds. |
| """ |
| if query_delay < 0: |
| raise ValueError('query_delay should not be negative.') |
| self.query_delay = query_delay |
| try: |
| resource_manager = visa.ResourceManager() # Use NI backend |
| except OSError: |
| resource_manager = visa.ResourceManager('@py') # Use Linux-GPIB |
| except OSError: |
| raise OSError('Cannot find the GPIB backend. For Windows platform ' |
| 'please install NI-488.2 driver. For Linux platform ' |
| 'please install linux-gpib and PyVisa-Py module.') |
| try: |
| name = u'GPIB%d::%d::INSTR' % (minor, primary) |
| self.device = resource_manager.open_resource(name) |
| # PyVisa will set the smallest valid timeout that BIGGER than |
| # the value we set. For example, the valid timeouts are 1000, 3000, 10000. |
| # When we set 1000~2999, PyVisa would set 3000. When we set 3000~9999, |
| # PyVisa would set 10000. So we minus 0.1 to let PyVisa set the smallest |
| # valid timeout that SAME OR BIGGER than the value we set. |
| self.device.timeout = (timeout * 1000) - 0.1 |
| except Exception as ex: |
| raise ValueError('GPIBLink Init failed. %s' % ex) |
| |
| def Close(self): |
| if self.device is not None: |
| self.device.close() |
| self.device = None |
| |
| def Push(self, local, remote): |
| raise NotImplementedError |
| |
| def Pull(self, remote, local=None): |
| raise NotImplementedError |
| |
| def Shell(self, command, stdin=None, stdout=None, stderr=None): |
| raise NotImplementedError |
| |
| def IsReady(self): |
| try: |
| info = self.CallOutput('*IDN?') |
| return info != '' |
| except ValueError: |
| return False |
| |
| # pylint: disable=W0221 |
| def Call(self, command, stdin=None, stdout=None, stderr=None): |
| """Send command with GPIB interface. |
| |
| Write the command to the device. If stdout is not None, then read the result |
| back and store into stdout. Since it is not a real linux shell, other |
| standard streams are not supported. |
| |
| Args: |
| command: a string or a list, to be write to device. |
| Returns: the return code. |
| """ |
| if (stdin, stderr) != (None, None): |
| raise NotImplementedError('Standard input and error are not supported.') |
| |
| if isinstance(command, list): |
| command = ' '.join([str(arg) for arg in command]) |
| logger.debug('GPIB Write: %s', command) |
| return_code = self.device.write(command) |
| # The return value should be (byte size, Status code), but PyVisa-py only |
| # returns the status code while successful. |
| if not isinstance(return_code, int): |
| return_code = int(return_code[1]) |
| |
| if stdout is not None and return_code == 0: |
| time.sleep(self.query_delay) |
| output = self.device.read() |
| stdout.write(output) |
| return return_code |