#!/usr/bin/env python3 # # Copyright 2016 - The Android Open Source Project # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """ Controller interface for Anritsu Signal Generator MG3710A. """ import logging import time import socket from enum import Enum from enum import IntEnum from acts.controllers.anritsu_lib._anritsu_utils import AnritsuError from acts.controllers.anritsu_lib._anritsu_utils import NO_ERROR from acts.controllers.anritsu_lib._anritsu_utils import OPERATION_COMPLETE from acts import tracelogger TERMINATOR = "\n" def create(configs): objs = [] for c in configs: ip_address = c["ip_address"] objs.append(MG3710A(ip_address)) return objs def destroy(objs): return class MG3710A(object): """Class to communicate with Anritsu Signal Generator MG3710A. This uses GPIB command to interface with Anritsu MG3710A """ def __init__(self, ip_address): self._ipaddr = ip_address self.log = tracelogger.TraceLogger(logging.getLogger()) # Open socket connection to Signaling Tester self.log.info("Opening Socket Connection with " "Signal Generator MG3710A ({}) ".format(self._ipaddr)) try: self._sock = socket.create_connection( (self._ipaddr, 49158), timeout=30) self.send_query("*IDN?", 60) self.log.info("Communication Signal Generator MG3710A OK.") self.log.info("Opened Socket connection to ({})" "with handle ({})".format(self._ipaddr, self._sock)) except socket.timeout: raise AnritsuError("Timeout happened while conencting to" " Anritsu MG3710A") except socket.error: raise AnritsuError("Socket creation error") def disconnect(self): """ Disconnect Signal Generator MG3710A Args: None Returns: None """ self.send_command(":SYST:COMM:GTL", opc=False) self._sock.close() def send_query(self, query, sock_timeout=10): """ Sends a Query message to Anritsu MG3710A and return response Args: query - Query string Returns: query response """ self.log.info("--> {}".format(query)) querytoSend = (query + TERMINATOR).encode('utf-8') self._sock.settimeout(sock_timeout) try: self._sock.send(querytoSend) result = self._sock.recv(256).rstrip(TERMINATOR.encode('utf-8')) response = result.decode('utf-8') self.log.info('<-- {}'.format(response)) return response except socket.timeout: raise AnritsuError("Timeout: Response from Anritsu") except socket.error: raise AnritsuError("Socket Error") def send_command(self, command, sock_timeout=30, opc=True): """ Sends a Command message to Anritsu MG3710A Args: command - command string Returns: None """ self.log.info("--> {}".format(command)) cmdToSend = (command + TERMINATOR).encode('utf-8') self._sock.settimeout(sock_timeout) try: self._sock.send(cmdToSend) if opc: # check operation status status = self.send_query("*OPC?") if int(status) != OPERATION_COMPLETE: raise AnritsuError("Operation not completed") except socket.timeout: raise AnritsuError("Timeout for Command Response from Anritsu") except socket.error: raise AnritsuError("Socket Error for Anritsu command") return @property def sg(self): """ Gets current selected signal generator(SG) Args: None Returns: selected signal generatr number """ return self.send_query("PORT?") @sg.setter def sg(self, sg_number): """ Selects the signal generator to be controlled Args: sg_number: sg number 1 | 2 Returns: None """ cmd = "PORT {}".format(sg_number) self.send_command(cmd) def get_modulation_state(self, sg=1): """ Gets the RF signal modulation state (ON/OFF) of signal generator Args: sg: signal generator number. Default is 1 Returns: modulation state . 0 (OFF) | 1(ON) """ return self.send_query("OUTP{}:MOD?".format(sg)) def set_modulation_state(self, state, sg=1): """ Sets the RF signal modulation state Args: sg: signal generator number. Default is 1 state : ON/OFF Returns: None """ cmd = "OUTP{}:MOD {}".format(sg, state) self.send_command(cmd) def get_rf_output_state(self, sg=1): """ Gets RF signal output state (ON/OFF) of signal generator Args: sg: signal generator number. Default is 1 Returns: RF signal output state . 0 (OFF) | 1(ON) """ return self.send_query("OUTP{}?".format(sg)) def set_rf_output_state(self, state, sg=1): """ Sets the RF signal output state Args: sg: signal generator number. Default is 1 state : ON/OFF Returns: None """ cmd = "OUTP{} {}".format(sg, state) self.send_command(cmd) def get_frequency(self, sg=1): """ Gets the selected frequency of signal generator Args: sg: signal generator number. Default is 1 Returns: selected frequency """ return self.send_query("SOUR{}:FREQ?".format(sg)) def set_frequency(self, freq, sg=1): """ Sets the frequency of signal generator Args: sg: signal generator number. Default is 1 freq : frequency Returns: None """ cmd = "SOUR{}:FREQ {}".format(sg, freq) self.send_command(cmd) def get_frequency_offset_state(self, sg=1): """ Gets the Frequency Offset enable state (ON/OFF) of signal generator Args: sg: signal generator number. Default is 1 Returns: Frequency Offset enable state . 0 (OFF) | 1(ON) """ return self.send_query("SOUR{}:FREQ:OFFS:STAT?".format(sg)) def set_frequency_offset_state(self, state, sg=1): """ Sets the Frequency Offset enable state Args: sg: signal generator number. Default is 1 state : enable state, ON/OFF Returns: None """ cmd = "SOUR{}:FREQ:OFFS:STAT {}".format(sg, state) self.send_command(cmd) def get_frequency_offset(self, sg=1): """ Gets the current frequency offset value Args: sg: signal generator number. Default is 1 Returns: current frequency offset value """ return self.send_query("SOUR{}:FREQ:OFFS?".format(sg)) def set_frequency_offset(self, offset, sg=1): """ Sets the frequency offset value Args: sg: signal generator number. Default is 1 offset : frequency offset value Returns: None """ cmd = "SOUR{}:FREQ:OFFS {}".format(sg, offset) self.send_command(cmd) def get_frequency_offset_multiplier_state(self, sg=1): """ Gets the Frequency Offset multiplier enable state (ON/OFF) of signal generator Args: sg: signal generator number. Default is 1 Returns: Frequency Offset multiplier enable state . 0 (OFF) | 1(ON) """ return self.send_query("SOUR{}:FREQ:MULT:STAT?".format(sg)) def set_frequency_offset_multiplier_state(self, state, sg=1): """ Sets the Frequency Offset multiplier enable state Args: sg: signal generator number. Default is 1 state : enable state, ON/OFF Returns: None """ cmd = "SOUR{}:FREQ:MULT:STAT {}".format(sg, state) self.send_command(cmd) def get_frequency_offset_multiplier(self, sg=1): """ Gets the current frequency offset multiplier value Args: sg: signal generator number. Default is 1 Returns: frequency offset multiplier value """ return self.send_query("SOUR{}:FREQ:MULT?".format(sg)) def set_frequency_offset_multiplier(self, multiplier, sg=1): """ Sets the frequency offset multiplier value Args: sg: signal generator number. Default is 1 multiplier : frequency offset multiplier value Returns: None """ cmd = "SOUR{}:FREQ:MULT {}".format(sg, multiplier) self.send_command(cmd) def get_channel(self, sg=1): """ Gets the current channel number Args: sg: signal generator number. Default is 1 Returns: current channel number """ return self.send_query("SOUR{}:FREQ:CHAN:NUMB?".format(sg)) def set_channel(self, channel, sg=1): """ Sets the channel number Args: sg: signal generator number. Default is 1 channel : channel number Returns: None """ cmd = "SOUR{}:FREQ:CHAN:NUMB {}".format(sg, channel) self.send_command(cmd) def get_channel_group(self, sg=1): """ Gets the current channel group number Args: sg: signal generator number. Default is 1 Returns: current channel group number """ return self.send_query("SOUR{}:FREQ:CHAN:GRO?".format(sg)) def set_channel_group(self, group, sg=1): """ Sets the channel group number Args: sg: signal generator number. Default is 1 group : channel group number Returns: None """ cmd = "SOUR{}:FREQ:CHAN:GRO {}".format(sg, group) self.send_command(cmd) def get_rf_output_level(self, sg=1): """ Gets the current RF output level Args: sg: signal generator number. Default is 1 Returns: current RF output level """ return self.send_query("SOUR{}:POW:CURR?".format(sg)) def get_output_level_unit(self, sg=1): """ Gets the current RF output level unit Args: sg: signal generator number. Default is 1 Returns: current RF output level unit """ return self.send_query("UNIT{}:POW?".format(sg)) def set_output_level_unit(self, unit, sg=1): """ Sets the RF output level unit Args: sg: signal generator number. Default is 1 unit : Output level unit Returns: None """ cmd = "UNIT{}:POW {}".format(sg, unit) self.send_command(cmd) def get_output_level(self, sg=1): """ Gets the Output level Args: sg: signal generator number. Default is 1 Returns: Output level """ return self.send_query("SOUR{}:POW?".format(sg)) def set_output_level(self, level, sg=1): """ Sets the Output level Args: sg: signal generator number. Default is 1 level : Output level Returns: None """ cmd = "SOUR{}:POW {}".format(sg, level) self.send_command(cmd) def get_arb_state(self, sg=1): """ Gets the ARB function state Args: sg: signal generator number. Default is 1 Returns: ARB function state . 0 (OFF) | 1(ON) """ return self.send_query("SOUR{}:RAD:ARB?".format(sg)) def set_arb_state(self, state, sg=1): """ Sets the ARB function state Args: sg: signal generator number. Default is 1 state : enable state (ON/OFF) Returns: None """ cmd = "SOUR{}:RAD:ARB {}".format(sg, state) self.send_command(cmd) def restart_arb_waveform_pattern(self, sg=1): """ playback the waveform pattern from the beginning. Args: sg: signal generator number. Default is 1 Returns: None """ cmd = "SOUR{}:RAD:ARB:WAV:REST".format(sg) self.send_command(cmd) def load_waveform(self, package_name, pattern_name, memory, sg=1): """ loads the waveform from HDD to specified memory Args: sg: signal generator number. Default is 1 package_name : Package name of signal pattern_name : Pattern name of signal memory: memory for the signal - "A" or "B" Returns: None """ cmd = "MMEM{}:LOAD:WAV:WM{} '{}','{}'".format(sg, memory, package_name, pattern_name) self.send_command(cmd) def select_waveform(self, package_name, pattern_name, memory, sg=1): """ Selects the waveform to output on specified memory Args: sg: signal generator number. Default is 1 package_name : Package name of signal pattern_name : Pattern name of signal memory: memory for the signal - "A" or "B" Returns: None """ cmd = "SOUR{}:RAD:ARB:WM{}:WAV '{}','{}'".format( sg, memory, package_name, pattern_name) self.send_command(cmd) def get_freq_relative_display_status(self, sg=1): """ Gets the frequency relative display status Args: sg: signal generator number. Default is 1 Returns: frequency relative display status. 0 (OFF) | 1(ON) """ return self.send_query("SOUR{}:FREQ:REF:STAT?".format(sg)) def set_freq_relative_display_status(self, enable, sg=1): """ Sets frequency relative display status Args: sg: signal generator number. Default is 1 enable : enable type (ON/OFF) Returns: None """ cmd = "SOUR{}:FREQ:REF:STAT {}".format(sg, enable) self.send_command(cmd) def get_freq_channel_display_type(self, sg=1): """ Gets the selected type(frequency/channel) for input display Args: sg: signal generator number. Default is 1 Returns: selected type(frequecy/channel) for input display """ return self.send_query("SOUR{}:FREQ:TYPE?".format(sg)) def set_freq_channel_display_type(self, freq_channel, sg=1): """ Sets thes type(frequency/channel) for input display Args: sg: signal generator number. Default is 1 freq_channel : display type (frequency/channel) Returns: None """ cmd = "SOUR{}:FREQ:TYPE {}".format(sg, freq_channel) self.send_command(cmd) def get_arb_combination_mode(self, sg=1): """ Gets the current mode to generate the pattern Args: sg: signal generator number. Default is 1 Returns: current mode to generate the pattern """ return self.send_query("SOUR{}:RAD:ARB:PCOM?".format(sg)) def set_arb_combination_mode(self, mode, sg=1): """ Sets the mode to generate the pattern Args: sg: signal generator number. Default is 1 mode : pattern generation mode Returns: None """ cmd = "SOUR{}:RAD:ARB:PCOM {}".format(sg, mode) self.send_command(cmd) def get_arb_pattern_aorb_state(self, a_or_b, sg=1): """ Gets the Pattern A/B output state Args: sg: signal generator number. Default is 1 a_or_b : Patten A or Pattern B( "A" or "B") Returns: Pattern A/B output state . 0(OFF) | 1(ON) """ return self.send_query("SOUR{}:RAD:ARB:WM{}:OUTP?".format(a_or_b, sg)) def set_arb_pattern_aorb_state(self, a_or_b, state, sg=1): """ Sets the Pattern A/B output state Args: sg: signal generator number. Default is 1 a_or_b : Patten A or Pattern B( "A" or "B") state : output state Returns: None """ cmd = "SOUR{}:RAD:ARB:WM{}:OUTP {}".format(sg, a_or_b, state) self.send_command(cmd) def get_arb_level_aorb(self, a_or_b, sg=1): """ Gets the Pattern A/B output level Args: sg: signal generator number. Default is 1 a_or_b : Patten A or Pattern B( "A" or "B") Returns: Pattern A/B output level """ return self.send_query("SOUR{}:RAD:ARB:WM{}:POW?".format(sg, a_or_b)) def set_arb_level_aorb(self, a_or_b, level, sg=1): """ Sets the Pattern A/B output level Args: sg: signal generator number. Default is 1 a_or_b : Patten A or Pattern B( "A" or "B") level : output level Returns: None """ cmd = "SOUR{}:RAD:ARB:WM{}:POW {}".format(sg, a_or_b, level) self.send_command(cmd) def get_arb_freq_offset(self, sg=1): """ Gets the frequency offset between Pattern A and Patten B when CenterSignal is A or B. Args: sg: signal generator number. Default is 1 Returns: frequency offset between Pattern A and Patten B """ return self.send_query("SOUR{}:RAD:ARB:FREQ:OFFS?".format(sg)) def set_arb_freq_offset(self, offset, sg=1): """ Sets the frequency offset between Pattern A and Patten B when CenterSignal is A or B. Args: sg: signal generator number. Default is 1 offset : frequency offset Returns: None """ cmd = "SOUR{}:RAD:ARB:FREQ:OFFS {}".format(sg, offset) self.send_command(cmd) def get_arb_freq_offset_aorb(self, sg=1): """ Gets the frequency offset of Pattern A/Pattern B based on Baseband center frequency Args: sg: signal generator number. Default is 1 Returns: frequency offset """ return self.send_query( "SOUR{}:RAD:ARB:WM{}:FREQ:OFFS?".format(sg, a_or_b)) def set_arb_freq_offset_aorb(self, a_or_b, offset, sg=1): """ Sets the frequency offset of Pattern A/Pattern B based on Baseband center frequency Args: sg: signal generator number. Default is 1 a_or_b : Patten A or Pattern B( "A" or "B") offset : frequency offset Returns: None """ cmd = "SOUR{}:RAD:ARB:WM{}:FREQ:OFFS {}".format(sg, a_or_b, offset) self.send_command(cmd)