コード例 #1
0
        /// <summary>
        /// Returns the nominal (Item1), min (Item2), and max (Item3) allowed HBM Peak Current to be within JS-001 specification
        /// </summary>
        /// <param name="hbmVoltage">The voltage of the HBM pulse waveform (polarity is ignored, absolute value will be used)</param>
        /// <returns>The nominal (Item1), min (Item2), and max (Item3) allowed HBM Peak Current to be within JS-001 specification</returns>
        internal static Tuple <double, double, double> HBMPeakCurrentNominalMinMax(double hbmVoltage)
        {
            double absHBMVoltage = System.Math.Abs(hbmVoltage);

            HBM500OhmJS001WaveformCharacteristicsSet set = HBM500OhmJS001WaveformCharacteristics.GenerateSetForHBMVoltage(absHBMVoltage);

            return(new Tuple <double, double, double>(
                       DoubleRangeExtensions.CenterOfRange(set.PeakCurrent.Item1, set.PeakCurrent.Item2),
                       set.PeakCurrent.Item1,
                       set.PeakCurrent.Item2));
        }
コード例 #2
0
        /// <summary>
        /// Returns the nominal (Item1), min (Item2), and max (Item3) allowed CDM Full Width at Half Maximum to be within the JS-002 specification
        /// </summary>
        /// <param name="signedCDMVoltage">The sign value of the CDM pulse waveform</param>
        /// <param name="isLargeTarget">A value indicating whether the CDM target is large or not (if not, then it is small)</param>
        /// <param name="oscilloscopeIsHighBandwidth">A value indicating whether the oscilloscope is high bandwidth (6GHz+) or not</param>
        /// <returns>The nominal (Item1), min (Item2), and max (Item3) allowed CDM Full Width at Half Maximum to be within the JS-002 specification</returns>
        public static Tuple <double, double, double> FullWidthHalfMaxNominalMinMax(double signedCDMVoltage, bool isLargeTarget, bool oscilloscopeIsHighBandwidth)
        {
            CDMJS002WaveformCharacteristicsSet set = CDMJS002WaveformCharacteristics.GenerateSetForCDMVoltageAndCharacteristics(
                signedCDMVoltage,
                isLargeTarget,
                oscilloscopeIsHighBandwidth);

            return(new Tuple <double, double, double>(
                       DoubleRangeExtensions.CenterOfRange(set.FullWidthAtHalfMaximum.Item1, set.FullWidthAtHalfMaximum.Item2),
                       set.FullWidthAtHalfMaximum.Item1,
                       set.FullWidthAtHalfMaximum.Item2));
        }
