classdef RFConnector < handle & matlab.mixin.Copyable
    %RFCONNECTOR - Create an RF connector
    %   C = RFConnector creates an RF coaxial connector.
    %
    %   C = RFConnector(Name,Value) creates an RF coaxial connector with
    %   one or more Name-Value pair arguments that are Name, InnerRadius,
    %   OuterRadius, EpsilonR, PinFootprint and PinLength.
    %
    %   RFCONNECTOR properties:
    %      Name         - The name of an RF connector. The default value is 'Connector'.
    %      InnerRadius  - Inner radius of an RF coaxial connector. InnerRadius is 
    %                     a scalar double and the default value is 0.5e-3 meter.
    %      OuterRadius  - Outer radius of an RF coaxial connector. OuterRadius is 
    %                     a scalar double and the default value is 1.5e-3 meter.
    %      EpsilonR     - Relative permittivity of the waveguided region of an
    %                     RF coaxial connector. EpsilonR is a scalar double and 
    %                     the default value is 1.734106.
    %      PinFootprint - Shape of contact footprint between an RF connector pin 
    %                     and signal trace. PinFootprint can take one of the 
    %                     following: 'Taper' and 'Rectangular'. The default value
    %                     is 'Taper'.
    %      PinLength    - Length of an RF connector pin. PinLength is a scalar double 
    %                     and the default value is 1e-3 meter.
    %      Impedance    - The characteristic impedance of an RF coaxial connector.
    %                     Impedance is a read-only property.

    %   Copyright 2023 The MathWorks, Inc.
    
    properties
        Name = 'Connector'
    end

    properties(Hidden)
        Type = 'Coaxial'
    end

    properties(Dependent)
        InnerRadius
        OuterRadius
    end

    properties
        EpsilonR
    end

    properties(Dependent)
        PinFootprint
        PinLength
    end

    properties(SetAccess=protected,GetAccess=public)
        Impedance
    end

    properties(Hidden,Access={?rfpcb.RFShield})
        Parent
    end

    properties(Access=private)
        protectedInnerRadius
        protectedOuterRadius
        protectedPinFootprint
        protectedPinLength
    end
    
    methods
        function obj = RFConnector(options)
            arguments
                options.Name (1,:)
                options.InnerRadius (1,1) double
                options.OuterRadius (1,1) double
                options.EpsilonR (1,1) double
                options.PinFootprint = 'Taper'
                options.PinLength (1,1) double
            end

            if isfield(options,'Name')
                obj.Name = options.Name;
            end

            if isfield(options,'InnerRadius')
                obj.InnerRadius = options.InnerRadius;
            else
                obj.InnerRadius = 0.5e-3;
            end

            if isfield(options,'OuterRadius')
                obj.OuterRadius = options.OuterRadius;
            else
                obj.OuterRadius = 1.5e-3;
            end

            if isfield(options,'EpsilonR')
                obj.EpsilonR = options.EpsilonR;
            else
                obj.EpsilonR = 1.734106;
            end

            obj.PinFootprint = options.PinFootprint;

            if isfield(options,'PinLength')
                obj.PinLength = options.PinLength;
            else
                obj.PinLength = 3e-3;
            end
        end
    end

    methods
        function set.Name(obj,str)
            mustBeTextScalar(str)
            obj.Name = str;
        end

        function set.InnerRadius(obj,propVal)
            mustBeNonempty(propVal)
            mustBeScalarOrEmpty(propVal)
            mustBeNonNan(propVal)
            mustBeFinite(propVal)
            mustBePositive(propVal)
            if ~isempty(obj.OuterRadius)
                mustBeLessThan(propVal,obj.OuterRadius)
            end
            obj.protectedInnerRadius = propVal;
            if ~isempty(obj.Parent)
                setHasStructureChanged(obj.Parent);
                parentObj = getParent(obj.Parent);
                while ~isempty(parentObj)
                    setHasStructureChanged(parentObj);
                    parentObj = getParent(parentObj);
                end
            end
        end

        function set.OuterRadius(obj,propVal)
            mustBeNonempty(propVal)
            mustBeScalarOrEmpty(propVal)
            mustBeNonNan(propVal)
            mustBeFinite(propVal)
            mustBePositive(propVal)
            if ~isempty(obj.InnerRadius)
                mustBeGreaterThan(propVal,obj.InnerRadius)
            end
            obj.protectedOuterRadius = propVal;
            if ~isempty(obj.Parent)
                setHasStructureChanged(obj.Parent);
                parentObj = getParent(obj.Parent);
                while ~isempty(parentObj)
                    setHasStructureChanged(parentObj);
                    parentObj = getParent(parentObj);
                end
            end
        end

        function set.EpsilonR(obj,propVal)
            mustBeNonempty(propVal)
            mustBeScalarOrEmpty(propVal)
            mustBeNonNan(propVal)
            mustBeFinite(propVal)
            mustBePositive(propVal)
            mustBeInRange(propVal,1.0,100)
            obj.EpsilonR = propVal;
        end

        function set.PinFootprint(obj,str)
            str = validatestring(str,{'Rectangular','Taper'});
            obj.protectedPinFootprint = str;
            if ~isempty(obj.Parent)
                setHasStructureChanged(obj.Parent);
                parentObj = getParent(obj.Parent);
                while ~isempty(parentObj)
                    setHasStructureChanged(parentObj);
                    parentObj = getParent(parentObj);
                end
            end
        end

        function set.PinLength(obj,propVal)
            mustBeNonempty(propVal)
            mustBeScalarOrEmpty(propVal)
            mustBeNonNan(propVal)
            mustBeFinite(propVal)
            mustBeNonnegative(propVal)
            obj.protectedPinLength = propVal;
            if ~isempty(obj.Parent)
                setRFPCBStructureChanged(obj.Parent);
                setHasStructureChanged(obj.Parent);
                parentObj = getParent(obj.Parent);
                while ~isempty(parentObj)
                    setHasStructureChanged(parentObj);
                    parentObj = getParent(parentObj);
                end
            end
        end

        function set.Parent(obj,propVal)
            obj.Parent = propVal;
        end

        function val = get.InnerRadius(obj)
            val = obj.protectedInnerRadius;
        end

        function val = get.OuterRadius(obj)
            val = obj.protectedOuterRadius;
        end

        function val = get.PinFootprint(obj)
            val = obj.protectedPinFootprint;
        end

        function val = get.PinLength(obj)
            val = obj.protectedPinLength;
        end

        function val = get.Impedance(obj)
            val = 138*log10(obj.OuterRadius/obj.InnerRadius)/sqrt(double(obj.EpsilonR));
        end
    end

    methods (Access=private)
        function eps = getCoaxialPortEpsilonR(obj,imp)
            % Zo = 138*log10(D/d)/sqrt(epsilonR)
            eps = (138*log10(obj.OuterRadius/obj.InnerRadius)/imp)^2;
        end
    end
end