RetroArch/wii/wiiuse/nunchuk.c

158 lines
4.4 KiB
C

/* This source as presented is a modified version of original wiiuse for use
* with RetroArch, and must not be confused with the original software. */
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include "dynamics.h"
#include "definitions.h"
#include "wiiuse_internal.h"
#include "nunchuk.h"
#include "io.h"
/**
* @brief Find what buttons are pressed.
*
* @param nc Pointer to a nunchuk_t structure.
* @param msg The message byte specified in the event packet.
*/
static void nunchuk_pressed_buttons(struct nunchuk_t* nc, ubyte now) {
/* message is inverted (0 is active, 1 is inactive) */
now = ~now & NUNCHUK_BUTTON_ALL;
/* preserve old btns pressed */
nc->btns_last = nc->btns;
/* pressed now & were pressed, then held */
nc->btns_held = (now & nc->btns);
/* were pressed or were held & not pressed now, then released */
nc->btns_released = ((nc->btns | nc->btns_held) & ~now);
/* buttons pressed now */
nc->btns = now;
}
int nunchuk_handshake(struct wiimote_t *wm,struct nunchuk_t *nc,ubyte *data,uword len)
{
//int i;
int offset = 0;
nc->btns = 0;
nc->btns_held = 0;
nc->btns_released = 0;
nc->flags = &wm->flags;
nc->accel_calib = wm->accel_calib;
//for(i=0;i<len;i++) data[i] = (data[i]^0x17)+0x17;
if(data[offset]==0xff) {
if(data[offset+16]==0xff) {
// try to read the calibration data again
wiiuse_read_data(wm,data,WM_EXP_MEM_CALIBR,EXP_HANDSHAKE_LEN,wiiuse_handshake_expansion);
} else
offset += 16;
}
nc->accel_calib.cal_zero.x = (data[offset + 0]<<2)|((data[offset + 3]>>4)&3);
nc->accel_calib.cal_zero.y = (data[offset + 1]<<2)|((data[offset + 3]>>2)&3);
nc->accel_calib.cal_zero.z = (data[offset + 2]<<2)|(data[offset + 3]&3);
nc->accel_calib.cal_g.x = (data[offset + 4]<<2)|((data[offset + 7]>>4)&3);
nc->accel_calib.cal_g.y = (data[offset + 5]<<2)|((data[offset + 7]>>2)&3);
nc->accel_calib.cal_g.z = (data[offset + 6]<<2)|(data[offset + 7]&3);
nc->js.max.x = data[offset + 8];
nc->js.min.x = data[offset + 9];
nc->js.center.x = data[offset + 10];
nc->js.max.y = data[offset + 11];
nc->js.min.y = data[offset + 12];
nc->js.center.y = data[offset + 13];
// set to defaults (averages from 5 nunchuks) if calibration data is invalid
if(nc->accel_calib.cal_zero.x == 0)
nc->accel_calib.cal_zero.x = 499;
if(nc->accel_calib.cal_zero.y == 0)
nc->accel_calib.cal_zero.y = 509;
if(nc->accel_calib.cal_zero.z == 0)
nc->accel_calib.cal_zero.z = 507;
if(nc->accel_calib.cal_g.x == 0)
nc->accel_calib.cal_g.x = 703;
if(nc->accel_calib.cal_g.y == 0)
nc->accel_calib.cal_g.y = 709;
if(nc->accel_calib.cal_g.z == 0)
nc->accel_calib.cal_g.z = 709;
if(nc->js.max.x == 0)
nc->js.max.x = 223;
if(nc->js.min.x == 0)
nc->js.min.x = 27;
if(nc->js.center.x == 0)
nc->js.center.x = 126;
if(nc->js.max.y == 0)
nc->js.max.y = 222;
if(nc->js.min.y == 0)
nc->js.min.y = 30;
if(nc->js.center.y == 0)
nc->js.center.y = 131;
wm->event = WIIUSE_NUNCHUK_INSERTED;
wm->exp.type = EXP_NUNCHUK;
return 1;
}
/**
* @brief The nunchuk disconnected.
*
* @param nc A pointer to a nunchuk_t structure.
*/
void nunchuk_disconnected(struct nunchuk_t* nc)
{
//printf("nunchuk_disconnected()\n");
memset(nc, 0, sizeof(struct nunchuk_t));
}
/**
* @brief Handle nunchuk event.
*
* @param nc A pointer to a nunchuk_t structure.
* @param msg The message specified in the event packet.
*/
void nunchuk_event(struct nunchuk_t* nc, ubyte* msg) {
//int i;
/* decrypt data */
/*
for (i = 0; i < 6; ++i)
msg[i] = (msg[i] ^ 0x17) + 0x17;
*/
/* get button states */
nunchuk_pressed_buttons(nc, msg[5]);
nc->js.pos.x = msg[0];
nc->js.pos.y = msg[1];
/* extend min and max values to physical range of motion */
if (nc->js.center.x) {
if (nc->js.min.x > nc->js.pos.x) nc->js.min.x = nc->js.pos.x;
if (nc->js.max.x < nc->js.pos.x) nc->js.max.x = nc->js.pos.x;
}
if (nc->js.center.y) {
if (nc->js.min.y > nc->js.pos.y) nc->js.min.y = nc->js.pos.y;
if (nc->js.max.y < nc->js.pos.y) nc->js.max.y = nc->js.pos.y;
}
#ifndef GEKKO
/* calculate joystick state */
calc_joystick_state(&nc->js, nc->js.pos.x, nc->js.pos.y);
#endif
/* calculate orientation */
nc->accel.x = (msg[2]<<2) + ((msg[5]>>2)&3);
nc->accel.y = (msg[3]<<2) + ((msg[5]>>4)&3);
nc->accel.z = (msg[4]<<2) + ((msg[5]>>6)&3);
#ifndef GEKKO
calculate_orientation(&nc->accel_calib, &nc->accel, &nc->orient, NUNCHUK_IS_FLAG_SET(nc, WIIUSE_SMOOTHING));
calculate_gforce(&nc->accel_calib, &nc->accel, &nc->gforce);
#endif
}