cargo.map: Tweaks
[neverball] / share / tilt.c
1 /*
2  * Copyright (C) 2003 Robert Kooima
3  *
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.
8  *
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.
13  */
14
15 #include <SDL.h>
16 #include <SDL_thread.h>
17 #include <math.h>
18 #include <stdio.h>
19
20 #include "config.h"
21
22 /*---------------------------------------------------------------------------*/
23 #ifdef ENABLE_WII
24
25 #define _ENABLE_TILT
26 #include <libcwiimote/wiimote.h>
27 #include <libcwiimote/wiimote_api.h>
28
29 /*
30  * This data structure tracks button changes, counting transitions so that
31  * none are missed if the event handling thread falls significantly behind
32  * the device IO thread.
33  */
34
35 #define BUTTON_NC 0
36 #define BUTTON_DN 1
37 #define BUTTON_UP 2
38
39 struct button_state
40 {
41     unsigned char curr;
42     unsigned char last;
43     unsigned char upc;
44     unsigned char dnc;
45 };
46
47 static void set_button(struct button_state *B, int s)
48 {
49     if ((B->curr == 0) != (s == 0))
50     {
51         if (B->curr)
52         {
53             B->upc++;
54             B->curr = 0;
55         }
56         else
57         {
58             B->dnc++;
59             B->curr = 1;
60         }
61     }
62 }
63
64 static int get_button(struct button_state *B)
65 {
66     int ch = BUTTON_NC;
67
68     if      (B->last == 1 && B->upc > 0)
69     {
70         B->upc--;
71         B->last = 0;
72         ch = BUTTON_UP;
73     }
74     else if (B->last == 0 && B->dnc > 0)
75     {
76         B->dnc--;
77         B->last = 1;
78         ch = BUTTON_DN;
79     }
80
81     return ch;
82 }
83
84 /*---------------------------------------------------------------------------*/
85
86 struct tilt_state
87 {
88     int   status;
89     float x;
90     float z;
91     struct button_state A;
92     struct button_state B;
93     struct button_state plus;
94     struct button_state minus;
95     struct button_state home;
96     struct button_state L;
97     struct button_state R;
98     struct button_state U;
99     struct button_state D;
100 };
101
102 static struct tilt_state state;
103 static SDL_mutex        *mutex  = NULL;
104 static SDL_Thread       *thread = NULL;
105
106 #define FILTER 8
107
108 static int tilt_func(void *data)
109 {
110     wiimote_t wiimote = WIIMOTE_INIT;
111     char      address[MAXSTR];
112
113     config_get_s(CONFIG_WIIMOTE_ADDR, address, MAXSTR);
114
115     if (strlen(address) > 0)
116     {
117         if (wiimote_connect(&wiimote, address) < 0)
118             fprintf(stderr, "%s\n", wiimote_get_error());
119         else
120         {
121             int running = 1;
122
123             wiimote.mode.bits = WIIMOTE_MODE_ACC;
124             wiimote.led.one   = 1;
125
126             SDL_mutexP(mutex);
127             state.status = running;
128             SDL_mutexV(mutex);
129
130             while (mutex && running && wiimote_is_open(&wiimote))
131             {
132                 if (wiimote_update(&wiimote) < 0)
133                     break;
134
135                 SDL_mutexP(mutex);
136                 {
137                     running = state.status;
138
139                     set_button(&state.A,     wiimote.keys.a);
140                     set_button(&state.B,     wiimote.keys.b);
141                     set_button(&state.plus,  wiimote.keys.plus);
142                     set_button(&state.minus, wiimote.keys.minus);
143                     set_button(&state.home,  wiimote.keys.home);
144                     set_button(&state.L,     wiimote.keys.left);
145                     set_button(&state.R,     wiimote.keys.right);
146                     set_button(&state.U,     wiimote.keys.up);
147                     set_button(&state.D,     wiimote.keys.down);
148
149                     if (isnormal(wiimote.tilt.y))
150                     {
151                         state.x = (state.x * (FILTER - 1) +
152                                    wiimote.tilt.y) / FILTER;
153                     }
154                     if (isnormal(wiimote.tilt.x))
155                     {
156                         state.z = (state.z * (FILTER - 1) +
157                                    wiimote.tilt.x) / FILTER;
158                     }
159                 }
160                 SDL_mutexV(mutex);
161             }
162
163             wiimote_disconnect(&wiimote);
164         }
165     }
166     return 0;
167 }
168
169 void tilt_init(void)
170 {
171     memset(&state, 0, sizeof (struct tilt_state));
172
173     mutex  = SDL_CreateMutex();
174     thread = SDL_CreateThread(tilt_func, NULL);
175 }
176
177 void tilt_free(void)
178 {
179     int b = 0;
180
181     if (mutex)
182     {
183         /* Get/set the status of the tilt sensor thread. */
184
185         SDL_mutexP(mutex);
186         b = state.status;
187         state.status = 0;
188         SDL_mutexV(mutex);
189
190         /* Kill the thread and destroy the mutex. */
191
192         SDL_KillThread(thread);
193         SDL_DestroyMutex(mutex);
194
195         mutex  = NULL;
196         thread = NULL;
197     }
198 }
199
200 int tilt_get_button(int *b, int *s)
201 {
202     int ch = BUTTON_NC;
203
204     if (mutex)
205     {
206         SDL_mutexP(mutex);
207         {
208             if      ((ch = get_button(&state.A)))
209             {
210                 *b = config_get_d(CONFIG_JOYSTICK_BUTTON_A);
211                 *s = (ch == BUTTON_DN);
212             }
213             else if ((ch = get_button(&state.B)))
214             {
215                 *b = config_get_d(CONFIG_JOYSTICK_BUTTON_B);
216                 *s = (ch == BUTTON_DN);
217             }
218             else if ((ch = get_button(&state.plus)))
219             {
220                 *b = config_get_d(CONFIG_JOYSTICK_BUTTON_R);
221                 *s = (ch == BUTTON_DN);
222             }
223             else if ((ch = get_button(&state.minus)))
224             {
225                 *b = config_get_d(CONFIG_JOYSTICK_BUTTON_L);
226                 *s = (ch == BUTTON_DN);
227             }
228             else if ((ch = get_button(&state.home)))
229             {
230                 *b = config_get_d(CONFIG_JOYSTICK_BUTTON_EXIT);
231                 *s = (ch == BUTTON_DN);
232             }
233             else if ((ch = get_button(&state.L)))
234             {
235                 *b = config_get_d(CONFIG_JOYSTICK_DPAD_L);
236                 *s = (ch == BUTTON_DN);
237             }
238             else if ((ch = get_button(&state.R)))
239             {
240                 *b = config_get_d(CONFIG_JOYSTICK_DPAD_R);
241                 *s = (ch == BUTTON_DN);
242             }
243             else if ((ch = get_button(&state.U)))
244             {
245                 *b = config_get_d(CONFIG_JOYSTICK_DPAD_U);
246                 *s = (ch == BUTTON_DN);
247             }
248             else if ((ch = get_button(&state.D)))
249             {
250                 *b = config_get_d(CONFIG_JOYSTICK_DPAD_D);
251                 *s = (ch == BUTTON_DN);
252             }
253         }
254         SDL_mutexV(mutex);
255     }
256     return ch;
257 }
258
259 float tilt_get_x(void)
260 {
261     float x = 0.0f;
262
263     if (mutex)
264     {
265         SDL_mutexP(mutex);
266         x = state.x;
267         SDL_mutexV(mutex);
268     }
269
270     return x;
271 }
272
273 float tilt_get_z(void)
274 {
275     float z = 0.0f;
276
277     if (mutex)
278     {
279         SDL_mutexP(mutex);
280         z = state.z;
281         SDL_mutexV(mutex);
282     }
283
284     return z;
285 }
286
287 int tilt_stat(void)
288 {
289     int b = 0;
290
291     if (mutex)
292     {
293         SDL_mutexP(mutex);
294         b = state.status;
295         SDL_mutexV(mutex);
296     }
297     return b;
298 }
299
300 #endif
301 /*---------------------------------------------------------------------------*/
302 #ifndef ENABLE_WII
303
304 void tilt_init(void)
305 {
306 }
307
308 void tilt_free(void)
309 {
310 }
311
312 int tilt_stat(void)
313 {
314     return 0;
315 }
316
317 int  tilt_get_button(int *b, int *s)
318 {
319     return 0;
320 }
321
322 void tilt_get_direct(int *x, int *y)
323 {
324     *x = 1;
325     *y = 1;
326 }
327
328 float tilt_get_x(void)
329 {
330     return 0.0f;
331 }
332
333 float tilt_get_z(void)
334 {
335     return 0.0f;
336 }
337
338 #endif
339 /*---------------------------------------------------------------------------*/