Exemplo n.º 1
0
        /// <summary>
        /// Returns the max allowed CDM Undershoot as a percentage 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 max allowed CDM Undershoot as a percentage to be within ESDA/JEDEC joint specification</returns>
        public static double UndershootMaxPercent(double signedCDMVoltage, bool isLargeTarget, bool oscilloscopeIsHighBandwidth)
        {
            CDMJS002WaveformCharacteristicsSet set = CDMJS002WaveformCharacteristics.GenerateSetForCDMVoltageAndCharacteristics(
                signedCDMVoltage,
                isLargeTarget,
                oscilloscopeIsHighBandwidth);

            return(set.UndershootMaxPercent);
        }
Exemplo n.º 2
0
        /// <summary>
        /// Returns the max allowed CDM Rise Time to be within 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 max allowed CDM Rise Time to be within JS-002 specification</returns>
        public static double RiseTimeMax(double signedCDMVoltage, bool isLargeTarget, bool oscilloscopeIsHighBandwidth)
        {
            CDMJS002WaveformCharacteristicsSet set = CDMJS002WaveformCharacteristics.GenerateSetForCDMVoltageAndCharacteristics(
                signedCDMVoltage,
                isLargeTarget,
                oscilloscopeIsHighBandwidth);

            return(set.RiseTimeMax);
        }
        /// <summary>
        /// Calculates the Undershoot related values
        /// </summary>
        /// <param name="undershootMaxTimeFWHMMultiplier">(Optional) The multiplier of the FWHM time to determine how long after the peak current time to search for undershoot (Default: 2.5x)</param>
        private void CalculateUndershoot(double undershootMaxTimeFWHMMultiplier = 2.5)
        {
            if (undershootMaxTimeFWHMMultiplier <= 0)
            {
                throw new ArgumentOutOfRangeException("The Undershoot Max Time multiplier cannot be less than or equal to 0");
            }

            // Determine how much time after the max data point of the waveform to keep for Undershoot
            double timeForUndershootDetectionAfterMaxTime = this.FullWidthHalfMaxValue * undershootMaxTimeFWHMMultiplier;

            // Add the undershoot allowed time to the max data point time
            double endTimeForUndershootDetection = this.PeakCurrentDataPoint.X + timeForUndershootDetectionAfterMaxTime;

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

            // Trim the end of the waveform from the max time until 2.5x the FWHM time
            Waveform absoluteUndershootApplicableWaveform = absoluteWaveformAfterPeakCurrentTime.TrimEnd(endTimeForUndershootDetection);

            // Find the (absolute) undershoot data point of the absolute Current waveform after the max time
            DataPoint absoluteUndershootDataPoint = absoluteUndershootApplicableWaveform.Minimum();

            // Look up what the undershoot max percent can be (it is a negative value)
            this.UndershootAllowedMaximumPercent = CDMJS002WaveformCharacteristics.UndershootMaxPercent(this.SignedVoltage, this.IsLargeTarget, this.OscilloscopeIsHighBandwidth);

            // Calculate what the maximum undershoot value can be (it is a negative number since we are referring to undershoot)
            this.UndershootAllowedMaximumValue = this.PeakCurrentValue * this.UndershootAllowedMaximumPercent;

            // Convert the absolute undershoot value to the signed value
            double absoluteUndershootValue = absoluteUndershootDataPoint.Y;

            // If the absolute undershoot is greater than zero, set it to zero.  Otherwise set it to the signed value
            if (absoluteUndershootValue > 0)
            {
                this.UndershootValue = 0;
            }
            else
            {
                this.UndershootValue = absoluteUndershootValue.InvertValueIfNegativePolarity(this.WaveformIsPositivePolarity);
            }

            // Determine if the Undershoot is passing
            if (this.WaveformIsPositivePolarity)
            {
                this.UndershootIsPassing = this.UndershootValue >= this.UndershootAllowedMaximumValue;
            }
            else
            {
                this.UndershootIsPassing = this.UndershootValue <= this.UndershootAllowedMaximumValue;
            }

            // Create the undershoot signed Data Point
            this.UndershootDataPoint = absoluteUndershootDataPoint.InvertYValueIfNegativePolarity(this.WaveformIsPositivePolarity);
        }
Exemplo n.º 4
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));
        }
        /// <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 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);
        }
        /// <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 the max allowed Rise Time to be passing
                    this.RiseTimeAllowedMaximum = CDMJS002WaveformCharacteristics.RiseTimeMax(this.SignedVoltage, this.IsLargeTarget, this.OscilloscopeIsHighBandwidth);

                    // Determine if the Rise Time is passing
                    this.RiseTimeIsPassing = this.RiseTimeValue <= this.RiseTimeAllowedMaximum;
                }
                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.
            }
        }