summaryrefslogtreecommitdiff
path: root/src/hal/components/joyhandle.comp
blob: 055541e491cc5fa50c2ae1702ec607626bf7a7dd (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
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
//   This is a component for EMC2 HAL
//   Copyright 2008 Paul Willutzki <paul[at]willutzki[dot]de>
//
//   This program is free software; you can redistribute it and/or
//   modify it under the terms of version 2 of the GNU General
//   Public License as published by the Free Software Foundation.
//
//   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

component joyhandle "sets nonlinear joypad movements, deadbands and scales";
pin in float in;
pin out float out;
param rw float power = 2.0;
param rw float deadband = 0.;
param rw float scale = 1.;
param rw float offset = 0.;
param rw bit inverse = 0;	

description """
The component \\fBjoyhandle\\fR uses the following formula for a non linear joypad movements:

\\fBy = (scale * (a*x^power + b*x)) + offset\\fR

The parameters a and b are adjusted in such a way, that the function starts at (deadband,offset) and ends at (1,scale+offset).

Negative values will be treated point symetrically to origin. Values -deadband < x < +deadband will be set to zero.

Values x > 1 and x < -1 will be skipped to \\(+-(scale+offset). Invert transforms the function to a progressive movement.

With power one can adjust the nonlinearity (default = 2). Default for deadband is 0.

Valid values are: power >= 1.0 (reasonable values are 1.x .. 4-5, take higher power-values for higher deadbands (>0.5), if you want to start with a nearly horizontal slope), 0 <= deadband < 0.99 (reasonable 0.1).

An additional offset component can be set in special cases (default = 0).

All values can be adjusted for each instance separately.
""";

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

FUNCTION(_) {
double p,a,b,alin,clin,xm,ym,xinv,yinv;

if (power < 1.0) power =1.0;

if (deadband >= 0.99) deadband = 0.99;
else if (deadband <= 0.) deadband = 0.;

p = power - 1.;
a = -1./(pow(deadband,p)-1.);
b = 1. - a;
alin = -scale/(deadband-1);
clin = 1.*(scale+offset-alin);

if (in >= 1.) out = scale + offset;
else if ((in <= deadband) && (in >= (-1*deadband))) out = 0.;
else if (in <= -1.) out = -scale - offset;
else if ((in > deadband) && (in < 1.))
    {
	if (power == 1.) out=alin*in + clin;
 	else {
		if (inverse == 0) out = scale*(a*pow(in,power) + b*in) + offset;
		else {
			xm = (deadband+1)/2;
        		ym = alin*xm + clin;
        		xinv = 2*xm-in;
        		yinv = scale*(a*pow(xinv,power) + b*xinv) + offset;
        		out =2*ym-yinv;
		     }
	     }
     }
else if ((in < (-1.*deadband)) && (in > -1.))
    {
	if (power == 1.) out=-1.*(alin*-1.*in + clin);
 	else {
		if (inverse == 0) out = -1*(scale*(a*pow((-1.*in),power) - b*in) + offset);
		else {
			xm = (deadband+1)/2;
        		ym = alin*xm + clin;
        		xinv = 2*xm+in;
        		yinv = scale*(a*pow(xinv,power) + b*xinv) + offset;
        		out =-2*ym-yinv;
		     }
	     }
     }
else out = 0.;
 
// out = scale*(a*pow(in,power) + b*in) + offset;
}