classdef phaseShifter < rfpcb.PCBComponent & rfpcb.PrintedLine
%phaseShifter creates a phase shifter in the microstrip form.
%
%   h = phaseShifter creates a phase shifter. The default substrate
%   is Teflon with a thickness of 0.0016 m.
%
%   h = phaseShifter ('Property1', value1,'Property2', value2,...)
%   returns a phase shifter, based on the specified properties. Properties
%   you do not specify retain their default values.
%
%
%   phaseShifter properties:
%
%   NumSections      - Number of U-Sections in phase shifter. The default
%                      value is 1.
%   SectionShape     - Shape of the U-Sections. Supports ubendRightAngle,
%                      ubendMitered and ubendCurved. The default is 
%                      ubendRightAngle.
%   PortLineLength   - Length of the port line in meter. The default
%                      value is 0.0100 m.
%   PortLineWidth    - Width of the Port Line in meter. The default
%                      value is 0.0050 m.
%   Height           - Height of the phase shifter to the ground plane
%                      in meter. In case of a multi-layer substrate the
%                      Height property can be used to create a phase
%                      shifter at the interface of the two dielectrics.
%                      The default value is 0.0016 m.
%   GroundPlaneWidth - Width of the ground plane in meter. The default
%                      value is 0.0500 m.
%   Conductor        - Type of metal used for the conducting layers
%                     (accepts an object). The default object is PEC.
%   Substrate        - Type of dielectric material (accepts an object).
%                      The default object is dielectric (Teflon).
%   IsShielded       - Add a metal shielding to the phase shifter, 
%                      specified as logical 1 (true) if a metal shielding
%                      is added to the phase shifter. Otherwise logical 0
%                      (false). The default is logical 0 (false).
%   Shielding        - Metal shielding of the phase shifter, specified as
%                      a shape.Box object. The default value is a shape.Box
%                      whose length is the length of the ground plane,
%                      width is the width of the ground plane and center is
%                      [0 0 0.5*Shielding.Height]. You can modify the 
%                      property once you have created the object using dot 
%                      notation.
%   Connector        - Type of RF connector assembled at the feed locations
%                      of the phase shifter, specified as RFConnector
%                      object. The default value is RFConnector with
%                      default values.
%
%   phaseShifter methods:
%
%   show             - Visualize the phase shifter
%   sparameters      - Calculate S-parameter of the phase shifter
%   mesh             - Change or display the mesh properties for the
%                      phase shifter
%   current          - Calculate and/or plot the current distribution
%   charge           - Calculate and/or plot the charge distribution
%   feedCurrent      - Calculate the current at the feed port
%   layout           - Display all the metal layers along with feed and vias
%   shapes           - Return all the shapes of the metal layers in PCB
%   design           - Design a phase shifter at a particular
%                      frequency, arbitrary phase shift and 
%                      arbitrary impedance
%   dgs              - Create a defected ground structure for
%                      phase shifter
%
%   % Examples
%
%   % Example 1:
%   % Create a 3-section phase shifter and visualize it.
%
%   ps = phaseShifter('NumSections',3);
%   show(ps)
%
%   % Example 2:
%   % Create phase shifter at the interface of the multi-layer dielectric
%   % and visualize it.
%
%   ps = phaseShifter;
%   ps.Substrate = dielectric('Name',{'Teflon','Teflon'},'EpsilonR', ...
%   [2.1 2.1],'LossTangent',[0 0],'Thickness',[0.8e-3 0.8e-3]);
%   ps.Height = 0.8e-3;
%   show(ps);
%
%   See also microstripLine, wilkinsonSplitter

