Home | History | Annotate | Download | only in minicircuits
      1 #!/usr/bin/env python3.4
      2 
      3 #   Copyright 2016- The Android Open Source Project
      4 #
      5 #   Licensed under the Apache License, Version 2.0 (the "License");
      6 #   you may not use this file except in compliance with the License.
      7 #   You may obtain a copy of the License at
      8 #
      9 #       http://www.apache.org/licenses/LICENSE-2.0
     10 #
     11 #   Unless required by applicable law or agreed to in writing, software
     12 #   distributed under the License is distributed on an "AS IS" BASIS,
     13 #   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14 #   See the License for the specific language governing permissions and
     15 #   limitations under the License.
     16 
     17 """
     18 Class for Telnet control of Mini-Circuits RCDAT series attenuators
     19 
     20 This class provides a wrapper to the MC-RCDAT attenuator modules for purposes
     21 of simplifying and abstracting control down to the basic necessities. It is
     22 not the intention of the module to expose all functionality, but to allow
     23 interchangeable HW to be used.
     24 
     25 See http://www.minicircuits.com/softwaredownload/Prog_Manual-6-Programmable_Attenuator.pdf
     26 """
     27 
     28 from acts.controllers import attenuator
     29 from acts.controllers.attenuator_lib import _tnhelper
     30 
     31 
     32 class AttenuatorInstrument(attenuator.AttenuatorInstrument):
     33     r"""This provides a specific telnet-controlled implementation of AttenuatorInstrument for
     34     Mini-Circuits RC-DAT attenuators.
     35 
     36     With the exception of telnet-specific commands, all functionality is defined by the
     37     AttenuatorInstrument class. Because telnet is a stateful protocol, the functionality of
     38     AttenuatorInstrument is contingent upon a telnet connection being established.
     39     """
     40 
     41     def __init__(self, num_atten=0):
     42         super(AttenuatorInstrument, self).__init__(num_atten)
     43         self._tnhelper = _tnhelper._TNHelper(tx_cmd_separator="\r\n",
     44                                              rx_cmd_separator="\r\n",
     45                                              prompt="")
     46 
     47     def __del__(self):
     48         if self.is_open():
     49             self.close()
     50 
     51     def open(self, host, port=23):
     52         r"""Opens a telnet connection to the desired AttenuatorInstrument and queries basic
     53         information.
     54 
     55         Parameters
     56         ----------
     57         host : A valid hostname (IP address or DNS-resolvable name) to an MC-DAT attenuator
     58         instrument.
     59         port : An optional port number (defaults to telnet default 23)
     60         """
     61 
     62         self._tnhelper.open(host, port)
     63 
     64         if self.num_atten == 0:
     65             self.num_atten = 1
     66 
     67         config_str = self._tnhelper.cmd("MN?")
     68 
     69         if config_str.startswith("MN="):
     70             config_str = config_str[len("MN="):]
     71 
     72         self.properties = dict(zip(['model', 'max_freq', 'max_atten'], config_str.split("-", 2)))
     73         self.max_atten = float(self.properties['max_atten'])
     74 
     75     def is_open(self):
     76         r"""This function returns the state of the telnet connection to the underlying
     77         AttenuatorInstrument.
     78 
     79         Returns
     80         -------
     81         Bool
     82             True if there is a successfully open connection to the AttenuatorInstrument
     83         """
     84 
     85         return bool(self._tnhelper.is_open())
     86 
     87     def close(self):
     88         r"""Closes a telnet connection to the desired AttenuatorInstrument.
     89 
     90         This should be called as part of any teardown procedure prior to the attenuator
     91         instrument leaving scope.
     92         """
     93 
     94         self._tnhelper.close()
     95 
     96     def set_atten(self, idx, value):
     97         r"""This function sets the attenuation of an attenuator given its index in the instrument.
     98 
     99         Parameters
    100         ----------
    101         idx : This zero-based index is the identifier for a particular attenuator in an
    102               instrument. For instruments that only has one channel, this is ignored by the device.
    103         value : This is a floating point value for nominal attenuation to be set.
    104 
    105         Raises
    106         ------
    107         InvalidOperationError
    108             This error occurs if the underlying telnet connection to the instrument is not open.
    109         IndexError
    110             If the index of the attenuator is greater than the maximum index of the underlying
    111             instrument, this error will be thrown. Do not count on this check programmatically.
    112         ValueError
    113             If the requested set value is greater than the maximum attenuation value, this error
    114             will be thrown. Do not count on this check programmatically.
    115         """
    116 
    117         if not self.is_open():
    118             raise attenuator.InvalidOperationError("Connection not open!")
    119 
    120         if idx >= self.num_atten:
    121             raise IndexError("Attenuator index out of range!", self.num_atten, idx)
    122 
    123         if value > self.max_atten:
    124             raise ValueError("Attenuator value out of range!", self.max_atten, value)
    125         # The actual device uses one-based index for channel numbers.
    126         self._tnhelper.cmd("CHAN:%s:SETATT:%s" % (idx + 1, value))
    127 
    128     def get_atten(self, idx):
    129         r"""This function returns the current attenuation from an attenuator at a given index in
    130         the instrument.
    131 
    132         Parameters
    133         ----------
    134         idx : This zero-based index is the identifier for a particular attenuator in an instrument.
    135 
    136         Raises
    137         ------
    138         InvalidOperationError
    139             This error occurs if the underlying telnet connection to the instrument is not open.
    140 
    141         Returns
    142         -------
    143         float
    144             Returns a the current attenuation value
    145         """
    146 
    147         if not self.is_open():
    148             raise attenuator.InvalidOperationError("Connection not open!")
    149 
    150         if idx >= self.num_atten or idx < 0:
    151             raise IndexError("Attenuator index out of range!", self.num_atten, idx)
    152 
    153         atten_val_str = self._tnhelper.cmd("CHAN:%s:ATT?" % (idx + 1))
    154         atten_val = float(atten_val_str)
    155         return atten_val