コード例 #3
0
        /// <summary>
        /// Calculates the Full Width at Half Max related values
        /// </summary>
        /// <param name="fullWidthHalfMaxPercent">(Optional) The threshold of where to measure the FWHM as a percent of the peak current (Default: 50%)</param>
        private void CalculateFullWidthAtHalfMax(double fullWidthHalfMaxPercent = 0.5)
        {
            if (fullWidthHalfMaxPercent <= 0.0 || fullWidthHalfMaxPercent >= 1.0)
            {
                throw new ArgumentOutOfRangeException("The Full Width Half Max Percentage cannot be less than or equal to 0% or greater than or equal to 100%");
            }

            // Calculate what the half-max current value is (default is 50% of max amplitude)
            double fullWidthHalfMaxCurrentSigned   = this.PeakCurrentValue * fullWidthHalfMaxPercent;
            double fullWidthHalfMaxCurrentAbsolute = fullWidthHalfMaxCurrentSigned.InvertValueIfNegativePolarity(this.WaveformIsPositivePolarity);

            // Find the first (interpolated) data point that is on the rising edge of the initial spike (of the absolute value waveform)
            DataPoint?fullWidthHalfMaxRisingAbsoluteDataPoint = this.AbsoluteWaveform.DataPointAtYThreshold(fullWidthHalfMaxCurrentAbsolute, true);

            if (fullWidthHalfMaxRisingAbsoluteDataPoint.HasValue)
            {
                // Convert the rising data point to the signed value
                this.FullWidthHalfMaxStartDataPoint = fullWidthHalfMaxRisingAbsoluteDataPoint.Value.InvertYValueIfNegativePolarity(this.WaveformIsPositivePolarity);

                // Trim the waveform, removing everything before the max peak
                Waveform absoluteWaveformAfterPeakCurrentTime = this.AbsoluteWaveform.TrimStart(this.PeakCurrentDataPoint.X);

                // Find the first (interpolated) data point that is on the falling edge of the initial spike (of the absolute value waveform)
                DataPoint?fullWidthHalfMaxFallingDataPointAbsolute = absoluteWaveformAfterPeakCurrentTime.DataPointAtYThreshold(fullWidthHalfMaxCurrentAbsolute, true);

                if (fullWidthHalfMaxFallingDataPointAbsolute.HasValue)
                {
                    // Convert the falling data point to the signed value
                    this.FullWidthHalfMaxEndDataPoint = fullWidthHalfMaxFallingDataPointAbsolute.Value.InvertYValueIfNegativePolarity(this.WaveformIsPositivePolarity);

                    // Find the full width half max time
                    this.FullWidthHalfMaxValue = this.FullWidthHalfMaxEndDataPoint.X - this.FullWidthHalfMaxStartDataPoint.X;

                    // Determine the min and max values for the Full Width Half Max to be passing
                    Tuple <double, double, double> nomMinMaxFullWidthHalfMax = CDMJS002WaveformCharacteristics.FullWidthHalfMaxNominalMinMax(this.SignedVoltage, this.IsLargeTarget, this.OscilloscopeIsHighBandwidth);
                    this.FullWidthHalfMaxAllowedMinimum = nomMinMaxFullWidthHalfMax.Item2;
                    this.FullWidthHalfMaxAllowedMaximum = nomMinMaxFullWidthHalfMax.Item3;

                    // Determine if the Full Width Half Max is passing
                    this.FullWidthHalfMaxIsPassing = DoubleRangeExtensions.BetweenInclusive(this.FullWidthHalfMaxAllowedMinimum, this.FullWidthHalfMaxAllowedMaximum, this.FullWidthHalfMaxValue);
                }
                else
                {
                    // Full Width Half Max falling data point could not be found, no calculations could be made.
                }
            }
            else
            {
                // Full Width Half Max rising data point could not be found, no calculations could be made.
            }
        }
        /// <summary>
        /// Calculates the Peak Current (Ips) related values
        /// </summary>
        private void CalculatePeakCurrent()
        {
            // Calculate the (absolute) Peak Current DataPoint
            DataPoint absolutePeakCurrentDataPoint = this.AbsoluteWaveform.Maximum();

            // Convert to the signed Peak Current DataPoint
            this.PeakCurrentDataPoint = absolutePeakCurrentDataPoint.InvertYValueIfNegativePolarity(this.WaveformIsPositivePolarity);

            // Extract the Peak Current value
            this.PeakCurrentValue = this.PeakCurrentDataPoint.Y;

            // Determine the min and max allowed values for the Peak Current to be passing
            Tuple <double, double, double> nomMinMaxPeakCurrent = HBM500OhmJS001WaveformCharacteristics.HBMPeakCurrentNominalMinMax(this.SignedVoltage);

            this.PeakCurrentAllowedMinimum = nomMinMaxPeakCurrent.Item2.InvertValueIfNegativePolarity(this.WaveformIsPositivePolarity);
            this.PeakCurrentAllowedMaximum = nomMinMaxPeakCurrent.Item3.InvertValueIfNegativePolarity(this.WaveformIsPositivePolarity);

            // Determine if the Peak Current is passing
            this.PeakCurrentIsPassing = DoubleRangeExtensions.BetweenInclusive(this.PeakCurrentAllowedMinimum, this.PeakCurrentAllowedMaximum, this.PeakCurrentValue);
        }
