Post Go back to editing

GNURADIO with Phaser

Category: Software

Have anyone tried GNURADIO with Phaser? 

I am wondering if anyone has a GNURADIO file that works with the phaser and can share it (it does not matter what is for, I need to check what hardware blocks are used)

I have tried to build a system for the Phaser based on the ADAR1000 GNURadio tutorials but it does not work Disappointed

My objective is to build a monopole tracking with GNURadio and the phaser

  • Hi Ameno,

    Here is a talk that Mark Thoren and I did last year at the GNU radio conference.  It could help you:

    https://www.youtube.com/live/i17fZ7J8e_c?si=aO_co_t9LqTYcG0b&t=20144

    And attached are the GRC flowgraph files from that demo (remove the .txt from the file names):

    # Copyright (C) 2023 Analog Devices, Inc.
    # All rights reserved.
    # jon.kraft@analog.com
    # wiki.analog.com/phaser
    
    # Redistribution and use in source and binary forms, with or without modification,
    # are permitted provided that the following conditions are met:
    #     - Redistributions of source code must retain the above copyright
    #       notice, this list of conditions and the following disclaimer.
    #     - Redistributions in binary form must reproduce the above copyright
    #       notice, this list of conditions and the following disclaimer in
    #       the documentation and/or other materials provided with the
    #       distribution.
    #     - Neither the name of Analog Devices, Inc. nor the names of its
    #       contributors may be used to endorse or promote products derived
    #       from this software without specific prior written permission.
    #     - The use of this software may or may not infringe the patent rights
    #       of one or more patent holders.  This license does not release you
    #       from the requirement that you obtain separate licenses from these
    #       patent holders to use this software.
    #     - Use of the software either in source or binary form, must be run
    #       on or directly connected to an Analog Devices Inc. component.
    #
    # THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
    # INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A
    # PARTICULAR PURPOSE ARE DISCLAIMED.
    #
    # IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
    # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, INTELLECTUAL PROPERTY
    # RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
    # BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
    # STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
    # THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    
    
    """
    Embedded Python Blocks:
    
    Each time this file is saved, GRC will instantiate the first class it finds
    to get ports and parameters of your block. The arguments to __init__  will
    be the parameters. All of them are required to have default values!
    """
    import sys
    import pickle
    import os
    
    import adi
    import numpy as np
    sys.path.append('/home/analog/pyadi-iio/examples/phaser/')
    import SDR_functions as SDR  # import the Pluto SDR functions
    import ADAR_pyadi_functions_edited1 as ADAR  # import the ADAR1000 functions
    from gnuradio import gr
    
    class blk(gr.sync_block):
        def __init__(self, step_size=3, save_trace=False, clear_trace=False,
                     gain1=100, gain2=100, gain3=100, gain4=100, gain5=100, gain6=100, gain7=100, gain8=100,
                     phase1=0, phase2=0, phase3=0, phase4=0, phase5=0, phase6=0, phase7=0, phase8=0,
                     null_enable_1 = False, null_angle_1=0, null_enable_2 = False, null_angle_2=0):  # only default arguments here
            """arguments to this function show up as parameters in GRC"""
            gr.sync_block.__init__(
                self,
                name='Phaser Python Control Block',   # will show up in GRC
                in_sig=[],
                out_sig=[np.complex64, np.complex64]
            )
            # if an attribute with the same name as a parameter is found,
            # a callback is registered (properties work, too)
            
            # =============================================================================
            # User parameters
            # =============================================================================
            self.step_size = step_size  # steering angle step size (in degrees)
            self.save_trace = save_trace
            self.clear_trace = clear_trace
            self.saved_trace = np.ones(4094)*(0-100000j)
            
            self.gain1=gain1
            self.gain2=gain2
            self.gain3=gain3
            self.gain4=gain4
            self.gain5=gain5
            self.gain6=gain6
            self.gain7=gain7
            self.gain8=gain8
            
            self.phase1=phase1
            self.phase2=phase2
            self.phase3=phase3
            self.phase4=phase4
            self.phase5=phase5
            self.phase6=phase6
            self.phase7=phase7
            self.phase8=phase8
            
            self.null_enable_1 = null_enable_1
            self.null_angle_1 = null_angle_1
            self.null_enable_2 = null_enable_2
            self.null_angle_2 = null_angle_2
            
            rpi_ip = "ip:phaser.local"  # default IP address of Phaser's Raspberry Pi
            sdr_ip = "ip:192.168.2.1"   # default Pluto IP address
            
            # select which signal source to use
            # HB100 (external source)
            # OUT1  (transmit freq is set in config.py)
            # OUT2  (transmit freq is set in config.py)
            SignalSource = 'HB100'     # 'HB100', 'OUT1', or 'OUT2'
            
            # config.py has all the key parameters that you might want to modify
            try:
                import config as config
            except:
                print("Make sure config.py is in this directory")
                sys.exit(0)
                
            
            # =============================================================================
            # Variables setup
            # =============================================================================
            
            # if using HB100, load the signal frequency from "phaser_find_hb100.py" output file
            if SignalSource == 'HB100':
                try:
                    #with open("/home/analog/pyadi-iio/examples/phaser/hb100_freq_val.pkl", "rb") as file1: 
                    with open("hb100_freq_val.pkl", "rb") as file1: 
                        config.SignalFreq = pickle.load(file1)
                    print("Found signal freq file, ", config.SignalFreq/1e9, " GHz")
                except:
                    print("No signal freq found, keeping at ", config.SignalFreq/1e9, " GHz")
            
            """SET DEFAULT VALUES"""
            sdr_address = sdr_ip
            self.SignalFreq = config.SignalFreq
            Tx_freq = config.Tx_freq  # Pluto's Tx LO freq.
            Rx_freq = config.Rx_freq  # Pluto's Rx LO freq
            LO_freq = self.SignalFreq + Rx_freq  # freq of the LTC5548 mixer LO
            SampleRate = config.SampleRate
            Rx_gain = config.Rx_gain
            Tx_gain = config.Tx_gain
            self.RxPhase1 = config.Rx1_cal
            self.RxPhase2 = config.Rx2_cal
            self.RxPhase3 = config.Rx3_cal
            self.RxPhase4 = config.Rx4_cal
            self.RxPhase5 = config.Rx5_cal
            self.RxPhase6 = config.Rx6_cal
            self.RxPhase7 = config.Rx7_cal
            self.RxPhase8 = config.Rx8_cal
            self.phase_step_size = 2.8125
            self.c = 299792458  # speed of light in m/s
            self.d = config.d   # antenna spacing for phaser is 14mm
            self.gainList = np.array([
                self.gain1,
                self.gain2,
                self.gain3,
                self.gain4,
                self.gain5,
                self.gain6,
                self.gain7,
                self.gain8
                ])
            self.phaseList = np.array([
                self.RxPhase1,
                self.RxPhase2,
                self.RxPhase3,
                self.RxPhase4,
                self.RxPhase5,
                self.RxPhase6,
                self.RxPhase7,
                self.RxPhase8
                ])        
            
            # Use the onboard VCO to generate the LO?  Or apply source to EXT_LO?
            gpios = adi.one_bit_adc_dac(rpi_ip)
            gpios.gpio_vctrl_1 = 1  # 1=Use onboard PLL/LO source  (0=use external LO input)
            gpios.gpio_vctrl_2 = 1  # 1=Send LO to transmit circuitry  (0=disable Tx path and send LO to LO_OUT)
            
            # setup GPIOs to control if Tx is output on OUT1 or OUT2
            gpios.gpio_div_mr = 1
            gpios.gpio_div_s0 = 0
            gpios.gpio_div_s1 = 0
            gpios.gpio_div_s2 = 0
            attempt = True
            while attempt:
                try:
                    # Initialize Pluto
                    self.sdr = SDR.SDR_init(
                        sdr_address,
                        SampleRate,
                        Tx_freq,
                        Rx_freq,
                        Rx_gain,
                        Tx_gain,
                        config.buffer_size,
                        )
                    SDR.SDR_LO_init(rpi_ip, LO_freq)  # Set Phaser's ADF4159 to the LO_freq
                    
                    # Intialize the ADAR1000 receive array
                    self.rx_array = adi.adar1000_array(
                        uri=rpi_ip,
                        chip_ids=["BEAM0", "BEAM1"],  # these are the ADAR1000s' labels in the device tree
                        device_map=[[1], [2]],
                        element_map=[[1, 2, 3, 4, 5, 6, 7, 8]],
                        device_element_map={
                            1: [7, 8, 5, 6],  # i.e. channel2 of device1 (BEAM0), maps to element 8
                            2: [3, 4, 1, 2],
                            },
                        )
                    attempt = False
                    print('Connected to Phaser')
                except:
                    print('Could not connect to Phaser')
                    continue
            for device in self.rx_array.devices.values():
                ADAR.ADAR_init(device)  # resets the ADAR1000
                ADAR.ADAR_set_mode(device, "rx")  # ADAR1000s on Phaser are receive only, so mode is always "rx"
            ADAR.ADAR_set_Taper(
                self.rx_array,
                self.gainList
                )
            # Set transmitter to either OUT1 or OUT2 SMA port.  Or disable if using HB100
            if SignalSource == 'OUT1':    # use Phaser's OUT1 SMA port as the transmitter
                gpios.gpio_tx_sw = 1      # 0=OUT2, 1=OUT1
                gpios.gpio_vctrl_2 = 1    # 1=Send LO to transmit circuitry
            elif SignalSource == 'OUT2':  # use OUT2 as the transmitter
                gpios.gpio_tx_sw = 0      # 0=OUT2, 1=OUT1
                gpios.gpio_vctrl_2 = 1    # 1=Send LO to transmit circuitry
            else:   # use HB100 as the transmit signal source
                gpios.gpio_tx_sw = 0 
                SDR.SDR_setTx(self.sdr, -80) # disable tx output by attenuating it
                       
        def ConvertPhaseToSteerAngle(self, PhDelta):
                # steering angle theta = arcsin(c*deltaphase/(2*pi*f*d)
            value1 = (self.c * np.radians(np.abs(PhDelta))) / (
                2 * 3.14159 * (self.SignalFreq) * self.d)
            clamped_value1 = max(min(1, value1), -1)  # arcsin argument must be between 1 and -1
            theta = np.degrees(np.arcsin(clamped_value1))
            if PhDelta >= 0:
                SteerAngle = theta  # positive PhaseDelta covers 0deg to 90 deg
            else:
                SteerAngle = -theta  # negative phase delta covers 0 deg to -90 deg
            return SteerAngle    
            
        def dbfs(self, raw_data):
            # function to convert IQ samples to FFT plot, scaled in dBFS
            NumSamples = len(raw_data)
            win = np.hamming(NumSamples)
            y = raw_data * win
            s_fft = np.fft.fft(y) / np.sum(win)
            s_shift = np.fft.fftshift(s_fft)
            s_dbfs = 20*np.log10(np.abs(s_shift)/(2**11))     # Pluto is a signed 12 bit ADC, so use 2^11 to convert to dBFS
            return s_dbfs
        
        def updateGainPhase(self):
            self.gainList = np.array([
                self.gain1,
                self.gain2,
                self.gain3,
                self.gain4,
                self.gain5,
                self.gain6,
                self.gain7,
                self.gain8
                ])  # gains from 0 to 100
            
            self.phaseList = np.array([
                self.RxPhase1 + self.phase1,
                self.RxPhase2 + self.phase2,
                self.RxPhase3 + self.phase3,
                self.RxPhase4 + self.phase4,
                self.RxPhase5 + self.phase5,
                self.RxPhase6 + self.phase6,
                self.RxPhase7 + self.phase7,
                self.RxPhase8 + self.phase8
                ])
            
        def null_vec(self, null_angle):
            null_phase = 2*np.pi*self.SignalFreq*self.d*np.sin(np.deg2rad(null_angle))/self.c
            null_phases = np.array([0,1,2,3,4,5,6,7])*null_phase # create array with phase shifts for null angle
            polar_null_phases = np.exp(1j * null_phases) # null steer vector
            return polar_null_phases
    
        def work(self, input_items, output_items):
            save_this_trace=False
            clear_this_trace=False
            enable_null_1 = self.null_enable_1
            enable_null_2 = self.null_enable_2
            if enable_null_1 == True:
                polar_null_phases = self.null_vec(self.null_angle_1)
                wn1 = self.gainList * polar_null_phases   # beam weights for null direction
            if enable_null_2 == True:
                polar_null_phases = self.null_vec(self.null_angle_2)
                wn2 = self.gainList * polar_null_phases   # beam weights for null direction
                
            SteerValues = np.arange(-90, 90 + self.step_size, self.step_size)
            # Phase delta = 2*Pi*d*sin(theta)/lambda = 2*Pi*d*sin(theta)*f/c
            PhaseValues = np.degrees(
                2*np.pi*self.d* np.sin(np.radians(SteerValues))
                * self.SignalFreq / self.c)
            self.updateGainPhase()
            
            for x in range(len(PhaseValues)):
                if self.save_trace == True:
                    save_this_trace = True
                if self.clear_trace == True:
                    clear_this_trace = True
                PhDelta = PhaseValues[x]
                steer_phases = (np.array([0,1,2,3,4,5,6,7])*PhDelta) % 360
                wd = self.gainList * np.exp(1j * np.deg2rad(steer_phases))
                # wd is the beam weights for desired steering direction
                # details here:  https://www.mathworks.com/help/phased/ug/array-pattern-synthesis.html
                
                if enable_null_1 == True:
                    wn1_herm = np.conjugate(wn1.reshape(1,len(wn1)))
                    rn = wn1_herm @ wd / (wn1_herm @ wn1)
                    wd = wd - wn1 * rn
                    
                if enable_null_2 == True:
                    wn2_herm = np.conjugate(wn2.reshape(1,len(wn2)))
                    rn = wn2_herm @ wd / (wn2_herm @ wn2)
                    wd = wd - wn2 * rn
                    
                new_gains = np.abs(wd)
                new_gains = np.clip(new_gains, 0, 100)
                new_phases = np.angle(wd)
                new_phases = np.rad2deg(new_phases)
                
                ADAR.ADAR_set_Taper(
                    self.rx_array,
                    new_gains
                    )
                ADAR.ADAR_set_Phase(
                    self.rx_array,
                    0,
                    self.phase_step_size,
                    new_phases
                    )
                
                data = self.sdr.rx()
                data_sum = data[0]+data[1]
                sum_dbfs = self.dbfs(data_sum)
                peak_dbfs = max(sum_dbfs)
                output_items[0][x] = (1*(self.ConvertPhaseToSteerAngle(PhDelta)) + 1j*peak_dbfs)
                output_items[1][x] = 0-10000000j
                
            for x in range(len(output_items[0])-len(SteerValues)):
                # fill in the empty parts of the array with large negative numbers to make it plot nicely
                output_items[0][len(SteerValues)+x] = 0-10000000j
            if save_this_trace==True:
                for x in range(len(self.saved_trace)):
                    self.saved_trace[x] = output_items[0][x]
            if clear_this_trace==True:
                self.saved_trace = np.ones(4094)*(0-100000j)
            for x in range(len(self.saved_trace)):
                output_items[1][x] = self.saved_trace[x]
    
            return len(output_items[0])
    
    #!/usr/bin/env python3
    # -*- coding: utf-8 -*-
    
    #
    # SPDX-License-Identifier: GPL-3.0
    #
    # GNU Radio Python Flow Graph
    # Title: GNU Radio Phaser
    # GNU Radio version: 3.8.2.0
    
    from distutils.version import StrictVersion
    
    if __name__ == '__main__':
        import ctypes
        import sys
        if sys.platform.startswith('linux'):
            try:
                x11 = ctypes.cdll.LoadLibrary('libX11.so')
                x11.XInitThreads()
            except:
                print("Warning: failed to XInitThreads()")
    
    from PyQt5 import Qt
    from gnuradio import qtgui
    import sip
    from gnuradio import gr
    from gnuradio.filter import firdes
    import sys
    import signal
    from argparse import ArgumentParser
    from gnuradio.eng_arg import eng_float, intx
    from gnuradio import eng_notation
    from gnuradio.qtgui import Range, RangeWidget
    import epy_block_0
    
    from gnuradio import qtgui
    
    class phaser_grc(gr.top_block, Qt.QWidget):
    
        def __init__(self):
            gr.top_block.__init__(self, "GNU Radio Phaser")
            Qt.QWidget.__init__(self)
            self.setWindowTitle("GNU Radio Phaser")
            qtgui.util.check_set_qss()
            try:
                self.setWindowIcon(Qt.QIcon.fromTheme('gnuradio-grc'))
            except:
                pass
            self.top_scroll_layout = Qt.QVBoxLayout()
            self.setLayout(self.top_scroll_layout)
            self.top_scroll = Qt.QScrollArea()
            self.top_scroll.setFrameStyle(Qt.QFrame.NoFrame)
            self.top_scroll_layout.addWidget(self.top_scroll)
            self.top_scroll.setWidgetResizable(True)
            self.top_widget = Qt.QWidget()
            self.top_scroll.setWidget(self.top_widget)
            self.top_layout = Qt.QVBoxLayout(self.top_widget)
            self.top_grid_layout = Qt.QGridLayout()
            self.top_layout.addLayout(self.top_grid_layout)
    
            self.settings = Qt.QSettings("GNU Radio", "phaser_grc")
    
            try:
                if StrictVersion(Qt.qVersion()) < StrictVersion("5.0.0"):
                    self.restoreGeometry(self.settings.value("geometry").toByteArray())
                else:
                    self.restoreGeometry(self.settings.value("geometry"))
            except:
                pass
    
            ##################################################
            # Variables
            ##################################################
            self.step_size = step_size = 1.5
            self.save_trace = save_trace = False
            self.phase8 = phase8 = 0
            self.phase7 = phase7 = 0
            self.phase6 = phase6 = 0
            self.phase5 = phase5 = 0
            self.phase4 = phase4 = 0
            self.phase3 = phase3 = 0
            self.phase2 = phase2 = 0
            self.phase1 = phase1 = 0
            self.null_enable_2 = null_enable_2 = False
            self.null_enable_1 = null_enable_1 = False
            self.null_angle_2 = null_angle_2 = 10
            self.null_angle_1 = null_angle_1 = 30
            self.gain8 = gain8 = 100
            self.gain7 = gain7 = 100
            self.gain6 = gain6 = 100
            self.gain5 = gain5 = 100
            self.gain4 = gain4 = 100
            self.gain3 = gain3 = 100
            self.gain2 = gain2 = 100
            self.gain1 = gain1 = 100
            self.clear_trace = clear_trace = False
    
            ##################################################
            # Blocks
            ##################################################
            self.tab = Qt.QTabWidget()
            self.tab_widget_0 = Qt.QWidget()
            self.tab_layout_0 = Qt.QBoxLayout(Qt.QBoxLayout.TopToBottom, self.tab_widget_0)
            self.tab_grid_layout_0 = Qt.QGridLayout()
            self.tab_layout_0.addLayout(self.tab_grid_layout_0)
            self.tab.addTab(self.tab_widget_0, 'control')
            self.tab_widget_1 = Qt.QWidget()
            self.tab_layout_1 = Qt.QBoxLayout(Qt.QBoxLayout.TopToBottom, self.tab_widget_1)
            self.tab_grid_layout_1 = Qt.QGridLayout()
            self.tab_layout_1.addLayout(self.tab_grid_layout_1)
            self.tab.addTab(self.tab_widget_1, 'gain')
            self.tab_widget_2 = Qt.QWidget()
            self.tab_layout_2 = Qt.QBoxLayout(Qt.QBoxLayout.TopToBottom, self.tab_widget_2)
            self.tab_grid_layout_2 = Qt.QGridLayout()
            self.tab_layout_2.addLayout(self.tab_grid_layout_2)
            self.tab.addTab(self.tab_widget_2, 'phase')
            self.tab_widget_3 = Qt.QWidget()
            self.tab_layout_3 = Qt.QBoxLayout(Qt.QBoxLayout.TopToBottom, self.tab_widget_3)
            self.tab_grid_layout_3 = Qt.QGridLayout()
            self.tab_layout_3.addLayout(self.tab_grid_layout_3)
            self.tab.addTab(self.tab_widget_3, 'null steering')
            self.top_grid_layout.addWidget(self.tab, 0, 0, 6, 2)
            for r in range(0, 6):
                self.top_grid_layout.setRowStretch(r, 1)
            for c in range(0, 2):
                self.top_grid_layout.setColumnStretch(c, 1)
            self._step_size_range = Range(0.5, 5, .5, 1.5, 200)
            self._step_size_win = RangeWidget(self._step_size_range, self.set_step_size, 'step_size', "counter_slider", float)
            self.tab_grid_layout_0.addWidget(self._step_size_win, 0, 0, 1, 3)
            for r in range(0, 1):
                self.tab_grid_layout_0.setRowStretch(r, 1)
            for c in range(0, 3):
                self.tab_grid_layout_0.setColumnStretch(c, 1)
            _save_trace_push_button = Qt.QPushButton('')
            _save_trace_push_button = Qt.QPushButton('save_trace')
            self._save_trace_choices = {'Pressed': True, 'Released': False}
            _save_trace_push_button.pressed.connect(lambda: self.set_save_trace(self._save_trace_choices['Pressed']))
            _save_trace_push_button.released.connect(lambda: self.set_save_trace(self._save_trace_choices['Released']))
            self.top_grid_layout.addWidget(_save_trace_push_button, 5, 2, 1, 1)
            for r in range(5, 6):
                self.top_grid_layout.setRowStretch(r, 1)
            for c in range(2, 3):
                self.top_grid_layout.setColumnStretch(c, 1)
            self._phase8_range = Range(-180, 180, 1, 0, 200)
            self._phase8_win = RangeWidget(self._phase8_range, self.set_phase8, 'phase8', "counter_slider", int)
            self.tab_grid_layout_2.addWidget(self._phase8_win, 7, 0, 1, 3)
            for r in range(7, 8):
                self.tab_grid_layout_2.setRowStretch(r, 1)
            for c in range(0, 3):
                self.tab_grid_layout_2.setColumnStretch(c, 1)
            self._phase7_range = Range(-180, 180, 1, 0, 200)
            self._phase7_win = RangeWidget(self._phase7_range, self.set_phase7, 'phase7', "counter_slider", int)
            self.tab_grid_layout_2.addWidget(self._phase7_win, 6, 0, 1, 3)
            for r in range(6, 7):
                self.tab_grid_layout_2.setRowStretch(r, 1)
            for c in range(0, 3):
                self.tab_grid_layout_2.setColumnStretch(c, 1)
            self._phase6_range = Range(-180, 180, 1, 0, 200)
            self._phase6_win = RangeWidget(self._phase6_range, self.set_phase6, 'phase6', "counter_slider", int)
            self.tab_grid_layout_2.addWidget(self._phase6_win, 5, 0, 1, 3)
            for r in range(5, 6):
                self.tab_grid_layout_2.setRowStretch(r, 1)
            for c in range(0, 3):
                self.tab_grid_layout_2.setColumnStretch(c, 1)
            self._phase5_range = Range(-180, 180, 1, 0, 200)
            self._phase5_win = RangeWidget(self._phase5_range, self.set_phase5, 'phase5', "counter_slider", int)
            self.tab_grid_layout_2.addWidget(self._phase5_win, 4, 0, 1, 3)
            for r in range(4, 5):
                self.tab_grid_layout_2.setRowStretch(r, 1)
            for c in range(0, 3):
                self.tab_grid_layout_2.setColumnStretch(c, 1)
            self._phase4_range = Range(-180, 180, 1, 0, 200)
            self._phase4_win = RangeWidget(self._phase4_range, self.set_phase4, 'phase4', "counter_slider", int)
            self.tab_grid_layout_2.addWidget(self._phase4_win, 3, 0, 1, 3)
            for r in range(3, 4):
                self.tab_grid_layout_2.setRowStretch(r, 1)
            for c in range(0, 3):
                self.tab_grid_layout_2.setColumnStretch(c, 1)
            self._phase3_range = Range(-180, 180, 1, 0, 200)
            self._phase3_win = RangeWidget(self._phase3_range, self.set_phase3, 'phase3', "counter_slider", int)
            self.tab_grid_layout_2.addWidget(self._phase3_win, 2, 0, 1, 3)
            for r in range(2, 3):
                self.tab_grid_layout_2.setRowStretch(r, 1)
            for c in range(0, 3):
                self.tab_grid_layout_2.setColumnStretch(c, 1)
            self._phase2_range = Range(-180, 180, 1, 0, 200)
            self._phase2_win = RangeWidget(self._phase2_range, self.set_phase2, 'phase2', "counter_slider", int)
            self.tab_grid_layout_2.addWidget(self._phase2_win, 1, 0, 1, 3)
            for r in range(1, 2):
                self.tab_grid_layout_2.setRowStretch(r, 1)
            for c in range(0, 3):
                self.tab_grid_layout_2.setColumnStretch(c, 1)
            self._phase1_range = Range(-180, 180, 1, 0, 200)
            self._phase1_win = RangeWidget(self._phase1_range, self.set_phase1, 'phase1', "counter_slider", int)
            self.tab_grid_layout_2.addWidget(self._phase1_win, 0, 0, 1, 3)
            for r in range(0, 1):
                self.tab_grid_layout_2.setRowStretch(r, 1)
            for c in range(0, 3):
                self.tab_grid_layout_2.setColumnStretch(c, 1)
            _null_enable_2_check_box = Qt.QCheckBox('null_enable_2')
            self._null_enable_2_choices = {True: True, False: False}
            self._null_enable_2_choices_inv = dict((v,k) for k,v in self._null_enable_2_choices.items())
            self._null_enable_2_callback = lambda i: Qt.QMetaObject.invokeMethod(_null_enable_2_check_box, "setChecked", Qt.Q_ARG("bool", self._null_enable_2_choices_inv[i]))
            self._null_enable_2_callback(self.null_enable_2)
            _null_enable_2_check_box.stateChanged.connect(lambda i: self.set_null_enable_2(self._null_enable_2_choices[bool(i)]))
            self.tab_grid_layout_3.addWidget(_null_enable_2_check_box, 1, 4, 1, 1)
            for r in range(1, 2):
                self.tab_grid_layout_3.setRowStretch(r, 1)
            for c in range(4, 5):
                self.tab_grid_layout_3.setColumnStretch(c, 1)
            _null_enable_1_check_box = Qt.QCheckBox('null_enable_1')
            self._null_enable_1_choices = {True: True, False: False}
            self._null_enable_1_choices_inv = dict((v,k) for k,v in self._null_enable_1_choices.items())
            self._null_enable_1_callback = lambda i: Qt.QMetaObject.invokeMethod(_null_enable_1_check_box, "setChecked", Qt.Q_ARG("bool", self._null_enable_1_choices_inv[i]))
            self._null_enable_1_callback(self.null_enable_1)
            _null_enable_1_check_box.stateChanged.connect(lambda i: self.set_null_enable_1(self._null_enable_1_choices[bool(i)]))
            self.tab_grid_layout_3.addWidget(_null_enable_1_check_box, 0, 4, 1, 1)
            for r in range(0, 1):
                self.tab_grid_layout_3.setRowStretch(r, 1)
            for c in range(4, 5):
                self.tab_grid_layout_3.setColumnStretch(c, 1)
            self._null_angle_2_range = Range(-90, 90, 1, 10, 200)
            self._null_angle_2_win = RangeWidget(self._null_angle_2_range, self.set_null_angle_2, 'null_angle_2', "counter_slider", int)
            self.tab_grid_layout_3.addWidget(self._null_angle_2_win, 1, 0, 1, 3)
            for r in range(1, 2):
                self.tab_grid_layout_3.setRowStretch(r, 1)
            for c in range(0, 3):
                self.tab_grid_layout_3.setColumnStretch(c, 1)
            self._null_angle_1_range = Range(-90, 90, 1, 30, 200)
            self._null_angle_1_win = RangeWidget(self._null_angle_1_range, self.set_null_angle_1, 'null_angle_1', "counter_slider", int)
            self.tab_grid_layout_3.addWidget(self._null_angle_1_win, 0, 0, 1, 3)
            for r in range(0, 1):
                self.tab_grid_layout_3.setRowStretch(r, 1)
            for c in range(0, 3):
                self.tab_grid_layout_3.setColumnStretch(c, 1)
            self._gain8_range = Range(0, 100, 1, 100, 200)
            self._gain8_win = RangeWidget(self._gain8_range, self.set_gain8, 'gain8', "counter_slider", int)
            self.tab_grid_layout_1.addWidget(self._gain8_win, 7, 0, 1, 3)
            for r in range(7, 8):
                self.tab_grid_layout_1.setRowStretch(r, 1)
            for c in range(0, 3):
                self.tab_grid_layout_1.setColumnStretch(c, 1)
            self._gain7_range = Range(0, 100, 1, 100, 200)
            self._gain7_win = RangeWidget(self._gain7_range, self.set_gain7, 'gain7', "counter_slider", int)
            self.tab_grid_layout_1.addWidget(self._gain7_win, 6, 0, 1, 3)
            for r in range(6, 7):
                self.tab_grid_layout_1.setRowStretch(r, 1)
            for c in range(0, 3):
                self.tab_grid_layout_1.setColumnStretch(c, 1)
            self._gain6_range = Range(0, 100, 1, 100, 200)
            self._gain6_win = RangeWidget(self._gain6_range, self.set_gain6, 'gain6', "counter_slider", int)
            self.tab_grid_layout_1.addWidget(self._gain6_win, 5, 0, 1, 3)
            for r in range(5, 6):
                self.tab_grid_layout_1.setRowStretch(r, 1)
            for c in range(0, 3):
                self.tab_grid_layout_1.setColumnStretch(c, 1)
            self._gain5_range = Range(0, 100, 1, 100, 200)
            self._gain5_win = RangeWidget(self._gain5_range, self.set_gain5, 'gain5', "counter_slider", int)
            self.tab_grid_layout_1.addWidget(self._gain5_win, 4, 0, 1, 3)
            for r in range(4, 5):
                self.tab_grid_layout_1.setRowStretch(r, 1)
            for c in range(0, 3):
                self.tab_grid_layout_1.setColumnStretch(c, 1)
            self._gain4_range = Range(0, 100, 1, 100, 200)
            self._gain4_win = RangeWidget(self._gain4_range, self.set_gain4, 'gain4', "counter_slider", int)
            self.tab_grid_layout_1.addWidget(self._gain4_win, 3, 0, 1, 3)
            for r in range(3, 4):
                self.tab_grid_layout_1.setRowStretch(r, 1)
            for c in range(0, 3):
                self.tab_grid_layout_1.setColumnStretch(c, 1)
            self._gain3_range = Range(0, 100, 1, 100, 200)
            self._gain3_win = RangeWidget(self._gain3_range, self.set_gain3, 'gain3', "counter_slider", int)
            self.tab_grid_layout_1.addWidget(self._gain3_win, 2, 0, 1, 3)
            for r in range(2, 3):
                self.tab_grid_layout_1.setRowStretch(r, 1)
            for c in range(0, 3):
                self.tab_grid_layout_1.setColumnStretch(c, 1)
            self._gain2_range = Range(0, 100, 1, 100, 200)
            self._gain2_win = RangeWidget(self._gain2_range, self.set_gain2, 'gain2', "counter_slider", int)
            self.tab_grid_layout_1.addWidget(self._gain2_win, 1, 0, 1, 3)
            for r in range(1, 2):
                self.tab_grid_layout_1.setRowStretch(r, 1)
            for c in range(0, 3):
                self.tab_grid_layout_1.setColumnStretch(c, 1)
            self._gain1_range = Range(0, 100, 1, 100, 200)
            self._gain1_win = RangeWidget(self._gain1_range, self.set_gain1, 'gain1', "counter_slider", int)
            self.tab_grid_layout_1.addWidget(self._gain1_win, 0, 0, 1, 3)
            for r in range(0, 1):
                self.tab_grid_layout_1.setRowStretch(r, 1)
            for c in range(0, 3):
                self.tab_grid_layout_1.setColumnStretch(c, 1)
            _clear_trace_push_button = Qt.QPushButton('')
            _clear_trace_push_button = Qt.QPushButton('clear_trace')
            self._clear_trace_choices = {'Pressed': True, 'Released': False}
            _clear_trace_push_button.pressed.connect(lambda: self.set_clear_trace(self._clear_trace_choices['Pressed']))
            _clear_trace_push_button.released.connect(lambda: self.set_clear_trace(self._clear_trace_choices['Released']))
            self.top_grid_layout.addWidget(_clear_trace_push_button, 5, 3, 1, 1)
            for r in range(5, 6):
                self.top_grid_layout.setRowStretch(r, 1)
            for c in range(3, 4):
                self.top_grid_layout.setColumnStretch(c, 1)
            self.qtgui_const_sink_x_0 = qtgui.const_sink_c(
                4094, #size
                "", #name
                2 #number of inputs
            )
            self.qtgui_const_sink_x_0.set_update_time(0.10)
            self.qtgui_const_sink_x_0.set_y_axis(-75, 0)
            self.qtgui_const_sink_x_0.set_x_axis(-89, 89)
            self.qtgui_const_sink_x_0.set_trigger_mode(qtgui.TRIG_MODE_FREE, qtgui.TRIG_SLOPE_POS, 0.0, 0, "")
            self.qtgui_const_sink_x_0.enable_autoscale(False)
            self.qtgui_const_sink_x_0.enable_grid(True)
            self.qtgui_const_sink_x_0.enable_axis_labels(True)
    
            self.qtgui_const_sink_x_0.disable_legend()
    
            labels = ['', '', '', '', '',
                '', '', '', '', '']
            widths = [2, 1, 1, 1, 1,
                1, 1, 1, 1, 1]
            colors = ["blue", "red", "red", "red", "red",
                "red", "red", "red", "red", "red"]
            styles = [1, 1, 0, 0, 0,
                0, 0, 0, 0, 0]
            markers = [-1, -1, 0, 0, 0,
                0, 0, 0, 0, 0]
            alphas = [1.0, 1.0, 1.0, 1.0, 1.0,
                1.0, 1.0, 1.0, 1.0, 1.0]
    
            for i in range(2):
                if len(labels[i]) == 0:
                    self.qtgui_const_sink_x_0.set_line_label(i, "Data {0}".format(i))
                else:
                    self.qtgui_const_sink_x_0.set_line_label(i, labels[i])
                self.qtgui_const_sink_x_0.set_line_width(i, widths[i])
                self.qtgui_const_sink_x_0.set_line_color(i, colors[i])
                self.qtgui_const_sink_x_0.set_line_style(i, styles[i])
                self.qtgui_const_sink_x_0.set_line_marker(i, markers[i])
                self.qtgui_const_sink_x_0.set_line_alpha(i, alphas[i])
    
            self._qtgui_const_sink_x_0_win = sip.wrapinstance(self.qtgui_const_sink_x_0.pyqwidget(), Qt.QWidget)
            self.top_grid_layout.addWidget(self._qtgui_const_sink_x_0_win, 0, 2, 5, 3)
            for r in range(0, 5):
                self.top_grid_layout.setRowStretch(r, 1)
            for c in range(2, 5):
                self.top_grid_layout.setColumnStretch(c, 1)
            self.epy_block_0 = epy_block_0.blk(step_size=step_size, save_trace=save_trace, clear_trace=clear_trace, gain1=gain1, gain2=gain2, gain3=gain3, gain4=gain4, gain5=gain5, gain6=gain6, gain7=gain7, gain8=gain8, phase1=phase1, phase2=phase2, phase3=phase3, phase4=phase4, phase5=phase5, phase6=phase6, phase7=phase7, phase8=phase8, null_enable_1=null_enable_1, null_angle_1=null_angle_1, null_enable_2=null_enable_2, null_angle_2=null_angle_2)
    
    
    
            ##################################################
            # Connections
            ##################################################
            self.connect((self.epy_block_0, 1), (self.qtgui_const_sink_x_0, 1))
            self.connect((self.epy_block_0, 0), (self.qtgui_const_sink_x_0, 0))
    
    
        def closeEvent(self, event):
            self.settings = Qt.QSettings("GNU Radio", "phaser_grc")
            self.settings.setValue("geometry", self.saveGeometry())
            event.accept()
    
        def get_step_size(self):
            return self.step_size
    
        def set_step_size(self, step_size):
            self.step_size = step_size
            self.epy_block_0.step_size = self.step_size
    
        def get_save_trace(self):
            return self.save_trace
    
        def set_save_trace(self, save_trace):
            self.save_trace = save_trace
            self.epy_block_0.save_trace = self.save_trace
    
        def get_phase8(self):
            return self.phase8
    
        def set_phase8(self, phase8):
            self.phase8 = phase8
            self.epy_block_0.phase8 = self.phase8
    
        def get_phase7(self):
            return self.phase7
    
        def set_phase7(self, phase7):
            self.phase7 = phase7
            self.epy_block_0.phase7 = self.phase7
    
        def get_phase6(self):
            return self.phase6
    
        def set_phase6(self, phase6):
            self.phase6 = phase6
            self.epy_block_0.phase6 = self.phase6
    
        def get_phase5(self):
            return self.phase5
    
        def set_phase5(self, phase5):
            self.phase5 = phase5
            self.epy_block_0.phase5 = self.phase5
    
        def get_phase4(self):
            return self.phase4
    
        def set_phase4(self, phase4):
            self.phase4 = phase4
            self.epy_block_0.phase4 = self.phase4
    
        def get_phase3(self):
            return self.phase3
    
        def set_phase3(self, phase3):
            self.phase3 = phase3
            self.epy_block_0.phase3 = self.phase3
    
        def get_phase2(self):
            return self.phase2
    
        def set_phase2(self, phase2):
            self.phase2 = phase2
            self.epy_block_0.phase2 = self.phase2
    
        def get_phase1(self):
            return self.phase1
    
        def set_phase1(self, phase1):
            self.phase1 = phase1
            self.epy_block_0.phase1 = self.phase1
    
        def get_null_enable_2(self):
            return self.null_enable_2
    
        def set_null_enable_2(self, null_enable_2):
            self.null_enable_2 = null_enable_2
            self._null_enable_2_callback(self.null_enable_2)
            self.epy_block_0.null_enable_2 = self.null_enable_2
    
        def get_null_enable_1(self):
            return self.null_enable_1
    
        def set_null_enable_1(self, null_enable_1):
            self.null_enable_1 = null_enable_1
            self._null_enable_1_callback(self.null_enable_1)
            self.epy_block_0.null_enable_1 = self.null_enable_1
    
        def get_null_angle_2(self):
            return self.null_angle_2
    
        def set_null_angle_2(self, null_angle_2):
            self.null_angle_2 = null_angle_2
            self.epy_block_0.null_angle_2 = self.null_angle_2
    
        def get_null_angle_1(self):
            return self.null_angle_1
    
        def set_null_angle_1(self, null_angle_1):
            self.null_angle_1 = null_angle_1
            self.epy_block_0.null_angle_1 = self.null_angle_1
    
        def get_gain8(self):
            return self.gain8
    
        def set_gain8(self, gain8):
            self.gain8 = gain8
            self.epy_block_0.gain8 = self.gain8
    
        def get_gain7(self):
            return self.gain7
    
        def set_gain7(self, gain7):
            self.gain7 = gain7
            self.epy_block_0.gain7 = self.gain7
    
        def get_gain6(self):
            return self.gain6
    
        def set_gain6(self, gain6):
            self.gain6 = gain6
            self.epy_block_0.gain6 = self.gain6
    
        def get_gain5(self):
            return self.gain5
    
        def set_gain5(self, gain5):
            self.gain5 = gain5
            self.epy_block_0.gain5 = self.gain5
    
        def get_gain4(self):
            return self.gain4
    
        def set_gain4(self, gain4):
            self.gain4 = gain4
            self.epy_block_0.gain4 = self.gain4
    
        def get_gain3(self):
            return self.gain3
    
        def set_gain3(self, gain3):
            self.gain3 = gain3
            self.epy_block_0.gain3 = self.gain3
    
        def get_gain2(self):
            return self.gain2
    
        def set_gain2(self, gain2):
            self.gain2 = gain2
            self.epy_block_0.gain2 = self.gain2
    
        def get_gain1(self):
            return self.gain1
    
        def set_gain1(self, gain1):
            self.gain1 = gain1
            self.epy_block_0.gain1 = self.gain1
    
        def get_clear_trace(self):
            return self.clear_trace
    
        def set_clear_trace(self, clear_trace):
            self.clear_trace = clear_trace
            self.epy_block_0.clear_trace = self.clear_trace
    
    
    
    
    
    def main(top_block_cls=phaser_grc, options=None):
    
        if StrictVersion("4.5.0") <= StrictVersion(Qt.qVersion()) < StrictVersion("5.0.0"):
            style = gr.prefs().get_string('qtgui', 'style', 'raster')
            Qt.QApplication.setGraphicsSystem(style)
        qapp = Qt.QApplication(sys.argv)
    
        tb = top_block_cls()
    
        tb.start()
    
        tb.show()
    
        def sig_handler(sig=None, frame=None):
            Qt.QApplication.quit()
    
        signal.signal(signal.SIGINT, sig_handler)
        signal.signal(signal.SIGTERM, sig_handler)
    
        timer = Qt.QTimer()
        timer.start(500)
        timer.timeout.connect(lambda: None)
    
        def quitting():
            tb.stop()
            tb.wait()
    
        qapp.aboutToQuit.connect(quitting)
        qapp.exec_()
    
    if __name__ == '__main__':
        main()
    
    options:
      parameters:
        author: ''
        category: '[GRC Hier Blocks]'
        cmake_opt: ''
        comment: ''
        copyright: ''
        description: ''
        gen_cmake: 'On'
        gen_linking: dynamic
        generate_options: qt_gui
        hier_block_src_path: '.:'
        id: phaser_grc
        max_nouts: '0'
        output_language: python
        placement: (0,0)
        qt_qss_theme: ''
        realtime_scheduling: ''
        run: 'True'
        run_command: '{python} -u {filename}'
        run_options: prompt
        sizing_mode: fixed
        thread_safe_setters: ''
        title: GNU Radio Phaser
        window_size: (1000,1000)
      states:
        bus_sink: false
        bus_source: false
        bus_structure: null
        coordinate: [8, 8]
        rotation: 0
        state: enabled
    
    blocks:
    - name: clear_trace
      id: variable_qtgui_push_button
      parameters:
        comment: ''
        gui_hint: 5,3,1,1
        label: ''
        pressed: 'True'
        released: 'False'
        type: bool
        value: 'False'
      states:
        bus_sink: false
        bus_source: false
        bus_structure: null
        coordinate: [1072, 420.0]
        rotation: 0
        state: true
    - name: gain1
      id: variable_qtgui_range
      parameters:
        comment: ''
        gui_hint: 'tab@1: 0, 0, 1, 3'
        label: ''
        min_len: '200'
        orient: Qt.Horizontal
        rangeType: int
        start: '0'
        step: '1'
        stop: '100'
        value: '100'
        widget: counter_slider
      states:
        bus_sink: false
        bus_source: false
        bus_structure: null
        coordinate: [432, 32.0]
        rotation: 0
        state: true
    - name: gain2
      id: variable_qtgui_range
      parameters:
        comment: ''
        gui_hint: 'tab@1: 1, 0, 1, 3'
        label: ''
        min_len: '200'
        orient: Qt.Horizontal
        rangeType: int
        start: '0'
        step: '1'
        stop: '100'
        value: '100'
        widget: counter_slider
      states:
        bus_sink: false
        bus_source: false
        bus_structure: null
        coordinate: [568, 32.0]
        rotation: 0
        state: true
    - name: gain3
      id: variable_qtgui_range
      parameters:
        comment: ''
        gui_hint: 'tab@1: 2, 0, 1, 3'
        label: ''
        min_len: '200'
        orient: Qt.Horizontal
        rangeType: int
        start: '0'
        step: '1'
        stop: '100'
        value: '100'
        widget: counter_slider
      states:
        bus_sink: false
        bus_source: false
        bus_structure: null
        coordinate: [704, 32.0]
        rotation: 0
        state: true
    - name: gain4
      id: variable_qtgui_range
      parameters:
        comment: ''
        gui_hint: 'tab@1: 3, 0, 1, 3'
        label: ''
        min_len: '200'
        orient: Qt.Horizontal
        rangeType: int
        start: '0'
        step: '1'
        stop: '100'
        value: '100'
        widget: counter_slider
      states:
        bus_sink: false
        bus_source: false
        bus_structure: null
        coordinate: [840, 32.0]
        rotation: 0
        state: true
    - name: gain5
      id: variable_qtgui_range
      parameters:
        comment: ''
        gui_hint: 'tab@1: 4, 0, 1, 3'
        label: ''
        min_len: '200'
        orient: Qt.Horizontal
        rangeType: int
        start: '0'
        step: '1'
        stop: '100'
        value: '100'
        widget: counter_slider
      states:
        bus_sink: false
        bus_source: false
        bus_structure: null
        coordinate: [976, 32.0]
        rotation: 0
        state: true
    - name: gain6
      id: variable_qtgui_range
      parameters:
        comment: ''
        gui_hint: 'tab@1: 5, 0, 1, 3'
        label: ''
        min_len: '200'
        orient: Qt.Horizontal
        rangeType: int
        start: '0'
        step: '1'
        stop: '100'
        value: '100'
        widget: counter_slider
      states:
        bus_sink: false
        bus_source: false
        bus_structure: null
        coordinate: [1112, 32.0]
        rotation: 0
        state: true
    - name: gain7
      id: variable_qtgui_range
      parameters:
        comment: ''
        gui_hint: 'tab@1: 6, 0, 1, 3'
        label: ''
        min_len: '200'
        orient: Qt.Horizontal
        rangeType: int
        start: '0'
        step: '1'
        stop: '100'
        value: '100'
        widget: counter_slider
      states:
        bus_sink: false
        bus_source: false
        bus_structure: null
        coordinate: [1248, 32.0]
        rotation: 0
        state: true
    - name: gain8
      id: variable_qtgui_range
      parameters:
        comment: ''
        gui_hint: 'tab@1: 7, 0, 1, 3'
        label: ''
        min_len: '200'
        orient: Qt.Horizontal
        rangeType: int
        start: '0'
        step: '1'
        stop: '100'
        value: '100'
        widget: counter_slider
      states:
        bus_sink: false
        bus_source: false
        bus_structure: null
        coordinate: [1384, 32.0]
        rotation: 0
        state: true
    - name: null_angle_1
      id: variable_qtgui_range
      parameters:
        comment: ''
        gui_hint: 'tab@3: 0, 0, 1, 3'
        label: ''
        min_len: '200'
        orient: Qt.Horizontal
        rangeType: int
        start: '-90'
        step: '1'
        stop: '90'
        value: '30'
        widget: counter_slider
      states:
        bus_sink: false
        bus_source: false
        bus_structure: null
        coordinate: [760, 300.0]
        rotation: 0
        state: true
    - name: null_angle_2
      id: variable_qtgui_range
      parameters:
        comment: ''
        gui_hint: 'tab@3: 1, 0, 1, 3'
        label: ''
        min_len: '200'
        orient: Qt.Horizontal
        rangeType: int
        start: '-90'
        step: '1'
        stop: '90'
        value: '10'
        widget: counter_slider
      states:
        bus_sink: false
        bus_source: false
        bus_structure: null
        coordinate: [760, 428.0]
        rotation: 0
        state: true
    - name: null_enable_1
      id: variable_qtgui_check_box
      parameters:
        comment: ''
        'false': 'False'
        gui_hint: 'tab@3: 0, 4, 1, 1'
        label: ''
        'true': 'True'
        type: bool
        value: 'False'
      states:
        bus_sink: false
        bus_source: false
        bus_structure: null
        coordinate: [880, 308.0]
        rotation: 0
        state: true
    - name: null_enable_2
      id: variable_qtgui_check_box
      parameters:
        comment: ''
        'false': 'False'
        gui_hint: 'tab@3: 1, 4, 1, 1'
        label: ''
        'true': 'True'
        type: bool
        value: 'False'
      states:
        bus_sink: false
        bus_source: false
        bus_structure: null
        coordinate: [888, 428.0]
        rotation: 0
        state: true
    - name: phase1
      id: variable_qtgui_range
      parameters:
        comment: ''
        gui_hint: 'tab@2: 0, 0, 1, 3'
        label: ''
        min_len: '200'
        orient: Qt.Horizontal
        rangeType: int
        start: '-180'
        step: '1'
        stop: '180'
        value: '0'
        widget: counter_slider
      states:
        bus_sink: false
        bus_source: false
        bus_structure: null
        coordinate: [432, 168.0]
        rotation: 0
        state: true
    - name: phase2
      id: variable_qtgui_range
      parameters:
        comment: ''
        gui_hint: 'tab@2: 1, 0, 1, 3'
        label: ''
        min_len: '200'
        orient: Qt.Horizontal
        rangeType: int
        start: '-180'
        step: '1'
        stop: '180'
        value: '0'
        widget: counter_slider
      states:
        bus_sink: false
        bus_source: false
        bus_structure: null
        coordinate: [568, 168.0]
        rotation: 0
        state: true
    - name: phase3
      id: variable_qtgui_range
      parameters:
        comment: ''
        gui_hint: 'tab@2: 2, 0, 1, 3'
        label: ''
        min_len: '200'
        orient: Qt.Horizontal
        rangeType: int
        start: '-180'
        step: '1'
        stop: '180'
        value: '0'
        widget: counter_slider
      states:
        bus_sink: false
        bus_source: false
        bus_structure: null
        coordinate: [704, 168.0]
        rotation: 0
        state: true
    - name: phase4
      id: variable_qtgui_range
      parameters:
        comment: ''
        gui_hint: 'tab@2: 3, 0, 1, 3'
        label: ''
        min_len: '200'
        orient: Qt.Horizontal
        rangeType: int
        start: '-180'
        step: '1'
        stop: '180'
        value: '0'
        widget: counter_slider
      states:
        bus_sink: false
        bus_source: false
        bus_structure: null
        coordinate: [840, 168.0]
        rotation: 0
        state: true
    - name: phase5
      id: variable_qtgui_range
      parameters:
        comment: ''
        gui_hint: 'tab@2: 4, 0, 1, 3'
        label: ''
        min_len: '200'
        orient: Qt.Horizontal
        rangeType: int
        start: '-180'
        step: '1'
        stop: '180'
        value: '0'
        widget: counter_slider
      states:
        bus_sink: false
        bus_source: false
        bus_structure: null
        coordinate: [976, 168.0]
        rotation: 0
        state: true
    - name: phase6
      id: variable_qtgui_range
      parameters:
        comment: ''
        gui_hint: 'tab@2: 5, 0, 1, 3'
        label: ''
        min_len: '200'
        orient: Qt.Horizontal
        rangeType: int
        start: '-180'
        step: '1'
        stop: '180'
        value: '0'
        widget: counter_slider
      states:
        bus_sink: false
        bus_source: false
        bus_structure: null
        coordinate: [1112, 168.0]
        rotation: 0
        state: true
    - name: phase7
      id: variable_qtgui_range
      parameters:
        comment: ''
        gui_hint: 'tab@2: 6, 0, 1, 3'
        label: ''
        min_len: '200'
        orient: Qt.Horizontal
        rangeType: int
        start: '-180'
        step: '1'
        stop: '180'
        value: '0'
        widget: counter_slider
      states:
        bus_sink: false
        bus_source: false
        bus_structure: null
        coordinate: [1248, 168.0]
        rotation: 0
        state: true
    - name: phase8
      id: variable_qtgui_range
      parameters:
        comment: ''
        gui_hint: 'tab@2: 7, 0, 1, 3'
        label: ''
        min_len: '200'
        orient: Qt.Horizontal
        rangeType: int
        start: '-180'
        step: '1'
        stop: '180'
        value: '0'
        widget: counter_slider
      states:
        bus_sink: false
        bus_source: false
        bus_structure: null
        coordinate: [1384, 168.0]
        rotation: 0
        state: true
    - name: save_trace
      id: variable_qtgui_push_button
      parameters:
        comment: ''
        gui_hint: 5,2,1,1
        label: ''
        pressed: 'True'
        released: 'False'
        type: bool
        value: 'False'
      states:
        bus_sink: false
        bus_source: false
        bus_structure: null
        coordinate: [1072, 308.0]
        rotation: 0
        state: true
    - name: step_size
      id: variable_qtgui_range
      parameters:
        comment: ''
        gui_hint: 'tab@0: 0, 0, 1, 3'
        label: ''
        min_len: '200'
        orient: Qt.Horizontal
        rangeType: float
        start: '0.5'
        step: '.5'
        stop: '5'
        value: '1.5'
        widget: counter_slider
      states:
        bus_sink: false
        bus_source: false
        bus_structure: null
        coordinate: [192, 172.0]
        rotation: 0
        state: true
    - name: epy_block_0
      id: epy_block
      parameters:
        _source_code: "# Copyright (C) 2023 Analog Devices, Inc.\n# All rights reserved.\n\
          # jon.kraft@analog.com\n# wiki.analog.com/phaser\n\n# Redistribution and use\
          \ in source and binary forms, with or without modification,\n# are permitted\
          \ provided that the following conditions are met:\n#     - Redistributions of\
          \ source code must retain the above copyright\n#       notice, this list of\
          \ conditions and the following disclaimer.\n#     - Redistributions in binary\
          \ form must reproduce the above copyright\n#       notice, this list of conditions\
          \ and the following disclaimer in\n#       the documentation and/or other materials\
          \ provided with the\n#       distribution.\n#     - Neither the name of Analog\
          \ Devices, Inc. nor the names of its\n#       contributors may be used to endorse\
          \ or promote products derived\n#       from this software without specific prior\
          \ written permission.\n#     - The use of this software may or may not infringe\
          \ the patent rights\n#       of one or more patent holders.  This license does\
          \ not release you\n#       from the requirement that you obtain separate licenses\
          \ from these\n#       patent holders to use this software.\n#     - Use of the\
          \ software either in source or binary form, must be run\n#       on or directly\
          \ connected to an Analog Devices Inc. component.\n#\n# THIS SOFTWARE IS PROVIDED\
          \ BY ANALOG DEVICES \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES,\n# INCLUDING,\
          \ BUT NOT LIMITED TO, NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A\n\
          # PARTICULAR PURPOSE ARE DISCLAIMED.\n#\n# IN NO EVENT SHALL ANALOG DEVICES\
          \ BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n# EXEMPLARY, OR\
          \ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, INTELLECTUAL PROPERTY\n\
          # RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\
          \ PROFITS; OR\n# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\
          \ LIABILITY, WHETHER IN CONTRACT,\n# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE\
          \ OR OTHERWISE) ARISING IN ANY WAY OUT OF\n# THE USE OF THIS SOFTWARE, EVEN\
          \ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n\n\"\"\"\nEmbedded Python\
          \ Blocks:\n\nEach time this file is saved, GRC will instantiate the first class\
          \ it finds\nto get ports and parameters of your block. The arguments to __init__\
          \  will\nbe the parameters. All of them are required to have default values!\n\
          \"\"\"\nimport sys\nimport pickle\nimport os\n\nimport adi\nimport numpy as\
          \ np\nsys.path.append('/home/analog/pyadi-iio/examples/phaser/')\nimport SDR_functions\
          \ as SDR  # import the Pluto SDR functions\nimport ADAR_pyadi_functions_edited1\
          \ as ADAR  # import the ADAR1000 functions\nfrom gnuradio import gr\n\nclass\
          \ blk(gr.sync_block):\n    def __init__(self, step_size=3, save_trace=False,\
          \ clear_trace=False,\n                 gain1=100, gain2=100, gain3=100, gain4=100,\
          \ gain5=100, gain6=100, gain7=100, gain8=100,\n                 phase1=0, phase2=0,\
          \ phase3=0, phase4=0, phase5=0, phase6=0, phase7=0, phase8=0,\n            \
          \     null_enable_1 = False, null_angle_1=0, null_enable_2 = False, null_angle_2=0):\
          \  # only default arguments here\n        \"\"\"arguments to this function show\
          \ up as parameters in GRC\"\"\"\n        gr.sync_block.__init__(\n         \
          \   self,\n            name='Phaser Python Control Block',   # will show up\
          \ in GRC\n            in_sig=[],\n            out_sig=[np.complex64, np.complex64]\n\
          \        )\n        # if an attribute with the same name as a parameter is found,\n\
          \        # a callback is registered (properties work, too)\n        \n     \
          \   # =============================================================================\n\
          \        # User parameters\n        # =============================================================================\n\
          \        self.step_size = step_size  # steering angle step size (in degrees)\n\
          \        self.save_trace = save_trace\n        self.clear_trace = clear_trace\n\
          \        self.saved_trace = np.ones(4094)*(0-100000j)\n        \n        self.gain1=gain1\n\
          \        self.gain2=gain2\n        self.gain3=gain3\n        self.gain4=gain4\n\
          \        self.gain5=gain5\n        self.gain6=gain6\n        self.gain7=gain7\n\
          \        self.gain8=gain8\n        \n        self.phase1=phase1\n        self.phase2=phase2\n\
          \        self.phase3=phase3\n        self.phase4=phase4\n        self.phase5=phase5\n\
          \        self.phase6=phase6\n        self.phase7=phase7\n        self.phase8=phase8\n\
          \        \n        self.null_enable_1 = null_enable_1\n        self.null_angle_1\
          \ = null_angle_1\n        self.null_enable_2 = null_enable_2\n        self.null_angle_2\
          \ = null_angle_2\n        \n        rpi_ip = \"ip:phaser.local\"  # default\
          \ IP address of Phaser's Raspberry Pi\n        sdr_ip = \"ip:192.168.2.1\" \
          \  # default Pluto IP address\n        \n        # select which signal source\
          \ to use\n        # HB100 (external source)\n        # OUT1  (transmit freq\
          \ is set in config.py)\n        # OUT2  (transmit freq is set in config.py)\n\
          \        SignalSource = 'HB100'     # 'HB100', 'OUT1', or 'OUT2'\n        \n\
          \        # config.py has all the key parameters that you might want to modify\n\
          \        try:\n            import config as config\n        except:\n      \
          \      print(\"Make sure config.py is in this directory\")\n            sys.exit(0)\n\
          \            \n        \n        # =============================================================================\n\
          \        # Variables setup\n        # =============================================================================\n\
          \        \n        # if using HB100, load the signal frequency from \"phaser_find_hb100.py\"\
          \ output file\n        if SignalSource == 'HB100':\n            try:\n     \
          \           #with open(\"/home/analog/pyadi-iio/examples/phaser/hb100_freq_val.pkl\"\
          , \"rb\") as file1: \n                with open(\"hb100_freq_val.pkl\", \"rb\"\
          ) as file1: \n                    config.SignalFreq = pickle.load(file1)\n \
          \               print(\"Found signal freq file, \", config.SignalFreq/1e9, \"\
          \ GHz\")\n            except:\n                print(\"No signal freq found,\
          \ keeping at \", config.SignalFreq/1e9, \" GHz\")\n        \n        \"\"\"\
          SET DEFAULT VALUES\"\"\"\n        sdr_address = sdr_ip\n        self.SignalFreq\
          \ = config.SignalFreq\n        Tx_freq = config.Tx_freq  # Pluto's Tx LO freq.\n\
          \        Rx_freq = config.Rx_freq  # Pluto's Rx LO freq\n        LO_freq = self.SignalFreq\
          \ + Rx_freq  # freq of the LTC5548 mixer LO\n        SampleRate = config.SampleRate\n\
          \        Rx_gain = config.Rx_gain\n        Tx_gain = config.Tx_gain\n      \
          \  self.RxPhase1 = config.Rx1_cal\n        self.RxPhase2 = config.Rx2_cal\n\
          \        self.RxPhase3 = config.Rx3_cal\n        self.RxPhase4 = config.Rx4_cal\n\
          \        self.RxPhase5 = config.Rx5_cal\n        self.RxPhase6 = config.Rx6_cal\n\
          \        self.RxPhase7 = config.Rx7_cal\n        self.RxPhase8 = config.Rx8_cal\n\
          \        self.phase_step_size = 2.8125\n        self.c = 299792458  # speed\
          \ of light in m/s\n        self.d = config.d   # antenna spacing for phaser\
          \ is 14mm\n        self.gainList = np.array([\n            self.gain1,\n   \
          \         self.gain2,\n            self.gain3,\n            self.gain4,\n  \
          \          self.gain5,\n            self.gain6,\n            self.gain7,\n \
          \           self.gain8\n            ])\n        self.phaseList = np.array([\n\
          \            self.RxPhase1,\n            self.RxPhase2,\n            self.RxPhase3,\n\
          \            self.RxPhase4,\n            self.RxPhase5,\n            self.RxPhase6,\n\
          \            self.RxPhase7,\n            self.RxPhase8\n            ])     \
          \   \n        \n        # Use the onboard VCO to generate the LO?  Or apply\
          \ source to EXT_LO?\n        gpios = adi.one_bit_adc_dac(rpi_ip)\n        gpios.gpio_vctrl_1\
          \ = 1  # 1=Use onboard PLL/LO source  (0=use external LO input)\n        gpios.gpio_vctrl_2\
          \ = 1  # 1=Send LO to transmit circuitry  (0=disable Tx path and send LO to\
          \ LO_OUT)\n        \n        # setup GPIOs to control if Tx is output on OUT1\
          \ or OUT2\n        gpios.gpio_div_mr = 1\n        gpios.gpio_div_s0 = 0\n  \
          \      gpios.gpio_div_s1 = 0\n        gpios.gpio_div_s2 = 0\n        attempt\
          \ = True\n        while attempt:\n            try:\n                # Initialize\
          \ Pluto\n                self.sdr = SDR.SDR_init(\n                    sdr_address,\n\
          \                    SampleRate,\n                    Tx_freq,\n           \
          \         Rx_freq,\n                    Rx_gain,\n                    Tx_gain,\n\
          \                    config.buffer_size,\n                    )\n          \
          \      SDR.SDR_LO_init(rpi_ip, LO_freq)  # Set Phaser's ADF4159 to the LO_freq\n\
          \                \n                # Intialize the ADAR1000 receive array\n\
          \                self.rx_array = adi.adar1000_array(\n                    uri=rpi_ip,\n\
          \                    chip_ids=[\"BEAM0\", \"BEAM1\"],  # these are the ADAR1000s'\
          \ labels in the device tree\n                    device_map=[[1], [2]],\n  \
          \                  element_map=[[1, 2, 3, 4, 5, 6, 7, 8]],\n               \
          \     device_element_map={\n                        1: [7, 8, 5, 6],  # i.e.\
          \ channel2 of device1 (BEAM0), maps to element 8\n                        2:\
          \ [3, 4, 1, 2],\n                        },\n                    )\n       \
          \         attempt = False\n                print('Connected to Phaser')\n  \
          \          except:\n                print('Could not connect to Phaser')\n \
          \               continue\n        for device in self.rx_array.devices.values():\n\
          \            ADAR.ADAR_init(device)  # resets the ADAR1000\n            ADAR.ADAR_set_mode(device,\
          \ \"rx\")  # ADAR1000s on Phaser are receive only, so mode is always \"rx\"\n\
          \        ADAR.ADAR_set_Taper(\n            self.rx_array,\n            self.gainList\n\
          \            )\n        # Set transmitter to either OUT1 or OUT2 SMA port. \
          \ Or disable if using HB100\n        if SignalSource == 'OUT1':    # use Phaser's\
          \ OUT1 SMA port as the transmitter\n            gpios.gpio_tx_sw = 1      #\
          \ 0=OUT2, 1=OUT1\n            gpios.gpio_vctrl_2 = 1    # 1=Send LO to transmit\
          \ circuitry\n        elif SignalSource == 'OUT2':  # use OUT2 as the transmitter\n\
          \            gpios.gpio_tx_sw = 0      # 0=OUT2, 1=OUT1\n            gpios.gpio_vctrl_2\
          \ = 1    # 1=Send LO to transmit circuitry\n        else:   # use HB100 as the\
          \ transmit signal source\n            gpios.gpio_tx_sw = 0 \n            SDR.SDR_setTx(self.sdr,\
          \ -80) # disable tx output by attenuating it\n                   \n    def ConvertPhaseToSteerAngle(self,\
          \ PhDelta):\n            # steering angle theta = arcsin(c*deltaphase/(2*pi*f*d)\n\
          \        value1 = (self.c * np.radians(np.abs(PhDelta))) / (\n            2\
          \ * 3.14159 * (self.SignalFreq) * self.d)\n        clamped_value1 = max(min(1,\
          \ value1), -1)  # arcsin argument must be between 1 and -1\n        theta =\
          \ np.degrees(np.arcsin(clamped_value1))\n        if PhDelta >= 0:\n        \
          \    SteerAngle = theta  # positive PhaseDelta covers 0deg to 90 deg\n     \
          \   else:\n            SteerAngle = -theta  # negative phase delta covers 0\
          \ deg to -90 deg\n        return SteerAngle    \n        \n    def dbfs(self,\
          \ raw_data):\n        # function to convert IQ samples to FFT plot, scaled in\
          \ dBFS\n        NumSamples = len(raw_data)\n        win = np.hamming(NumSamples)\n\
          \        y = raw_data * win\n        s_fft = np.fft.fft(y) / np.sum(win)\n \
          \       s_shift = np.fft.fftshift(s_fft)\n        s_dbfs = 20*np.log10(np.abs(s_shift)/(2**11))\
          \     # Pluto is a signed 12 bit ADC, so use 2^11 to convert to dBFS\n     \
          \   return s_dbfs\n    \n    def updateGainPhase(self):\n        self.gainList\
          \ = np.array([\n            self.gain1,\n            self.gain2,\n         \
          \   self.gain3,\n            self.gain4,\n            self.gain5,\n        \
          \    self.gain6,\n            self.gain7,\n            self.gain8\n        \
          \    ])  # gains from 0 to 100\n        \n        self.phaseList = np.array([\n\
          \            self.RxPhase1 + self.phase1,\n            self.RxPhase2 + self.phase2,\n\
          \            self.RxPhase3 + self.phase3,\n            self.RxPhase4 + self.phase4,\n\
          \            self.RxPhase5 + self.phase5,\n            self.RxPhase6 + self.phase6,\n\
          \            self.RxPhase7 + self.phase7,\n            self.RxPhase8 + self.phase8\n\
          \            ])\n        \n    def null_vec(self, null_angle):\n        null_phase\
          \ = 2*np.pi*self.SignalFreq*self.d*np.sin(np.deg2rad(null_angle))/self.c\n \
          \       null_phases = np.array([0,1,2,3,4,5,6,7])*null_phase # create array\
          \ with phase shifts for null angle\n        polar_null_phases = np.exp(1j *\
          \ null_phases) # null steer vector\n        return polar_null_phases\n\n   \
          \ def work(self, input_items, output_items):\n        save_this_trace=False\n\
          \        clear_this_trace=False\n        enable_null_1 = self.null_enable_1\n\
          \        enable_null_2 = self.null_enable_2\n        if enable_null_1 == True:\n\
          \            polar_null_phases = self.null_vec(self.null_angle_1)\n        \
          \    wn1 = self.gainList * polar_null_phases   # beam weights for null direction\n\
          \        if enable_null_2 == True:\n            polar_null_phases = self.null_vec(self.null_angle_2)\n\
          \            wn2 = self.gainList * polar_null_phases   # beam weights for null\
          \ direction\n            \n        SteerValues = np.arange(-90, 90 + self.step_size,\
          \ self.step_size)\n        # Phase delta = 2*Pi*d*sin(theta)/lambda = 2*Pi*d*sin(theta)*f/c\n\
          \        PhaseValues = np.degrees(\n            2*np.pi*self.d* np.sin(np.radians(SteerValues))\n\
          \            * self.SignalFreq / self.c)\n        self.updateGainPhase()\n \
          \       \n        for x in range(len(PhaseValues)):\n            if self.save_trace\
          \ == True:\n                save_this_trace = True\n            if self.clear_trace\
          \ == True:\n                clear_this_trace = True\n            PhDelta = PhaseValues[x]\n\
          \            steer_phases = (np.array([0,1,2,3,4,5,6,7])*PhDelta) % 360\n  \
          \          wd = self.gainList * np.exp(1j * np.deg2rad(steer_phases))\n    \
          \        # wd is the beam weights for desired steering direction\n         \
          \   # details here:  https://www.mathworks.com/help/phased/ug/array-pattern-synthesis.html\n\
          \            \n            if enable_null_1 == True:\n                wn1_herm\
          \ = np.conjugate(wn1.reshape(1,len(wn1)))\n                rn = wn1_herm @ wd\
          \ / (wn1_herm @ wn1)\n                wd = wd - wn1 * rn\n                \n\
          \            if enable_null_2 == True:\n                wn2_herm = np.conjugate(wn2.reshape(1,len(wn2)))\n\
          \                rn = wn2_herm @ wd / (wn2_herm @ wn2)\n                wd =\
          \ wd - wn2 * rn\n                \n            new_gains = np.abs(wd)\n    \
          \        new_gains = np.clip(new_gains, 0, 100)\n            new_phases = np.angle(wd)\n\
          \            new_phases = np.rad2deg(new_phases)\n            \n           \
          \ ADAR.ADAR_set_Taper(\n                self.rx_array,\n                new_gains\n\
          \                )\n            ADAR.ADAR_set_Phase(\n                self.rx_array,\n\
          \                0,\n                self.phase_step_size,\n               \
          \ new_phases\n                )\n            \n            data = self.sdr.rx()\n\
          \            data_sum = data[0]+data[1]\n            sum_dbfs = self.dbfs(data_sum)\n\
          \            peak_dbfs = max(sum_dbfs)\n            output_items[0][x] = (1*(self.ConvertPhaseToSteerAngle(PhDelta))\
          \ + 1j*peak_dbfs)\n            output_items[1][x] = 0-10000000j\n          \
          \  \n        for x in range(len(output_items[0])-len(SteerValues)):\n      \
          \      # fill in the empty parts of the array with large negative numbers to\
          \ make it plot nicely\n            output_items[0][len(SteerValues)+x] = 0-10000000j\n\
          \        if save_this_trace==True:\n            for x in range(len(self.saved_trace)):\n\
          \                self.saved_trace[x] = output_items[0][x]\n        if clear_this_trace==True:\n\
          \            self.saved_trace = np.ones(4094)*(0-100000j)\n        for x in\
          \ range(len(self.saved_trace)):\n            output_items[1][x] = self.saved_trace[x]\n\
          \n        return len(output_items[0])\n"
        affinity: ''
        alias: ''
        clear_trace: clear_trace
        comment: ''
        gain1: gain1
        gain2: gain2
        gain3: gain3
        gain4: gain4
        gain5: gain5
        gain6: gain6
        gain7: gain7
        gain8: gain8
        maxoutbuf: '0'
        minoutbuf: '0'
        null_angle_1: null_angle_1
        null_angle_2: null_angle_2
        null_enable_1: null_enable_1
        null_enable_2: null_enable_2
        phase1: phase1
        phase2: phase2
        phase3: phase3
        phase4: phase4
        phase5: phase5
        phase6: phase6
        phase7: phase7
        phase8: phase8
        save_trace: save_trace
        step_size: step_size
      states:
        _io_cache: ('Phaser Python Control Block', 'blk', [('step_size', '3'), ('save_trace',
          'False'), ('clear_trace', 'False'), ('gain1', '100'), ('gain2', '100'), ('gain3',
          '100'), ('gain4', '100'), ('gain5', '100'), ('gain6', '100'), ('gain7', '100'),
          ('gain8', '100'), ('phase1', '0'), ('phase2', '0'), ('phase3', '0'), ('phase4',
          '0'), ('phase5', '0'), ('phase6', '0'), ('phase7', '0'), ('phase8', '0'), ('null_enable_1',
          'False'), ('null_angle_1', '0'), ('null_enable_2', 'False'), ('null_angle_2',
          '0')], [], [('0', 'complex', 1), ('1', 'complex', 1)], 'arguments to this function
          show up as parameters in GRC', ['clear_trace', 'gain1', 'gain2', 'gain3', 'gain4',
          'gain5', 'gain6', 'gain7', 'gain8', 'null_angle_1', 'null_angle_2', 'null_enable_1',
          'null_enable_2', 'phase1', 'phase2', 'phase3', 'phase4', 'phase5', 'phase6',
          'phase7', 'phase8', 'save_trace', 'step_size'])
        bus_sink: false
        bus_source: false
        bus_structure: null
        coordinate: [184, 300.0]
        rotation: 0
        state: true
    - name: qtgui_const_sink_x_0
      id: qtgui_const_sink_x
      parameters:
        affinity: ''
        alias: ''
        alpha1: '1.0'
        alpha10: '1.0'
        alpha2: '1.0'
        alpha3: '1.0'
        alpha4: '1.0'
        alpha5: '1.0'
        alpha6: '1.0'
        alpha7: '1.0'
        alpha8: '1.0'
        alpha9: '1.0'
        autoscale: 'False'
        axislabels: 'True'
        color1: '"blue"'
        color10: '"red"'
        color2: '"red"'
        color3: '"red"'
        color4: '"red"'
        color5: '"red"'
        color6: '"red"'
        color7: '"red"'
        color8: '"red"'
        color9: '"red"'
        comment: ''
        grid: 'True'
        gui_hint: 0,2,5,3
        label1: ''
        label10: ''
        label2: ''
        label3: ''
        label4: ''
        label5: ''
        label6: ''
        label7: ''
        label8: ''
        label9: ''
        legend: 'False'
        marker1: '-1'
        marker10: '0'
        marker2: '-1'
        marker3: '0'
        marker4: '0'
        marker5: '0'
        marker6: '0'
        marker7: '0'
        marker8: '0'
        marker9: '0'
        name: '""'
        nconnections: '2'
        size: '4094'
        style1: '1'
        style10: '0'
        style2: '1'
        style3: '0'
        style4: '0'
        style5: '0'
        style6: '0'
        style7: '0'
        style8: '0'
        style9: '0'
        tr_chan: '0'
        tr_level: '0.0'
        tr_mode: qtgui.TRIG_MODE_FREE
        tr_slope: qtgui.TRIG_SLOPE_POS
        tr_tag: '""'
        type: complex
        update_time: '0.10'
        width1: '2'
        width10: '1'
        width2: '1'
        width3: '1'
        width4: '1'
        width5: '1'
        width6: '1'
        width7: '1'
        width8: '1'
        width9: '1'
        xmax: '89'
        xmin: '-89'
        ymax: '0'
        ymin: '-75'
      states:
        bus_sink: false
        bus_source: false
        bus_structure: null
        coordinate: [424, 464.0]
        rotation: 0
        state: true
    - name: tab
      id: qtgui_tab_widget
      parameters:
        alias: ''
        comment: ''
        gui_hint: 0,0,6,2
        label0: control
        label1: gain
        label10: Tab 10
        label11: Tab 11
        label12: Tab 12
        label13: Tab 13
        label14: Tab 14
        label15: Tab 15
        label16: Tab 16
        label17: Tab 17
        label18: Tab 18
        label19: Tab 19
        label2: phase
        label3: null steering
        label4: Tab 4
        label5: Tab 5
        label6: Tab 6
        label7: Tab 7
        label8: Tab 8
        label9: Tab 9
        num_tabs: '4'
      states:
        bus_sink: false
        bus_source: false
        bus_structure: null
        coordinate: [200, 36.0]
        rotation: 0
        state: true
    
    connections:
    - [epy_block_0, '0', qtgui_const_sink_x_0, '0']
    - [epy_block_0, '1', qtgui_const_sink_x_0, '1']
    
    metadata:
      file_format: 1
    

  • I couldn't make it run. The "Phaser Python Control Block" from GNURadio says "Can't interpret source code: module 'iio' has no attribute 'Context'

    I did the following workarounds:

    -In "epy_block_0.py"  I changed "ADAR_pyadi_functions_edited1" by ADAR_pyadi_functions, as this is the standar name of the folder it comes with the installation.

    -Also in "epy_block_0.py"  used the workaround for the conflict between gr-iio and pyadi-iio, adding "import iiopy as iio" as you did in the ADAR1000 GRC files.

    I save it all.

    Then I tried to run the GRC file again the error still. I also checked, that the "epy_block" (using open editor option in the block) within GRC did not implemented the changes I made (they are visible only in the 'epy_block_0.py' file of the folder), I do not know what is going on. 

  • Ok, it could be that something has changed with the new GRC version.  By end of Aug, I'll have looked into this and will publish a guide on how to set this up.  But in the meantime, you can see from my scripts what the general flow is -- we're just using the GRC python module/block to implement pyadi-iio code.  So perhaps start with a simpler setup and then you'll be able to fix what is broken as you progress.