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 Aeroflex 832X and 833X Series Attenuator Modules 19 20 This class provides a wrapper to the Aeroflex 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.aeroflex.com/ams/weinschel/PDFILES/IM-608-Models-8320-&-8321-preliminary.pdf 26 """ 27 28 29 from acts.controllers import attenuator 30 from acts.controllers.attenuator_lib import _tnhelper 31 32 33 class AttenuatorInstrument(attenuator.AttenuatorInstrument): 34 35 def __init__(self, num_atten=0): 36 super(AttenuatorInstrument, self).__init__(num_atten) 37 38 self._tnhelper = _tnhelper._TNHelper(tx_cmd_separator="\r\n", 39 rx_cmd_separator="\r\n", 40 prompt=">") 41 self.properties = None 42 43 def open(self, host, port=23): 44 r"""Opens a telnet connection to the desired AttenuatorInstrument and queries basic 45 information. 46 47 Parameters 48 ---------- 49 host : A valid hostname (IP address or DNS-resolvable name) to an MC-DAT attenuator 50 instrument. 51 port : An optional port number (defaults to telnet default 23) 52 """ 53 self._tnhelper.open(host, port) 54 55 # work around a bug in IO, but this is a good thing to do anyway 56 self._tnhelper.cmd("*CLS", False) 57 58 if self.num_atten == 0: 59 self.num_atten = int(self._tnhelper.cmd("RFCONFIG? CHAN")) 60 61 configstr = self._tnhelper.cmd("RFCONFIG? ATTN 1") 62 63 self.properties = dict(zip(['model', 'max_atten', 'min_step', 64 'unknown', 'unknown2', 'cfg_str'], 65 configstr.split(", ", 5))) 66 67 self.max_atten = float(self.properties['max_atten']) 68 69 def is_open(self): 70 r"""This function returns the state of the telnet connection to the underlying 71 AttenuatorInstrument. 72 73 Returns 74 ------- 75 Bool 76 True if there is a successfully open connection to the AttenuatorInstrument 77 """ 78 79 return bool(self._tnhelper.is_open()) 80 81 def close(self): 82 r"""Closes a telnet connection to the desired AttenuatorInstrument. 83 84 This should be called as part of any teardown procedure prior to the attenuator 85 instrument leaving scope. 86 """ 87 88 self._tnhelper.close() 89 90 def set_atten(self, idx, value): 91 r"""This function sets the attenuation of an attenuator given its index in the instrument. 92 93 Parameters 94 ---------- 95 idx : This zero-based index is the identifier for a particular attenuator in an 96 instrument. 97 value : This is a floating point value for nominal attenuation to be set. 98 99 Raises 100 ------ 101 InvalidOperationError 102 This error occurs if the underlying telnet connection to the instrument is not open. 103 IndexError 104 If the index of the attenuator is greater than the maximum index of the underlying 105 instrument, this error will be thrown. Do not count on this check programmatically. 106 ValueError 107 If the requested set value is greater than the maximum attenuation value, this error 108 will be thrown. Do not count on this check programmatically. 109 """ 110 111 112 if not self.is_open(): 113 raise attenuator.InvalidOperationError("Connection not open!") 114 115 if idx >= self.num_atten: 116 raise IndexError("Attenuator index out of range!", self.num_atten, idx) 117 118 if value > self.max_atten: 119 raise ValueError("Attenuator value out of range!", self.max_atten, value) 120 121 self._tnhelper.cmd("ATTN " + str(idx+1) + " " + str(value), False) 122 123 def get_atten(self, idx): 124 r"""This function returns the current attenuation from an attenuator at a given index in 125 the instrument. 126 127 Parameters 128 ---------- 129 idx : This zero-based index is the identifier for a particular attenuator in an instrument. 130 131 Raises 132 ------ 133 InvalidOperationError 134 This error occurs if the underlying telnet connection to the instrument is not open. 135 136 Returns 137 ------- 138 float 139 Returns a the current attenuation value 140 """ 141 if not self.is_open(): 142 raise attenuator.InvalidOperationError("Connection not open!") 143 144 # Potentially redundant safety check removed for the moment 145 # if idx >= self.num_atten: 146 # raise IndexError("Attenuator index out of range!", self.num_atten, idx) 147 148 atten_val = self._tnhelper.cmd("ATTN? " + str(idx+1)) 149 150 return float(atten_val) 151