コード例 #5
0
        /// <summary>
        /// Calculates the Peak Current (Ips) related values
        /// </summary>
        private void CalculatePeakCurrent()
        {
            // Calculate the (absolute) Max Current DataPoint
            DataPoint ipsMaxAbsoluteDataPoint = this.IpsMaxDataPoint.InvertYValueIfNegativePolarity(this.WaveformIsPositivePolarity);

            // Determine Ips by evaluating the ips Polynomial at the IpsMax time
            double ipsAbsoluteValue = this.AbsoluteIpsPolynomial.Evaluate(ipsMaxAbsoluteDataPoint.X);

            // Determine the Peak Current (Ips) value
            this.PeakCurrentValue = ipsAbsoluteValue.InvertValueIfNegativePolarity(this.WaveformIsPositivePolarity);

            // Create a DataPoint at the time of Ips with the Ips value
            this.PeakCurrentDataPoint = new DataPoint(ipsMaxAbsoluteDataPoint.X, this.PeakCurrentValue);

            // Determine the min and max allowed values for the Peak Current to be passing
            Tuple <double, double, double> nomMinMaxPeakCurrent = HBM0OhmJS001WaveformCharacteristics.HBMPeakCurrentNominalMinMax(this.SignedVoltage);

            this.PeakCurrentAllowedMinimum = nomMinMaxPeakCurrent.Item2.InvertValueIfNegativePolarity(this.WaveformIsPositivePolarity);
            this.PeakCurrentAllowedMaximum = nomMinMaxPeakCurrent.Item3.InvertValueIfNegativePolarity(this.WaveformIsPositivePolarity);

            // Determine if the Peak Current is passing
            this.PeakCurrentIsPassing = DoubleRangeExtensions.BetweenInclusive(this.PeakCurrentAllowedMinimum, this.PeakCurrentAllowedMaximum, this.PeakCurrentValue);
        }
コード例 #6
0
        /// <summary>
        /// Calculates the Peak Current related values
        /// </summary>
        /// <param name="pointsAroundPeakToAverage">Number of points around the absolute peak to average together (Default: 0)</param>
        private void CalculatePeakCurrent(int pointsAroundPeakToAverage)
        {
            // Calculate the (absolute) Peak Current DataPoint
            DataPoint absolutePeakCurrentDataPoint = this.AbsoluteWaveform.Maximum();

            List <DataPoint> absWfmDataPoints = this.AbsoluteWaveform.DataPoints.ToList();
            int peakIndex      = absWfmDataPoints.IndexOf(absolutePeakCurrentDataPoint);
            int peakStartIndex = Math.Max(0, peakIndex - pointsAroundPeakToAverage);
            int peakStopIndex  = Math.Min(absWfmDataPoints.Count - 1, peakIndex + pointsAroundPeakToAverage);
            List <DataPoint> peakDataPoints = new List <DataPoint>();

            for (int i = peakStartIndex; i <= peakStopIndex; i++)
            {
                peakDataPoints.Add(absWfmDataPoints[i]);
            }

            Waveform peakWaveform = new Waveform(peakDataPoints);
            double   peakCurrent  = peakWaveform.Average();

            if (!this.WaveformIsPositivePolarity)
            {
                peakCurrent *= -1.0;
            }

            // Extract the Peak Current value
            this.PeakCurrentValue     = peakCurrent;
            this.PeakCurrentDataPoint = new DataPoint(absolutePeakCurrentDataPoint.X, peakCurrent);

            // Determine the min and max allowed values for the Peak Current to be passing
            Tuple <double, double, double> nomMinMaxPeakCurrent = CDMJS002WaveformCharacteristics.PeakCurrentNominalMinMax(this.SignedVoltage, this.IsLargeTarget, this.OscilloscopeIsHighBandwidth);

            this.PeakCurrentAllowedMinimum = nomMinMaxPeakCurrent.Item2.InvertValueIfNegativePolarity(this.WaveformIsPositivePolarity);
            this.PeakCurrentAllowedMaximum = nomMinMaxPeakCurrent.Item3.InvertValueIfNegativePolarity(this.WaveformIsPositivePolarity);

            // Determine if the Peak Current is passing
            this.PeakCurrentIsPassing = DoubleRangeExtensions.BetweenInclusive(this.PeakCurrentAllowedMinimum, this.PeakCurrentAllowedMaximum, this.PeakCurrentValue);
        }
