5 * Michael Laforest < para >
6 * Email: < thepara (--AT--) g m a i l [--DOT--] com >
10 * This file is part of wiiuse.
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 3 of the License, or
15 * (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program. If not, see <http://www.gnu.org/licenses/>.
25 * $Header: /lvm/shared/ds/ds/cvs/devkitpro-cvsbackup/libogc/wiiuse/dynamics.c,v 1.2 2008-11-14 13:34:57 shagkur Exp $
31 * @brief Handles the dynamics of the wiimote.
33 * The file includes functions that handle the dynamics
34 * of the wiimote. Such dynamics include orientation and
46 #include "definitions.h"
47 #include "wiiuse_internal.h"
52 * @brief Calculate the roll, pitch, yaw.
54 * @param ac An accelerometer (accel_t) structure.
55 * @param accel [in] Pointer to a vec3w_t structure that holds the raw acceleration data.
56 * @param orient [out] Pointer to a orient_t structure that will hold the orientation data.
57 * @param rorient [out] Pointer to a orient_t structure that will hold the non-smoothed orientation data.
58 * @param smooth If smoothing should be performed on the angles calculated. 1 to enable, 0 to disable.
60 * Given the raw acceleration data from the accelerometer struct, calculate
61 * the orientation of the device and set it in the \a orient parameter.
63 void calculate_orientation(struct accel_t
* ac
, struct vec3w_t
* accel
, struct orient_t
* orient
, int smooth
) {
68 * roll - use atan(z / x) [ ranges from -180 to 180 ]
69 * pitch - use atan(z / y) [ ranges from -180 to 180 ]
70 * yaw - impossible to tell without IR
73 /* yaw - set to 0, IR will take care of it if it's enabled */
76 /* find out how much it has to move to be 1g */
77 xg
= (float)ac
->cal_g
.x
;
78 yg
= (float)ac
->cal_g
.y
;
79 zg
= (float)ac
->cal_g
.z
;
81 /* find out how much it actually moved and normalize to +/- 1g */
82 x
= ((float)accel
->x
- (float)ac
->cal_zero
.x
) / xg
;
83 y
= ((float)accel
->y
- (float)ac
->cal_zero
.y
) / yg
;
84 z
= ((float)accel
->z
- (float)ac
->cal_zero
.z
) / zg
;
86 /* make sure x,y,z are between -1 and 1 for the tan functions */
87 if (x
< -1.0f
) x
= -1.0f
;
88 else if (x
> 1.0f
) x
= 1.0f
;
89 if (y
< -1.0f
) y
= -1.0f
;
90 else if (y
> 1.0f
) y
= 1.0f
;
91 if (z
< -1.0f
) z
= -1.0f
;
92 else if (z
> 1.0f
) z
= 1.0f
;
94 /* if it is over 1g then it is probably accelerating and not reliable */
95 if (abs(accel
->x
- ac
->cal_zero
.x
) <= (ac
->cal_g
.x
+10)) {
97 x
= RAD_TO_DEGREE(atan2f(x
, z
));
104 if (abs(accel
->y
- ac
->cal_zero
.y
) <= (ac
->cal_g
.y
+10)) {
106 y
= RAD_TO_DEGREE(atan2f(y
, z
));
113 /* smooth the angles if enabled */
115 apply_smoothing(ac
, orient
, SMOOTH_ROLL
);
116 apply_smoothing(ac
, orient
, SMOOTH_PITCH
);
122 * @brief Calculate the gravity forces on each axis.
124 * @param ac An accelerometer (accel_t) structure.
125 * @param accel [in] Pointer to a vec3w_t structure that holds the raw acceleration data.
126 * @param gforce [out] Pointer to a gforce_t structure that will hold the gravity force data.
128 void calculate_gforce(struct accel_t
* ac
, struct vec3w_t
* accel
, struct gforce_t
* gforce
) {
131 /* find out how much it has to move to be 1g */
132 xg
= (float)ac
->cal_g
.x
;
133 yg
= (float)ac
->cal_g
.y
;
134 zg
= (float)ac
->cal_g
.z
;
136 /* find out how much it actually moved and normalize to +/- 1g */
137 gforce
->x
= ((float)accel
->x
- (float)ac
->cal_zero
.x
) / xg
;
138 gforce
->y
= ((float)accel
->y
- (float)ac
->cal_zero
.y
) / yg
;
139 gforce
->z
= ((float)accel
->z
- (float)ac
->cal_zero
.z
) / zg
;
144 * @brief Calculate the angle and magnitude of a joystick.
146 * @param js [out] Pointer to a joystick_t structure.
147 * @param x The raw x-axis value.
148 * @param y The raw y-axis value.
150 void calc_joystick_state(struct joystick_t
* js
, float x
, float y
) {
154 * Since the joystick center may not be exactly:
156 * Then the range from the min to the center and the center to the max
158 * Because of this, depending on if the current x or y value is greater
159 * or less than the assoicated axis center value, it needs to be interpolated
160 * between the center and the minimum or maxmimum rather than between
161 * the minimum and maximum.
163 * So we have something like this:
164 * (x min) [-1] ---------*------ [0] (x center) [0] -------- [1] (x max)
165 * Where the * is the current x value.
166 * The range is therefore -1 to 1, 0 being the exact center rather than
167 * the middle of min and max.
169 if (x
== js
->center
.x
)
171 else if (x
>= js
->center
.x
)
172 rx
= ((float)(x
- js
->center
.x
) / (float)(js
->max
.x
- js
->center
.x
));
174 rx
= ((float)(x
- js
->min
.x
) / (float)(js
->center
.x
- js
->min
.x
)) - 1.0f
;
176 if (y
== js
->center
.y
)
178 else if (y
>= js
->center
.y
)
179 ry
= ((float)(y
- js
->center
.y
) / (float)(js
->max
.y
- js
->center
.y
));
181 ry
= ((float)(y
- js
->min
.y
) / (float)(js
->center
.y
- js
->min
.y
)) - 1.0f
;
183 /* calculate the joystick angle and magnitude */
184 ang
= RAD_TO_DEGREE(atanf(ry
/ rx
));
189 js
->mag
= (float) sqrt((rx
* rx
) + (ry
* ry
));
193 void apply_smoothing(struct accel_t
* ac
, struct orient_t
* orient
, int type
) {
197 /* it's possible last iteration was nan or inf, so set it to 0 if that happened */
198 if (isnan(ac
->st_roll
) || isinf(ac
->st_roll
))
202 * If the sign changes (which will happen if going from -180 to 180)
203 * or from (-1 to 1) then don't smooth, just use the new angle.
205 if (((ac
->st_roll
< 0) && (orient
->roll
> 0)) || ((ac
->st_roll
> 0) && (orient
->roll
< 0))) {
206 ac
->st_roll
= orient
->roll
;
208 orient
->roll
= ac
->st_roll
+ (ac
->st_alpha
* (orient
->a_roll
- ac
->st_roll
));
209 ac
->st_roll
= orient
->roll
;
217 if (isnan(ac
->st_pitch
) || isinf(ac
->st_pitch
))
220 if (((ac
->st_pitch
< 0) && (orient
->pitch
> 0)) || ((ac
->st_pitch
> 0) && (orient
->pitch
< 0))) {
221 ac
->st_pitch
= orient
->pitch
;
223 orient
->pitch
= ac
->st_pitch
+ (ac
->st_alpha
* (orient
->a_pitch
- ac
->st_pitch
));
224 ac
->st_pitch
= orient
->pitch
;
232 void calc_balanceboard_state(struct wii_board_t
*wb
)
236 Calculations borrowed from wiili.org - No names to mention sadly :( http://www.wiili.org/index.php/Wii_Balance_Board_PC_Drivers
239 if(wb
->rtr
<wb
->ctr
[1])
241 wb
->tr
= 17.0f
*(f32
)(wb
->rtr
-wb
->ctr
[0])/(f32
)(wb
->ctr
[1]-wb
->ctr
[0]);
245 wb
->tr
= 17.0f
*(f32
)(wb
->rtr
-wb
->ctr
[1])/(f32
)(wb
->ctr
[2]-wb
->ctr
[1]) + 17.0f
;
248 if(wb
->rtl
<wb
->ctl
[1])
250 wb
->tl
= 17.0f
*(f32
)(wb
->rtl
-wb
->ctl
[0])/(f32
)(wb
->ctl
[1]-wb
->ctl
[0]);
254 wb
->tl
= 17.0f
*(f32
)(wb
->rtl
-wb
->ctl
[1])/(f32
)(wb
->ctl
[2]-wb
->ctl
[1]) + 17.0f
;
257 if(wb
->rbr
<wb
->cbr
[1])
259 wb
->br
= 17.0f
*(f32
)(wb
->rbr
-wb
->cbr
[0])/(f32
)(wb
->cbr
[1]-wb
->cbr
[0]);
263 wb
->br
= 17.0f
*(f32
)(wb
->rbr
-wb
->cbr
[1])/(f32
)(wb
->cbr
[2]-wb
->cbr
[1]) + 17.0f
;
266 if(wb
->rbl
<wb
->cbl
[1])
268 wb
->bl
= 17.0f
*(f32
)(wb
->rbl
-wb
->cbl
[0])/(f32
)(wb
->cbl
[1]-wb
->cbl
[0]);
272 wb
->bl
= 17.0f
*(f32
)(wb
->rbl
-wb
->cbl
[1])/(f32
)(wb
->cbl
[2]-wb
->cbl
[1]) + 17.0f
;
275 wb
->x
= ((wb
->tr
+wb
->br
) - (wb
->tl
+wb
->bl
))/2.0f
;
276 wb
->y
= ((wb
->bl
+wb
->br
) - (wb
->tl
+wb
->tr
))/2.0f
;