enable large file support on Wii. used by tinysmb.
[libogc.git] / wiiuse / nunchuk.c
blob950c0eeb5703262a1bfeb42dbf2d90180cffb7f3
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <math.h>
4 #include <string.h>
6 #include "dynamics.h"
7 #include "definitions.h"
8 #include "wiiuse_internal.h"
9 #include "nunchuk.h"
10 #include "io.h"
12 /**
13 * @brief Find what buttons are pressed.
15 * @param nc Pointer to a nunchuk_t structure.
16 * @param msg The message byte specified in the event packet.
18 static void nunchuk_pressed_buttons(struct nunchuk_t* nc, ubyte now) {
19 /* message is inverted (0 is active, 1 is inactive) */
20 now = ~now & NUNCHUK_BUTTON_ALL;
22 /* preserve old btns pressed */
23 nc->btns_last = nc->btns;
25 /* pressed now & were pressed, then held */
26 nc->btns_held = (now & nc->btns);
28 /* were pressed or were held & not pressed now, then released */
29 nc->btns_released = ((nc->btns | nc->btns_held) & ~now);
31 /* buttons pressed now */
32 nc->btns = now;
35 int nunchuk_handshake(struct wiimote_t *wm,struct nunchuk_t *nc,ubyte *data,uword len)
37 //int i;
38 int offset = 0;
40 nc->btns = 0;
41 nc->btns_held = 0;
42 nc->btns_released = 0;
43 nc->flags = &wm->flags;
44 nc->accel_calib = wm->accel_calib;
46 //for(i=0;i<len;i++) data[i] = (data[i]^0x17)+0x17;
47 if(data[offset]==0xff) {
48 if(data[offset+16]==0xff) {
49 // try to read the calibration data again
50 wiiuse_read_data(wm,data,WM_EXP_MEM_CALIBR,EXP_HANDSHAKE_LEN,wiiuse_handshake_expansion);
51 } else
52 offset += 16;
55 nc->accel_calib.cal_zero.x = (data[offset + 0]<<2)|((data[offset + 3]>>4)&3);
56 nc->accel_calib.cal_zero.y = (data[offset + 1]<<2)|((data[offset + 3]>>2)&3);
57 nc->accel_calib.cal_zero.z = (data[offset + 2]<<2)|(data[offset + 3]&3);
58 nc->accel_calib.cal_g.x = (data[offset + 4]<<2)|((data[offset + 7]>>4)&3);
59 nc->accel_calib.cal_g.y = (data[offset + 5]<<2)|((data[offset + 7]>>2)&3);
60 nc->accel_calib.cal_g.z = (data[offset + 6]<<2)|(data[offset + 7]&3);
61 nc->js.max.x = data[offset + 8];
62 nc->js.min.x = data[offset + 9];
63 nc->js.center.x = data[offset + 10];
64 nc->js.max.y = data[offset + 11];
65 nc->js.min.y = data[offset + 12];
66 nc->js.center.y = data[offset + 13];
68 // set to defaults (averages from 5 nunchuks) if calibration data is invalid
69 if(nc->accel_calib.cal_zero.x == 0)
70 nc->accel_calib.cal_zero.x = 499;
71 if(nc->accel_calib.cal_zero.y == 0)
72 nc->accel_calib.cal_zero.y = 509;
73 if(nc->accel_calib.cal_zero.z == 0)
74 nc->accel_calib.cal_zero.z = 507;
75 if(nc->accel_calib.cal_g.x == 0)
76 nc->accel_calib.cal_g.x = 703;
77 if(nc->accel_calib.cal_g.y == 0)
78 nc->accel_calib.cal_g.y = 709;
79 if(nc->accel_calib.cal_g.z == 0)
80 nc->accel_calib.cal_g.z = 709;
81 if(nc->js.max.x == 0)
82 nc->js.max.x = 223;
83 if(nc->js.min.x == 0)
84 nc->js.min.x = 27;
85 if(nc->js.center.x == 0)
86 nc->js.center.x = 126;
87 if(nc->js.max.y == 0)
88 nc->js.max.y = 222;
89 if(nc->js.min.y == 0)
90 nc->js.min.y = 30;
91 if(nc->js.center.y == 0)
92 nc->js.center.y = 131;
94 wm->event = WIIUSE_NUNCHUK_INSERTED;
95 wm->exp.type = EXP_NUNCHUK;
97 return 1;
101 * @brief The nunchuk disconnected.
103 * @param nc A pointer to a nunchuk_t structure.
105 void nunchuk_disconnected(struct nunchuk_t* nc)
107 //printf("nunchuk_disconnected()\n");
108 memset(nc, 0, sizeof(struct nunchuk_t));
112 * @brief Handle nunchuk event.
114 * @param nc A pointer to a nunchuk_t structure.
115 * @param msg The message specified in the event packet.
117 void nunchuk_event(struct nunchuk_t* nc, ubyte* msg) {
118 //int i;
120 /* decrypt data */
122 for (i = 0; i < 6; ++i)
123 msg[i] = (msg[i] ^ 0x17) + 0x17;
125 /* get button states */
126 nunchuk_pressed_buttons(nc, msg[5]);
128 nc->js.pos.x = msg[0];
129 nc->js.pos.y = msg[1];
131 /* extend min and max values to physical range of motion */
132 if (nc->js.center.x) {
133 if (nc->js.min.x > nc->js.pos.x) nc->js.min.x = nc->js.pos.x;
134 if (nc->js.max.x < nc->js.pos.x) nc->js.max.x = nc->js.pos.x;
136 if (nc->js.center.y) {
137 if (nc->js.min.y > nc->js.pos.y) nc->js.min.y = nc->js.pos.y;
138 if (nc->js.max.y < nc->js.pos.y) nc->js.max.y = nc->js.pos.y;
141 #ifndef GEKKO
142 /* calculate joystick state */
143 calc_joystick_state(&nc->js, nc->js.pos.x, nc->js.pos.y);
144 #endif
145 /* calculate orientation */
146 nc->accel.x = (msg[2]<<2) + ((msg[5]>>2)&3);
147 nc->accel.y = (msg[3]<<2) + ((msg[5]>>4)&3);
148 nc->accel.z = (msg[4]<<2) + ((msg[5]>>6)&3);
149 #ifndef GEKKO
150 calculate_orientation(&nc->accel_calib, &nc->accel, &nc->orient, NUNCHUK_IS_FLAG_SET(nc, WIIUSE_SMOOTHING));
151 calculate_gforce(&nc->accel_calib, &nc->accel, &nc->gforce);
152 #endif