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