aboutsummaryrefslogtreecommitdiffstats
path: root/src/hal/components/lincurve.comp
blob: 2c6306828aba70f557461ed422d68abffddec041 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
component lincurve "one-dimensional lookup table";
description """This component can be used to map any floating-point input to a
floating-point output. Typical uses would include linearisation of
thermocouples, defining PID gains that vary with external factors or to
substitute for any mathematical function where absolute accuracy is not
required.

The component can be thought of as a 2-dimensional graph of points in (x,y)
space joined by straight lines. The input value is located on the x axis,
followed up until it touches the line, and the output of the component is set
to the corresponding y-value.

The (x,y) points are defined by the x-val-NN and y-val-NN parameters which need
to be set in the HAL file using "setp" commands.

The maximum number if (x,y) points supported is 16.

For input values less than the x-val-00 breakpoint the y-val-00 is returned. 
For x greater than the largest x-val-NN the yval corresponding to x-max is
returned (ie, no extrapolation is performed.)

Sample usage: loadrt lincurve count=3 personality=4,4,4 
for a set of three 4-element graphs.
 """;

param rw float x-val-##[16 : personality] "axis breakpoints";
param rw float y-val-##[16 : personality] "output values to be interpolated";

pin in float in_ "The input value";
pin out float out_ "The output value";
pin io float out-io "The output value, compatible with PID gains";

variable unsigned i = 0;

option extra_setup 1;

author "Andy Pugh";
license "GPL";

function _;

;;

FUNCTION(_){
    double f, x;
    x = in_;
    if (x >= x_val(personality-1)) {
        out_ = y_val(personality-1);
        out_io = out_;
        return;
    }
    if (x <= x_val(0)) {
        out_ = y_val(0);
        out_io = out_;
        return;
    }
    while (x > x_val(i+1)) { i++;}
    while (x < (x_val(i))) { i--;}
    
    f = (x - x_val(i))/(x_val(i+1)-x_val(i));
    out_ = y_val(i) + f * (y_val(i+1) - y_val(i));
    out_io = out_;
}

EXTRA_SETUP(){
	if (personality > 16) personality = 16;
	if (personality < 2) personality = 2;
	return 0;
}
bues.ch cgit interface