コード例 #7
0
        /// <summary>
        /// Calculates the Decay Time related values
        /// </summary>
        private void CalculateDecayTime()
        {
            // The percentage of the Peak Current to be the end of the decay time (1/e)
            double decayTimeEndPercentOfIps = 1.0 / System.Math.E;

            // Trim the waveform, removing everything before the max peak
            Waveform absoluteWaveformAfterPeakCurrentTime = this.AbsoluteWaveform.TrimStart(this.PeakCurrentDataPoint.X);

            // Find the start/stop times for the noise-reducing exponential fit waveform
            DataPoint?expFitStartDataPoint = absoluteWaveformAfterPeakCurrentTime.DataPointAtYThreshold(0.5 * System.Math.Abs(this.PeakCurrentValue), true);

            if (expFitStartDataPoint.HasValue)
            {
                double    expFitStartTimeThreshold = expFitStartDataPoint.Value.X;
                DataPoint?expFitEndDataPoint       = absoluteWaveformAfterPeakCurrentTime.DataPointAtYThreshold(0.3 * System.Math.Abs(this.PeakCurrentValue), true);

                // The waveform was truncated before the lower end of the decaying region,
                // however there might be enough data to calculate by using the last data point instead.
                if (!expFitEndDataPoint.HasValue)
                {
                    expFitEndDataPoint = absoluteWaveformAfterPeakCurrentTime.DataPoints.Last();
                }

                double expFitEndTimeThreshold = expFitEndDataPoint.Value.X;

                // Gate the waveform to just the area for the noise-reducing exponential fit waveform
                Waveform absoluteWaveformDecayingRegion = this.AbsoluteWaveform.Gates(expFitStartTimeThreshold, expFitEndTimeThreshold);

                if (absoluteWaveformDecayingRegion.DataPoints.Any())
                {
                    // Find the exponential fit constants of the waveform from 0.5 * Ips to 0.3 * Ips to eliminate noise
                    Tuple <double, double> expFitAbsoluteWaveformDecayingRegionConstants = absoluteWaveformDecayingRegion.ExponentialFit();

                    // Create time values that go out far enough to ensure the decay time end threshold can be found
                    List <double> timeValues   = (from dp in absoluteWaveformDecayingRegion.DataPoints select dp.X).ToList();
                    double        samplingTime = absoluteWaveformDecayingRegion.SamplingTime();
                    while (timeValues.Last() < 0.000000800 && samplingTime > 0)
                    {
                        timeValues.Add(timeValues.Last() + samplingTime);
                    }

                    // Create the exponential fit equivalent waveform which has noise eliminated
                    Waveform expFitAbsoluteWaveformDecayingRegion = WaveformExtensions.CreateExponentialFitWaveform(
                        expFitAbsoluteWaveformDecayingRegionConstants.Item1,
                        expFitAbsoluteWaveformDecayingRegionConstants.Item2,
                        timeValues);

                    // Calculate what the decay time end threshold is (1/e % of Ips)
                    double decayTimeEndThreshold = System.Math.Abs(this.PeakCurrentValue) * decayTimeEndPercentOfIps;

                    // Find the first (interpolated) data point that is at 1/e % of Ips value (of the absolute value waveform)
                    DataPoint?decayTimeEndDataPointAbsolute = expFitAbsoluteWaveformDecayingRegion.DataPointAtYThreshold(decayTimeEndThreshold, true);

                    if (decayTimeEndDataPointAbsolute.HasValue)
                    {
                        // Convert the Decay Time end DataPoint to the signed value
                        this.DecayTimeEndDataPoint = decayTimeEndDataPointAbsolute.Value.InvertYValueIfNegativePolarity(this.WaveformIsPositivePolarity);

                        // Calculate the Decay Time
                        this.DecayTimeValue = this.DecayTimeEndDataPoint.X - this.PeakCurrentDataPoint.X;

                        // Determine if the Decay Time is passing
                        this.DecayTimeIsPassing = DoubleRangeExtensions.BetweenInclusive(this.DecayTimeAllowedMinimum, this.DecayTimeAllowedMaximum, this.DecayTimeValue);
                    }
                    else
                    {
                        // The derived exponential fit waveform didn't go out to a far enough time to capture the 1/e time.
                    }
                }
                else
                {
                    // Could not find any data points in the decay time window.  Likely due to a malformed waveform.
                }
            }
            else
            {
                // Since the waveform was truncated before even the start of the window to calculate the decaying region, the decay time cannot be calculated.
            }
        }
