component xhc_hb04_utilv2 "xhc-hb04 convenience utility";
description """Provides logic for a start/pause button and an interface
to halui.program.is_paused,is_idle,is_running to generate outputs for
halui.program.pause,resume,run.

Includes 4 simple lowpass filters with coef and scale pins.  The coef value should
be 0 <= coef <=1, smaller coef values slow response.  Note: the xhc_hb04
component includes smoothing so these values can usually be left at 1.0
""";

pin_ptr in bit      start_or_pause;
pin_ptr in bit      is_paused;
pin_ptr in bit      is_idle;
pin_ptr in bit      is_running;
pin_ptr out bit     pause;
pin_ptr out bit     resume;
pin_ptr out bit     run;

// integer low pass filters (see ilowpass.comp)
pin_ptr in s32      in0;
pin_ptr in s32      in1;
pin_ptr in s32      in2;
pin_ptr in s32      in3;
pin_ptr out s32     out0;
pin_ptr out s32     out1;
pin_ptr out s32     out2;
pin_ptr out s32     out3;
pin_ptr in float    scale0 = 1.0;
pin_ptr in float    scale1 = 1.0;
pin_ptr in float    scale2 = 1.0;
pin_ptr in float    scale3 = 1.0;
pin_ptr in float    coef0 = 1.0;
pin_ptr in float    coef1 = 1.0;
pin_ptr in float    coef2 = 1.0;
pin_ptr in float    coef3 = 1.0;

variable hal_float_t value0 = 0.0;
variable hal_float_t value1 = 0.0;
variable hal_float_t value2 = 0.0;
variable hal_float_t value3 = 0.0;
variable hal_bit_t old_start_or_pause = false;

function _;
license "GPL";
;;
#include "rtapi_math.h"

FUNCTION(_)
{
    // protect so that 0 <= coef <= 1
    value0 += (gs(in0) - value0) * (rtapi_fabs(gf(coef0)) < 1 ? rtapi_fabs(gf(coef0)) : 1);
    value1 += (gs(in1) - value1) * (rtapi_fabs(gf(coef1)) < 1 ? rtapi_fabs(gf(coef1)) : 1);
    value2 += (gs(in2) - value2) * (rtapi_fabs(gf(coef2)) < 1 ? rtapi_fabs(gf(coef2)) : 1);
    value3 += (gs(in3) - value3) * (rtapi_fabs(gf(coef3)) < 1 ? rtapi_fabs(gf(coef3)) : 1);

    ss(out0, rtapi_ceil(value0 - .5) * gf(scale0));
    ss(out1, rtapi_ceil(value1 - .5) * gf(scale1));
    ss(out2, rtapi_ceil(value2 - .5) * gf(scale2));
    ss(out3, rtapi_ceil(value3 - .5) * gf(scale3));

    if (old_start_or_pause == gb(start_or_pause))
        return 0;
    old_start_or_pause = gb(start_or_pause);
    if (!gb(start_or_pause))
        {
        sb(pause, false);
        sb(run, false);
        sb(resume, false);
        return 0;
        }
    if (gb(is_paused))  {sb(pause, false); sb(run, false); sb(resume, true); }
    if (gb(is_running)) {sb(pause, true);  sb(run, false); sb(resume, false); }
    if (gb(is_idle))    {sb(pause, false); sb(run, true); sb(resume, false); }

    return 0;
}
