2 * Copyright (C) 2010 Neverball authors
4 * NEVERBALL is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published
6 * by the Free Software Foundation; either version 2 of the License,
7 * or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
16 #include <SDL_thread.h>
22 /*---------------------------------------------------------------------------*/
24 /* FIXME: I did not copy paste this from tilt_wii.c, I swear! */
27 * This data structure tracks button changes, counting transitions so that
28 * none are missed if the event handling thread falls significantly behind
29 * the device IO thread.
44 static void set_button(struct button_state *B, int s)
46 if ((B->curr == 0) != (s == 0))
61 static int get_button(struct button_state *B)
65 if (B->last == 1 && B->upc > 0)
71 else if (B->last == 0 && B->dnc > 0)
81 /*---------------------------------------------------------------------------*/
88 struct button_state A;
89 struct button_state B;
90 struct button_state plus;
91 struct button_state minus;
92 struct button_state home;
93 struct button_state L;
94 struct button_state R;
95 struct button_state U;
96 struct button_state D;
99 static struct tilt_state state;
100 static SDL_mutex *mutex = NULL;
101 static SDL_Thread *thread = NULL;
103 /*---------------------------------------------------------------------------*/
105 #include "freespace/freespace.h"
106 #include "freespace/freespace_codecs.h"
112 static int tilt_func(void *data)
114 FreespaceDeviceId deviceId;
115 uint8_t buffer[FREESPACE_MAX_OUTPUT_MESSAGE_SIZE];
118 struct freespace_DataMotionControl d;
119 struct freespace_UserFrame userFrame;
125 float eulerAngles[3];
128 rc = freespace_getDeviceList(&deviceId, 1, &numIds);
133 rc = freespace_openDevice(deviceId);
134 if (rc != FREESPACE_SUCCESS) {
138 rc = freespace_flush(deviceId);
139 if (rc != FREESPACE_SUCCESS) {
143 d.enableBodyMotion = 0;
144 d.enableUserPosition = 1;
145 d.inhibitPowerManager = 0;
146 d.enableMouseMovement = 1;
147 d.disableFreespace = 0;
148 rc = freespace_encodeDataMotionControl(&d, buffer, sizeof(buffer));
150 rc = freespace_send(deviceId, buffer, rc);
151 if (rc != FREESPACE_SUCCESS) {
158 state.status = running;
161 while (mutex && running)
164 running = state.status;
167 rc = freespace_read(deviceId, buffer, FREESPACE_MAX_INPUT_MESSAGE_SIZE, 100, &length);
168 if (rc != FREESPACE_SUCCESS) {
176 if (freespace_decodeUserFrame(buffer, length, &userFrame) == FREESPACE_SUCCESS) {
177 /* Hillcrest quaternion is rotate the world type, so make it rotate the object type by conjugating*/
178 quat[0] = userFrame.angularPosA;
179 quat[1] = -userFrame.angularPosB;
180 quat[2] = -userFrame.angularPosC;
181 quat[3] = -userFrame.angularPosD;
184 /* This function does euler decomposition for rotate the object type (ZYX, aerospace) */
185 q_euler(eulerAngles, quat);
189 /* Since the game expects "rotate the world type", conjugate by negating all angles & convert to degrees
193 z = -eulerAngles[0] * 57.2957795;
194 y = -eulerAngles[1] * 57.2957795;
195 x = -eulerAngles[2] * 57.2957795;
197 state.x = y * DAMPENING;
198 state.z = -x * DAMPENING;
200 set_button(&state.home, userFrame.button3);
201 set_button(&state.U, userFrame.deltaWheel > 0);
202 set_button(&state.D, userFrame.deltaWheel < 0);
209 freespace_closeDevice(deviceId);
215 memset(&state, 0, sizeof (struct tilt_state));
219 mutex = SDL_CreateMutex();
220 thread = SDL_CreateThread(tilt_func, NULL);
229 /* Get/set the status of the tilt sensor thread. */
236 /* Kill the thread and destroy the mutex. */
238 SDL_WaitThread(thread, &b);
239 SDL_DestroyMutex(mutex);
248 int tilt_get_button(int *b, int *s)
256 if ((ch = get_button(&state.A)))
258 *b = config_get_d(CONFIG_JOYSTICK_BUTTON_A);
259 *s = (ch == BUTTON_DN);
261 else if ((ch = get_button(&state.B)))
263 *b = config_get_d(CONFIG_JOYSTICK_BUTTON_B);
264 *s = (ch == BUTTON_DN);
266 else if ((ch = get_button(&state.home)))
268 *b = config_get_d(CONFIG_JOYSTICK_BUTTON_EXIT);
269 *s = (ch == BUTTON_DN);
271 else if ((ch = get_button(&state.U)))
273 *b = config_get_d(CONFIG_JOYSTICK_DPAD_U);
274 *s = (ch == BUTTON_DN);
276 else if ((ch = get_button(&state.D)))
278 *b = config_get_d(CONFIG_JOYSTICK_DPAD_D);
279 *s = (ch == BUTTON_DN);
287 float tilt_get_x(void)
301 float tilt_get_z(void)
328 /*---------------------------------------------------------------------------*/