using System; using System.Collections.Generic; using System.Text; using Vector.CANoe.Runtime; using Vector.Tools; namespace SignalGenerators { /// /// Interface for a signal generator. /// public interface IGenerator : IDisposable { bool Start(); void Stop(); } /// /// Abstract base class for a generator. Provides the infrastructure /// /// The signal that should be used by the generator public abstract class AbstractGenerator : IGenerator where T : class, Vector.CANoe.Runtime.IRuntimeValue { protected AbstractGenerator(int cycle) { CycleTime = cycle; } // Concrete generators have to calculate the signal value here protected abstract double CalcValue(TimeSpan currentTime); // Concrete signal generators have to check their parameters to allow the start of the generator protected abstract bool ParametersOK(); // Concrete signal generators need that to calculate the next value protected double StartTime { get { return mStartTime; } } public int CycleTime { get { return mCycleTime; } set { mCycleTime = value; if (mStarted) { mSignalPushTimer.Interval = TimeSpan.FromMilliseconds(mCycleTime); } } } private bool AllParametersOK() { return (mCycleTime > 0) && ParametersOK(); } // Timer elapsed handler - calculates and sets the signal value public void PushValue(Object o, ElapsedEventArgs e) { RuntimeObject.Value = CalcValue(Measurement.CurrentTime); } public bool Start() { if (!mStarted) { if (AllParametersOK()) { if (mSignalPushTimer == null) mSignalPushTimer = new Timer(PushValue); mSignalPushTimer.AutoReset = true; mStartTime = Measurement.CurrentTime.TotalMilliseconds; mSignalPushTimer.Interval = TimeSpan.FromMilliseconds(mCycleTime); mSignalPushTimer.Start(); mStarted = true; return true; } else Vector.Tools.Output.WriteLine("Preconditions are not fulfilled to start the signal generator", "Test"); } return false; } public void Stop() { if (mStarted) { mSignalPushTimer.Stop(); mSignalPushTimer.Dispose(); mSignalPushTimer = null; mStarted = false; } } public void Dispose() { Stop(); } private int mCycleTime; private Timer mSignalPushTimer; private bool mStarted = false; private double mStartTime = 0; } /// /// Ramp generator /// public class RampGenerator : AbstractGenerator where T : class, Vector.CANoe.Runtime.IRuntimeValue { public RampGenerator(double highBorder, double lowBorder, int delayBefore, int riseTime, int holdTime, int fallTime, int cycleTime, bool repeat) : base(cycleTime) { mHighBorder = highBorder; mLowBorder = lowBorder; mDelayBefore = delayBefore; mRiseTime = riseTime; mHoldTime = holdTime; mFallTime = fallTime; mRepeat = repeat; CalcFactors(); CalcPeriod(); } // calculates the factors of the rising and falling edge private void CalcFactors() { double diff = mHighBorder - mLowBorder; mRiseFactor = mRiseTime != 0 ? diff / mRiseTime : 0.0; mFallFactor = mFallTime != 0 ? diff / mFallTime : 0.0; } // calculates the period of the ramp private void CalcPeriod() { mPeriod = mDelayBefore + mRiseTime + mHoldTime + mFallTime; } protected override double CalcValue(TimeSpan currentTime) { // calculate time difference since start of the generator double time = currentTime.TotalMilliseconds - StartTime; if (mRepeat) time %= mPeriod; // calculate the time within a single period else if (time >= mPeriod) return mLowBorder; // if there is no repeat mode the low border value is returned // delay before rising the value if (time <= mDelayBefore) return mLowBorder; // value of the rising edge time -= mDelayBefore; if (time < mRiseTime) return mHighBorder - (mRiseTime - time) * mRiseFactor; // value of the hold time time -= mRiseTime; if (time <= mHoldTime) return mHighBorder; // value of the falling edge time -= mHoldTime; if (time < mFallTime) return mLowBorder - (time - mFallTime) * mFallFactor; return mLowBorder; } protected override bool ParametersOK() { return (mPeriod > 0) && (mHighBorder > mLowBorder); } private double mHighBorder; private double mLowBorder; private int mDelayBefore; private int mRiseTime; private int mHoldTime; private int mFallTime; private bool mRepeat; private double mRiseFactor; private double mFallFactor; private int mPeriod; } }