
component hbridgev2 "generate driving signals for 2 PWM generators to drive an H-Bridge";
description """
Together with 2 PWM's, this comp can be used to drive a DC motor through an H-bridge.
If the H-bridge needs a PWM signal at full speed (e.g. for charge pumps), limit the
output value by setting maxout.
See also: http://en.wikipedia.org/wiki/H_bridge .

Two output pins, up and down. For positive inputs, the PWM/PDM driving signal appears on up, while down is low. For negative inputs, the driving signal on down, while up is low. Suitable for driving the two sides of an H-bridge to generate a bipolar output.

""";

pin_ptr in float  command "target speed, < 0: reverse, > 0: forward";
pin_ptr out float down   "driving value for PWM1, 0..maxout";
pin_ptr out float up     "driving value for PWM2, 0..maxout";
pin_ptr out bit   enable-out "output to enable both half-bridges";
pin_ptr in  bit   enable "let motor free run if false";
pin_ptr in  bit   brake  "brake motor if true; needs enable to be true";

pin_ptr io float maxout = 1.0 "limit for the up and down pins";
function _ fp;
license "GPL v2";
;;
#define MINIMUM(x, y) (((x) > (y))?(y):(x))

FUNCTION(_)
{
hal_float_t negcmd;

    if (gb(enable)) {
        if (gb(brake)) 
            {
            // motor DC brake
            sf(up, 0.0);
            sf(down, 0.0);
            sb(enable_out, true);
            } 
        else {
            // normal forward/reverse operation
            negcmd = gf(command) * - 1.0;
            if (gf(command) < 0.0) {
                sf(up, 0.0);
                sf(down, (hal_float_t)MINIMUM(negcmd, gf(maxout)));
                } 
            else {
                sf(up, (hal_float_t)MINIMUM(gf(command), (double)gf(maxout)));
                sf(down, 0.0);
                }
            sb(enable_out, true);
            }
        } 
    else {
        // let motor run freely
        sf(up, 0.0);
        sf(down, 0.0);
        sb(enable_out, false);
    }

    return 0;
}