%   Copyright 2022-2023 The MathWorks, Inc.

    properties (SetAccess=protected, GetAccess = public)
        FeedDiameter
        GroundPlaneLength
    end
    properties (SetObservable)
        % Length of the port line in meter.
        PortLineLength
        % Width of the port line in meter.
        PortLineWidth
        % Number of U-Sections in phase shifter.
        NumSections
        % Shape of the U-Sections.
        SectionShape
        % Width of the ground plane in meter.
        GroundPlaneWidth
    end
    methods
        function obj = phaseShifter(varargin)
            parserObj = inputParser;
            addParameter(parserObj,'PortLineLength',10e-3);
            addParameter(parserObj,'PortLineWidth',5e-3);
            addParameter(parserObj,'NumSections',1);
            addParameter(parserObj,'SectionShape',ubendRightAngle);
            addParameter(parserObj,'Height',1.6e-3);
            addParameter(parserObj,'GroundPlaneLength',12e-3)
            addParameter(parserObj,'GroundPlaneWidth',50e-3)
            addParameter(parserObj,'Conductor',metal('PEC'))
            addParameter(parserObj,'Substrate',dielectric('Teflon')) %Teflon
            addParameter(parserObj,'Tilt',0)
            addParameter(parserObj,'TiltAxis',[0 0 1])
            addParameter(parserObj,'IsShielded',false)
            addParameter(parserObj,'Connector',[])
            parse(parserObj,varargin{:});
            obj = obj@rfpcb.PCBComponent(parserObj.Results.Height,...
                parserObj.Results.Substrate,parserObj.Results.Conductor,...
                parserObj.Results.Tilt,parserObj.Results.TiltAxis);
            obj.PortLineLength      = parserObj.Results.PortLineLength;
            obj.PortLineWidth       = parserObj.Results.PortLineWidth;
            obj.NumSections         = parserObj.Results.NumSections;
            obj.SectionShape        = parserObj.Results.SectionShape;
            obj.GroundPlaneWidth    = parserObj.Results.GroundPlaneWidth;
            obj.GroundPlaneLength   = parserObj.Results.GroundPlaneLength;
            obj.Tilt                = parserObj.Results.Tilt;
            obj.TiltAxis            = parserObj.Results.TiltAxis;
            setSubstrateLength(obj,obj.Substrate);
            setSubstrateWidth(obj,obj.Substrate);
            obj.IsShielded          = parserObj.Results.IsShielded;
            if ~isempty(parserObj.Results.Connector)
                obj.Connector       = parserObj.Results.Connector;
            end

            % Assign feed type for model
            setFeedType(obj,'singleedge');
            obj.SolverStruct.Source.type = 'voltage';
            setSourceVoltage(obj, 1, 2);
            setPhaseShift(obj, 0, 2);
            %             setPortConnections(obj,containers.Map([1,2],{[],[]}));
        end

        function obj = design(pobj,f,options)
            %DESIGN method calculates the dimensions for phase shifter. The
            %design is enabled only for a single section.
            %
            %   ps = design(psobj,1e9) returns a design of phase shifter
            %   at 1 GHz with the default values.
            %
            %   ps = design(psobj,1e9,'PhaseShift',90) returns a design 
            %   of phase shifter at 1 GHz with a Phase shift of 90 degrees.
            %
            %   Input Arguments:
            %
            %       psobj           : phaseShifter object.
            %       Frequency       : Design frequency. This input is
            %                         required from the user.
            %       PhaseShift      : Phase Shift of the phase shifter in degree.
            %                         The default is 90 deg.
            %       Z0              : Characteristic Impedance of the phase
            %                         shifter in ohms. The default value is 50.
            %
            %
            %   % Examples:
            %
            %   % Example 1:
            %   % Design a phase shifter at 1.8 GHz and with a phase shift of
            %   % 75 degrees.
            %
            %   ps = design(phaseShifter, 1.8e9, 'PhaseShift',75);
            %   figure;
            %   show(ps);
            %
            %   % Example 2:
            %   % Design a phase shifter at 1.8 GHz with a characteristic
            %   % impedance of 75 ohms.
            %
            %   ps = design(phaseShifter, 1.8e9, 'Z0',75)
            %   figure;
            %   show(ps);
            %
            arguments
                pobj (1,1) phaseShifter
                f (1,1) {mustBePositive,mustBeFinite,mustBeNonNan,mustBeNonempty}
                options.PhaseShift (1,1) {mustBePositive,mustBeFinite,mustBeNonNan,mustBeNonempty} = 90;
                options.Z0 (1,1) {mustBePositive,mustBeFinite,mustBeNonNan,mustBeNonempty,mustBeInRange(options.Z0,40,80)} = 50;
            end
            obj = copy(pobj);
            if obj.NumSections>1
                error(message('rfpcb:rfpcberrors:Unsupported','phase shifter design','NumSections greater than 1'));
            end
            pshift = options.PhaseShift;
            Zo = options.Z0;
            if numel(obj.Substrate.Thickness)>1
                error(message('rfpcb:rfpcberrors:Unsupported','phase shifter design','multiple substrates'));
            end
            em.MeshGeometry.checkFrequency(f);
            line = microstripLine;
            line = design(line,f,'Z0',Zo,'LineLength',pshift/360);

            len1 = line.Length;  
            linelen = len1/(2*obj.NumSections-1);
            linelen1 = linelen;
            i =1;
            if Zo<50
                CheckVal = 60e-3;
            else
                CheckVal = 48e-3;
            end
            while linelen < CheckVal
                line1 = microstripLine;
                line1 = design(line1,f,'Z0',Zo,'LineLength',1);
                linelen1 = len1+line1.Length*i;
                linelen = linelen1/(2*obj.NumSections-1);
                i=i+1;
            end
            obj.PortLineLength = 8e-3;
            linelen2 = (linelen1-16e-3);
            if f >= 5e9
                correction = (linelen2*f/1e9)/180;   
            else
                correction = 0;
            end
            obj.SectionShape.Length(1) = linelen2*(2/5)-correction/2;
            obj.SectionShape.Length(2) = linelen2*(1/5);
            obj.SectionShape.Length(3) = linelen2*(2/5)-correction/2;
            obj.PortLineWidth          = line.Width;
            obj.SectionShape.Width     = [line.Width line.Width line.Width];
            obj.GroundPlaneWidth = obj.SectionShape.Length(1)*3;
            if isa(obj.SectionShape,'ubendCurved')
                obj.SectionShape.CurveRadius = obj.SectionShape.Width(1)/2;
            elseif isa(obj.SectionShape,'ubendMitered')
                obj.SectionShape.MiterDiagonal = obj.SectionShape.Width(1)/2;
            end
        end
        function set.PortLineLength(obj,propVal)
            validateattributes(propVal,{'numeric'},...
                {'nonempty','scalar','real','nonnan','finite','positive'}...
                ,'phaseShifter', 'PortLineLength');
            if isPropertyChanged(obj,obj.PortLineLength,propVal)
                obj.PortLineLength =  propVal;
                setSubstrateLength(obj,obj.Substrate);
            end
        end
        function set.PortLineWidth(obj,propVal)
            validateattributes(propVal,{'numeric'},...
                {'nonempty','scalar','real','nonnan','finite','positive'}...
                ,'phaseShifter', 'PortLineWidth');
            if isPropertyChanged(obj,obj.PortLineWidth,propVal)
                obj.PortLineWidth =  propVal;
                setSubstrateLength(obj,obj.Substrate);
                setSubstrateWidth(obj,obj.Substrate);
            end
        end
        function set.NumSections(obj,propVal)
            validateattributes(propVal,{'numeric'},...
                {'nonempty','scalar','integer','nonnan','finite','positive','<=',9}...
                ,'phaseShifter', 'NumSections');
            if isPropertyChanged(obj,obj.NumSections,propVal)
                obj.NumSections =  propVal;
                setSubstrateLength(obj,obj.Substrate);
                setSubstrateWidth(obj,obj.Substrate);
            end
        end
        function set.SectionShape(obj,propVal)
            if (ismember(class(propVal),{'cell'})) ==1
                    error(message('rfpcb:rfpcberrors:Unsupported','cell array input',...
                    'SectionShape'));
            end
            if ~(isa(propVal,'antenna.Shape'))
                error(message('rfpcb:rfpcberrors:InvalidShape','SectionShape'));
            end
            if numel(propVal)>1
                error(message('rfpcb:rfpcberrors:Unsupported','More than one Shape',...
                    'phaseShifter'));
            end
            if ~ismember(class(propVal),{'ubendMitered','ubendCurved','ubendRightAngle'})
                error(message('rfpcb:rfpcberrors:Unsupported','This Shape',...
                    'phaseShifter. Supported Shape is ubendMitered, ubendCurved and ubendRightAngle'));
            end
            setHasStructureChanged(obj);
            if isPropertyChanged(obj,obj.SectionShape,propVal)
                obj.SectionShape = propVal;
                setSubstrateLength(obj,obj.Substrate);
                setSubstrateWidth(obj,obj.Substrate);
            end
        end
        function set.GroundPlaneWidth(obj,propVal)
            validateattributes(propVal,{'numeric'},...
                {'nonempty','scalar','real','nonnan','finite','positive'}...
                ,'phaseShifter', 'GroundPlaneWidth');
            if isPropertyChanged(obj,obj.GroundPlaneWidth,propVal)
                obj.GroundPlaneWidth =  propVal;
                setSubstrateWidth(obj,obj.Substrate)
            end
        end
        function propVal = get.GroundPlaneLength(obj)
            if ~isempty(obj.SectionShape)
                shape = obj.SectionShape;
                GLength = obj.PortLineLength*2+(shape.Width(1)+shape.Length(2)+shape.Width(1))*obj.NumSections+shape.Length(2)*(obj.NumSections-1);
                if ~obj.IsShielded 
                    propVal = GLength;
                else
                    propVal = GLength+(2*obj.Connector.PinLength);
                end
            else
                propVal = [];
            end
        end
    end

    methods (Hidden)
        function [edgePortLineLength,growthRate] = calculateMeshParams(obj,lambda)
            createGeometry(obj);
            Aboard = area(obj.privateStack.BoardShape);
            metalLayers = find(cellfun(@(x) isa(x,'antenna.Shape'),obj.privateStack.Layers));
            A_phys  = cellfun(@(x) area(x),obj.privateStack.Layers(metalLayers));
            epsr    = obj.Substrate.EpsilonR;
            lambda  = lambda/sqrt(mean(epsr));
            [edgePortLineLength,minel,growthRate] = calcMeshParamsCore(obj,lambda, Aboard, A_phys, 0.3);
            setMeshMinContourEdgeLength(obj,minel);
        end
        function CheckDimensions(obj)
            % Checking the top metal layer height and if it doesnt lie at
            % the interface of the Dielectric then we error out.
            layerHeights = round(cumsum(obj.Substrate.Thickness),18);
            NumSubLayer =  numel(layerHeights);
            A = find(round(abs(layerHeights-obj.Height),15) <= eps(max(abs(layerHeights),abs(obj.Height))), 1);
            if isempty(A)
                 Height = layerHeights(1,1:NumSubLayer);
                 error(message('rfpcb:rfpcberrors:InvalidHeight',num2str(Height)));
            end
            if(numel(obj.SectionShape.Tilt)>1)
                error(message('rfpcb:rfpcberrors:Unsupported','Rotated ubend in the SectionShape',...
                    'phaseShifter'));
            end
            if obj.SectionShape.Length(1)<2*obj.SectionShape.Width(2)
                error(message('rfpcb:rfpcberrors:InvalidValueGreaterEqual', ...
                    'Length(1) of SectionShape','twice the Width(2) of SectionShape'));
            end
            if obj.SectionShape.Length(3)<2*obj.SectionShape.Width(2)
                error(message('rfpcb:rfpcberrors:InvalidValueGreaterEqual', ...
                    'Length(3) of SectionShape','twice the Width(2) of SectionShape'));
            end
            if ~isequal(obj.SectionShape.Length(1),obj.SectionShape.Length(3))
                error(message('rfpcb:rfpcberrors:IncorrectValues','Length','that the Length(1) and Length(3) of SectionShape is same'));

            end
        end
        function createGeometry(obj,varargin)
            CheckDimensions(obj);
            setSubstrateLength(obj,obj.Substrate);
            setSubstrateWidth(obj,obj.Substrate);
            obj.SectionShape.NumPoints = 5;
            shape = copy(obj.SectionShape);
            % Creates the Geometry for the phase shifter
            if strcmp(class(obj.SectionShape),'ubendRightAngle') %#ok<STISA> 
                if obj.SectionShape.Length(1) < obj.PortLineWidth
                    error(message('rfpcb:rfpcberrors:InvalidValueLessEqual', ...
                        'PortLineWidth','Length(1) of u-bend'));
                end
                inLine  = bendRightAngle('Length',[obj.PortLineLength+shape.Width(1)/2 obj.SectionShape.Length(1)/2],'Width',[obj.PortLineWidth obj.SectionShape.Width(1)],'ReferencePoint',[obj.PortLineLength+shape.Width(1)/2,0]);
                outLine1= bendRightAngle('Length',[obj.PortLineLength+shape.Width(1)/2 obj.SectionShape.Length(1)/2],'Width',[obj.PortLineWidth obj.SectionShape.Width(1)],'ReferencePoint',[shape.Width(1)/2,0]);
                outLine1 = mirrorY(outLine1);
            end
            if strcmp(class(obj.SectionShape),'ubendMitered') %#ok<STISA> 
                if obj.SectionShape.Length(1) < obj.PortLineWidth
                    error(message('rfpcb:rfpcberrors:InvalidValueLessEqual', ...
                        'PortLineWidth','Length(1) of u-bend'));
                end
                inLine  = bendMitered('Length',[obj.PortLineLength+shape.Width(1)/2 obj.SectionShape.Length(1)/2],'Width',[obj.PortLineWidth obj.SectionShape.Width(1)],'ReferencePoint',[obj.PortLineLength+shape.Width(1)/2,0]);
                inLine.MiterDiagonal = obj.SectionShape.MiterDiagonal;
                outLine1= bendMitered('Length',[obj.PortLineLength+shape.Width(1)/2 obj.SectionShape.Length(1)/2],'Width',[obj.PortLineWidth obj.SectionShape.Width(1)],'ReferencePoint',[shape.Width(1)/2,0]);
                outLine1.MiterDiagonal = obj.SectionShape.MiterDiagonal;
                outLine1 = mirrorY(outLine1);
            end
            if strcmp(class(obj.SectionShape),'ubendCurved') %#ok<STISA> 
                if obj.SectionShape.Length(1) < obj.PortLineWidth
                    error(message('rfpcb:rfpcberrors:InvalidValueLessEqual', ...
                        'PortLineWidth','Length(1) of u-bend'));
                end
                obj.SectionShape.NumPoints = 5;
                inLine  = bendCurved('Length',[obj.PortLineLength+shape.Width(1)/2 obj.SectionShape.Length(1)/2],'Width',[obj.PortLineWidth obj.SectionShape.Width(1)],'ReferencePoint',[obj.PortLineLength+shape.Width(1)/2,0],'NumPoints',5);
                inLine.CurveRadius = obj.SectionShape.CurveRadius;
                outLine1= bendCurved('Length',[obj.PortLineLength+shape.Width(1)/2 obj.SectionShape.Length(1)/2],'Width',[obj.PortLineWidth obj.SectionShape.Width(1)],'ReferencePoint',[shape.Width(1)/2,0],'NumPoints',5);
                outLine1.CurveRadius = obj.SectionShape.CurveRadius;
                outLine1 = mirrorY(outLine1);
            end
            shape.ReferencePoint = [0,0];
            shape2  = rotateZ(copy(shape),180);
            shape = translate(shape,[shape.Width(1)+shape.Length(2)/2,-shape.Length(1),0]);
            shape2 = translate(shape2,[shape2.Width(1)+shape2.Length(2)/2,shape2.Length(1),0]);
            finalshape = inLine;
            transVec = obj.PortLineLength;
            for i=1:obj.NumSections
                if i ==1
                    shapeN = copy(shape);
                    shapeN.Length(1) = shapeN.Length(1)/2;
                    if obj.NumSections ==1
                        shapeN.Length(3) = shapeN.Length(3)/2;
                    end
                    shape1  = translate(copy(shapeN),[transVec,0,0]);
                elseif i ==obj.NumSections
                    shapeN = copy(shape);
                    shapeN.Length(3) = shapeN.Length(3)/2;
                    shape1  = translate(copy(shapeN),[transVec,0,0]);
                else
                    shape1  = translate(copy(shape),[transVec,0,0]);
                end
                
                transVec = transVec + shape1.Width(1)+shape1.Length(2)+shape1.Width(3);
                %                 intLine1 = translate(copy(intLine),[transVec,0,0]);
                shape3  = translate(copy(shape2),[transVec-shape2.Width(3),0,0]);
                transVec = transVec + shape1.Length(2);
                finalshape = finalshape + shape1;
                if i ~= obj.NumSections
                    finalshape = finalshape + shape3;
                end

            end
            outLine1  = translate(copy(outLine1),[transVec-shape1.Length(2),0,0]);
            finalshape = finalshape+outLine1;
            % Setting the Ground Plane
            glen = obj.PortLineLength*2+(shape.Width(1)+shape.Length(2)+shape.Width(1))*obj.NumSections+shape.Length(2)*(obj.NumSections-1);

            finalshape = translate(finalshape,[-glen/2,0,0]);
            obj.GroundPlaneLength = glen;
            gndPlane  =    antenna.Rectangle('Length',obj.GroundPlaneLength,...
                'Width',obj.GroundPlaneWidth,'Center',[0,0]);
            setFeedType(obj,'singleedge');

            %setting feed diameter to half the line PortLineWidth
            obj.FeedDiameter = obj.PortLineWidth/2;

            diel = buildSubstrate(obj);

            % Create the pcb stack
            MetalLayers = GetMetalLayer(obj,finalshape,gndPlane);
            subL = obj.Substrate.Length;
            subW = obj.Substrate.Width;
            boardshape = antenna.Rectangle('Length',subL,'Width',subW);
            buildStack(obj, 'phase shifter', MetalLayers, diel, boardshape, 1, 0 );
            % Save the geometry
            geom        = saveStackGeom(obj);

            % Set feed PortLineWidth
            feed_Width      = obj.privateStack.FeedWidth;
            obj.FeedWidth   = feed_Width;
            setFeedWidth(obj, feed_Width);
            savePrintedAntennaGeometry(obj,geom);

        end%of createGeometry

        function meshGenerator(obj,varargin)
            % Create phase shifter geometry
            createGeometry(obj);

            s = getMeshEdgeLength(obj);
            gr= getMeshGrowthRate(obj);
            minel = getMinContourEdgeLength(obj);
            minel = fixMinEdgeLength(obj,s,minel);
            printedmesh = meshStack(obj, s, gr,minel);
            setFeedType(obj,getFeedType(obj.privateStack));
            saveMesh(obj, printedmesh.Mesh);
        end

        function rObj = superLoad(obj,s)
            if nargin>1
                obj.PortLineLength       = s.PortLineLength;
                obj.PortLineWidth        = s.PortLineWidth;
                obj.SectionShape         = s.SectionShape;
                obj.NumSections          = s.NumSections;
                obj.GroundPlaneWidth     = s.GroundPlaneWidth;
                obj.privateStack     = s.privateStack;
                rObj = superLoadPCBComponent(obj,s,{'Gnd','Feed','Rad'});
            end
        end

        function [c,l,w,h] = getShieldingDefault(obj)
            l = obj.GroundPlaneLength;
            w = obj.GroundPlaneWidth;
            h = 5*obj.Height;
            c = [0 0 0.5*h];
        end
    end

    methods(Hidden)
        % Override superclass method(from em.Antenna specific to this
        % element since there is control on feed location
        function feedpoint = GetFeedPoint(obj)
            layerHeights = round(cumsum(obj.Substrate.Thickness),18);
            if obj.Height < max(layerHeights)
                % StripLine Configuration - The metal can be between any
                % dielectric layer
                % Calculates the metal layer position for the GroundPlane
                % and the top metal layer for passing to the feed point.
                substrateIndex  = find(round(abs(layerHeights-obj.Height),15) <= eps(max(abs(layerHeights),abs(obj.Height))));
                tempLayers                     	= numel(cell(1,numel(layerHeights) + 2));
                metalLayer1                   	= tempLayers;
                metalLayer2                    	= tempLayers-1-substrateIndex;
                %                 metalLayer3                   	= 1;

            else
                %Microstrip Configuration
                tempLayers                     	= numel(cell(1,numel(layerHeights) + 2));      %{topLayer};
                metalLayer1                    	= tempLayers;
                substrateIndex                 	= find(layerHeights<=obj.Height);
                metalLayer2                    	= tempLayers-1-numel(substrateIndex);

            end
            feedpoint       =   [-obj.GroundPlaneLength/2 0 obj.Height metalLayer2 metalLayer1;...
                obj.GroundPlaneLength/2 0 obj.Height metalLayer2 metalLayer1];
        end

        function MetalLayers = GetMetalLayer(obj,topLayer,gndPlane)

            layerHeights = round(cumsum(obj.Substrate.Thickness),18);
            if obj.Height < max(layerHeights)
                %StripLine Configuration - The metal can be between any
                %dielectric layer
                substrateIndex  = find(round(abs(layerHeights-obj.Height),15) <= eps(max(abs(layerHeights),abs(obj.Height))));
                tempLayers                       = cell(1,numel(layerHeights) + 2);
                tempLayers{end}                  = gndPlane;
                tempLayers{end-1-substrateIndex} = topLayer;
                %                 tempLayers{1}                    = gndPlane;
                MetalLayers = tempLayers;
            else
                % Microstrip Configuration
                tempLayers                               = cell(1,numel(layerHeights) + 2);      %{topLayer};
                tempLayers{end}                          = gndPlane;
                substrateIndex                           = find(layerHeights<=obj.Height);
                tempLayers{end-1-numel(substrateIndex)}  = topLayer;
                MetalLayers                              = tempLayers;

            end
        end
    end

    methods (Access=protected)
        function group = getPropertyGroups(obj)
            title = '';
            p = {'NumSections','SectionShape','PortLineLength',...
                'PortLineWidth','Height','GroundPlaneWidth', ...
                'Substrate','Conductor','IsShielded'};
            if obj.IsShielded
                pr = rfpcb.RFShield.getRFShieldPropertyGroups;
                p = [p pr];
            end
            group = objectProps(obj,p,title);
        end
    end

    methods (Static = true,Hidden) % ----LOADOBJ only IMPLEMENTATION ---%
        function r = loadobj(obj)
            if isobject(obj)&& isObjectFromCurrentVersion(obj)
                r = obj;
            else
                % Create default phase shifter
                newphaseShifter = phaseShifter;
                % Populate the properties
                r = superLoad(newphaseShifter,obj);
            end
            r = loadobj@em.EmStructures(r);
        end
    end

    methods(Hidden)
        function feededge = getFeedingEdges(obj, edges, FeedPoint,P)
            feededge = getFeedingEdges(obj.privateStack, edges, FeedPoint,P);
        end
    end
end % of phase shifter