BooleanTable

block BooleanTable "Generate a Boolean output signal based on a vector of time instants"
    parameter Modelica.SIunits.Time table[:] = {0, 1} "Vector of time points. At every time point, the output y gets its opposite value (e.g., table={0,1})"
        annotation (Dialog(group = "Table data definition"));
    parameter Boolean startValue = false "Start value of y. At time = table[1], y changes to 'not startValue'"
        annotation (Dialog(
            group = "Table data interpretation",
            groupImage = "modelica://Modelica/Resources/Images/Blocks/Sources/BooleanTable.png"));
    parameter Modelica.Blocks.Types.Extrapolation extrapolation = Modelica.Blocks.Types.Extrapolation.HoldLastPoint "Extrapolation of data outside the definition range"
        annotation (Dialog(group = "Table data interpretation"));
    parameter Modelica.SIunits.Time startTime = -Modelica.Constants.inf "Output = false for time < startTime"
        annotation (Dialog(group = "Table data interpretation"));
    parameter Modelica.SIunits.Time shiftTime = 0 "Shift time of table"
        annotation (Dialog(group = "Table data interpretation"));

    extends Interfaces.partialBooleanSO;

    CombiTimeTable combiTimeTable(final table = if 0 < n then if startValue then [table[1],1; table,{mod(i + 1, 2) for i in 1:n}] else [table[1],0; table,{mod(i, 2) for i in 1:n}] else if startValue then [0,1] else [0,0], final smoothness = Modelica.Blocks.Types.Smoothness.ConstantSegments, final columns = {2}, final extrapolation = extrapolation, final startTime = startTime, final shiftTime = shiftTime) annotation (Placement(transformation(extent = {
        {-30, -10}, 
        {-10, 10}})));
    Modelica.Blocks.Math.RealToBoolean realToBoolean annotation (Placement(transformation(extent = {
        {10, -10}, 
        {30, 10}})));
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 0 < n then 
            for i in 2:n loop
                assert(table[i - 1] < table[i], "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) annotation (Line(
        points = {
            {-9, 0}, 
            {8, 0}},
        color = {0, 0, 127}));
    connect(realToBoolean.y,y) annotation (Line(
        points = {
            {31, 0}, 
            {110, 0}, 
            {110, 0}},
        color = {255, 127, 0}));

    annotation (
        Icon(
            coordinateSystem(
                preserveAspectRatio = true,
                extent = {
                    {-100, -100}, 
                    {100, 100}}),
            graphics = {
                Polygon(
                    points = {
                        {-80, 88}, 
                        {-88, 66}, 
                        {-72, 66}, 
                        {-80, 88}},
                    lineColor = {255, 0, 255},
                    fillColor = {255, 0, 255},
                    fillPattern = FillPattern.Solid), 
                Line(
                    points = {
                        {-80, 66}, 
                        {-80, -82}},
                    color = {255, 0, 255}), 
                Line(
                    points = {
                        {-90, -70}, 
                        {72, -70}},
                    color = {255, 0, 255}), 
                Polygon(
                    points = {
                        {90, -70}, 
                        {68, -62}, 
                        {68, -78}, 
                        {90, -70}},
                    lineColor = {255, 0, 255},
                    fillColor = {255, 0, 255},
                    fillPattern = FillPattern.Solid), 
                Rectangle(
                    extent = {
                        {-18, 70}, 
                        {32, -50}},
                    lineColor = {255, 255, 255},
                    fillColor = {192, 192, 192},
                    fillPattern = FillPattern.Solid), 
                Line(points = {
                    {-18, -50}, 
                    {-18, 70}, 
                    {32, 70}, 
                    {32, -50}, 
                    {-18, -50}, 
                    {-18, -20}, 
                    {32, -20}, 
                    {32, 10}, 
                    {-18, 10}, 
                    {-18, 40}, 
                    {32, 40}, 
                    {32, 70}, 
                    {32, 70}, 
                    {32, -51}})}),
        Documentation(info = "<html>\n<p>\nThe Boolean output y is a signal defined by parameter vector <strong>table</strong>.\nIn the vector time points are stored.\nThe table interpolation has the following properties:\n</p>\n\n<ul>\n<li>At every time point, the output y\n    changes its value to the negated value of the previous one.</li>\n<li>Values <strong>outside</strong> of the table range, are computed by\n    extrapolation according to the setting of parameter <strong>extrapolation</strong>:\n<pre>\n  extrapolation = 1: Hold the <strong>startValue</strong> or last value of the table,\n                     if outside of the table scope.\n                = 2: Extrapolate by using the derivative at the first/last table\n                     points if outside of the table scope.\n                     (This setting is not suitable and triggers an assert.)\n                = 3: Periodically repeat the table data (periodical function).\n                = 4: No extrapolation, i.e. extrapolation triggers an error\n</pre></li>\n<li>Via parameter <strong>shiftTime</strong> the curve defined by the table can be shifted\n    in time.\n    The time instants stored in the table are therefore <strong>relative</strong>\n    to <strong>shiftTime</strong>.</li>\n<li>If time &lt; startTime, no interpolation is performed and <strong>false</strong>\n    is used as ordinate value for the output.</li>\n</ul>\n\n<p>\n<img src=\"modelica://Modelica/Resources/Images/Blocks/Sources/BooleanTable.png\"\n     alt=\"BooleanTable.png\">\n</p>\n\n<p>\nThe precise semantics is:\n</p>\n\n<pre>\n  <strong>if</strong> size(table,1) == 0 <strong>then</strong>\n     y = startValue;\n  <strong>else</strong>\n     //            time &lt; table[1]: y = startValue\n     // table[1] &le; time &lt; table[2]: y = not startValue\n     // table[2] &le; time &lt; table[3]: y = startValue\n     // table[3] &le; time &lt; table[4]: y = not startValue\n     // ...\n  <strong>end if</strong>;\n</pre>\n</html>"));
end BooleanTable;