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