コード例 #8
0
        /// <summary>
        /// Calculates the Rise Time related values
        /// </summary>
        /// <param name="riseTimeStartPercent">Rise Time starting percentage (Default: 90%)</param>
        /// <param name="riseTimeEndPercent">Rise Time ending percentage (Default: 10%)</param>
        private void CalculateRiseTime(double riseTimeStartPercent, double riseTimeEndPercent)
        {
            if (riseTimeStartPercent < 0.0 || riseTimeStartPercent >= 1.0)
            {
                throw new ArgumentOutOfRangeException("The Rise Time Start % cannot be less than 0% or greater than or equal to 100%");
            }

            if (riseTimeEndPercent <= 0.0 || riseTimeEndPercent > 1.0)
            {
                throw new ArgumentOutOfRangeException("The Rise Time End % cannot be less than or equal to 0% or greater than 100%");
            }

            if (riseTimeStartPercent >= riseTimeEndPercent)
            {
                throw new ArgumentOutOfRangeException("The Rise Time Start % cannot be equal to or greater than the Rise Time End %");
            }

            // Generate an absolute-value version of the peak current value
            double peakCurrentAbsoluteValue = this.PeakCurrentValue.InvertValueIfNegativePolarity(this.WaveformIsPositivePolarity);

            // Calculate what the rise time end threshold is (a percentage of peak current)
            double riseTimeEndThreshold = peakCurrentAbsoluteValue * riseTimeEndPercent;

            // Find the first (interpolated) data point that is at the rise time end threshold (of the absolute value waveform)
            DataPoint?riseTimeEndAbsoluteDataPoint = this.AbsoluteWaveform.DataPointAtYThreshold(riseTimeEndThreshold, true);

            if (riseTimeEndAbsoluteDataPoint.HasValue)
            {
                // Convert the first Rise Time Data Point to the signed value
                this.RiseTimeEndDataPoint = riseTimeEndAbsoluteDataPoint.Value.InvertYValueIfNegativePolarity(this.WaveformIsPositivePolarity);

                // Trim the waveform, removing everything after the Rise Time End Time
                Waveform absoluteWaveformUntilRiseTimeEnd = this.AbsoluteWaveform.TrimEnd(this.RiseTimeEndDataPoint.X);

                // Calculate what the Rise Time Start Threshold is (a percentage of peak current)
                double riseTimeStartThreshold = peakCurrentAbsoluteValue * riseTimeStartPercent;

                // Find the last Data Point (interpolated) Data Point that is below the Rise Time Start Threshold (of the absolute trimmed waveform)
                DataPoint?riseTimeStartAbsoluteDataPoint = absoluteWaveformUntilRiseTimeEnd.DataPointAtYThreshold(riseTimeStartThreshold, false);

                if (riseTimeStartAbsoluteDataPoint.HasValue)
                {
                    // Convert the last Rise Time Data Point to the signed value
                    this.RiseTimeStartDataPoint = riseTimeStartAbsoluteDataPoint.Value.InvertYValueIfNegativePolarity(this.WaveformIsPositivePolarity);

                    // Find the Rise Time
                    this.RiseTimeValue = this.RiseTimeEndDataPoint.X - this.RiseTimeStartDataPoint.X;

                    // Determine if the Rise Time is passing
                    this.RiseTimeIsPassing = DoubleRangeExtensions.BetweenInclusive(this.RiseTimeAllowedMinimum, this.RiseTimeAllowedMaximum, this.RiseTimeValue);
                }
                else
                {
                    // Risetime start data point could not be found, no calculations could be made.
                }
            }
            else
            {
                // Risetime end data point could not be found, no calculations could be made.
            }
        }
