within Modelica.Blocks;
package Sources
  "Library of signal source blocks generating Real, Integer and Boolean signals"
  import Modelica.Blocks.Interfaces;

  extends Modelica.Icons.SourcesPackage;

  block RealExpression "Set output signal to a time varying Real expression"

    Modelica.Blocks.Interfaces.RealOutput y=0.0 "Value of Real output"

  end RealExpression;

  block IntegerExpression
    "Set output signal to a time varying Integer expression"

    Modelica.Blocks.Interfaces.IntegerOutput y=0 "Value of Integer output"

  end IntegerExpression;

  block BooleanExpression
    "Set output signal to a time varying Boolean expression"

    Modelica.Blocks.Interfaces.BooleanOutput y=false "Value of Boolean output"

  end BooleanExpression;

  block ContinuousClock "Generate current time signal"
    extends Interfaces.SignalSource;

  equation
    y = offset + smooth(0, (if time < startTime then 0 else time - startTime));
  end ContinuousClock;

  block Constant "Generate constant signal of type Real"
    parameter Real k(start=1) "Constant output value"
    extends Interfaces.SO;

  equation
    y = k;
  end Constant;

  block Step "Generate step signal of type Real"
    parameter Real height=1 "Height of step"
    extends Interfaces.SignalSource;

  equation
    y = offset + (if time < startTime then 0 else height);
  end Step;

  block Ramp "Generate ramp signal"
    parameter Real height=1 "Height of ramp"
    parameter SI.Time duration(min=0.0, start=2)
      "Duration of ramp (= 0.0 gives a Step)";
    extends Interfaces.SignalSource;

  equation
    y = offset + (if time < startTime then 0 else if time < (startTime +
      duration) then (time - startTime)*height/duration else height);
  end Ramp;

  block Sine "Generate sine signal"
    import Modelica.Constants.pi;
    parameter Real amplitude=1 "Amplitude of sine wave"
    parameter SI.Frequency f(start=1) "Frequency of sine wave";
    parameter SI.Angle phase=0 "Phase of sine wave";
    parameter Boolean continuous = false "Make output continuous by starting at offset + amplitude*sin(phase)"
    extends Interfaces.SignalSource;
  equation
    if continuous then
      y = offset + amplitude*smooth(0, (if time < startTime then Modelica.Math.sin(phase)
        else Modelica.Math.sin(2*pi*f*(time - startTime) + phase)));
    else
      y = offset + (if time < startTime then 0 else amplitude*Modelica.Math.sin(2
       *pi*f*(time - startTime) + phase));
    end if;
  end Sine;

  block Cosine "Generate cosine signal"
    import Modelica.Constants.pi;
    parameter Real amplitude=1 "Amplitude of cosine wave"
    parameter SI.Frequency f(start=1) "Frequency of cosine wave";
    parameter SI.Angle phase=0 "Phase of cosine wave";
    parameter Boolean continuous = false "Make output continuous by starting at offset + amplitude*cos(phase)"
    extends Interfaces.SignalSource;
  equation
    if continuous then
      y = offset + smooth(0, amplitude*(if time < startTime then Modelica.Math.cos(phase)
       else Modelica.Math.cos(2*pi*f*(time - startTime) + phase)));
    else
      y = offset + (if time < startTime then 0 else amplitude*Modelica.Math.cos(2
        *pi*f*(time - startTime) + phase));
    end if;
  end Cosine;

  block SineVariableFrequencyAndAmplitude
    "Generate sine signal with variable frequency and amplitude"
    extends Interfaces.SO;
    import Modelica.Constants.pi;
    parameter Boolean useConstantAmplitude=false "Enable constant amplitude";
    parameter Real constantAmplitude=1 "Constant amplitude"
    parameter Boolean useConstantFrequency=false "Enable constant frequency";
    parameter SI.Frequency constantFrequency=1 "Constant frequency"
    parameter Real offset=0 "Offset of the sine wave"
    SI.Angle phi(start=0) "Phase of the sine wave";
    Blocks.Interfaces.RealInput amplitude if not useConstantAmplitude "Amplitude"
    Blocks.Interfaces.RealInput f(unit="Hz") if not useConstantFrequency
      "Frequency"
  protected
    Blocks.Interfaces.RealInput amplitude_internal "Amplitude"
    Blocks.Interfaces.RealInput f_internal(unit="Hz") "Frequency"
    Blocks.Sources.Constant amplitude_constant(final k=constantAmplitude) if
      useConstantAmplitude
    Blocks.Sources.Constant f_constant(final k=constantFrequency) if
      useConstantFrequency
  equation
    der(phi) = 2*pi*f_internal;
    y = offset + amplitude_internal*sin(phi);
    connect(f, f_internal)
    connect(amplitude, amplitude_internal)
    connect(amplitude_constant.y, amplitude_internal)
    connect(f_constant.y, f_internal)
  end SineVariableFrequencyAndAmplitude;

  block CosineVariableFrequencyAndAmplitude
    "Generate cosine signal with variable frequency and amplitude"
    extends Interfaces.SO;
    import Modelica.Constants.pi;
    parameter Boolean useConstantAmplitude=false "Enable constant amplitude";
    parameter Real constantAmplitude=1 "Constant amplitude"
    parameter Boolean useConstantFrequency=false "Enable constant frequency";
    parameter SI.Frequency constantFrequency=1 "Constant frequency"
    parameter Real offset=0 "Offset of the sine wave"
    SI.Angle phi(start=0) "Phase of the sine wave";
    Blocks.Interfaces.RealInput amplitude if not useConstantAmplitude "Amplitude"
    Blocks.Interfaces.RealInput f(unit="Hz") if not useConstantFrequency
      "Frequency"
  protected
    Blocks.Interfaces.RealInput amplitude_internal "Amplitude"
    Blocks.Interfaces.RealInput f_internal(unit="Hz") "Frequency"
    Blocks.Sources.Constant amplitude_constant(final k=constantAmplitude) if
      useConstantAmplitude
    Blocks.Sources.Constant f_constant(final k=constantFrequency) if
      useConstantFrequency
  equation
    der(phi) = 2*pi*f_internal;
    y = offset + amplitude_internal*cos(phi);
    connect(f, f_internal)
    connect(amplitude, amplitude_internal)
    connect(amplitude_constant.y, amplitude_internal)
    connect(f_constant.y, f_internal)
  end CosineVariableFrequencyAndAmplitude;

  block Sinc "Generate sinc signal"
    import Modelica.Constants.pi;
    import Modelica.Constants.eps;
    parameter Real amplitude=1 "Amplitude of sine wave"
    parameter SI.Frequency f(start=1) "Frequency of sine wave";
    parameter Boolean continuous = false "Make output (continuously) differentiable by starting at offset + amplitude rather than just offset"
    extends Interfaces.SignalSource;
  protected
    SI.Angle x=2*pi*f*(time - startTime);
  equation
    if continuous then
     y = offset + amplitude*smooth(1, (if time < startTime then 1 else
        (if noEvent(time - startTime < eps) then 1 else (sin(x))/x)));
    else
      y = offset + (if time < startTime then 0 else amplitude*
        (if noEvent(time - startTime < eps) then 1 else (sin(x))/x));
    end if;
  end Sinc;

  block ExpSine "Generate exponentially damped sine signal"
    import Modelica.Constants.pi;
    parameter Real amplitude=1 "Amplitude of sine wave"
    parameter SI.Frequency f(start=2) "Frequency of sine wave";
    parameter SI.Angle phase=0 "Phase of sine wave";
    parameter SI.Damping damping(start=1)
      "Damping coefficient of sine wave";
    extends Interfaces.SignalSource;
  equation
    y = offset + (if time < startTime then 0 else amplitude*Modelica.Math.exp(-
      (time - startTime)*damping)*Modelica.Math.sin(2*pi*f*(time -
      startTime) + phase));
  end ExpSine;

  block Exponentials "Generate a rising and falling exponential signal"

    parameter Real outMax=1 "Height of output for infinite riseTime"
    parameter SI.Time riseTime(min=0,start=0.5) "Rise time";
    parameter SI.Time riseTimeConst(min=Modelica.Constants.small) = 0.1
      "Rise time constant; rising is defined as outMax*(1-exp(-riseTime/riseTimeConst))";
    parameter SI.Time fallTimeConst(min=Modelica.Constants.small)=
      riseTimeConst "Fall time constant";
    extends Interfaces.SignalSource;
  protected
    Real y_riseTime;

  equation
    y_riseTime = outMax*(1 - Modelica.Math.exp(-riseTime/riseTimeConst));
    y = offset + (if (time < startTime) then 0 else if (time < (startTime +
      riseTime)) then outMax*(1 - Modelica.Math.exp(-(time - startTime)/
      riseTimeConst)) else y_riseTime*Modelica.Math.exp(-(time - startTime -
      riseTime)/fallTimeConst));
  end Exponentials;

  block Pulse "Generate pulse signal of type Real"
    parameter Real amplitude=1 "Amplitude of pulse"
    parameter Real width(
      final min=Modelica.Constants.small,
      final max=100) = 50 "Width of pulse in % of period";
    parameter SI.Time period(final min=Modelica.Constants.small,
        start=1) "Time for one period";
    parameter Integer nperiod=-1
      "Number of periods (< 0 means infinite number of periods)";
    extends Interfaces.SignalSource;
  protected
    SI.Time T_width=period*width/100;
    SI.Time T_start "Start time of current period";
    Integer count "Period count";
  initial algorithm
    count := integer((time - startTime)/period);
    T_start := startTime + count*period;
  equation
    //The following formulation causes a state event
    //when integer((time - startTime)/period) > pre(count) then
    //A formulation causing a time event is more efficient:
    when time >= (pre(count) + 1)*period + startTime then
      count = pre(count) + 1;
      T_start = time;
    end when;
    y = offset + (if (time < startTime or nperiod == 0 or (nperiod > 0 and
      count >= nperiod)) then 0 else if time < T_start + T_width then amplitude
       else 0);
  end Pulse;

  block SawTooth "Generate saw tooth signal"
    parameter Real amplitude=1 "Amplitude of saw tooth"
    parameter SI.Time period(final min=Modelica.Constants.small,start=1)
      "Time for one period";
    parameter Integer nperiod=-1
      "Number of periods (< 0 means infinite number of periods)";
    extends Interfaces.SignalSource;
  protected
    SI.Time T_start(final start=startTime) "Start time of current period";
    Integer count "Period count";
  initial algorithm
    count := integer((time - startTime)/period);
    T_start := startTime + count*period;
  equation
    //The following formulation causes a state event
    //when integer((time - startTime)/period) > pre(count) then
    //A formulation causing a time event is more efficient:
    when time >= (pre(count) + 1)*period + startTime then
      count = pre(count) + 1;
      T_start = time;
    end when;
    y = offset + (if (time < startTime or nperiod == 0 or (nperiod > 0 and
      count >= nperiod)) then 0 else amplitude*(time - T_start)/period);
  end SawTooth;

  block Trapezoid "Generate trapezoidal signal of type Real"
    parameter Real amplitude=1 "Amplitude of trapezoid"
    parameter SI.Time rising(final min=0) = 0
      "Rising duration of trapezoid";
    parameter SI.Time width(final min=0) = 0.5
      "Width duration of trapezoid";
    parameter SI.Time falling(final min=0) = 0
      "Falling duration of trapezoid";
    parameter SI.Time period(final min=Modelica.Constants.small, start=1)
      "Time for one period";
    parameter Integer nperiod=-1
      "Number of periods (< 0 means infinite number of periods)";
    extends Interfaces.SignalSource;
  protected
    parameter SI.Time T_rising=rising
      "End time of rising phase within one period";
    parameter SI.Time T_width=T_rising + width
      "End time of width phase within one period";
    parameter SI.Time T_falling=T_width + falling
      "End time of falling phase within one period";
    SI.Time T_start "Start time of current period";
    Integer count "Period count";
  initial algorithm
    count := integer((time - startTime)/period);
    T_start := startTime + count*period;
  equation
    //The following formulation causes a state event
    //when integer((time - startTime)/period) > pre(count) then
    //A formulation causing a time event is more efficient:
    when time >= (pre(count) + 1)*period + startTime then
      count = pre(count) + 1;
      T_start = time;
    end when;
    y = offset + (if (time < startTime or nperiod == 0 or (nperiod > 0 and
      count >= nperiod)) then 0 else if (time < T_start + T_rising) then
      amplitude*(time - T_start)/rising else if (time < T_start + T_width)
       then amplitude else if (time < T_start + T_falling) then amplitude*(
      T_start + T_falling - time)/falling else 0);
  end Trapezoid;

  block LogFrequencySweep "Logarithmic frequency sweep"
    extends Modelica.Blocks.Interfaces.SO;
    import Modelica.Constants.eps;
    parameter Real wMin(final min=eps) "Start frequency"
    parameter Real wMax(final min=eps) "End frequency";
    parameter SI.Time startTime=0 "Start time of frequency sweep";
    parameter SI.Time duration(min=0.0, start=1) "Duration of ramp (= 0.0 gives a Step)";
  equation
    y = if time < startTime then wMin else
      if time < (startTime + max(duration,eps)) then
        wMin * (wMax/wMin)^min(1, (time-startTime)/max(duration,eps))
      else
        wMax;
  end LogFrequencySweep;

  block KinematicPTP
    "Move as fast as possible along a distance within given kinematic constraints"

    parameter Real deltaq[:]={1} "Distance to move"
    parameter Real qd_max[:](each final min=Modelica.Constants.small) = {1}
      "Maximum velocities der(q)";
    parameter Real qdd_max[:](each final min=Modelica.Constants.small) = {1}
      "Maximum accelerations der(qd)";
    parameter SI.Time startTime=0 "Time instant at which movement starts";

    extends Interfaces.MO(final nout=max([size(deltaq, 1); size(qd_max, 1); size(qdd_max, 1)]));

  protected
    parameter Real p_deltaq[nout]=(if size(deltaq, 1) == 1 then ones(nout)*
        deltaq[1] else deltaq);
    parameter Real p_qd_max[nout]=(if size(qd_max, 1) == 1 then ones(nout)*
        qd_max[1] else qd_max);
    parameter Real p_qdd_max[nout]=(if size(qdd_max, 1) == 1 then ones(nout)*
        qdd_max[1] else qdd_max);
    Real sd_max;
    Real sdd_max;
    Real sdd;
    Real aux1[nout];
    Real aux2[nout];
    SI.Time Ta1;
    SI.Time Ta2;
    SI.Time Tv;
    SI.Time Te;
    Boolean noWphase;

  equation
    for i in 1:nout loop
      aux1[i] = p_deltaq[i]/p_qd_max[i];
      aux2[i] = p_deltaq[i]/p_qdd_max[i];
    end for;
    sd_max = 1/max(abs(aux1));
    sdd_max = 1/max(abs(aux2));

    Ta1 = sqrt(1/sdd_max);
    Ta2 = sd_max/sdd_max;
    noWphase = Ta2 >= Ta1;
    Tv = if noWphase then Ta1 else 1/sd_max;
    Te = if noWphase then Ta1 + Ta1 else Tv + Ta2;

    // path-acceleration
    sdd = if time < startTime then 0 else ((if noWphase then (if time < Ta1 +
      startTime then sdd_max else (if time < Te + startTime then -sdd_max else
      0)) else (if time < Ta2 + startTime then sdd_max else (if time < Tv +
      startTime then 0 else (if time < Te + startTime then -sdd_max else 0)))));

    // acceleration
    y = p_deltaq*sdd;
  end KinematicPTP;

  block KinematicPTP2
    "Move as fast as possible from start to end position within given kinematic constraints with output signals q, qd=der(q), qdd=der(qd)"

    parameter Real q_begin[:]={0} "Start position"
    parameter Real q_end[:]={1} "End position";
    parameter Real qd_max[:](each final min=Modelica.Constants.small) = {1}
      "Maximum velocities der(q)";
    parameter Real qdd_max[:](each final min=Modelica.Constants.small) = {1}
      "Maximum accelerations der(qd)";
    parameter SI.Time startTime=0
      "Time instant at which movement starts";

    extends Modelica.Blocks.Icons.Block;
    final parameter Integer nout=max([size(q_begin, 1); size(q_end, 1); size(qd_max, 1); size(qdd_max, 1)])
      "Number of output signals (= dimension of q, qd, qdd, moving)";
    output SI.Time endTime "Time instant at which movement stops";

    Modelica.Blocks.Interfaces.RealOutput q[nout]
      "Reference position of path planning"
    Modelica.Blocks.Interfaces.RealOutput qd[nout]
      "Reference speed of path planning"
    Modelica.Blocks.Interfaces.RealOutput qdd[nout]
      "Reference acceleration of path planning"
    Modelica.Blocks.Interfaces.BooleanOutput moving[nout]
      "= true, if end position not yet reached; = false, if end position reached or axis is completely at rest"

  protected
    parameter Real p_q_begin[nout]=(if size(q_begin, 1) == 1 then ones(nout)*
        q_begin[1] else q_begin);
    parameter Real p_q_end[nout]=(if size(q_end, 1) == 1 then ones(nout)*q_end[
        1] else q_end);
    parameter Real p_qd_max[nout]=(if size(qd_max, 1) == 1 then ones(nout)*
        qd_max[1] else qd_max);
    parameter Real p_qdd_max[nout]=(if size(qdd_max, 1) == 1 then ones(nout)*
        qdd_max[1] else qdd_max);
    parameter Real p_deltaq[nout]=p_q_end - p_q_begin;
    constant Real eps=10*Modelica.Constants.eps;
    Boolean motion_ref;
    Real sd_max_inv;
    Real sdd_max_inv;
    Real sd_max;
    Real sdd_max;
    Real sdd;
    Real aux1[nout];
    Real aux2[nout];
    SI.Time Ta1;
    SI.Time Ta2;
    SI.Time Tv;
    SI.Time Te;
    Boolean noWphase;
    SI.Time Ta1s;
    SI.Time Ta2s;
    SI.Time Tvs;
    SI.Time Tes;
    Real sd_max2;
    Real s1;
    Real s2;
    Real s3;
    Real s;
    Real sd;

  equation
    for i in 1:nout loop
      aux1[i] = p_deltaq[i]/p_qd_max[i];
      aux2[i] = p_deltaq[i]/p_qdd_max[i];
    end for;

    sd_max_inv = max(abs(aux1));
    sdd_max_inv = max(abs(aux2));

    if sd_max_inv <= eps or sdd_max_inv <= eps then
      sd_max = 0;
      sdd_max = 0;
      Ta1 = 0;
      Ta2 = 0;
      noWphase = false;
      Tv = 0;
      Te = 0;
      Ta1s = 0;
      Ta2s = 0;
      Tvs = 0;
      Tes = 0;
      sd_max2 = 0;
      s1 = 0;
      s2 = 0;
      s3 = 0;
      s = 0;
    else
      sd_max = 1/max(abs(aux1));
      sdd_max = 1/max(abs(aux2));
      Ta1 = sqrt(1/sdd_max);
      Ta2 = sd_max/sdd_max;
      noWphase = Ta2 >= Ta1;
      Tv = if noWphase then Ta1 else 1/sd_max;
      Te = if noWphase then Ta1 + Ta1 else Tv + Ta2;
      Ta1s = Ta1 + startTime;
      Ta2s = Ta2 + startTime;
      Tvs = Tv + startTime;
      Tes = Te + startTime;
      sd_max2 = sdd_max*Ta1;
      s1 = sdd_max*(if noWphase then Ta1*Ta1 else Ta2*Ta2)/2;
      s2 = s1 + (if noWphase then sd_max2*(Te - Ta1) - (sdd_max/2)*(Te - Ta1)^2
         else sd_max*(Tv - Ta2));
      s3 = s2 + sd_max*(Te - Tv) - (sdd_max/2)*(Te - Tv)*(Te - Tv);

      if time < startTime then
        s = 0;
      elseif noWphase then
        if time < Ta1s then
          s = (sdd_max/2)*(time - startTime)*(time - startTime);
        elseif time < Tes then
          s = s1 + sd_max2*(time - Ta1s) - (sdd_max/2)*(time - Ta1s)*(time -
            Ta1s);
        else
          s = s2;
        end if;
      elseif time < Ta2s then
        s = (sdd_max/2)*(time - startTime)*(time - startTime);
      elseif time < Tvs then
        s = s1 + sd_max*(time - Ta2s);
      elseif time < Tes then
        s = s2 + sd_max*(time - Tvs) - (sdd_max/2)*(time - Tvs)*(time - Tvs);
      else
        s = s3;
      end if;

    end if;

    sd = der(s);
    sdd = der(sd);

    qdd = p_deltaq*sdd;
    qd = p_deltaq*sd;
    q = p_q_begin + p_deltaq*s;
    endTime = Tes;

    // report when axis is moving
    motion_ref = time < endTime;
    for i in 1:nout loop
      moving[i] = if abs(q_begin[i] - q_end[i]) > eps then motion_ref else
        false;
    end for;
  end KinematicPTP2;

  block TimeTable
    "Generate a (possibly discontinuous) signal by linear interpolation in a table"

    parameter Real table[:, 2] = fill(0.0, 0, 2)
      "Table matrix (time = first column; e.g., table=[0, 0; 1, 1; 2, 4])"
    parameter SI.Time timeScale(
      min=Modelica.Constants.eps)=1 "Time scale of first table column"
    extends Interfaces.SignalSource;
    parameter SI.Time shiftTime=startTime
      "Shift time of first table column";
  protected
    discrete Real a "Interpolation coefficient a of actual interval (y=a*x+b)";
    discrete Real b "Interpolation coefficient b of actual interval (y=a*x+b)";
    Integer last(start=1) "Last used lower grid index";
    discrete SI.Time nextEvent(start=0, fixed=true) "Next event instant";
    discrete Real nextEventScaled(start=0, fixed=true)
      "Next scaled event instant";
    Real timeScaled "Scaled time";

    function getInterpolationCoefficients
      "Determine interpolation coefficients and next time event"
      extends Modelica.Icons.Function;
      input Real table[:, 2] "Table for interpolation";
      input Real offset "y-offset";
      input Real startTimeScaled "Scaled time-offset";
      input Real timeScaled "Actual scaled time instant";
      input Integer last "Last used lower grid index";
      input Real TimeEps "Relative epsilon to check for identical time instants";
      input Real shiftTimeScaled "Time shift";
      output Real a "Interpolation coefficient a (y=a*x + b)";
      output Real b "Interpolation coefficient b (y=a*x + b)";
      output Real nextEventScaled "Next scaled event instant";
      output Integer next "New lower grid index";
    protected
      Integer columns=2 "Column to be interpolated";
      Integer ncol=2 "Number of columns to be interpolated";
      Integer nrow=size(table, 1) "Number of table rows";
      Integer next0;
      Real tp;
      Real dt;
    algorithm
      next := last;
      nextEventScaled := timeScaled - TimeEps*abs(timeScaled);
      // in case there are no more time events
      tp := timeScaled + TimeEps*abs(timeScaled);

      if tp < startTimeScaled then
        // First event not yet reached
        nextEventScaled := startTimeScaled;
        a := 0;
        b := offset;
      elseif nrow < 2 then
        // Special action if table has only one row
        a := 0;
        b := offset + table[1, columns];
      else
        tp := tp - shiftTimeScaled;
        // Find next time event instant. Note, that two consecutive time instants
        // in the table may be identical due to a discontinuous point.
        while next < nrow and tp >= table[next, 1] loop
          next := next + 1;
        end while;

        // Define next time event, if last table entry not reached
        if next < nrow then
          nextEventScaled := shiftTimeScaled + table[next, 1];
        end if;

        // Determine interpolation coefficients
        if next == 1 then
          next := 2;
        end if;
        next0 := next - 1;
        dt := table[next, 1] - table[next0, 1];
        if dt <= TimeEps*abs(table[next, 1]) then
          // Interpolation interval is not big enough, use "next" value
          a := 0;
          b := offset + table[next, columns];
        else
          a := (table[next, columns] - table[next0, columns])/dt;
          b := offset + table[next0, columns] - a*table[next0, 1];
        end if;
      end if;
      // Take into account shiftTimeScaled "a*(time - shiftTime) + b"
      b := b - a*shiftTimeScaled;
    end getInterpolationCoefficients;
  algorithm
    if size(table, 1) > 1 then
      assert(not (table[1, 1] > 0.0 or table[1, 1] < 0.0), "The first point in time has to be set to 0, but is table[1,1] = " + String(table[1, 1]));
    end if;
    when {time >= pre(nextEvent),initial()} then
      (a,b,nextEventScaled,last) := getInterpolationCoefficients(
          table,
          offset,
          startTime/timeScale,
          timeScaled,
          last,
          100*Modelica.Constants.eps,
          shiftTime/timeScale);
      nextEvent := nextEventScaled*timeScale;
    end when;
  equation
    assert(size(table, 1) > 0, "No table values defined.");
    timeScaled = time/timeScale;
    y = a*timeScaled + b;
  end TimeTable;

  block CombiTimeTable
    "Table look-up with respect to time and various interpolation and extrapolation methods (data from matrix/file)"
    import Modelica.Blocks.Tables.Internal;
    extends Modelica.Blocks.Interfaces.MO(final nout=max([size(columns, 1); size(offset, 1)]));
    parameter Boolean tableOnFile=false
      "= true, if table is defined on file or in function usertab"
    parameter Real table[:, :] = fill(0.0, 0, 2)
      "Table matrix (time = first column; e.g., table=[0, 0; 1, 1; 2, 4])"
    parameter String tableName="NoName"
      "Table name on file or in function usertab (see docu)"
    parameter String fileName="NoName" "File where matrix is stored";MATLAB MAT-files (*.mat);;Comma-separated values files (*.csv)",
            caption="Open file in which table is present")));
    parameter String delimiter="," "Column delimiter character for CSV file"
    parameter Integer nHeaderLines=0 "Number of header lines to ignore for CSV file"
    parameter Boolean verboseRead=true
      "= true, if info message that file is loading is to be printed"
    parameter Integer columns[:]=2:size(table, 2)
      "Columns of table to be interpolated"
    parameter Modelica.Blocks.Types.Smoothness smoothness=Modelica.Blocks.Types.Smoothness.LinearSegments
      "Smoothness of table interpolation"
    parameter Modelica.Blocks.Types.Extrapolation extrapolation=Modelica.Blocks.Types.Extrapolation.LastTwoPoints
      "Extrapolation of data outside the definition range"
    parameter SI.Time timeScale(
      min=Modelica.Constants.eps)=1 "Time scale of first table column"
    parameter Real offset[:]={0} "Offsets of output signals"
    parameter SI.Time startTime=0
      "Output = offset for time < startTime"
    parameter SI.Time shiftTime=startTime
      "Shift time of first table column"
    parameter Modelica.Blocks.Types.TimeEvents timeEvents=Modelica.Blocks.Types.TimeEvents.Always
      "Time event handling of table interpolation"
    parameter Boolean verboseExtrapolation=false
      "= true, if warning messages are to be printed if time is outside the table definition range"
    final parameter SI.Time t_min=t_minScaled*timeScale
      "Minimum abscissa value defined in table";
    final parameter SI.Time t_max=t_maxScaled*timeScale
      "Maximum abscissa value defined in table";
    final parameter Real t_minScaled=Internal.getTimeTableTmin(tableID)
      "Minimum (scaled) abscissa value defined in table";
    final parameter Real t_maxScaled=Internal.getTimeTableTmax(tableID)
      "Maximum (scaled) abscissa value defined in table";
  protected
    final parameter Real p_offset[nout]=(if size(offset, 1) == 1 then ones(nout)*offset[1] else offset)
      "Offsets of output signals";
    parameter Modelica.Blocks.Types.ExternalCombiTimeTable tableID=
        Modelica.Blocks.Types.ExternalCombiTimeTable(
          if tableOnFile then if isCsvExt then "Values" else tableName else "NoName",
          if tableOnFile and fileName <> "NoName" and not Modelica.Utilities.Strings.isEmpty(fileName) then fileName else "NoName",
          table,
          startTime/timeScale,
          columns,
          smoothness,
          extrapolation,
          shiftTime/timeScale,
          if smoothness == Modelica.Blocks.Types.Smoothness.LinearSegments then timeEvents elseif smoothness == Modelica.Blocks.Types.Smoothness.ConstantSegments then Modelica.Blocks.Types.TimeEvents.Always else Modelica.Blocks.Types.TimeEvents.NoTimeEvents,
          if tableOnFile then verboseRead else false,
          delimiter,
          nHeaderLines) "External table object";
    discrete SI.Time nextTimeEvent(start=0, fixed=true)
      "Next time event instant";
    discrete Real nextTimeEventScaled(start=0, fixed=true)
      "Next scaled time event instant";
    Real timeScaled "Scaled time";
    final parameter Boolean isCsvExt = if tableOnFile then Modelica.Utilities.Strings.findLast(fileName, ".csv", caseSensitive=false) + 3 == Modelica.Utilities.Strings.length(fileName) else false;
  equation
    if tableOnFile then
      assert(tableName <> "NoName" or isCsvExt,
        "tableOnFile = true and no table name given");
    else
      assert(size(table, 1) > 0 and size(table, 2) > 0,
        "tableOnFile = false and parameter table is an empty matrix");
    end if;

    if verboseExtrapolation and (
      extrapolation == Modelica.Blocks.Types.Extrapolation.LastTwoPoints or
      extrapolation == Modelica.Blocks.Types.Extrapolation.HoldLastPoint) then
      assert(noEvent(time >= t_min + shiftTime), "
Extrapolation warning: Time must be greater or equal
than the shifted minimum abscissa value defined in the table.
", level=AssertionLevel.warning);
      assert(noEvent(time <= t_max + shiftTime), "
Extrapolation warning: Time must be less or equal
than the shifted maximum abscissa value defined in the table.
", level=AssertionLevel.warning);
    end if;

    timeScaled = time/timeScale;
    when {time >= pre(nextTimeEvent), initial()} then
      nextTimeEventScaled = Internal.getNextTimeEvent(tableID, timeScaled);
      nextTimeEvent = if nextTimeEventScaled < Modelica.Constants.inf then nextTimeEventScaled*timeScale else Modelica.Constants.inf;
    end when;
    if smoothness == Modelica.Blocks.Types.Smoothness.ConstantSegments then
      for i in 1:nout loop
        y[i] = p_offset[i] + Internal.getTimeTableValueNoDer(tableID, i, timeScaled, nextTimeEventScaled, pre(nextTimeEventScaled));
      end for;
    elseif smoothness == Modelica.Blocks.Types.Smoothness.LinearSegments then
      for i in 1:nout loop
        y[i] = p_offset[i] + Internal.getTimeTableValueNoDer2(tableID, i, timeScaled, nextTimeEventScaled, pre(nextTimeEventScaled));
      end for;
    else
      for i in 1:nout loop
        y[i] = p_offset[i] + Internal.getTimeTableValue(tableID, i, timeScaled, nextTimeEventScaled, pre(nextTimeEventScaled));
      end for;
    end if;
  end CombiTimeTable;

  block BooleanConstant "Generate constant signal of type Boolean"
    parameter Boolean k=true "Constant output value"
    extends Interfaces.partialBooleanSource;

  equation
    y = k;
  end BooleanConstant;

  block BooleanStep "Generate step signal of type Boolean"
    parameter SI.Time startTime=0 "Time instant of step start"
    parameter Boolean startValue=false "Output before startTime";

    extends Interfaces.partialBooleanSource;
  equation
    y = if time >= startTime then not startValue else startValue;
  end BooleanStep;

  block BooleanPulse "Generate pulse signal of type Boolean"

    parameter Real width(
      final min=Modelica.Constants.small,
      final max=100) = 50 "Width of pulse in % of period"
    parameter SI.Time period(final min=Modelica.Constants.small,
        start=1) "Time for one period";
    parameter SI.Time startTime=0 "Time instant of first pulse";
    extends Modelica.Blocks.Interfaces.partialBooleanSource;

  protected
    parameter SI.Time Twidth=period*width/100
      "Width of one pulse"
    discrete SI.Time pulseStart "Start time of pulse"
  initial equation
    pulseStart = startTime;
  equation
    when sample(startTime, period) then
      pulseStart = time;
    end when;
    y = time >= pulseStart and time < pulseStart + Twidth;
  end BooleanPulse;

  block SampleTrigger "Generate sample trigger signal"
    parameter SI.Time period(final min=Modelica.Constants.small,
        start=0.01) "Sample period"
    parameter SI.Time startTime=0
      "Time instant of first sample trigger";
    extends Interfaces.partialBooleanSource;

  equation
    y = sample(startTime, period);
  end SampleTrigger;

  block BooleanTable
    "Generate a Boolean output signal based on a vector of time instants"

    parameter SI.Time table[:]={0,1}
      "Vector of time points. At every time point, the output y gets its opposite value (e.g., table={0,1})"
    parameter Boolean startValue=false
      "Start value of y. At time = table[1], y changes to 'not startValue'"
    parameter Modelica.Blocks.Types.Extrapolation extrapolation=Modelica.Blocks.Types.Extrapolation.HoldLastPoint
      "Extrapolation of data outside the definition range"
    parameter SI.Time startTime=-Modelica.Constants.inf
      "Output = false for time < startTime"
    parameter SI.Time shiftTime=0
      "Shift time of table"

    extends Interfaces.partialBooleanSO;

    CombiTimeTable combiTimeTable(
      final table=if n > 0 then if startValue then [table[1], 1.0; table, {mod(i + 1, 2.0) for i in 1:n}] else [table[1], 0.0; table, {mod(i, 2.0) for i in 1:n}] else if startValue then [0.0, 1.0] else [0.0, 0.0],
      final smoothness=Modelica.Blocks.Types.Smoothness.ConstantSegments,
      final columns={2},
      final extrapolation=extrapolation,
      final startTime=startTime,
      final shiftTime=shiftTime)
    Modelica.Blocks.Math.RealToBoolean realToBoolean

  protected
      function isValidTable "Check if table is valid"
        extends Modelica.Icons.Function;
        input Real table[:] "Vector of time instants";
    protected
        Integer n=size(table, 1) "Number of table points";
      algorithm
        if n > 0 then
          // Check whether time values are strict monotonically increasing
          for i in 2:n loop
            assert(table[i] > table[i-1],
              "Time values of table not strict monotonically increasing: table["
               + String(i - 1) + "] = " + String(table[i - 1]) + ", table[" +
              String(i) + "] = " + String(table[i]));
          end for;
        end if;
      end isValidTable;

      parameter Integer n=size(table, 1) "Number of table points";
  initial algorithm
      isValidTable(table);
  equation
      assert(extrapolation <> Modelica.Blocks.Types.Extrapolation.LastTwoPoints, "Unsuitable extrapolation setting.");
      connect(combiTimeTable.y[1], realToBoolean.u)
      connect(realToBoolean.y, y)
  end BooleanTable;

  block RadioButtonSource "Boolean signal source that mimics a radio button"

    parameter SI.Time buttonTimeTable[:]={0,1}
      "Time instants where button is pressed";
    input Boolean reset[:]={false}
      "Reset button to false, if an element of reset becomes true"

    Modelica.Blocks.Interfaces.BooleanOutput on(start=false,fixed=true)
  protected
    Modelica.Blocks.Sources.BooleanTable table(table=buttonTimeTable, y(start=false, fixed=true));
    parameter Integer nReset=size(reset, 1);
    Boolean pre_reset[nReset];
  initial equation
    pre(pre_reset) = fill(false, nReset);
    pre(reset) = fill(false, nReset);
  algorithm
    pre_reset := pre(reset);
    when pre_reset then
      on := false;
    end when;

    when change(table.y) then
      on := true;
    end when;
RadioButtonSource stop (buttonTimeTable={2,4}, reset={start.on});
</pre></blockquote>

<p>
The \"start\" button is pressed at time=1 s and time=3 s,
whereas the \"stop\" button is pressed at time=2 s and time=4 s.
This gives the following result:
</p>

<blockquote>
<img src=\"modelica://Modelica/Resources/Images/Blocks/Sources/RadioButtonSource.png\"
     alt=\"RadioButtonSource.png\">
</blockquote>

<p>
This example is also available in
<a href=\"modelica://Modelica.Blocks.Examples.Interaction1\">Modelica.Blocks.Examples.Interaction1</a>
</p>

</html>"));
  end RadioButtonSource;

  block IntegerConstant "Generate constant signal of type Integer"
    parameter Integer k(start=1) "Constant output value";
    extends Interfaces.IntegerSO;

  equation
    y = k;
  end IntegerConstant;

  block IntegerStep "Generate step signal of type Integer"
    parameter Integer height=1 "Height of step";
    extends Interfaces.IntegerSignalSource;
  equation
    y = offset + (if time < startTime then 0 else height);
  end IntegerStep;

  block IntegerTable
    "Generate an Integer output signal based on a table matrix with [time, yi] values"

    parameter Real table[:, 2]=fill(0,0,2) "Table matrix (first column: time; second column: y)"
    parameter Modelica.Blocks.Types.Extrapolation extrapolation=Modelica.Blocks.Types.Extrapolation.HoldLastPoint
      "Extrapolation of data outside the definition range"
    parameter SI.Time startTime=-Modelica.Constants.inf
      "Output = 0 for time < startTime"
    parameter SI.Time shiftTime=0
      "Shift time of first table column"

    extends Interfaces.IntegerSO;

    CombiTimeTable combiTimeTable(
      final table=table,
      final smoothness=Modelica.Blocks.Types.Smoothness.ConstantSegments,
      final columns={2},
      final extrapolation=extrapolation,
      final startTime=startTime,
      final shiftTime=shiftTime)
    Modelica.Blocks.Math.RealToInteger realToInteger

  protected
      function isValidTable "Check if table is valid"
        extends Modelica.Icons.Function;
        input Real table[:, 2] "Table matrix";
    protected
        SI.Time t_last;
        Integer n=size(table, 1) "Number of table points";
      algorithm
        if n > 0 then
          // Check whether time values are strict monotonically increasing
          t_last := table[1, 1];
          for i in 2:n loop
            assert(table[i, 1] > t_last,
              "Time values of table not strict monotonically increasing: table["
               + String(i - 1) + ",1] = " + String(table[i - 1, 1]) + "table[" +
              String(i) + ",1] = " + String(table[i, 1]));
          end for;

          // Check that all values in the second column are Integer values
          for i in 1:n loop
            assert(rem(table[i, 2], 1) == 0.0,
              "Table value is not an Integer: table[" + String(i) + ",2] = " +
              String(table[i, 2]));
          end for;
        end if;
      end isValidTable;

      parameter Integer n=size(table, 1) "Number of table points";
  initial algorithm
      isValidTable(table);
  equation
      assert(n > 0, "No table values defined.");
      assert(extrapolation <> Modelica.Blocks.Types.Extrapolation.LastTwoPoints, "Unsuitable extrapolation setting.");
      connect(combiTimeTable.y[1], realToInteger.u)
      connect(realToInteger.y, y)
  end IntegerTable;
end Sources;


within Modelica.Blocks;
package Tables
  "Library of blocks to interpolate in one and two-dimensional tables"
  extends Modelica.Icons.Package;
  block CombiTable1Ds
    "Table look-up in one dimension (matrix/file) with one input and n outputs"
    extends Modelica.Blocks.Interfaces.SIMO(final nout=size(columns, 1));
    parameter Boolean tableOnFile=false
      "= true, if table is defined on file or in function usertab"
    parameter Real table[:, :] = fill(0.0, 0, 2)
      "Table matrix (grid = first column; e.g., table=[0, 0; 1, 1; 2, 4])"
    parameter String tableName="NoName"
      "Table name on file or in function usertab (see docu)"
    parameter String fileName="NoName" "File where matrix is stored";MATLAB MAT-files (*.mat);;Comma-separated values files (*.csv)",
            caption="Open file in which table is present")));
    parameter String delimiter="," "Column delimiter character for CSV file"
    parameter Integer nHeaderLines=0 "Number of header lines to ignore for CSV file"
    parameter Boolean verboseRead=true
      "= true, if info message that file is loading is to be printed"
    parameter Integer columns[:]=2:size(table, 2)
      "Columns of table to be interpolated"
    parameter Modelica.Blocks.Types.Smoothness smoothness=Modelica.Blocks.Types.Smoothness.LinearSegments
      "Smoothness of table interpolation"
    parameter Modelica.Blocks.Types.Extrapolation extrapolation=Modelica.Blocks.Types.Extrapolation.LastTwoPoints
      "Extrapolation of data outside the definition range"
    parameter Boolean verboseExtrapolation=false
      "= true, if warning messages are to be printed if table input is outside the definition range"
    final parameter Real u_min=Internal.getTable1DAbscissaUmin(tableID)
      "Minimum abscissa value defined in table";
    final parameter Real u_max=Internal.getTable1DAbscissaUmax(tableID)
      "Maximum abscissa value defined in table";
  protected
    parameter Modelica.Blocks.Types.ExternalCombiTable1D tableID=
        Modelica.Blocks.Types.ExternalCombiTable1D(
          if tableOnFile then if isCsvExt then "Values" else tableName else "NoName",
          if tableOnFile and fileName <> "NoName" and not Modelica.Utilities.Strings.isEmpty(fileName) then fileName else "NoName",
          table,
          columns,
          smoothness,
          extrapolation,
          if tableOnFile then verboseRead else false,
          delimiter,
          nHeaderLines) "External table object";
    final parameter Boolean isCsvExt = if tableOnFile then Modelica.Utilities.Strings.findLast(fileName, ".csv", caseSensitive=false) + 3 == Modelica.Utilities.Strings.length(fileName) else false;
  equation
    if tableOnFile then
      assert(tableName <> "NoName" or isCsvExt,
        "tableOnFile = true and no table name given");
    else
      assert(size(table, 1) > 0 and size(table, 2) > 0,
        "tableOnFile = false and parameter table is an empty matrix");
    end if;

    if verboseExtrapolation and (
      extrapolation == Modelica.Blocks.Types.Extrapolation.LastTwoPoints or
      extrapolation == Modelica.Blocks.Types.Extrapolation.HoldLastPoint) then
      assert(noEvent(u >= u_min), "
Extrapolation warning: The value u (=" + String(u) + ") must be greater or equal
than the minimum abscissa value u_min (=" + String(u_min) + ") defined in the table.
", level=AssertionLevel.warning);
      assert(noEvent(u <= u_max), "
Extrapolation warning: The value u (=" + String(u) + ") must be less or equal
than the maximum abscissa value u_max (=" + String(u_max) + ") defined in the table.
", level=AssertionLevel.warning);
    end if;

    if smoothness == Modelica.Blocks.Types.Smoothness.ConstantSegments then
      for i in 1:nout loop
        y[i] = Internal.getTable1DValueNoDer(tableID, i, u);
      end for;
    elseif smoothness == Modelica.Blocks.Types.Smoothness.LinearSegments then
      for i in 1:nout loop
        y[i] = Internal.getTable1DValueNoDer2(tableID, i, u);
      end for;
    else
      for i in 1:nout loop
        y[i] = Internal.getTable1DValue(tableID, i, u);
      end for;
    end if;
  end CombiTable1Ds;

  block CombiTable1Dv
    "Table look-up in one dimension (matrix/file) with n inputs and n outputs"
    extends Modelica.Blocks.Interfaces.MIMOs(final n=size(columns, 1));
    parameter Boolean tableOnFile=false
      "= true, if table is defined on file or in function usertab"
    parameter Real table[:, :] = fill(0.0, 0, 2)
      "Table matrix (grid = first column; e.g., table=[0, 0; 1, 1; 2, 4])"
    parameter String tableName="NoName"
      "Table name on file or in function usertab (see docu)"
    parameter String fileName="NoName" "File where matrix is stored";MATLAB MAT-files (*.mat);;Comma-separated values files (*.csv)",
            caption="Open file in which table is present")));
    parameter String delimiter="," "Column delimiter character for CSV file"
    parameter Integer nHeaderLines=0 "Number of header lines to ignore for CSV file"
    parameter Boolean verboseRead=true
      "= true, if info message that file is loading is to be printed"
    parameter Integer columns[:]=2:size(table, 2)
      "Columns of table to be interpolated"
    parameter Modelica.Blocks.Types.Smoothness smoothness=Modelica.Blocks.Types.Smoothness.LinearSegments
      "Smoothness of table interpolation"
    parameter Modelica.Blocks.Types.Extrapolation extrapolation=Modelica.Blocks.Types.Extrapolation.LastTwoPoints
      "Extrapolation of data outside the definition range"
    parameter Boolean verboseExtrapolation=false
      "= true, if warning messages are to be printed if table input is outside the definition range"
    final parameter Real u_min=Internal.getTable1DAbscissaUmin(tableID)
      "Minimum abscissa value defined in table";
    final parameter Real u_max=Internal.getTable1DAbscissaUmax(tableID)
      "Maximum abscissa value defined in table";
  protected
    parameter Modelica.Blocks.Types.ExternalCombiTable1D tableID=
        Modelica.Blocks.Types.ExternalCombiTable1D(
          if tableOnFile then if isCsvExt then "Values" else tableName else "NoName",
          if tableOnFile and fileName <> "NoName" and not Modelica.Utilities.Strings.isEmpty(fileName) then fileName else "NoName",
          table,
          columns,
          smoothness,
          extrapolation,
          if tableOnFile then verboseRead else false,
          delimiter,
          nHeaderLines) "External table object";
    final parameter Boolean isCsvExt = if tableOnFile then Modelica.Utilities.Strings.findLast(fileName, ".csv", caseSensitive=false) + 3 == Modelica.Utilities.Strings.length(fileName) else false;
  equation
    if tableOnFile then
      assert(tableName <> "NoName" or isCsvExt,
        "tableOnFile = true and no table name given");
    else
      assert(size(table, 1) > 0 and size(table, 2) > 0,
        "tableOnFile = false and parameter table is an empty matrix");
    end if;

    if verboseExtrapolation and (
      extrapolation == Modelica.Blocks.Types.Extrapolation.LastTwoPoints or
      extrapolation == Modelica.Blocks.Types.Extrapolation.HoldLastPoint) then
      for i in 1:n loop
        assert(noEvent(u[i] >= u_min), "
Extrapolation warning: The value u[" + String(i) +"] (=" + String(u[i]) + ") must be greater or equal
than the minimum abscissa value u_min (=" + String(u_min) + ") defined in the table.
", level=AssertionLevel.warning);
        assert(noEvent(u[i] <= u_max), "
Extrapolation warning: The value u[" + String(i) +"] (=" + String(u[i]) + ") must be less or equal
than the maximum abscissa value u_max (=" + String(u_max) + ") defined in the table.
", level=AssertionLevel.warning);
      end for;
    end if;

    if smoothness == Modelica.Blocks.Types.Smoothness.ConstantSegments then
      for i in 1:n loop
        y[i] = Internal.getTable1DValueNoDer(tableID, i, u[i]);
      end for;
    elseif smoothness == Modelica.Blocks.Types.Smoothness.LinearSegments then
      for i in 1:n loop
        y[i] = Internal.getTable1DValueNoDer2(tableID, i, u[i]);
      end for;
    else
      for i in 1:n loop
        y[i] = Internal.getTable1DValue(tableID, i, u[i]);
      end for;
    end if;
  end CombiTable1Dv;

  block CombiTable2Ds "Table look-up in two dimensions (matrix/file)"
    extends Modelica.Blocks.Interfaces.SI2SO;
    extends Internal.CombiTable2DBase;
  equation
    if verboseExtrapolation and (
      extrapolation == Modelica.Blocks.Types.Extrapolation.LastTwoPoints or
      extrapolation == Modelica.Blocks.Types.Extrapolation.HoldLastPoint) then
      assert(noEvent(u1 >= u_min[1]), "
Extrapolation warning: The value u1 (=" + String(u1) + ") must be greater or equal
than the minimum abscissa value u_min[1] (=" + String(u_min[1]) + ") defined in the table.
", level=AssertionLevel.warning);
      assert(noEvent(u1 <= u_max[1]), "
Extrapolation warning: The value u1 (=" + String(u1) + ") must be less or equal
than the maximum abscissa value u_max[1] (=" + String(u_max[1]) + ") defined in the table.
", level=AssertionLevel.warning);
      assert(noEvent(u2 >= u_min[2]), "
Extrapolation warning: The value u2 (=" + String(u2) + ") must be greater or equal
than the minimum abscissa value u_min[2] (=" + String(u_min[2]) + ") defined in the table.
", level=AssertionLevel.warning);
      assert(noEvent(u2 <= u_max[2]), "
Extrapolation warning: The value u2 (=" + String(u2) + ") must be less or equal
than the maximum abscissa value u_max[2] (=" + String(u_max[2]) + ") defined in the table.
", level=AssertionLevel.warning);
    end if;

    if smoothness == Modelica.Blocks.Types.Smoothness.ConstantSegments then
      y = Internal.getTable2DValueNoDer(tableID, u1, u2);
    elseif smoothness == Modelica.Blocks.Types.Smoothness.LinearSegments then
      y = Internal.getTable2DValueNoDer2(tableID, u1, u2);
    else
      y = Internal.getTable2DValue(tableID, u1, u2);
    end if;
  end CombiTable2Ds;

  block CombiTable2Dv "Table look-up in two dimensions (matrix/file) with vector inputs and vector output of size n"
    extends Modelica.Blocks.Interfaces.MI2MO;
    extends Internal.CombiTable2DBase;
  equation
    if verboseExtrapolation and (
      extrapolation == Modelica.Blocks.Types.Extrapolation.LastTwoPoints or
      extrapolation == Modelica.Blocks.Types.Extrapolation.HoldLastPoint) then
      for j in 1:n loop
        assert(noEvent(u1[j] >= u_min[1]), "
Extrapolation warning: The value u1[" + String(j) + "] (=" + String(u1[j]) + ") must be greater or equal
than the minimum abscissa value u_min[1] (=" + String(u_min[1]) + ") defined in the table.
", level=AssertionLevel.warning);
        assert(noEvent(u1[j] <= u_max[1]), "
Extrapolation warning: The value u1[" + String(j) + "] (=" + String(u1[j]) + ") must be less or equal
than the maximum abscissa value u_max[1] (=" + String(u_max[1]) + ") defined in the table.
", level=AssertionLevel.warning);
        assert(noEvent(u2[j] >= u_min[2]), "
Extrapolation warning: The value u2[" + String(j) + "] (=" + String(u2[j]) + ") must be greater or equal
than the minimum abscissa value u_min[2] (=" + String(u_min[2]) + ") defined in the table.
", level=AssertionLevel.warning);
        assert(noEvent(u2[j] <= u_max[2]), "
Extrapolation warning: The value u2[" + String(j) + "] (=" + String(u2[j]) + ") must be less or equal
than the maximum abscissa value u_max[2] (=" + String(u_max[2]) + ") defined in the table.
", level=AssertionLevel.warning);
      end for;
    end if;

    if smoothness == Modelica.Blocks.Types.Smoothness.ConstantSegments then
      for j in 1:n loop
        y[j] = Modelica.Blocks.Tables.Internal.getTable2DValueNoDer(tableID, u1[j], u2[j]);
      end for;
    elseif smoothness == Modelica.Blocks.Types.Smoothness.LinearSegments then
      for j in 1:n loop
        y[j] = Modelica.Blocks.Tables.Internal.getTable2DValueNoDer2(tableID, u1[j], u2[j]);
      end for;
    else
      for j in 1:n loop
        y[j] = Modelica.Blocks.Tables.Internal.getTable2DValue(tableID, u1[j], u2[j]);
      end for;
    end if;
  end CombiTable2Dv;

  package Internal "Internal external object definitions for table functions that should not be directly utilized by the user"
    extends Modelica.Icons.InternalPackage;
    partial block CombiTable2DBase "Base class for variants of table look-up in two dimensions"
      parameter Boolean tableOnFile=false
        "= true, if table is defined on file or in function usertab"
      parameter Real table[:, :] = fill(0.0, 0, 2)
        "Table matrix (grid u1 = first column, grid u2 = first row; e.g., table=[0, 0; 0, 1])"
      parameter String tableName="NoName"
        "Table name on file or in function usertab (see docu)"
      parameter String fileName="NoName" "File where matrix is stored";MATLAB MAT-files (*.mat);;Comma-separated values files (*.csv)",
              caption="Open file in which table is present")));
      parameter String delimiter="," "Column delimiter character for CSV file"
      parameter Integer nHeaderLines=0 "Number of header lines to ignore for CSV file"
      parameter Boolean verboseRead=true
        "= true, if info message that file is loading is to be printed"
      parameter Modelica.Blocks.Types.Smoothness smoothness=Modelica.Blocks.Types.Smoothness.LinearSegments
        "Smoothness of table interpolation"
      parameter Modelica.Blocks.Types.Extrapolation extrapolation=Modelica.Blocks.Types.Extrapolation.LastTwoPoints
        "Extrapolation of data outside the definition range"
      parameter Boolean verboseExtrapolation=false
        "= true, if warning messages are to be printed if table input is outside the definition range"
      final parameter Real u_min[2]=getTable2DAbscissaUmin(tableID)
        "Minimum abscissa value defined in table";
      final parameter Real u_max[2]=getTable2DAbscissaUmax(tableID)
        "Maximum abscissa value defined in table";
      protected
        parameter Modelica.Blocks.Types.ExternalCombiTable2D tableID=
          Modelica.Blocks.Types.ExternalCombiTable2D(
            if tableOnFile then if isCsvExt then "Values" else tableName else "NoName",
            if tableOnFile and fileName <> "NoName" and not Modelica.Utilities.Strings.isEmpty(fileName) then fileName else "NoName",
            table,
            smoothness,
            extrapolation,
            if tableOnFile then verboseRead else false,
            delimiter,
            nHeaderLines) "External table object";
      final parameter Boolean isCsvExt = if tableOnFile then Modelica.Utilities.Strings.findLast(fileName, ".csv", caseSensitive=false) + 3 == Modelica.Utilities.Strings.length(fileName) else false;
    equation
        if tableOnFile then
          assert(tableName <> "NoName" or isCsvExt,
            "tableOnFile = true and no table name given");
        else
          assert(size(table, 1) > 0 and size(table, 2) > 0,
            "tableOnFile = false and parameter table is an empty matrix");
        end if;
    end CombiTable2DBase;

    pure function getTimeTableValue
      "Interpolate 1-dim. table where first column is time"
      extends Modelica.Icons.Function;
      input Modelica.Blocks.Types.ExternalCombiTimeTable tableID "External table object";
      input Integer icol "Column number";
      input Real timeIn "(Scaled) time value";
      input Real nextTimeEvent "(Scaled) next time event in table";
      input Real pre_nextTimeEvent "Pre-value of (scaled) next time event in table";
      output Real y "Interpolated value";
      external "C" y = ModelicaStandardTables_CombiTimeTable_getValue(tableID, icol, timeIn, nextTimeEvent, pre_nextTimeEvent)
    end getTimeTableValue;

    pure function getTimeTableValueNoDer
      "Interpolate 1-dim. table where first column is time (but do not provide a derivative function)"
      extends Modelica.Icons.Function;
      input Modelica.Blocks.Types.ExternalCombiTimeTable tableID "External table object";
      input Integer icol "Column number";
      input Real timeIn "(Scaled) time value";
      input Real nextTimeEvent "(Scaled) next time event in table";
      input Real pre_nextTimeEvent "Pre-value of (scaled) next time event in table";
      output Real y "Interpolated value";
      external "C" y = ModelicaStandardTables_CombiTimeTable_getValue(tableID, icol, timeIn, nextTimeEvent, pre_nextTimeEvent)
    end getTimeTableValueNoDer;

    pure function getTimeTableValueNoDer2
      "Interpolate 1-dim. table where first column is time (but do not provide a second derivative function)"
      extends Modelica.Icons.Function;
      input Modelica.Blocks.Types.ExternalCombiTimeTable tableID "External table object";
      input Integer icol "Column number";
      input Real timeIn "(Scaled) time value";
      input Real nextTimeEvent "(Scaled) next time event in table";
      input Real pre_nextTimeEvent "Pre-value of (scaled) next time event in table";
      output Real y "Interpolated value";
      external "C" y = ModelicaStandardTables_CombiTimeTable_getValue(tableID, icol, timeIn, nextTimeEvent, pre_nextTimeEvent)
    end getTimeTableValueNoDer2;

    pure function getDerTimeTableValue
      "Derivative of interpolated 1-dim. table where first column is time"
      extends Modelica.Icons.Function;
      input Modelica.Blocks.Types.ExternalCombiTimeTable tableID "External table object";
      input Integer icol "Column number";
      input Real timeIn "(Scaled) time value";
      input Real nextTimeEvent "(Scaled) next time event in table";
      input Real pre_nextTimeEvent "Pre-value of (scaled) next time event in table";
      input Real der_timeIn "Derivative of (scaled) time value";
      output Real der_y "Derivative of interpolated value";
      external "C" der_y = ModelicaStandardTables_CombiTimeTable_getDerValue(tableID, icol, timeIn, nextTimeEvent, pre_nextTimeEvent, der_timeIn)
    end getDerTimeTableValue;

    pure function getDerTimeTableValueNoDer
      "Derivative of interpolated 1-dim. table where first column is time (but do not provide a derivative function)"
      extends Modelica.Icons.Function;
      input Modelica.Blocks.Types.ExternalCombiTimeTable tableID "External table object";
      input Integer icol "Column number";
      input Real timeIn "(Scaled) time value";
      input Real nextTimeEvent "(Scaled) next time event in table";
      input Real pre_nextTimeEvent "Pre-value of (scaled) next time event in table";
      input Real der_timeIn "Derivative of (scaled) time value";
      output Real der_y "Derivative of interpolated value";
      external "C" der_y = ModelicaStandardTables_CombiTimeTable_getDerValue(tableID, icol, timeIn, nextTimeEvent, pre_nextTimeEvent, der_timeIn)
    end getDerTimeTableValueNoDer;

    pure function getDer2TimeTableValue
      "Second derivative of interpolated 1-dim. table where first column is time"
      extends Modelica.Icons.Function;
      input Modelica.Blocks.Types.ExternalCombiTimeTable tableID "External table object";
      input Integer icol "Column number";
      input Real timeIn "(Scaled) time value";
      input Real nextTimeEvent "(Scaled) next time event in table";
      input Real pre_nextTimeEvent "Pre-value of (scaled) next time event in table";
      input Real der_timeIn "Derivative of (scaled) time value";
      input Real der2_timeIn "Second derivative of (scaled) time value";
      output Real der2_y "Second derivative of interpolated value";
      external "C" der2_y = ModelicaStandardTables_CombiTimeTable_getDer2Value(tableID, icol, timeIn, nextTimeEvent, pre_nextTimeEvent, der_timeIn, der2_timeIn)
    end getDer2TimeTableValue;

    pure function getTimeTableTmin
      "Return minimum abscissa value of 1-dim. table where first column is time"
      extends Modelica.Icons.Function;
      input Modelica.Blocks.Types.ExternalCombiTimeTable tableID "External table object";
      output Real timeMin "Minimum abscissa value in table";
      external "C" timeMin = ModelicaStandardTables_CombiTimeTable_minimumTime(tableID)
    end getTimeTableTmin;

    pure function getTimeTableTmax
      "Return maximum abscissa value of 1-dim. table where first column is time"
      extends Modelica.Icons.Function;
      input Modelica.Blocks.Types.ExternalCombiTimeTable tableID "External table object";
      output Real timeMax "Maximum abscissa value in table";
      external "C" timeMax = ModelicaStandardTables_CombiTimeTable_maximumTime(tableID)
    end getTimeTableTmax;

    pure function getNextTimeEvent
      "Return next time event value of 1-dim. table where first column is time"
      extends Modelica.Icons.Function;
      input Modelica.Blocks.Types.ExternalCombiTimeTable tableID "External table object";
      input Real timeIn "(Scaled) time value";
      output Real nextTimeEvent "(Scaled) next time event in table";
      external "C" nextTimeEvent = ModelicaStandardTables_CombiTimeTable_nextTimeEvent(tableID, timeIn)
    end getNextTimeEvent;

    pure function getTable1DValue "Interpolate 1-dim. table defined by matrix"
      extends Modelica.Icons.Function;
      input Modelica.Blocks.Types.ExternalCombiTable1D tableID "External table object";
      input Integer icol "Column number";
      input Real u "Abscissa value";
      output Real y "Interpolated value";
      external "C" y = ModelicaStandardTables_CombiTable1D_getValue(tableID, icol, u)
    end getTable1DValue;

    pure function getTable1DValueNoDer
      "Interpolate 1-dim. table defined by matrix (but do not provide a derivative function)"
      extends Modelica.Icons.Function;
      input Modelica.Blocks.Types.ExternalCombiTable1D tableID "External table object";
      input Integer icol "Column number";
      input Real u "Abscissa value";
      output Real y "Interpolated value";
      external "C" y = ModelicaStandardTables_CombiTable1D_getValue(tableID, icol, u)
    end getTable1DValueNoDer;

    pure function getTable1DValueNoDer2
      "Interpolate 1-dim. table defined by matrix (but do not provide a second derivative function)"
      extends Modelica.Icons.Function;
      input Modelica.Blocks.Types.ExternalCombiTable1D tableID "External table object";
      input Integer icol "Column number";
      input Real u "Abscissa value";
      output Real y "Interpolated value";
      external "C" y = ModelicaStandardTables_CombiTable1D_getValue(tableID, icol, u)
    end getTable1DValueNoDer2;

    pure function getDerTable1DValue
      "Derivative of interpolated 1-dim. table defined by matrix"
      extends Modelica.Icons.Function;
      input Modelica.Blocks.Types.ExternalCombiTable1D tableID "External table object";
      input Integer icol "Column number";
      input Real u "Abscissa value";
      input Real der_u "Derivative of abscissa value";
      output Real der_y "Derivative of interpolated value";
      external "C" der_y = ModelicaStandardTables_CombiTable1D_getDerValue(tableID, icol, u, der_u)
    end getDerTable1DValue;

    pure function getDerTable1DValueNoDer
      "Derivative of interpolated 1-dim. table defined by matrix (but do not provide a second derivative function)"
      extends Modelica.Icons.Function;
      input Modelica.Blocks.Types.ExternalCombiTable1D tableID "External table object";
      input Integer icol "Column number";
      input Real u "Abscissa value";
      input Real der_u "Derivative of abscissa value";
      output Real der_y "Derivative of interpolated value";
      external "C" der_y = ModelicaStandardTables_CombiTable1D_getDerValue(tableID, icol, u, der_u)
    end getDerTable1DValueNoDer;

    pure function getDer2Table1DValue
      "Second derivative of interpolated 1-dim. table defined by matrix"
      extends Modelica.Icons.Function;
      input Modelica.Blocks.Types.ExternalCombiTable1D tableID "External table object";
      input Integer icol "Column number";
      input Real u "Abscissa value";
      input Real der_u "Derivative of abscissa value";
      input Real der2_u " Second derivative of abscissa value";
      output Real der2_y "Second derivative of interpolated value";
      external "C" der2_y = ModelicaStandardTables_CombiTable1D_getDer2Value(tableID, icol, u, der_u, der2_u)
    end getDer2Table1DValue;

    pure function getTable1DAbscissaUmin
      "Return minimum abscissa value of 1-dim. table defined by matrix"
      extends Modelica.Icons.Function;
      input Modelica.Blocks.Types.ExternalCombiTable1D tableID "External table object";
      output Real uMin "Minimum abscissa value in table";
      external "C" uMin = ModelicaStandardTables_CombiTable1D_minimumAbscissa(tableID)
    end getTable1DAbscissaUmin;

    pure function getTable1DAbscissaUmax
      "Return maximum abscissa value of 1-dim. table defined by matrix"
      extends Modelica.Icons.Function;
      input Modelica.Blocks.Types.ExternalCombiTable1D tableID "External table object";
      output Real uMax "Maximum abscissa value in table";
      external "C" uMax = ModelicaStandardTables_CombiTable1D_maximumAbscissa(tableID)
    end getTable1DAbscissaUmax;

    pure function getTable2DValue "Interpolate 2-dim. table defined by matrix"
      extends Modelica.Icons.Function;
      input Modelica.Blocks.Types.ExternalCombiTable2D tableID "External table object";
      input Real u1 "Value of first independent variable";
      input Real u2 "Value of second independent variable";
      output Real y "Interpolated value";
      external "C" y = ModelicaStandardTables_CombiTable2D_getValue(tableID, u1, u2)
    end getTable2DValue;

    pure function getTable2DValueNoDer
      "Interpolate 2-dim. table defined by matrix (but do not provide a derivative function)"
      extends Modelica.Icons.Function;
      input Modelica.Blocks.Types.ExternalCombiTable2D tableID "External table object";
      input Real u1 "Value of first independent variable";
      input Real u2 "Value of second independent variable";
      output Real y "Interpolated value";
      external "C" y = ModelicaStandardTables_CombiTable2D_getValue(tableID, u1, u2)
    end getTable2DValueNoDer;

    pure function getTable2DValueNoDer2
      "Interpolate 2-dim. table defined by matrix (but do not provide a second derivative function)"
      extends Modelica.Icons.Function;
      input Modelica.Blocks.Types.ExternalCombiTable2D tableID "External table object";
      input Real u1 "Value of first independent variable";
      input Real u2 "Value of second independent variable";
      output Real y "Interpolated value";
      external "C" y = ModelicaStandardTables_CombiTable2D_getValue(tableID, u1, u2)
    end getTable2DValueNoDer2;

    pure function getDerTable2DValue
      "Derivative of interpolated 2-dim. table defined by matrix"
      extends Modelica.Icons.Function;
      input Modelica.Blocks.Types.ExternalCombiTable2D tableID "External table object";
      input Real u1 "Value of first independent variable";
      input Real u2 "Value of second independent variable";
      input Real der_u1 "Derivative of first independent variable";
      input Real der_u2 "Derivative of second independent variable";
      output Real der_y "Derivative of interpolated value";
      external "C" der_y = ModelicaStandardTables_CombiTable2D_getDerValue(tableID, u1, u2, der_u1, der_u2)
    end getDerTable2DValue;

    pure function getDerTable2DValueNoDer
      "Derivative of interpolated 2-dim. table defined by matrix (but do not provide a second derivative function)"
      extends Modelica.Icons.Function;
      input Modelica.Blocks.Types.ExternalCombiTable2D tableID "External table object";
      input Real u1 "Value of first independent variable";
      input Real u2 "Value of second independent variable";
      input Real der_u1 "Derivative of first independent variable";
      input Real der_u2 "Derivative of second independent variable";
      output Real der_y "Derivative of interpolated value";
      external "C" der_y = ModelicaStandardTables_CombiTable2D_getDerValue(tableID, u1, u2, der_u1, der_u2)
    end getDerTable2DValueNoDer;

    pure function getDer2Table2DValue
      "Second derivative of interpolated 2-dim. table defined by matrix"
      extends Modelica.Icons.Function;
      input Modelica.Blocks.Types.ExternalCombiTable2D tableID "External table object";
      input Real u1 "Value of first independent variable";
      input Real u2 "Value of second independent variable";
      input Real der_u1 "Derivative of first independent variable";
      input Real der_u2 "Derivative of second independent variable";
      input Real der2_u1 "Second derivative of first independent variable";
      input Real der2_u2 "Second derivative of second independent variable";
      output Real der2_y "Second derivative of interpolated value";
      external "C" der2_y = ModelicaStandardTables_CombiTable2D_getDer2Value(tableID, u1, u2, der_u1, der_u2, der2_u1, der2_u2)
    end getDer2Table2DValue;

    pure function getTable2DAbscissaUmin
      "Return minimum abscissa value of 2-dim. table defined by matrix"
      extends Modelica.Icons.Function;
      input Modelica.Blocks.Types.ExternalCombiTable2D tableID "External table object";
      output Real uMin[2] "Minimum abscissa value in table";
      external "C" ModelicaStandardTables_CombiTable2D_minimumAbscissa(tableID, uMin)
    end getTable2DAbscissaUmin;

    pure function getTable2DAbscissaUmax
      "Return maximum abscissa value of 2-dim. table defined by matrix"
      extends Modelica.Icons.Function;
      input Modelica.Blocks.Types.ExternalCombiTable2D tableID "External table object";
      output Real uMax[2] "Maximum abscissa value in table";
      external "C" ModelicaStandardTables_CombiTable2D_maximumAbscissa(tableID, uMax)
    end getTable2DAbscissaUmax;
  end Internal;
  Modelica.Blocks.Tables.CombiTable1Dv table(tableOnFile=true, tableName=\"TestTable_1D_a\")
  Modelica.Blocks.Sources.ContinuousClock clock
protected
  encapsulated impure function getUsertab \"External dummy function to include \\\"usertab.c\\\"\"
    input Real dummy_u[:];
    output Real dummy_y;
    external \"C\" dummy_y = mydummyfunc(dummy_u);
  end getUsertab;
initial equation
  dummy = getUsertab(table.y);
equation
  connect(clock.y, table.u[1])
end ExampleCTable;
</pre></blockquote>
</html>"), Icon(coordinateSystem(preserveAspectRatio=false, extent={{-100,-100},
            {100,100}}), graphics={
        Rectangle(
          extent={{-76,-26},{80,-76}},
          lineColor={95,95,95},
          fillColor={235,235,235},
          fillPattern=FillPattern.Solid),
        Rectangle(
          extent={{-76,24},{80,-26}},
          lineColor={95,95,95},
          fillColor={235,235,235},
          fillPattern=FillPattern.Solid),
        Rectangle(
          extent={{-76,74},{80,24}},
          lineColor={95,95,95},
          fillColor={235,235,235},
          fillPattern=FillPattern.Solid),
        Line(
          points={{-28,74},{-28,-76}},
          color={95,95,95}),
        Line(
          points={{24,74},{24,-76}},
          color={95,95,95})}));
end Tables;


within Modelica.Blocks;
package Types
  "Library of constants, external objects and types with choices, especially to build menus"
  extends Modelica.Icons.TypesPackage;

  type Smoothness = enumeration(
      LinearSegments "Linear interpolation of table points",
      ContinuousDerivative
        "Akima spline interpolation of table points (such that the first derivative is continuous)",
      ConstantSegments
        "Piecewise constant interpolation of table points (the value from the previous abscissa point is returned)",
      MonotoneContinuousDerivative1
        "Fritsch-Butland spline interpolation (such that the monotonicity is preserved and the first derivative is continuous)",
      MonotoneContinuousDerivative2
        "Steffen spline interpolation of table points (such that the monotonicity is preserved and the first derivative is continuous)",
      ModifiedContinuousDerivative
        "Modified Akima spline interpolation of table points (such that the first derivative is continuous and shortcomings of the original Akima method are avoided)")
    "Enumeration defining the smoothness of table interpolation";

    type Extrapolation = enumeration(
      HoldLastPoint
        "Hold the first/last table point outside of the table scope",
      LastTwoPoints
        "Extrapolate by using the derivative at the first/last table points outside of the table scope",
      Periodic "Repeat the table scope periodically",
      NoExtrapolation "Extrapolation triggers an error")
    "Enumeration defining the extrapolation of table interpolation";

    type TimeEvents = enumeration(
      Always "Always generate time events at interval boundaries",
      AtDiscontinuities "Generate time events at discontinuities (defined by duplicated sample points)",
      NoTimeEvents "No time events at interval boundaries")
    "Enumeration defining the time event handling of time table interpolation";

    type Init = enumeration(
      NoInit
        "No initialization (start values are used as guess values with fixed=false)",
      SteadyState
        "Steady state initialization (derivatives of states are zero)",
      InitialState "Initialization with initial states",
      InitialOutput
        "Initialization with initial outputs (and steady state of the states if possible)")
    "Enumeration defining initialization of a block"

   type SimpleController = enumeration(
      P "P controller",
      PI "PI controller",
      PD "PD controller",
      PID "PID controller")
    "Enumeration defining P, PI, PD, or PID simple controller type"

  type AnalogFilter = enumeration(
      CriticalDamping "Filter with critical damping",
      Bessel "Bessel filter",
      Butterworth "Butterworth filter",
      ChebyshevI "Chebyshev I filter")
    "Enumeration defining the method of filtering"

  type FilterType = enumeration(
      LowPass "Low pass filter",
      HighPass "High pass filter",
      BandPass "Band pass filter",
      BandStop "Band stop / notch filter")
    "Enumeration of analog filter types (low, high, band pass or band stop filter)"

  type Regularization = enumeration(
      Exp "Exponential regularization (smooth)",
      Sine "Sinusoidal regularization (smooth 1st derivative)",
      Linear "Linear regularization",
      Cosine "Cosine regularization")
    "Enumeration defining the regularization around zero";

  type LimiterHomotopy = enumeration(
      NoHomotopy "Homotopy is not used",
      Linear "Simplified model without limits",
      UpperLimit "Simplified model fixed at upper limit",
      LowerLimit "Simplified model fixed at lower limit")
    "Enumeration defining use of homotopy in limiter components"

  type VariableLimiterHomotopy = enumeration(
      NoHomotopy "Simplified model = actual model",
      Linear "Simplified model: y = u",
      Fixed "Simplified model: y = ySimplified")
    "Enumeration defining use of homotopy in variable limiter components"

  class ExternalCombiTimeTable
    "External object of 1-dim. table where first column is time"
    extends ExternalObject;

    function constructor "Initialize 1-dim. table where first column is time"
      extends Modelica.Icons.Function;
      input String tableName "Table name";
      input String fileName "File name";
      input Real table[:, :];
      input Real startTime;
      input Integer columns[:];
      input Modelica.Blocks.Types.Smoothness smoothness;
      input Modelica.Blocks.Types.Extrapolation extrapolation;
      input Real shiftTime=0.0;
      input Modelica.Blocks.Types.TimeEvents timeEvents=Modelica.Blocks.Types.TimeEvents.Always;
      input Boolean verboseRead=true "= true: Print info message; = false: No info message";
      input String delimiter="," "Column delimiter character for CSV file";
      input Integer nHeaderLines=0 "Number of header lines to ignore for CSV file";
      output ExternalCombiTimeTable externalCombiTimeTable;
    external "C" externalCombiTimeTable = ModelicaStandardTables_CombiTimeTable_init3(
            fileName,
            tableName,
            table,
            size(table, 1),
            size(table, 2),
            startTime,
            columns,
            size(columns, 1),
            smoothness,
            extrapolation,
            shiftTime,
            timeEvents,
            verboseRead,
            delimiter,
            nHeaderLines)
    end constructor;

    function destructor "Terminate 1-dim. table where first column is time"
      extends Modelica.Icons.Function;
      input ExternalCombiTimeTable externalCombiTimeTable;
    external "C" ModelicaStandardTables_CombiTimeTable_close(
        externalCombiTimeTable)
    end destructor;

  end ExternalCombiTimeTable;

  class ExternalCombiTable1D
    "External object of 1-dim. table defined by matrix"
    extends ExternalObject;

    function constructor "Initialize 1-dim. table defined by matrix"
      extends Modelica.Icons.Function;
      input String tableName "Table name";
      input String fileName "File name";
      input Real table[:, :];
      input Integer columns[:];
      input Modelica.Blocks.Types.Smoothness smoothness;
      input Modelica.Blocks.Types.Extrapolation extrapolation=Modelica.Blocks.Types.Extrapolation.LastTwoPoints;
      input Boolean verboseRead=true "= true: Print info message; = false: No info message";
      input String delimiter="," "Column delimiter character for CSV file";
      input Integer nHeaderLines=0 "Number of header lines to ignore for CSV file";
      output ExternalCombiTable1D externalCombiTable1D;
    external "C" externalCombiTable1D = ModelicaStandardTables_CombiTable1D_init3(
            fileName,
            tableName,
            table,
            size(table, 1),
            size(table, 2),
            columns,
            size(columns, 1),
            smoothness,
            extrapolation,
            verboseRead,
            delimiter,
            nHeaderLines)
    end constructor;

    function destructor "Terminate 1-dim. table defined by matrix"
      extends Modelica.Icons.Function;
      input ExternalCombiTable1D externalCombiTable1D;
    external "C" ModelicaStandardTables_CombiTable1D_close(externalCombiTable1D)
    end destructor;

  end ExternalCombiTable1D;

  class ExternalCombiTable2D
    "External object of 2-dim. table defined by matrix"
    extends ExternalObject;

    function constructor "Initialize 2-dim. table defined by matrix"
      extends Modelica.Icons.Function;
      input String tableName "Table name";
      input String fileName "File name";
      input Real table[:, :];
      input Modelica.Blocks.Types.Smoothness smoothness;
      input Modelica.Blocks.Types.Extrapolation extrapolation=Modelica.Blocks.Types.Extrapolation.LastTwoPoints;
      input Boolean verboseRead=true "= true: Print info message; = false: No info message";
      input String delimiter="," "Column delimiter character for CSV file";
      input Integer nHeaderLines=0 "Number of header lines to ignore for CSV file";
      output ExternalCombiTable2D externalCombiTable2D;
    external "C" externalCombiTable2D = ModelicaStandardTables_CombiTable2D_init3(
            fileName,
            tableName,
            table,
            size(table, 1),
            size(table, 2),
            smoothness,
            extrapolation,
            verboseRead,
            delimiter,
            nHeaderLines)
    end constructor;

    function destructor "Terminate 2-dim. table defined by matrix"
      extends Modelica.Icons.Function;
      input ExternalCombiTable2D externalCombiTable2D;
    external "C" ModelicaStandardTables_CombiTable2D_close(externalCombiTable2D)
    end destructor;

  end ExternalCombiTable2D;
end Types;


within Modelica;
package Clocked "Clock triggered blocks for describing synchronous behavior suited for implementation of control
systems"
extends Modelica.Icons.Package;
end Clocked;


within Modelica.Clocked;
package BooleanSignals "Library of clocked blocks for Boolean signals"
  extends Modelica.Icons.Package;
  import Modelica.Units.SI;
end BooleanSignals;


within Modelica.Clocked.BooleanSignals;
package Interfaces "Library of partial blocks for components with clocked Boolean signals"
  extends Modelica.Icons.InterfacesPackage;
end Interfaces;


Block with clocked single input and clocked single output Boolean signals.

within Modelica.Clocked.BooleanSignals.Interfaces;
partial block PartialClockedSISO
  "Block with clocked single input and clocked single output Boolean signals"
  extends Clocked.ClockSignals.Interfaces.ClockedBlockIcon;

  Modelica.Blocks.Interfaces.BooleanInput u
    "Connector of clocked, Real input signal"
  Modelica.Blocks.Interfaces.BooleanOutput y
    "Connector of clocked, Real output signal"

end PartialClockedSISO;


Block with clocked single output Boolean signals.

within Modelica.Clocked.BooleanSignals.Interfaces;
partial block PartialClockedSO
  "Block with clocked single output Boolean signals"
  extends Clocked.ClockSignals.Interfaces.ClockedBlockIcon;

  Modelica.Blocks.Interfaces.BooleanOutput y
    "Connector of clocked, Real output signal"

end PartialClockedSO;


Basic block used for sampling of Boolean signals.

within Modelica.Clocked.BooleanSignals.Interfaces;
partial block PartialSISOSampler
  "Basic block used for sampling of Boolean signals"
extends Clocked.BooleanSignals.Interfaces.SamplerIcon;
  Modelica.Blocks.Interfaces.BooleanInput u
    "Connector of continuous-time, Real input signal"
  Modelica.Blocks.Interfaces.BooleanOutput y
    "Connector of clocked, Real output signal"
end PartialSISOSampler;


Basic graphical layout of block used for sampling of Boolean signals.

within Modelica.Clocked.BooleanSignals.Interfaces;
partial block SamplerIcon
  "Basic graphical layout of block used for sampling of Boolean signals"
end SamplerIcon;


Indicate Boolean signal changing. This block is a synchronous version of
Modelica.Blocks.Math.BooleanChange.
It uses previous instead of the implicit pre of
change to set the Boolean output y to
true when the boolean input u changed. Thus, it's
logic is:

within Modelica.Clocked.BooleanSignals.NonPeriodic;
block BooleanChange "Indicate Boolean signal changing"
  extends Clocked.ClockSignals.Interfaces.ClockedBlockIcon;

  Modelica.Blocks.Interfaces.BooleanInput u
    "Connector of Boolean input signal."
  Modelica.Blocks.Interfaces.BooleanOutput y
    "Connector of Boolean output signal."

equation
  if firstTick() then
    y = false;
  else
    y = not (u == previous(u));
  end if;
end if;

This block might be superfluous and replaced by
Modelica.Blocks.Math.BooleanChange when the semantics
of change are relaxed and well-defined for
clocked discrete-time partitions.

"));
end BooleanChange;


Block to translate clock signals to continuous Boolean events (each time the input clock ticks a rising Boolean output edge is produced)..

within Modelica.Clocked.BooleanSignals.NonPeriodic;
block ClockToBoolean
  "Block to translate clock signals to continuous Boolean events (each time the input clock ticks a rising Boolean output edge is produced)."
  extends ClockSignals.Interfaces.ClockedBlockIcon;
  extends Modelica.Blocks.Icons.PartialBooleanBlock;

  ClockSignals.Interfaces.ClockInput u
    "Connector of clock input signal."
  Modelica.Blocks.Interfaces.BooleanOutput y
    "Connector of continuous Boolean output signal."

  Sampler.SampleClocked input_sample
  Modelica.Blocks.MathBoolean.Not input_tick
  Sampler.Hold input_hold(y_start = false)
  Modelica.Blocks.MathBoolean.ChangingEdge input_ticked

equation
  connect(input_sample.y,input_tick.u)
  connect(input_hold.y,input_sample.u)
  connect(input_tick.y,input_hold.u)
  connect(input_hold.y,input_ticked.u)
  connect(u, input_sample.clock)
  connect(input_ticked.y, y)
end ClockToBoolean;


Delay the clocked input signal for a fractional multiple of the sample period.

within Modelica.Clocked.BooleanSignals.NonPeriodic;
block FractionalDelay
  "Delay the clocked input signal for a fractional multiple of the sample period"
extends Clocked.BooleanSignals.Interfaces.PartialClockedSISO;

  parameter Integer shift(min=0) = 0
    "Delay = interval() * shift/resolution";
  parameter Integer resolution(min=1) = 1
    "Time quantization resolution of sample interval";
protected
  parameter Integer n = div(shift,resolution);
  Boolean u_buffer[n+1](each start=false)
    "The previous values of the inputs; u_last[1] = u, u_last[2] = previous(u_last[1]); u_last[3] = previous(u_last[2])";
  Boolean first(start=true) "Used to identify the first clock tick";
equation
 first = false;
 u_buffer = if previous(first) then fill(u,n+1) else cat(1, {u}, previous(u_buffer[1:n]));
 y = shiftSample(u_buffer[n+1], shift, resolution);
end FractionalDelay;


within Modelica.Clocked.BooleanSignals;
package NonPeriodic "Library of blocks that operate on periodically and non-periodically clocked signals"
  extends Modelica.Icons.Package;

end NonPeriodic;


Delay the clocked input signal for one sample period. This block describes a unit delay:

within Modelica.Clocked.BooleanSignals.NonPeriodic;
block UnitDelay "Delay the clocked input signal for one sample period"
  extends Clocked.BooleanSignals.Interfaces.PartialClockedSISO(u(final
        start=y_start));
  parameter Boolean y_start=false
    "Value of output signal at first clock tick";
equation
  y = previous(u);
end UnitDelay;


Assign a clock to a clocked Boolean signal. This block for Boolean signals works similarly as the corresponding block for Real signals (see RealSignals.Sampler.AssignClock).

within Modelica.Clocked.BooleanSignals.Sampler;
block AssignClock "Assign a clock to a clocked Boolean signal"
  Modelica.Blocks.Interfaces.BooleanInput u
    "Connector of clocked, Boolean input signal"
  Modelica.Blocks.Interfaces.BooleanOutput y
    "Connector of clocked, Boolean output signal"
  Clocked.ClockSignals.Interfaces.ClockInput clock
equation
  when clock then
    y = u;
  end when;
end AssignClock;


Assign a clock to a clocked Boolean signal vector. This block for Boolean signals works similarly as the corresponding block for Real signals (see RealSignals.Sampler.AssignClockVectorized).

within Modelica.Clocked.BooleanSignals.Sampler;
block AssignClockVectorized
  "Assign a clock to a clocked Boolean signal vector"
  parameter Integer n(min=1)=1
    "Size of input signal vector u (= size of output signal vector y)";
  Modelica.Blocks.Interfaces.BooleanInput u[n]
    "Connector of clocked, Boolean input signal"
  Modelica.Blocks.Interfaces.BooleanOutput y[n]
    "Connector of clocked, Boolean output signal"
  Clocked.ClockSignals.Interfaces.ClockInput clock
equation
  when clock then
    y = u;
  end when;
end AssignClockVectorized;


Shift clock of Boolean input signal backwards in time (and access the most recent value of the input at this new clock). This block for Boolean signals works similarly as the corresponding block for Real signals (see RealSignals.Sampler.BackSample).

within Modelica.Clocked.BooleanSignals.Sampler;
block BackSample
  "Shift clock of Boolean input signal backwards in time (and access the most recent value of the input at this new clock)"
  parameter Integer backCounter(min=0)=0 "Numerator of shifting formula"
  parameter Integer resolution(min=1)=1 "Denominator of shifting formula"
  parameter Boolean y_start=false
    "Value of output y before the first clock tick of the input u";

  Modelica.Blocks.Interfaces.BooleanInput
                                       u(start=y_start)
    "Connector of clocked, Boolean input signal"
  Modelica.Blocks.Interfaces.BooleanOutput
                                        y
    "Connector of clocked, Boolean output signal (clock of y is faster than clock of u)"
equation
  y = backSample(u,backCounter,resolution);
end BackSample;


Hold the clocked, Boolean input signal and provide it as continuous-time output signal (zero order hold). This block for Boolean signals works similarly as the corresponding block for Real signals (see RealSignals.Sampler.Hold).

within Modelica.Clocked.BooleanSignals.Sampler;
block Hold
  "Hold the clocked, Boolean input signal and provide it as continuous-time output signal (zero order hold)"
  parameter Boolean y_start = false
    "Value of output y before the first tick of the clock associated to input u";

  Modelica.Blocks.Interfaces.BooleanInput
                                       u(final start=y_start)
    "Connector of clocked, Boolean input signal"
  Modelica.Blocks.Interfaces.BooleanOutput
                                        y
    "Connector of continuous-time, Boolean output signal"
equation
    y = hold(u);
end Hold;


within Modelica.Clocked.BooleanSignals;
package Sampler "Library of sampler and hold blocks for Boolean signals"
  extends Modelica.Icons.Package;
end Sampler;


Sample the continuous-time, Boolean input signal and provide it as clocked output signal (clock is inferred). This block for Boolean signals works similarly as the corresponding block for Real signals (see RealSignals.Sampler.Sample).

within Modelica.Clocked.BooleanSignals.Sampler;
block Sample
  "Sample the continuous-time, Boolean input signal and provide it as clocked output signal (clock is inferred)"
  extends Clocked.BooleanSignals.Interfaces.PartialSISOSampler;

equation
  y = sample(u);
end Sample;


Sample the continuous-time, Boolean input signal and provide it as clocked output signal. The clock is provided as input signal. This block for Boolean signals works similarly as the corresponding block for Real signals (see RealSignals.Sampler.SampleClocked).

within Modelica.Clocked.BooleanSignals.Sampler;
block SampleClocked
  "Sample the continuous-time, Boolean input signal and provide it as clocked output signal. The clock is provided as input signal"
  extends Clocked.BooleanSignals.Interfaces.SamplerIcon;
  Clocked.ClockSignals.Interfaces.ClockInput clock
    "Output signal y is associated with this clock input"
  Modelica.Blocks.Interfaces.BooleanInput
                                       u
    "Connector of continuous-time, Boolean input signal"
  Modelica.Blocks.Interfaces.BooleanOutput
                                        y
    "Connector of clocked, Boolean output signal"
equation
  y = sample(u,clock);
end SampleClocked;


Sample the continuous-time, Boolean input signal vector and provide it as clocked output signal vector. The clock is provided as input signal. This block for Boolean signals works similarly as the corresponding block for Real signals (see RealSignals.Sampler.SampleVectorizedAndClocked).

within Modelica.Clocked.BooleanSignals.Sampler;
block SampleVectorizedAndClocked
  "Sample the continuous-time, Boolean input signal vector and provide it as clocked output signal vector. The clock is provided as input signal"
  extends Clocked.BooleanSignals.Interfaces.SamplerIcon;
  parameter Integer n(min=1)=1
    "Size of input signal vector u (= size of output signal vector y)";
  Modelica.Blocks.Interfaces.BooleanInput
                                       u[n]
    "Connector of continuous-time, Boolean input signal vector"
  Modelica.Blocks.Interfaces.BooleanOutput
                                        y[n]
    "Connector of clocked, Boolean output signal vector"
  Clocked.ClockSignals.Interfaces.ClockInput clock
    "Output signal vector y is associated with this clock input"
equation
  y = sample(u,clock);
end SampleVectorizedAndClocked;


Shift the clocked Boolean input signal by a fraction of the last interval and provide it as clocked output signal. This block for Boolean signals works similarly as the corresponding block for Real signals (see RealSignals.Sampler.ShiftSample).

within Modelica.Clocked.BooleanSignals.Sampler;
block ShiftSample
  "Shift the clocked Boolean input signal by a fraction of the last interval and provide it as clocked output signal"
  parameter Integer shiftCounter(min=0)=0 "Numerator of shifting formula"
  parameter Integer resolution(min=1)=1 "Denominator of shifting formula"

  Modelica.Blocks.Interfaces.BooleanInput u
    "Connector of clocked, Boolean input signal"
  Modelica.Blocks.Interfaces.BooleanOutput y
    "Connector of clocked, Boolean output signal (clock of y is faster than clock of u)"
equation
  y = shiftSample(u,shiftCounter,resolution);
end ShiftSample;


Sub-sample the clocked Boolean input signal and provide it as clocked output signal. This block for Boolean signals works similarly as the corresponding block for Real signals (see RealSignals.Sampler.SubSample).

within Modelica.Clocked.BooleanSignals.Sampler;
block SubSample
  "Sub-sample the clocked Boolean input signal and provide it as clocked output signal"
  parameter Boolean inferFactor=true
    "= true, if sub-sampling factor is inferred"
  parameter Integer factor(min=1)=1
    "Sub-sampling factor >= 1 (ignored if inferFactor=true)"

  Modelica.Blocks.Interfaces.BooleanInput
                                       u
    "Connector of clocked, Boolean input signal"
  Modelica.Blocks.Interfaces.BooleanOutput
                                        y
    "Connector of clocked, Boolean output signal (clock of y is slower as clock of u)"
equation
  if inferFactor then
     y = subSample(u);
  else
     y = subSample(u,factor);
  end if;
end SubSample;


Super-sample the clocked Boolean input signal and provide it as clocked output signal. This block for Boolean signals works similarly as the corresponding block for Real signals (see RealSignals.Sampler.SuperSample).

within Modelica.Clocked.BooleanSignals.Sampler;
block SuperSample
  "Super-sample the clocked Boolean input signal and provide it as clocked output signal"
  parameter Boolean inferFactor=true
    "= true, if super-sampling factor is inferred"
  parameter Integer factor(min=1)=1
    "Super-sampling factor >= 1 (ignored if inferFactor=true)"

  Modelica.Blocks.Interfaces.BooleanInput
                                       u
    "Connector of clocked, Boolean input signal"
  Modelica.Blocks.Interfaces.BooleanOutput
                                        y
    "Connector of clocked, Boolean output signal (clock of y is faster as clock of u)"
equation
  if inferFactor then
     y = superSample(u);
  else
     y = superSample(u,factor);
  end if;
end SuperSample;


Generate a Boolean continuous-time square signal from a clocked Real input. This block for Boolean signals works similarly as the corresponding block for Real signals (see
RealSignals.Sampler.Utilities.AssignClockToSquareWaveHold).

within Modelica.Clocked.BooleanSignals.Sampler.Utilities;
block AssignClockToSquareWaveHold
"Generate a Boolean continuous-time square signal from a clocked Real input"
  extends Clocked.ClockSignals.Interfaces.ClockedBlockIcon;
  parameter Boolean y_start=false "Initial value of output signal";
  Modelica.Blocks.Interfaces.BooleanInput
                                       u
  Modelica.Blocks.Interfaces.BooleanOutput y
  "Connector of Boolean output signal"
protected
  Boolean y2(start=y_start);
equation
  // dummy condition to relate clock of u with y2
  y2 = if u == false then not previous(y2) else not previous(y2);
  y = hold(y2);
end AssignClockToSquareWaveHold;


Generate a Boolean continuous-time trigger signal from a clocked Boolean input. This block for Boolean signals works similarly as the corresponding block for Real signals (see
RealSignals.Sampler.Utilities.AssignClockToTriggerHold).

within Modelica.Clocked.BooleanSignals.Sampler.Utilities;
block AssignClockToTriggerHold
"Generate a Boolean continuous-time trigger signal from a clocked Boolean input"
  extends Clocked.ClockSignals.Interfaces.ClockedBlockIcon;
  parameter Boolean y_start=false "Initial value of output signal";
  Modelica.Blocks.Interfaces.BooleanInput
                                       u
  Modelica.Blocks.Interfaces.BooleanOutput y
  "Connector of Boolean output signal"
protected
  Boolean y2(start=y_start);
  Boolean y3(start=y_start, fixed=true);
  Boolean uu
equation
  when Clock() then
     uu = u "Dummy assignment to relate clock of u with y2";
     y2 = not previous(y2);
  end when;
  y3 = hold(y2);
  y = change(y3);
end AssignClockToTriggerHold;


within Modelica.Clocked.BooleanSignals.Sampler;
package Utilities "Utility components that are usually not directly used"
   extends Modelica.Icons.UtilitiesPackage;
end Utilities;


Upsample the clocked Boolean input signal and provide it as clocked output signal. This block for Boolean signals works similarly as the corresponding block for Real signals (see
RealSignals.Sampler.Utilities.UpSample).

within Modelica.Clocked.BooleanSignals.Sampler.Utilities;
block UpSample
  "Upsample the clocked Boolean input signal and provide it as clocked output signal"
  parameter Boolean inferFactor=true
    "= true, if upsampling factor is inferred"
  parameter Integer factor(min=1)=1
    "Upsampling factor >= 1 (if inferFactor=false)"
  Modelica.Blocks.Interfaces.BooleanInput
                                       u
    "Connector of clocked, Boolean input signal"
  Modelica.Blocks.Interfaces.BooleanOutput
                                        y
    "Connector of clocked, Boolean output signal (clock of y is faster as clock of u)"
protected
  Boolean dummy
  Boolean b(start=false);
  Boolean b_super(start=false);
  Boolean u_super;
equation
  when Clock() then // clock of u
     dummy = u;
     b = not previous(b);
  end when;

  when Clock() then // clock of y
     b_super = superSample(b);
     if inferFactor then
        u_super = superSample(u);
     else
        u_super = superSample(u,factor);
     end if;
     y = if b_super <> previous(b_super) then u_super else false;
  end when;
end UpSample;


within Modelica.Clocked.BooleanSignals;
package TickBasedSources "Package of signal source blocks generating clocked tick/sample based Boolean signals"
   extends Modelica.Icons.SourcesPackage;
end TickBasedSources;


Generate pulse signal of type Boolean. The block is similar to the block in Modelica.Blocks.Sources.BooleanPulse,
but adapted to work in clocked partitions (by internal sampling of the continuous time variable).

within Modelica.Clocked.BooleanSignals.TickBasedSources;
block Pulse "Generate pulse signal of type Boolean"
  extends BooleanSignals.Interfaces.PartialClockedSO;
  parameter Integer widthTicks(min=1,max=periodTicks) = 1
  "Width of one pulse in clock ticks";
  parameter Integer periodTicks(min=1,start=1) = 2
  "Number of clock ticks for one period";
  parameter Integer startTick(min=1)=1
  "Clock tick at which the first pulse starts";

protected
  Integer counter(start=0);
  Boolean startOutput(start=false)
  "Flag whether counter >= startTick reached once";
equation
  // restart counter after reaching threshold to avoid integer overflow for long running simulations
  if previous(startOutput) then
      counter = if previous(counter) == (periodTicks-1) then 0 else previous(counter) + 1;
      startOutput = previous(startOutput);
  else
    startOutput = previous(counter) >= (startTick-1);
    counter = if startOutput then 0 else previous(counter) + 1;
  end if;

  y = startOutput and (counter < widthTicks);
end Pulse;


Generate step signal of type Boolean. The Boolean output y is a step signal. The signal is defined in terms of clock ticks instead of simulation time:

within Modelica.Clocked.BooleanSignals.TickBasedSources;
block Step "Generate step signal of type Boolean"
  extends BooleanSignals.Interfaces.PartialClockedSO;

  parameter Integer startTick = 0
    "Output y = startValue for clock tick < startTick";
  parameter Boolean startValue = false "Output before startTick";

protected
  Integer counter(start=0);
equation
  // stop counter after counter = startTick to avoid integer overflow for long running simulations
  counter = if previous(counter) < startTick then previous(counter) + 1 else previous(counter);
  y = if counter >= startTick then not startValue else startValue;
end Step;


within Modelica.Clocked.BooleanSignals;
package TimeBasedSources "Package of signal source blocks generating clocked simulation time based Boolean signals"
   extends Modelica.Icons.SourcesPackage;
end TimeBasedSources;


within Modelica.Clocked.BooleanSignals.TimeBasedSources;
block Pulse "Generate pulse signal of type Boolean"
  extends BooleanSignals.Interfaces.PartialClockedSO;
  parameter Real width(
    final min=Modelica.Constants.small,
    final max=100) = 50 "Width of pulse in % of period";
  parameter SI.Time period(final min=Modelica.Constants.small,start=1)
  "Time for one period";
  parameter SI.Time startTime=0
  "Time instant of first pulse";

protected
  SI.Time simTime;
  parameter SI.Duration Twidth=period*width/100
  "Width of one pulse"

  SI.Time next(start=startTime, fixed=true)
  "next = startTime + n*period, for smallest n such that next>simTime";
  SI.Duration tol = 0.1*interval(simTime) "Tolerance for numeric comparisons";
equation
    simTime = sample(time);
    next = if (simTime >= previous(next) - tol) then previous(next) + period else previous(next);
    y = simTime >= next - period - tol and simTime < next - period + Twidth - tol;
end Pulse;


Generate step signal of type Boolean. The block is similar to the block in Modelica.Blocks.Sources.BooleanStep,
but adapted to work in clocked partitions (by internal sampling of the continuous time variable).

within Modelica.Clocked.BooleanSignals.TimeBasedSources;
block Step "Generate step signal of type Boolean"
  extends BooleanSignals.Interfaces.PartialClockedSO;
  parameter SI.Time startTime=0 "Time instant of step start";
  parameter Boolean startValue = false "Output before startTime";
protected
  SI.Time simTime;
equation
  simTime = sample(time);
  y = if simTime >= startTime then not startValue else startValue;
end Step;


Library of blocks for clocked signals

within Modelica.Clocked;
package ClockSignals "Library of blocks for clocked signals"
  extends Modelica.Icons.Package;
  import Modelica.Units.SI;
end ClockSignals;