/******************************************************************************
 *
 * Copyright (C) 2015 Alexander Rössler
 *
 *
 * This module acts as multiplexing gate for IO sinnals
 *
 ******************************************************************************
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 * 02110-1301, USA.
 *
 * THE AUTHORS OF THIS PROGRAM ACCEPT ABSOLUTELY NO LIABILITY FOR
 * ANY HARM OR LOSS RESULTING FROM ITS USE.  IT IS _EXTREMELY_ UNWISE
 * TO RELY ON SOFTWARE ALONE FOR SAFETY.  Any machinery capable of
 * harming persons must have provisions for completely removing power
 * from all motors, etc, before persons enter any danger area.  All
 * machinery must be designed to comply with local and national safety
 * codes, and the authors of this software can not, and do not, take
 * any responsibility for such compliance.
 *
 * This code was written as part of the LinuxCNC project.  For more
 * information, go to www.linuxcnc.org.
 *
 ******************************************************************************/
component io_muxnv2 "Gate one of N input values";
pin_ptr in s32 sel = 0;
pin_ptr io float out "Follows the value of \\fBin<M>\\fR whereas M is the value of the \\fBsel\\fR input. \
If \\fBsel\\fR is not in the range of available inputs 0 is output.";
pin_ptr io float in#.[pincount];

variable hal_s32_t last_sel = -1; // will apply input to output on start-up
variable hal_float_t last_in = 0.0;
variable hal_float_t last_out = 0.0;

instanceparam int pincount = 2;

option MAXCOUNT 16;

function _ fp;
license "GPL";
author "Alexander Roessler";
;;
FUNCTION(_)
{
    if ((gs(sel) < 0) || (gs(sel) >= local_pincount))
    {
        return 0; // incorrect sel, we change nothing
    }

    if (gs(sel) != last_sel)
    {
        sf(out, gf(in_(gs(sel))));
        last_sel = gs(sel);
        last_out = gf(out);
        last_in = gf(in_(gs(sel)));
    }
    else
    {
        if (last_out != gf(out))
        {
            sf(in_(gs(sel)), gf(out));
            last_out = gf(out);
            last_in = gf(out);
        }
        else if (last_in != gf(in_(gs(sel))))
        {
            sf(out, gf(in_(gs(sel))));
            last_in = gf(in_(gs(sel)));
            last_out = gf(in_(gs(sel)));
        }
    }

    return 0;
}