コード例 #9
0
        /// <summary>
        /// Generates a new set for the CDM voltage, interpolated from the JS-002 specification.
        /// </summary>
        /// <param name="cdmVoltage">The voltage of the CDM pulse waveform (polarity is ignored, absolute value will be used)</param>
        /// <param name="isLargeTarget">A value indicating whether the CDM target is large or not (if not, then it is small)</param>
        /// <param name="oscilloscopeIsHighBandwidth">A value indicating whether the oscilloscope is high bandwidth (6GHz+) or not</param>
        /// <returns>A new set for the CDM voltage, interpolated from the JS-002 specification</returns>
        private static CDMJS002WaveformCharacteristicsSet GenerateSetForCDMVoltageAndCharacteristics(double cdmVoltage, bool isLargeTarget, bool oscilloscopeIsHighBandwidth)
        {
            double absCDMVoltage = System.Math.Abs(cdmVoltage);

            List <CDMJS002WaveformCharacteristicsSet> possibleSets =
                (from set in CDMJS002WaveformCharacteristics.characteristicSets
                 where set.IsLargeTarget == isLargeTarget && set.IsHighBandwidth == oscilloscopeIsHighBandwidth
                 select set).ToList();

            if (possibleSets.Any(set => set.TestCondition == absCDMVoltage))
            {
                // If the voltage is an exact match to a set, use it
                return(possibleSets.First(set => set.TestCondition == absCDMVoltage).Clone());
            }
            else
            {
                // The voltage isn't an exact match to the table, so interpolate it
                CDMJS002WaveformCharacteristicsSet below = null;
                CDMJS002WaveformCharacteristicsSet above = null;

                // Try to find the closest sets that are below and above the Test Condition voltage
                foreach (CDMJS002WaveformCharacteristicsSet set in possibleSets)
                {
                    if (set.TestCondition < absCDMVoltage)
                    {
                        if (below == null || below.TestCondition < set.TestCondition)
                        {
                            below = set;
                        }
                    }
                    else
                    {
                        if (above == null || above.TestCondition > set.TestCondition)
                        {
                            above = set;
                        }
                    }
                }

                if (below != null && above != null)
                {
                    // Interpolate between the below and above table entries
                    double percentWithinRange = DoubleRangeExtensions.PercentWithinRange(absCDMVoltage, above.TestCondition, below.TestCondition);

                    // Only the Peak Current varies between different Test Conditions.
                    // All other properties are constant for a given target size and bandwidth.
                    Tuple <double, double> interpolatedPeakCurrent = new Tuple <double, double>(
                        DoubleRangeExtensions.EquivalentValueInNewRange(percentWithinRange, 1, 0, above.PeakCurrent.Item1, below.PeakCurrent.Item1),
                        DoubleRangeExtensions.EquivalentValueInNewRange(percentWithinRange, 1, 0, above.PeakCurrent.Item2, below.PeakCurrent.Item2));

                    return(new CDMJS002WaveformCharacteristicsSet()
                    {
                        IsHighBandwidth = below.IsHighBandwidth,
                        IsLargeTarget = below.IsLargeTarget,
                        TestCondition = absCDMVoltage,
                        PeakCurrent = interpolatedPeakCurrent,
                        RiseTimeMax = below.RiseTimeMax,
                        FullWidthAtHalfMaximum = new Tuple <double, double>(below.FullWidthAtHalfMaximum.Item1, below.FullWidthAtHalfMaximum.Item2),
                        UndershootMaxPercent = below.UndershootMaxPercent,
                    });
                }
                else if (below != null)
                {
                    // The CDM voltage is higher than the highest table entry, so scale the largest one
                    double multiplier = absCDMVoltage / below.TestCondition;

                    // Only the Peak Current varies between different Test Conditions.
                    // All other properties are constant for a given target size and bandwidth.
                    Tuple <double, double> scaledPeakCurrent = new Tuple <double, double>(
                        below.PeakCurrent.Item1 * multiplier,
                        below.PeakCurrent.Item2 * multiplier);

                    return(new CDMJS002WaveformCharacteristicsSet()
                    {
                        IsHighBandwidth = below.IsHighBandwidth,
                        IsLargeTarget = below.IsLargeTarget,
                        TestCondition = absCDMVoltage,
                        PeakCurrent = scaledPeakCurrent,
                        RiseTimeMax = below.RiseTimeMax,
                        FullWidthAtHalfMaximum = new Tuple <double, double>(below.FullWidthAtHalfMaximum.Item1, below.FullWidthAtHalfMaximum.Item2),
                        UndershootMaxPercent = below.UndershootMaxPercent,
                    });
                }
                else if (above != null)
                {
                    // The CDM voltage is lower than the lowest table entry, so scale the smallest one
                    double multiplier = absCDMVoltage / above.TestCondition;

                    // Only the Peak Current varies between different Test Conditions.
                    // All other properties are constant for a given target size and bandwidth.
                    Tuple <double, double> scaledPeakCurrent = new Tuple <double, double>(
                        above.PeakCurrent.Item1 * multiplier,
                        above.PeakCurrent.Item2 * multiplier);

                    return(new CDMJS002WaveformCharacteristicsSet()
                    {
                        IsHighBandwidth = above.IsHighBandwidth,
                        IsLargeTarget = above.IsLargeTarget,
                        TestCondition = absCDMVoltage,
                        PeakCurrent = scaledPeakCurrent,
                        RiseTimeMax = above.RiseTimeMax,
                        FullWidthAtHalfMaximum = new Tuple <double, double>(above.FullWidthAtHalfMaximum.Item1, above.FullWidthAtHalfMaximum.Item2),
                        UndershootMaxPercent = above.UndershootMaxPercent,
                    });
                }
                else
                {
                    throw new InvalidOperationException("Finding table entries for the CDM voltage " + absCDMVoltage + " failed.");
                }
            }
        }
