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 Controller interface for Anritsu Signal Generator MG3710A. 18 """ 19 20 import time 21 import socket 22 from enum import Enum 23 from enum import IntEnum 24 25 from acts.controllers.anritsu_lib._anritsu_utils import AnritsuError 26 from acts.controllers.anritsu_lib._anritsu_utils import NO_ERROR 27 from acts.controllers.anritsu_lib._anritsu_utils import OPERATION_COMPLETE 28 29 TERMINATOR = "\n" 30 31 32 def create(configs, logger): 33 objs = [] 34 for c in configs: 35 ip_address = c["ip_address"] 36 objs.append(MG3710A(ip_address, logger)) 37 return objs 38 39 40 def destroy(objs): 41 return 42 43 44 class MG3710A(object): 45 """Class to communicate with Anritsu Signal Generator MG3710A. 46 This uses GPIB command to interface with Anritsu MG3710A """ 47 48 def __init__(self, ip_address, log_handle): 49 self._ipaddr = ip_address 50 self.log = log_handle 51 52 # Open socket connection to Signaling Tester 53 self.log.info("Opening Socket Connection with " 54 "Signal Generator MG3710A ({}) ".format(self._ipaddr)) 55 try: 56 self._sock = socket.create_connection( 57 (self._ipaddr, 49158), timeout=30) 58 self.send_query("*IDN?", 60) 59 self.log.info("Communication Signal Generator MG3710A OK.") 60 self.log.info("Opened Socket connection to ({})" 61 "with handle ({})".format(self._ipaddr, self._sock)) 62 except socket.timeout: 63 raise AnritsuError("Timeout happened while conencting to" 64 " Anritsu MG3710A") 65 except socket.error: 66 raise AnritsuError("Socket creation error") 67 68 def disconnect(self): 69 """ Disconnect Signal Generator MG3710A 70 71 Args: 72 None 73 74 Returns: 75 None 76 """ 77 self.send_command(":SYST:COMM:GTL", opc=False) 78 self._sock.close() 79 80 def send_query(self, query, sock_timeout=10): 81 """ Sends a Query message to Anritsu MG3710A and return response 82 83 Args: 84 query - Query string 85 86 Returns: 87 query response 88 """ 89 self.log.info("--> {}".format(query)) 90 querytoSend = (query + TERMINATOR).encode('utf-8') 91 self._sock.settimeout(sock_timeout) 92 try: 93 self._sock.send(querytoSend) 94 result = self._sock.recv(256).rstrip(TERMINATOR.encode('utf-8')) 95 response = result.decode('utf-8') 96 self.log.info('<-- {}'.format(response)) 97 return response 98 except socket.timeout: 99 raise AnritsuError("Timeout: Response from Anritsu") 100 except socket.error: 101 raise AnritsuError("Socket Error") 102 103 def send_command(self, command, sock_timeout=30, opc=True): 104 """ Sends a Command message to Anritsu MG3710A 105 106 Args: 107 command - command string 108 109 Returns: 110 None 111 """ 112 self.log.info("--> {}".format(command)) 113 cmdToSend = (command + TERMINATOR).encode('utf-8') 114 self._sock.settimeout(sock_timeout) 115 try: 116 self._sock.send(cmdToSend) 117 if opc: 118 # check operation status 119 status = self.send_query("*OPC?") 120 if int(status) != OPERATION_COMPLETE: 121 raise AnritsuError("Operation not completed") 122 except socket.timeout: 123 raise AnritsuError("Timeout for Command Response from Anritsu") 124 except socket.error: 125 raise AnritsuError("Socket Error for Anritsu command") 126 return 127 128 @property 129 def sg(self): 130 """ Gets current selected signal generator(SG) 131 132 Args: 133 None 134 135 Returns: 136 selected signal generatr number 137 """ 138 return self.send_query("PORT?") 139 140 @sg.setter 141 def sg(self, sg_number): 142 """ Selects the signal generator to be controlled 143 144 Args: 145 sg_number: sg number 1 | 2 146 147 Returns: 148 None 149 """ 150 cmd = "PORT {}".format(sg_number) 151 self.send_command(cmd) 152 153 def get_modulation_state(self, sg=1): 154 """ Gets the RF signal modulation state (ON/OFF) of signal generator 155 156 Args: 157 sg: signal generator number. 158 Default is 1 159 160 Returns: 161 modulation state . 0 (OFF) | 1(ON) 162 """ 163 return self.send_query("OUTP{}:MOD?".format(sg)) 164 165 def set_modulation_state(self, state, sg=1): 166 """ Sets the RF signal modulation state 167 168 Args: 169 sg: signal generator number. 170 Default is 1 171 state : ON/OFF 172 173 Returns: 174 None 175 """ 176 cmd = "OUTP{}:MOD {}".format(sg, state) 177 self.send_command(cmd) 178 179 def get_rf_output_state(self, sg=1): 180 """ Gets RF signal output state (ON/OFF) of signal generator 181 182 Args: 183 sg: signal generator number. 184 Default is 1 185 186 Returns: 187 RF signal output state . 0 (OFF) | 1(ON) 188 """ 189 return self.send_query("OUTP{}?".format(sg)) 190 191 def set_rf_output_state(self, state, sg=1): 192 """ Sets the RF signal output state 193 194 Args: 195 sg: signal generator number. 196 Default is 1 197 state : ON/OFF 198 199 Returns: 200 None 201 """ 202 cmd = "OUTP{} {}".format(sg, state) 203 self.send_command(cmd) 204 205 def get_frequency(self, sg=1): 206 """ Gets the selected frequency of signal generator 207 208 Args: 209 sg: signal generator number. 210 Default is 1 211 212 Returns: 213 selected frequency 214 """ 215 return self.send_query("SOUR{}:FREQ?".format(sg)) 216 217 def set_frequency(self, freq, sg=1): 218 """ Sets the frequency of signal generator 219 220 Args: 221 sg: signal generator number. 222 Default is 1 223 freq : frequency 224 225 Returns: 226 None 227 """ 228 cmd = "SOUR{}:FREQ {}".format(sg, freq) 229 self.send_command(cmd) 230 231 def get_frequency_offset_state(self, sg=1): 232 """ Gets the Frequency Offset enable state (ON/OFF) of signal generator 233 234 Args: 235 sg: signal generator number. 236 Default is 1 237 238 Returns: 239 Frequency Offset enable state . 0 (OFF) | 1(ON) 240 """ 241 return self.send_query("SOUR{}:FREQ:OFFS:STAT?".format(sg)) 242 243 def set_frequency_offset_state(self, state, sg=1): 244 """ Sets the Frequency Offset enable state 245 246 Args: 247 sg: signal generator number. 248 Default is 1 249 state : enable state, ON/OFF 250 251 Returns: 252 None 253 """ 254 cmd = "SOUR{}:FREQ:OFFS:STAT {}".format(sg, state) 255 self.send_command(cmd) 256 257 def get_frequency_offset(self, sg=1): 258 """ Gets the current frequency offset value 259 260 Args: 261 sg: signal generator number. 262 Default is 1 263 264 Returns: 265 current frequency offset value 266 """ 267 return self.send_query("SOUR{}:FREQ:OFFS?".format(sg)) 268 269 def set_frequency_offset(self, offset, sg=1): 270 """ Sets the frequency offset value 271 272 Args: 273 sg: signal generator number. 274 Default is 1 275 offset : frequency offset value 276 277 Returns: 278 None 279 """ 280 cmd = "SOUR{}:FREQ:OFFS {}".format(sg, offset) 281 self.send_command(cmd) 282 283 def get_frequency_offset_multiplier_state(self, sg=1): 284 """ Gets the Frequency Offset multiplier enable state (ON/OFF) of 285 signal generator 286 287 Args: 288 sg: signal generator number. 289 Default is 1 290 291 Returns: 292 Frequency Offset multiplier enable state . 0 (OFF) | 1(ON) 293 """ 294 return self.send_query("SOUR{}:FREQ:MULT:STAT?".format(sg)) 295 296 def set_frequency_offset_multiplier_state(self, state, sg=1): 297 """ Sets the Frequency Offset multiplier enable state 298 299 Args: 300 sg: signal generator number. 301 Default is 1 302 state : enable state, ON/OFF 303 304 Returns: 305 None 306 """ 307 cmd = "SOUR{}:FREQ:MULT:STAT {}".format(sg, state) 308 self.send_command(cmd) 309 310 def get_frequency_offset_multiplier(self, sg=1): 311 """ Gets the current frequency offset multiplier value 312 313 Args: 314 sg: signal generator number. 315 Default is 1 316 317 Returns: 318 frequency offset multiplier value 319 """ 320 return self.send_query("SOUR{}:FREQ:MULT?".format(sg)) 321 322 def set_frequency_offset_multiplier(self, multiplier, sg=1): 323 """ Sets the frequency offset multiplier value 324 325 Args: 326 sg: signal generator number. 327 Default is 1 328 multiplier : frequency offset multiplier value 329 330 Returns: 331 None 332 """ 333 cmd = "SOUR{}:FREQ:MULT {}".format(sg, multiplier) 334 self.send_command(cmd) 335 336 def get_channel(self, sg=1): 337 """ Gets the current channel number 338 339 Args: 340 sg: signal generator number. 341 Default is 1 342 343 Returns: 344 current channel number 345 """ 346 return self.send_query("SOUR{}:FREQ:CHAN:NUMB?".format(sg)) 347 348 def set_channel(self, channel, sg=1): 349 """ Sets the channel number 350 351 Args: 352 sg: signal generator number. 353 Default is 1 354 channel : channel number 355 356 Returns: 357 None 358 """ 359 cmd = "SOUR{}:FREQ:CHAN:NUMB {}".format(sg, channel) 360 self.send_command(cmd) 361 362 def get_channel_group(self, sg=1): 363 """ Gets the current channel group number 364 365 Args: 366 sg: signal generator number. 367 Default is 1 368 369 Returns: 370 current channel group number 371 """ 372 return self.send_query("SOUR{}:FREQ:CHAN:GRO?".format(sg)) 373 374 def set_channel_group(self, group, sg=1): 375 """ Sets the channel group number 376 377 Args: 378 sg: signal generator number. 379 Default is 1 380 group : channel group number 381 382 Returns: 383 None 384 """ 385 cmd = "SOUR{}:FREQ:CHAN:GRO {}".format(sg, group) 386 self.send_command(cmd) 387 388 def get_rf_output_level(self, sg=1): 389 """ Gets the current RF output level 390 391 Args: 392 sg: signal generator number. 393 Default is 1 394 395 Returns: 396 current RF output level 397 """ 398 return self.send_query("SOUR{}:POW:CURR?".format(sg)) 399 400 def get_output_level_unit(self, sg=1): 401 """ Gets the current RF output level unit 402 403 Args: 404 sg: signal generator number. 405 Default is 1 406 407 Returns: 408 current RF output level unit 409 """ 410 return self.send_query("UNIT{}:POW?".format(sg)) 411 412 def set_output_level_unit(self, unit, sg=1): 413 """ Sets the RF output level unit 414 415 Args: 416 sg: signal generator number. 417 Default is 1 418 unit : Output level unit 419 420 Returns: 421 None 422 """ 423 cmd = "UNIT{}:POW {}".format(sg, unit) 424 self.send_command(cmd) 425 426 def get_output_level(self, sg=1): 427 """ Gets the Output level 428 429 Args: 430 sg: signal generator number. 431 Default is 1 432 433 Returns: 434 Output level 435 """ 436 return self.send_query("SOUR{}:POW?".format(sg)) 437 438 def set_output_level(self, level, sg=1): 439 """ Sets the Output level 440 441 Args: 442 sg: signal generator number. 443 Default is 1 444 level : Output level 445 446 Returns: 447 None 448 """ 449 cmd = "SOUR{}:POW {}".format(sg, level) 450 self.send_command(cmd) 451 452 def get_arb_state(self, sg=1): 453 """ Gets the ARB function state 454 455 Args: 456 sg: signal generator number. 457 Default is 1 458 459 Returns: 460 ARB function state . 0 (OFF) | 1(ON) 461 """ 462 return self.send_query("SOUR{}:RAD:ARB?".format(sg)) 463 464 def set_arb_state(self, state, sg=1): 465 """ Sets the ARB function state 466 467 Args: 468 sg: signal generator number. 469 Default is 1 470 state : enable state (ON/OFF) 471 472 Returns: 473 None 474 """ 475 cmd = "SOUR{}:RAD:ARB {}".format(sg, state) 476 self.send_command(cmd) 477 478 def restart_arb_waveform_pattern(self, sg=1): 479 """ playback the waveform pattern from the beginning. 480 481 Args: 482 sg: signal generator number. 483 Default is 1 484 485 Returns: 486 None 487 """ 488 cmd = "SOUR{}:RAD:ARB:WAV:REST".format(sg) 489 self.send_command(cmd) 490 491 def load_waveform(self, package_name, pattern_name, memory, sg=1): 492 """ loads the waveform from HDD to specified memory 493 494 Args: 495 sg: signal generator number. 496 Default is 1 497 package_name : Package name of signal 498 pattern_name : Pattern name of signal 499 memory: memory for the signal - "A" or "B" 500 501 Returns: 502 None 503 """ 504 cmd = "MMEM{}:LOAD:WAV:WM{} '{}','{}'".format(sg, memory, package_name, 505 pattern_name) 506 self.send_command(cmd) 507 508 def select_waveform(self, package_name, pattern_name, memory, sg=1): 509 """ Selects the waveform to output on specified memory 510 511 Args: 512 sg: signal generator number. 513 Default is 1 514 package_name : Package name of signal 515 pattern_name : Pattern name of signal 516 memory: memory for the signal - "A" or "B" 517 518 Returns: 519 None 520 """ 521 cmd = "SOUR{}:RAD:ARB:WM{}:WAV '{}','{}'".format( 522 sg, memory, package_name, pattern_name) 523 self.send_command(cmd) 524 525 def get_freq_relative_display_status(self, sg=1): 526 """ Gets the frequency relative display status 527 528 Args: 529 sg: signal generator number. 530 Default is 1 531 532 Returns: 533 frequency relative display status. 0 (OFF) | 1(ON) 534 """ 535 return self.send_query("SOUR{}:FREQ:REF:STAT?".format(sg)) 536 537 def set_freq_relative_display_status(self, enable, sg=1): 538 """ Sets frequency relative display status 539 540 Args: 541 sg: signal generator number. 542 Default is 1 543 enable : enable type (ON/OFF) 544 545 Returns: 546 None 547 """ 548 cmd = "SOUR{}:FREQ:REF:STAT {}".format(sg, enable) 549 self.send_command(cmd) 550 551 def get_freq_channel_display_type(self, sg=1): 552 """ Gets the selected type(frequency/channel) for input display 553 554 Args: 555 sg: signal generator number. 556 Default is 1 557 558 Returns: 559 selected type(frequecy/channel) for input display 560 """ 561 return self.send_query("SOUR{}:FREQ:TYPE?".format(sg)) 562 563 def set_freq_channel_display_type(self, freq_channel, sg=1): 564 """ Sets thes type(frequency/channel) for input display 565 566 Args: 567 sg: signal generator number. 568 Default is 1 569 freq_channel : display type (frequency/channel) 570 571 Returns: 572 None 573 """ 574 cmd = "SOUR{}:FREQ:TYPE {}".format(sg, freq_channel) 575 self.send_command(cmd) 576 577 def get_arb_combination_mode(self, sg=1): 578 """ Gets the current mode to generate the pattern 579 580 Args: 581 sg: signal generator number. 582 Default is 1 583 584 Returns: 585 current mode to generate the pattern 586 """ 587 return self.send_query("SOUR{}:RAD:ARB:PCOM?".format(sg)) 588 589 def set_arb_combination_mode(self, mode, sg=1): 590 """ Sets the mode to generate the pattern 591 592 Args: 593 sg: signal generator number. 594 Default is 1 595 mode : pattern generation mode 596 597 Returns: 598 None 599 """ 600 cmd = "SOUR{}:RAD:ARB:PCOM {}".format(sg, mode) 601 self.send_command(cmd) 602 603 def get_arb_pattern_aorb_state(self, a_or_b, sg=1): 604 """ Gets the Pattern A/B output state 605 606 Args: 607 sg: signal generator number. 608 Default is 1 609 a_or_b : Patten A or Pattern B( "A" or "B") 610 611 Returns: 612 Pattern A/B output state . 0(OFF) | 1(ON) 613 """ 614 return self.send_query("SOUR{}:RAD:ARB:WM{}:OUTP?".format(a_or_b, sg)) 615 616 def set_arb_pattern_aorb_state(self, a_or_b, state, sg=1): 617 """ Sets the Pattern A/B output state 618 619 Args: 620 sg: signal generator number. 621 Default is 1 622 a_or_b : Patten A or Pattern B( "A" or "B") 623 state : output state 624 625 Returns: 626 None 627 """ 628 cmd = "SOUR{}:RAD:ARB:WM{}:OUTP {}".format(sg, a_or_b, state) 629 self.send_command(cmd) 630 631 def get_arb_level_aorb(self, a_or_b, sg=1): 632 """ Gets the Pattern A/B output level 633 634 Args: 635 sg: signal generator number. 636 Default is 1 637 a_or_b : Patten A or Pattern B( "A" or "B") 638 639 Returns: 640 Pattern A/B output level 641 """ 642 return self.send_query("SOUR{}:RAD:ARB:WM{}:POW?".format(sg, a_or_b)) 643 644 def set_arb_level_aorb(self, a_or_b, level, sg=1): 645 """ Sets the Pattern A/B output level 646 647 Args: 648 sg: signal generator number. 649 Default is 1 650 a_or_b : Patten A or Pattern B( "A" or "B") 651 level : output level 652 653 Returns: 654 None 655 """ 656 cmd = "SOUR{}:RAD:ARB:WM{}:POW {}".format(sg, a_or_b, level) 657 self.send_command(cmd) 658 659 def get_arb_freq_offset(self, sg=1): 660 """ Gets the frequency offset between Pattern A and Patten B 661 when CenterSignal is A or B. 662 663 Args: 664 sg: signal generator number. 665 Default is 1 666 667 Returns: 668 frequency offset between Pattern A and Patten B 669 """ 670 return self.send_query("SOUR{}:RAD:ARB:FREQ:OFFS?".format(sg)) 671 672 def set_arb_freq_offset(self, offset, sg=1): 673 """ Sets the frequency offset between Pattern A and Patten B when 674 CenterSignal is A or B. 675 676 Args: 677 sg: signal generator number. 678 Default is 1 679 offset : frequency offset 680 681 Returns: 682 None 683 """ 684 cmd = "SOUR{}:RAD:ARB:FREQ:OFFS {}".format(sg, offset) 685 self.send_command(cmd) 686 687 def get_arb_freq_offset_aorb(self, sg=1): 688 """ Gets the frequency offset of Pattern A/Pattern B based on Baseband 689 center frequency 690 691 Args: 692 sg: signal generator number. 693 Default is 1 694 695 Returns: 696 frequency offset 697 """ 698 return self.send_query("SOUR{}:RAD:ARB:WM{}:FREQ:OFFS?".format(sg, 699 a_or_b)) 700 701 def set_arb_freq_offset_aorb(self, a_or_b, offset, sg=1): 702 """ Sets the frequency offset of Pattern A/Pattern B based on Baseband 703 center frequency 704 705 Args: 706 sg: signal generator number. 707 Default is 1 708 a_or_b : Patten A or Pattern B( "A" or "B") 709 offset : frequency offset 710 711 Returns: 712 None 713 """ 714 cmd = "SOUR{}:RAD:ARB:WM{}:FREQ:OFFS {}".format(sg, a_or_b, offset) 715 self.send_command(cmd) 716