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