コード例 #10
0
        /// <summary>
        /// Generates a new set for the HBM voltage from the JS-001 standard
        /// </summary>
        /// <param name="hbmVoltage">The voltage of the HBM pulse waveform (polarity is ignored, absolute value will be used)</param>
        /// <returns>A new set for the HBM voltage from the JS-001 standard</returns>
        private static HBM500OhmJS001WaveformCharacteristicsSet GenerateSetForHBMVoltage(double hbmVoltage)
        {
            double absHBMVoltage = System.Math.Abs(hbmVoltage);

            if (HBM500OhmJS001WaveformCharacteristics.characteristicSets.Any(set => set.TestCondition == absHBMVoltage))
            {
                // If the voltage is an exact match to a set, use it
                return(HBM500OhmJS001WaveformCharacteristics.characteristicSets.First(set => set.TestCondition == absHBMVoltage).Clone());
            }
            else
            {
                // The voltage isn't an exact match to the table, so interpolate it
                HBM500OhmJS001WaveformCharacteristicsSet below = null;
                HBM500OhmJS001WaveformCharacteristicsSet above = null;

                // Try to find the closest sets that are below and above the Test Condition voltage
                foreach (HBM500OhmJS001WaveformCharacteristicsSet set in HBM500OhmJS001WaveformCharacteristics.characteristicSets)
                {
                    if (set.TestCondition < absHBMVoltage)
                    {
                        if (below == null || below.TestCondition < set.TestCondition)
                        {
                            below = set;
                        }
                    }
                    else
                    {
                        if (above == null || above.TestCondition > set.TestCondition)
                        {
                            above = set;
                        }
                    }
                }

                if (below != null && above != null)
                {
                    // Interpolate between the below and above table entries
                    double percentWithinRange = DoubleRangeExtensions.PercentWithinRange(absHBMVoltage, above.TestCondition, below.TestCondition);

                    // Only the Peak Current varies between different Test Conditions.
                    // All other properties are constant for a given target size and bandwidth.
                    Tuple <double, double> interpolatedPeakCurrent = new Tuple <double, double>(
                        DoubleRangeExtensions.EquivalentValueInNewRange(percentWithinRange, 1, 0, above.PeakCurrent.Item1, below.PeakCurrent.Item1),
                        DoubleRangeExtensions.EquivalentValueInNewRange(percentWithinRange, 1, 0, above.PeakCurrent.Item2, below.PeakCurrent.Item2));

                    return(new HBM500OhmJS001WaveformCharacteristicsSet()
                    {
                        TestCondition = absHBMVoltage,
                        PeakCurrent = interpolatedPeakCurrent,
                    });
                }
                else if (below != null)
                {
                    // The HBM voltage is higher than the highest table entry, so scale the largest one
                    double multiplier = absHBMVoltage / below.TestCondition;

                    // Only the Peak Current varies between different Test Conditions.
                    // All other properties are constant for a given target size and bandwidth.
                    Tuple <double, double> scaledPeakCurrent = new Tuple <double, double>(
                        below.PeakCurrent.Item1 * multiplier,
                        below.PeakCurrent.Item2 * multiplier);

                    return(new HBM500OhmJS001WaveformCharacteristicsSet()
                    {
                        TestCondition = absHBMVoltage,
                        PeakCurrent = scaledPeakCurrent,
                    });
                }
                else if (above != null)
                {
                    // The HBM voltage is lower than the lowest table entry, so scale the smallest one
                    double multiplier = absHBMVoltage / above.TestCondition;

                    // Only the Peak Current varies between different Test Conditions.
                    // All other properties are constant for a given target size and bandwidth.
                    Tuple <double, double> scaledPeakCurrent = new Tuple <double, double>(
                        above.PeakCurrent.Item1 * multiplier,
                        above.PeakCurrent.Item2 * multiplier);

                    return(new HBM500OhmJS001WaveformCharacteristicsSet()
                    {
                        TestCondition = absHBMVoltage,
                        PeakCurrent = scaledPeakCurrent,
                    });
                }
                else
                {
                    throw new InvalidOperationException("Finding table entries for the HBM voltage " + absHBMVoltage + " failed.");
                }
            }
        }