WIP: checkpoint Wii native IMU and upstream IR bridge
Pause Wii pointing work with firmware 0.33-wii-trace installed. Preserve the pinned libogc IR pipeline, calibrated native IMU, software BOOTSEL, and standard camera sensitivity trial. Tracking instability, tracking loss, and ineffective vertical movement remain unresolved. Level-2 camera filtering is not hardware-qualified. Nine targeted regression tests pass; firmware and persistent storage were verified after flashing.
This commit is contained in:
parent
3040c9d294
commit
9f6dddb790
41 changed files with 7990 additions and 150 deletions
55
external/libogc_ir/upstream/definitions.h
vendored
Normal file
55
external/libogc_ir/upstream/definitions.h
vendored
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
#ifndef __DEFINITIONS_H__
|
||||
#define __DEFINITIONS_H__
|
||||
|
||||
#include "os.h"
|
||||
|
||||
#define WIIMOTE_PI 3.14159265f
|
||||
|
||||
//#define WITH_WIIUSE_DEBUG
|
||||
|
||||
/* Error output macros */
|
||||
#define WIIUSE_ERROR(fmt, ...) fprintf(stderr, "[ERROR] " fmt "\n", ##__VA_ARGS__)
|
||||
|
||||
/* Warning output macros */
|
||||
#define WIIUSE_WARNING(fmt, ...) fprintf(stderr, "[WARNING] " fmt "\n", ##__VA_ARGS__)
|
||||
|
||||
/* Information output macros */
|
||||
#define WIIUSE_INFO(fmt, ...) fprintf(stderr, "[INFO] " fmt "\n", ##__VA_ARGS__)
|
||||
|
||||
#ifdef WITH_WIIUSE_DEBUG
|
||||
#ifdef WIN32
|
||||
#define WIIUSE_DEBUG(fmt, ...) do { \
|
||||
char* file = __FILE__; \
|
||||
int i = strlen(file) - 1; \
|
||||
for (; i && (file[i] != '\\'); --i); \
|
||||
fprintf(stderr, "[DEBUG] %s:%i: " fmt "\n", file+i+1, __LINE__, ##__VA_ARGS__); \
|
||||
} while (0)
|
||||
#else
|
||||
#define WIIUSE_DEBUG(fmt, ...) fprintf(stderr, "[DEBUG] " __FILE__ ":%i: " fmt "\n", __LINE__, ##__VA_ARGS__)
|
||||
#endif
|
||||
#else
|
||||
#define WIIUSE_DEBUG(fmt, ...)
|
||||
#endif
|
||||
|
||||
#if 1
|
||||
#define WII_DEBUG(fmt, ...) do { \
|
||||
printf("[WDEBUG] " __FILE__ ":%i: " fmt "\n", __LINE__, ##__VA_ARGS__); \
|
||||
usleep(3000000); \
|
||||
} while (0)
|
||||
#else
|
||||
#define WII_DEBUG(fmt, ...)
|
||||
#endif
|
||||
|
||||
|
||||
/* Convert between radians and degrees */
|
||||
#define RAD_TO_DEGREE(r) ((r * 180.0f) / WIIMOTE_PI)
|
||||
#define DEGREE_TO_RAD(d) (d * (WIIMOTE_PI / 180.0f))
|
||||
|
||||
/* Convert to big endian */
|
||||
#define BIG_ENDIAN_LONG(i) (htonl(i))
|
||||
#define BIG_ENDIAN_SHORT(i) (htons(i))
|
||||
|
||||
#define absf(x) ((x >= 0) ? (x) : (x * -1.0f))
|
||||
#define diff_f(x, y) ((x >= y) ? (absf(x - y)) : (absf(y - x)))
|
||||
|
||||
#endif
|
||||
834
external/libogc_ir/upstream/ir.c
vendored
Normal file
834
external/libogc_ir/upstream/ir.c
vendored
Normal file
|
|
@ -0,0 +1,834 @@
|
|||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include <time.h>
|
||||
|
||||
#ifndef WIN32
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#ifdef GEKKO
|
||||
#include <ogcsys.h>
|
||||
#endif
|
||||
#include "definitions.h"
|
||||
#include "wiiuse_internal.h"
|
||||
#include "ir.h"
|
||||
|
||||
static int ir_correct_for_bounds(float* x, float* y, enum aspect_t aspect, int offset_x, int offset_y);
|
||||
static void ir_convert_to_vres(float* x, float* y, enum aspect_t aspect, unsigned int vx, unsigned int vy);
|
||||
|
||||
/**
|
||||
* @brief Get the IR sensitivity settings.
|
||||
*
|
||||
* @param wm Pointer to a wiimote_t structure.
|
||||
* @param block1 [out] Pointer to where block1 will be set.
|
||||
* @param block2 [out] Pointer to where block2 will be set.
|
||||
*
|
||||
* @return Returns the sensitivity level.
|
||||
*/
|
||||
static int get_ir_sens(struct wiimote_t* wm, char** block1, char** block2) {
|
||||
if (WIIMOTE_IS_SET(wm, WIIMOTE_STATE_IR_SENS_LVL1)) {
|
||||
*block1 = WM_IR_BLOCK1_LEVEL1;
|
||||
*block2 = WM_IR_BLOCK2_LEVEL1;
|
||||
return 1;
|
||||
} else if (WIIMOTE_IS_SET(wm, WIIMOTE_STATE_IR_SENS_LVL2)) {
|
||||
*block1 = WM_IR_BLOCK1_LEVEL2;
|
||||
*block2 = WM_IR_BLOCK2_LEVEL2;
|
||||
return 2;
|
||||
} else if (WIIMOTE_IS_SET(wm, WIIMOTE_STATE_IR_SENS_LVL3)) {
|
||||
*block1 = WM_IR_BLOCK1_LEVEL3;
|
||||
*block2 = WM_IR_BLOCK2_LEVEL3;
|
||||
return 3;
|
||||
} else if (WIIMOTE_IS_SET(wm, WIIMOTE_STATE_IR_SENS_LVL4)) {
|
||||
*block1 = WM_IR_BLOCK1_LEVEL4;
|
||||
*block2 = WM_IR_BLOCK2_LEVEL4;
|
||||
return 4;
|
||||
} else if (WIIMOTE_IS_SET(wm, WIIMOTE_STATE_IR_SENS_LVL5)) {
|
||||
*block1 = WM_IR_BLOCK1_LEVEL5;
|
||||
*block2 = WM_IR_BLOCK2_LEVEL5;
|
||||
return 5;
|
||||
}
|
||||
|
||||
*block1 = NULL;
|
||||
*block2 = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void rotate_dots(struct fdot_t* in, struct fdot_t *out, int count, float ang) {
|
||||
float s, c;
|
||||
int i;
|
||||
|
||||
if (ang == 0) {
|
||||
for (i = 0; i < count; ++i) {
|
||||
out[i].x = in[i].x;
|
||||
out[i].y = in[i].y;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
s = sin(DEGREE_TO_RAD(ang));
|
||||
c = cos(DEGREE_TO_RAD(ang));
|
||||
|
||||
/*
|
||||
* [ cos(theta) -sin(theta) ][ ir->rx ]
|
||||
* [ sin(theta) cos(theta) ][ ir->ry ]
|
||||
*/
|
||||
|
||||
for (i = 0; i < count; ++i) {
|
||||
out[i].x = (c * in[i].x) + (-s * in[i].y);
|
||||
out[i].y = (s * in[i].x) + (c * in[i].y);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Correct for the IR bounding box.
|
||||
*
|
||||
* @param x [out] The current X, it will be updated if valid.
|
||||
* @param y [out] The current Y, it will be updated if valid.
|
||||
* @param aspect Aspect ratio of the screen.
|
||||
* @param offset_x The X offset of the bounding box.
|
||||
* @param offset_y The Y offset of the bounding box.
|
||||
*
|
||||
* @return Returns 1 if the point is valid and was updated.
|
||||
*
|
||||
* Nintendo was smart with this bit. They sacrifice a little
|
||||
* precision for a big increase in usability.
|
||||
*/
|
||||
static int ir_correct_for_bounds(float* x, float* y, enum aspect_t aspect, int offset_x, int offset_y) {
|
||||
float x0, y0;
|
||||
int xs, ys;
|
||||
|
||||
if (aspect == WIIUSE_ASPECT_16_9) {
|
||||
xs = WM_ASPECT_16_9_X;
|
||||
ys = WM_ASPECT_16_9_Y;
|
||||
} else {
|
||||
xs = WM_ASPECT_4_3_X;
|
||||
ys = WM_ASPECT_4_3_Y;
|
||||
}
|
||||
|
||||
x0 = ((1024 - xs) / 2) + offset_x;
|
||||
y0 = ((768 - ys) / 2) + offset_y;
|
||||
|
||||
if ((*x >= x0)
|
||||
&& (*x <= (x0 + xs))
|
||||
&& (*y >= y0)
|
||||
&& (*y <= (y0 + ys)))
|
||||
{
|
||||
*x -= offset_x;
|
||||
*y -= offset_y;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Interpolate the point to the user defined virtual screen resolution.
|
||||
*/
|
||||
static void ir_convert_to_vres(float* x, float* y, enum aspect_t aspect, unsigned int vx, unsigned int vy) {
|
||||
int xs, ys;
|
||||
|
||||
if (aspect == WIIUSE_ASPECT_16_9) {
|
||||
xs = WM_ASPECT_16_9_X;
|
||||
ys = WM_ASPECT_16_9_Y;
|
||||
} else {
|
||||
xs = WM_ASPECT_4_3_X;
|
||||
ys = WM_ASPECT_4_3_Y;
|
||||
}
|
||||
|
||||
*x -= ((1024-xs)/2);
|
||||
*y -= ((768-ys)/2);
|
||||
|
||||
*x = (*x / (float)xs) * vx;
|
||||
*y = (*y / (float)ys) * vy;
|
||||
}
|
||||
|
||||
void wiiuse_set_ir_mode(struct wiimote_t *wm)
|
||||
{
|
||||
ubyte buf = 0x00;
|
||||
|
||||
if(!wm) return;
|
||||
if(!WIIMOTE_IS_SET(wm,WIIMOTE_STATE_IR)) return;
|
||||
|
||||
if(WIIMOTE_IS_SET(wm,WIIMOTE_STATE_EXP)) buf = WM_IR_TYPE_BASIC;
|
||||
else buf = WM_IR_TYPE_EXTENDED;
|
||||
wiiuse_write_data(wm,WM_REG_IR_MODENUM, &buf, 1, NULL);
|
||||
}
|
||||
|
||||
void wiiuse_set_ir(struct wiimote_t *wm,int status)
|
||||
{
|
||||
ubyte buf = 0x00;
|
||||
int ir_level = 0;
|
||||
char* block1 = NULL;
|
||||
char* block2 = NULL;
|
||||
|
||||
if(!wm) return;
|
||||
|
||||
/*
|
||||
* Wait for the handshake to finish first.
|
||||
* When it handshake finishes and sees that
|
||||
* IR is enabled, it will call this function
|
||||
* again to actually enable IR.
|
||||
*/
|
||||
if(!WIIMOTE_IS_SET(wm,WIIMOTE_STATE_HANDSHAKE_COMPLETE)) {
|
||||
WIIUSE_DEBUG("Tried to enable IR, will wait until handshake finishes.\n");
|
||||
if(status)
|
||||
WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_IR_INIT);
|
||||
else
|
||||
WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_IR_INIT);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check to make sure a sensitivity setting is selected.
|
||||
*/
|
||||
ir_level = get_ir_sens(wm, &block1, &block2);
|
||||
if (!ir_level) {
|
||||
WIIUSE_ERROR("No IR sensitivity setting selected.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (status) {
|
||||
/* if already enabled then stop */
|
||||
if (WIIMOTE_IS_SET(wm, WIIMOTE_STATE_IR) || WIIMOTE_IS_SET(wm, WIIMOTE_STATE_WIIU_PRO)) {
|
||||
wiiuse_status(wm,NULL);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
/* if already disabled then stop */
|
||||
if (!WIIMOTE_IS_SET(wm, WIIMOTE_STATE_IR)) {
|
||||
wiiuse_status(wm,NULL);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
buf = (status ? 0x04 : 0x00);
|
||||
wiiuse_sendcmd(wm,WM_CMD_IR,&buf,1,NULL);
|
||||
wiiuse_sendcmd(wm,WM_CMD_IR_2,&buf,1,NULL);
|
||||
|
||||
if (!status) {
|
||||
WIIUSE_DEBUG("Disabled IR cameras for wiimote id %i.", wm->unid);
|
||||
wiiuse_status(wm,NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
/* enable IR, set sensitivity */
|
||||
buf = 0x08;
|
||||
wiiuse_write_data(wm,WM_REG_IR,&buf,1,NULL);
|
||||
|
||||
wiiuse_write_data(wm, WM_REG_IR_BLOCK1, (ubyte*)block1, 9, NULL);
|
||||
wiiuse_write_data(wm, WM_REG_IR_BLOCK2, (ubyte*)block2, 2, NULL);
|
||||
|
||||
if(WIIMOTE_IS_SET(wm,WIIMOTE_STATE_EXP)) buf = WM_IR_TYPE_BASIC;
|
||||
else buf = WM_IR_TYPE_EXTENDED;
|
||||
wiiuse_write_data(wm,WM_REG_IR_MODENUM, &buf, 1, NULL);
|
||||
|
||||
wiiuse_status(wm,NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the virtual screen resolution for IR tracking.
|
||||
*
|
||||
* @param wm Pointer to a wiimote_t structure.
|
||||
* @param status 1 to enable, 0 to disable.
|
||||
*/
|
||||
void wiiuse_set_ir_vres(struct wiimote_t* wm, unsigned int x, unsigned int y) {
|
||||
if (!wm) return;
|
||||
|
||||
wm->ir.vres[0] = (x-1);
|
||||
wm->ir.vres[1] = (y-1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the XY position for the IR cursor.
|
||||
*
|
||||
* @param wm Pointer to a wiimote_t structure.
|
||||
*/
|
||||
void wiiuse_set_ir_position(struct wiimote_t* wm, enum ir_position_t pos) {
|
||||
if (!wm) return;
|
||||
|
||||
wm->ir.pos = pos;
|
||||
|
||||
switch (pos) {
|
||||
|
||||
case WIIUSE_IR_ABOVE:
|
||||
wm->ir.offset[0] = 0;
|
||||
|
||||
if (wm->ir.aspect == WIIUSE_ASPECT_16_9)
|
||||
wm->ir.offset[1] = WM_ASPECT_16_9_Y/2 - 70;
|
||||
else if (wm->ir.aspect == WIIUSE_ASPECT_4_3)
|
||||
wm->ir.offset[1] = WM_ASPECT_4_3_Y/2 - 100;
|
||||
|
||||
return;
|
||||
|
||||
case WIIUSE_IR_BELOW:
|
||||
wm->ir.offset[0] = 0;
|
||||
|
||||
if (wm->ir.aspect == WIIUSE_ASPECT_16_9)
|
||||
wm->ir.offset[1] = -WM_ASPECT_16_9_Y/2 + 70;
|
||||
else if (wm->ir.aspect == WIIUSE_ASPECT_4_3)
|
||||
wm->ir.offset[1] = -WM_ASPECT_4_3_Y/2 + 100;
|
||||
|
||||
return;
|
||||
|
||||
default:
|
||||
return;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the aspect ratio of the TV/monitor.
|
||||
*
|
||||
* @param wm Pointer to a wiimote_t structure.
|
||||
* @param aspect Either WIIUSE_ASPECT_16_9 or WIIUSE_ASPECT_4_3
|
||||
*/
|
||||
void wiiuse_set_aspect_ratio(struct wiimote_t* wm, enum aspect_t aspect) {
|
||||
if (!wm) return;
|
||||
|
||||
wm->ir.aspect = aspect;
|
||||
|
||||
if (aspect == WIIUSE_ASPECT_4_3) {
|
||||
wm->ir.vres[0] = WM_ASPECT_4_3_X;
|
||||
wm->ir.vres[1] = WM_ASPECT_4_3_Y;
|
||||
} else {
|
||||
wm->ir.vres[0] = WM_ASPECT_16_9_X;
|
||||
wm->ir.vres[1] = WM_ASPECT_16_9_Y;
|
||||
}
|
||||
|
||||
/* reset the position offsets */
|
||||
wiiuse_set_ir_position(wm, wm->ir.pos);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set the IR sensitivity.
|
||||
*
|
||||
* @param wm Pointer to a wiimote_t structure.
|
||||
* @param level 1-5, same as Wii system sensitivity setting.
|
||||
*
|
||||
* If the level is < 1, then level will be set to 1.
|
||||
* If the level is > 5, then level will be set to 5.
|
||||
*/
|
||||
void wiiuse_set_ir_sensitivity(struct wiimote_t* wm, int level) {
|
||||
char* block1 = NULL;
|
||||
char* block2 = NULL;
|
||||
|
||||
if (!wm) return;
|
||||
|
||||
if (level > 5) level = 5;
|
||||
if (level < 1) level = 1;
|
||||
|
||||
WIIMOTE_DISABLE_STATE(wm, (WIIMOTE_STATE_IR_SENS_LVL1 |
|
||||
WIIMOTE_STATE_IR_SENS_LVL2 |
|
||||
WIIMOTE_STATE_IR_SENS_LVL3 |
|
||||
WIIMOTE_STATE_IR_SENS_LVL4 |
|
||||
WIIMOTE_STATE_IR_SENS_LVL5));
|
||||
|
||||
switch (level) {
|
||||
case 1:
|
||||
WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_IR_SENS_LVL1);
|
||||
break;
|
||||
case 2:
|
||||
WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_IR_SENS_LVL2);
|
||||
break;
|
||||
case 3:
|
||||
WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_IR_SENS_LVL3);
|
||||
break;
|
||||
case 4:
|
||||
WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_IR_SENS_LVL4);
|
||||
break;
|
||||
case 5:
|
||||
WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_IR_SENS_LVL5);
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
if(!WIIMOTE_IS_SET(wm,WIIMOTE_STATE_IR)) return;
|
||||
|
||||
/* set the new sensitivity */
|
||||
get_ir_sens(wm, &block1, &block2);
|
||||
|
||||
wiiuse_write_data(wm, WM_REG_IR_BLOCK1, (ubyte*)block1, 9,NULL);
|
||||
wiiuse_write_data(wm, WM_REG_IR_BLOCK2, (ubyte*)block2, 2,NULL);
|
||||
|
||||
WIIUSE_DEBUG("Set IR sensitivity to level %i (unid %i)", level, wm->unid);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Calculate the data from the IR spots. Basic IR mode.
|
||||
*
|
||||
* @param wm Pointer to a wiimote_t structure.
|
||||
* @param data Data returned by the wiimote for the IR spots.
|
||||
*/
|
||||
void calculate_basic_ir(struct wiimote_t* wm, ubyte* data) {
|
||||
struct ir_dot_t* dot = wm->ir.dot;
|
||||
int i;
|
||||
|
||||
dot[0].rx = 1023 - (data[0] | ((data[2] & 0x30) << 4));
|
||||
dot[0].ry = data[1] | ((data[2] & 0xC0) << 2);
|
||||
|
||||
dot[1].rx = 1023 - (data[3] | ((data[2] & 0x03) << 8));
|
||||
dot[1].ry = data[4] | ((data[2] & 0x0C) << 6);
|
||||
|
||||
dot[2].rx = 1023 - (data[5] | ((data[7] & 0x30) << 4));
|
||||
dot[2].ry = data[6] | ((data[7] & 0xC0) << 2);
|
||||
|
||||
dot[3].rx = 1023 - (data[8] | ((data[7] & 0x03) << 8));
|
||||
dot[3].ry = data[9] | ((data[7] & 0x0C) << 6);
|
||||
|
||||
/* set each IR spot to visible if spot is in range */
|
||||
for (i = 0; i < 4; ++i) {
|
||||
dot[i].rx = BIG_ENDIAN_SHORT(dot[i].rx);
|
||||
dot[i].ry = BIG_ENDIAN_SHORT(dot[i].ry);
|
||||
|
||||
if (dot[i].ry == 1023)
|
||||
dot[i].visible = 0;
|
||||
else {
|
||||
dot[i].visible = 1;
|
||||
dot[i].size = 0; /* since we don't know the size, set it as 0 */
|
||||
}
|
||||
}
|
||||
#ifndef GEKKO
|
||||
interpret_ir_data(&wm->ir,&wm->orient,WIIMOTE_IS_SET(wm, WIIMOTE_STATE_ACC));
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Calculate the data from the IR spots. Extended IR mode.
|
||||
*
|
||||
* @param wm Pointer to a wiimote_t structure.
|
||||
* @param data Data returned by the wiimote for the IR spots.
|
||||
*/
|
||||
void calculate_extended_ir(struct wiimote_t* wm, ubyte* data) {
|
||||
struct ir_dot_t* dot = wm->ir.dot;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 4; ++i) {
|
||||
dot[i].rx = 1023 - (data[3*i] | ((data[(3*i)+2] & 0x30) << 4));
|
||||
dot[i].ry = data[(3*i)+1] | ((data[(3*i)+2] & 0xC0) << 2);
|
||||
|
||||
dot[i].size = data[(3*i)+2];
|
||||
|
||||
dot[i].rx = BIG_ENDIAN_SHORT(dot[i].rx);
|
||||
dot[i].ry = BIG_ENDIAN_SHORT(dot[i].ry);
|
||||
|
||||
dot[i].size = dot[i].size&0x0f;
|
||||
|
||||
/* if in range set to visible */
|
||||
if (dot[i].ry == 1023)
|
||||
dot[i].visible = 0;
|
||||
else
|
||||
dot[i].visible = 1;
|
||||
}
|
||||
#ifndef GEKKO
|
||||
interpret_ir_data(&wm->ir,&wm->orient,WIIMOTE_IS_SET(wm, WIIMOTE_STATE_ACC));
|
||||
#endif
|
||||
}
|
||||
|
||||
enum {
|
||||
IR_STATE_DEAD = 0,
|
||||
IR_STATE_GOOD,
|
||||
IR_STATE_SINGLE,
|
||||
IR_STATE_LOST,
|
||||
};
|
||||
|
||||
// half-height of the IR sensor if half-width is 1
|
||||
#define HEIGHT (384.0f / 512.0f)
|
||||
// maximum sensor bar slope (tan(35 degrees))
|
||||
#define MAX_SB_SLOPE 0.7f
|
||||
// minimum sensor bar width in view, relative to half of the IR sensor area
|
||||
#define MIN_SB_WIDTH 0.1f
|
||||
// reject "sensor bars" that happen to have a dot towards the middle
|
||||
#define SB_MIDDOT_REJECT 0.05f
|
||||
|
||||
// physical dimensions
|
||||
// cm center to center of emitters
|
||||
#define SB_WIDTH 19.5f
|
||||
// half-width in cm of emitters
|
||||
#define SB_DOT_WIDTH 2.25f
|
||||
// half-height in cm of emitters (with some tolerance)
|
||||
#define SB_DOT_HEIGHT 1.0f
|
||||
|
||||
#define SB_DOT_WIDTH_RATIO (SB_DOT_WIDTH / SB_WIDTH)
|
||||
#define SB_DOT_HEIGHT_RATIO (SB_DOT_HEIGHT / SB_WIDTH)
|
||||
|
||||
// dots further out than these coords are allowed to not be picked up
|
||||
// otherwise assume something's wrong
|
||||
//#define SB_OFF_SCREEN_X 0.8f
|
||||
//#define SB_OFF_SCREEN_Y (0.8f * HEIGHT)
|
||||
|
||||
// disable, may be doing more harm than good due to sensor pickup glitches
|
||||
#define SB_OFF_SCREEN_X 0.0f
|
||||
#define SB_OFF_SCREEN_Y 0.0f
|
||||
|
||||
// if a point is closer than this to one of the previous SB points
|
||||
// when it reappears, consider it the same instead of trying to guess
|
||||
// which one of the two it is
|
||||
#define SB_SINGLE_NOGUESS_DISTANCE (100.0 * 100.0)
|
||||
|
||||
// width of the sensor bar in pixels at one meter from the Wiimote
|
||||
#define SB_Z_COEFFICIENT 256.0f
|
||||
|
||||
// distance in meters from the center of the FOV to the left or right edge,
|
||||
// when the wiimote is at one meter
|
||||
#define WIIMOTE_FOV_COEFFICIENT 0.39f
|
||||
|
||||
#define SQUARED(x) ((x)*(x))
|
||||
#define WMAX(x,y) ((x>y)?(x):(y))
|
||||
#define WMIN(x,y) ((x<y)?(x):(y))
|
||||
|
||||
/**
|
||||
* @brief Interpret IR data into more user friendly variables.
|
||||
*
|
||||
* @param wm Pointer to a wiimote_t structure.
|
||||
*/
|
||||
void find_sensorbar(struct ir_t* ir, struct orient_t *orient) {
|
||||
struct fdot_t dots[4];
|
||||
struct fdot_t acc_dots[4];
|
||||
struct sb_t cand;
|
||||
struct sb_t candidates[6];
|
||||
struct sb_t sb;
|
||||
|
||||
fdot_t difference;
|
||||
|
||||
int num_candidates = 0;
|
||||
|
||||
int i;
|
||||
int j;
|
||||
int first, second;
|
||||
|
||||
WIIUSE_DEBUG("IR: orient angle: %.02f\n",orient->roll);
|
||||
|
||||
/* count visible dots and populate dots structure */
|
||||
/* dots[] is in -1..1 units for width */
|
||||
ir->num_dots = 0;
|
||||
for (i = 0; i < 4; i++) {
|
||||
if (ir->dot[i].visible) {
|
||||
dots[ir->num_dots].x = (ir->dot[i].rx - 512.0f) / 512.0f;
|
||||
dots[ir->num_dots].y = (ir->dot[i].ry - 384.0f) / 512.0f;
|
||||
WIIUSE_DEBUG("IR: dot %d at (%d,%d) (%.03f,%.03f)\n",ir->num_dots,ir->dot[i].rx,ir->dot[i].ry,dots[ir->num_dots].x,dots[ir->num_dots].y);
|
||||
ir->num_dots++;
|
||||
}
|
||||
}
|
||||
|
||||
WIIUSE_DEBUG("IR: found %d dots\n",ir->num_dots);
|
||||
|
||||
// nothing to track
|
||||
if(ir->num_dots == 0) {
|
||||
if(ir->state != IR_STATE_DEAD)
|
||||
ir->state = IR_STATE_LOST;
|
||||
ir->ax = 0;
|
||||
ir->ay = 0;
|
||||
ir->distance = 0.0f;
|
||||
ir->raw_valid = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
/* ==== Find the Sensor Bar ==== */
|
||||
|
||||
// first rotate according to accelerometer orientation
|
||||
rotate_dots(dots, acc_dots, ir->num_dots, orient->roll);
|
||||
if(ir->num_dots > 1) {
|
||||
WIIUSE_DEBUG("IR: locating sensor bar candidates\n");
|
||||
|
||||
// iterate through all dot pairs
|
||||
for(first=0; first < (ir->num_dots-1); first++) {
|
||||
for(second=(first+1); second < ir->num_dots; second++) {
|
||||
WIIUSE_DEBUG("IR: trying dots %d and %d\n",first,second);
|
||||
// order the dots leftmost first into cand
|
||||
// storing both the raw dots and the accel-rotated dots
|
||||
if(acc_dots[first].x > acc_dots[second].x) {
|
||||
cand.dots[0] = dots[second];
|
||||
cand.dots[1] = dots[first];
|
||||
cand.acc_dots[0] = acc_dots[second];
|
||||
cand.acc_dots[1] = acc_dots[first];
|
||||
} else {
|
||||
cand.dots[0] = dots[first];
|
||||
cand.dots[1] = dots[second];
|
||||
cand.acc_dots[0] = acc_dots[first];
|
||||
cand.acc_dots[1] = acc_dots[second];
|
||||
}
|
||||
difference.x = cand.acc_dots[1].x - cand.acc_dots[0].x;
|
||||
difference.y = cand.acc_dots[1].y - cand.acc_dots[0].y;
|
||||
|
||||
// check angle
|
||||
if(fabsf(difference.y / difference.x) > MAX_SB_SLOPE)
|
||||
continue;
|
||||
WIIUSE_DEBUG("IR: passed angle check\n");
|
||||
// rotate to the true sensor bar angle
|
||||
cand.off_angle = -RAD_TO_DEGREE(atan2(difference.y, difference.x));
|
||||
cand.angle = cand.off_angle + orient->roll;
|
||||
rotate_dots(cand.dots, cand.rot_dots, 2, cand.angle);
|
||||
WIIUSE_DEBUG("IR: off_angle: %.02f, angle: %.02f\n", cand.off_angle, cand.angle);
|
||||
// recalculate x distance - y should be zero now, so ignore it
|
||||
difference.x = cand.rot_dots[1].x - cand.rot_dots[0].x;
|
||||
|
||||
// check distance
|
||||
if(difference.x < MIN_SB_WIDTH)
|
||||
continue;
|
||||
// middle dot check. If there's another source somewhere in the
|
||||
// middle of this candidate, then this can't be a sensor bar
|
||||
|
||||
for(i=0; i<ir->num_dots; i++) {
|
||||
float wadj, hadj;
|
||||
struct fdot_t tdot;
|
||||
if(i==first || i==second) continue;
|
||||
hadj = SB_DOT_HEIGHT_RATIO * difference.x;
|
||||
wadj = SB_DOT_WIDTH_RATIO * difference.x;
|
||||
rotate_dots(&dots[i], &tdot, 1, cand.angle);
|
||||
if( ((cand.rot_dots[0].x + wadj) < tdot.x) &&
|
||||
((cand.rot_dots[1].x - wadj) > tdot.x) &&
|
||||
((cand.rot_dots[0].y + hadj) > tdot.y) &&
|
||||
((cand.rot_dots[0].y - hadj) < tdot.y))
|
||||
break;
|
||||
}
|
||||
// failed middle dot check
|
||||
if(i < ir->num_dots) continue;
|
||||
WIIUSE_DEBUG("IR: passed middle dot check\n");
|
||||
|
||||
cand.score = 1 / (cand.rot_dots[1].x - cand.rot_dots[0].x);
|
||||
|
||||
// we have a candidate, store it
|
||||
WIIUSE_DEBUG("IR: new candidate %d\n",num_candidates);
|
||||
candidates[num_candidates++] = cand;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(num_candidates == 0) {
|
||||
int closest = -1;
|
||||
int closest_to = 0;
|
||||
float best = 999.0f;
|
||||
float d;
|
||||
float dx[2];
|
||||
struct sb_t sbx[2];
|
||||
// no sensor bar candidates, try to work with a lone dot
|
||||
WIIUSE_DEBUG("IR: no candidates\n");
|
||||
switch(ir->state) {
|
||||
case IR_STATE_DEAD:
|
||||
WIIUSE_DEBUG("IR: we're dead\n");
|
||||
// we've never seen a sensor bar before, so we're screwed
|
||||
ir->ax = 0.0f;
|
||||
ir->ay = 0.0f;
|
||||
ir->distance = 0.0f;
|
||||
ir->raw_valid = 0;
|
||||
return;
|
||||
case IR_STATE_GOOD:
|
||||
case IR_STATE_SINGLE:
|
||||
case IR_STATE_LOST:
|
||||
WIIUSE_DEBUG("IR: trying to keep track of single dot\n");
|
||||
// try to find the dot closest to the previous sensor bar position
|
||||
for(i=0; i<ir->num_dots; i++) {
|
||||
WIIUSE_DEBUG("IR: checking dot %d (%.02f, %.02f)\n",i, acc_dots[i].x,acc_dots[i].y);
|
||||
for(j=0; j<2; j++) {
|
||||
WIIUSE_DEBUG(" to dot %d (%.02f, %.02f)\n",j, ir->sensorbar.acc_dots[j].x,ir->sensorbar.acc_dots[j].y);
|
||||
d = SQUARED(acc_dots[i].x - ir->sensorbar.acc_dots[j].x);
|
||||
d += SQUARED(acc_dots[i].y - ir->sensorbar.acc_dots[j].y);
|
||||
if(d < best) {
|
||||
best = d;
|
||||
closest_to = j;
|
||||
closest = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
WIIUSE_DEBUG("IR: closest dot is %d to %d\n",closest,closest_to);
|
||||
if(ir->state != IR_STATE_LOST || best < SB_SINGLE_NOGUESS_DISTANCE) {
|
||||
// now work out where the other dot would be, in the acc frame
|
||||
sb.acc_dots[closest_to] = acc_dots[closest];
|
||||
sb.acc_dots[closest_to^1].x = ir->sensorbar.acc_dots[closest_to^1].x - ir->sensorbar.acc_dots[closest_to].x + acc_dots[closest].x;
|
||||
sb.acc_dots[closest_to^1].y = ir->sensorbar.acc_dots[closest_to^1].y - ir->sensorbar.acc_dots[closest_to].y + acc_dots[closest].y;
|
||||
// get the raw frame
|
||||
rotate_dots(sb.acc_dots, sb.dots, 2, -orient->roll);
|
||||
if((fabsf(sb.dots[closest_to^1].x) < SB_OFF_SCREEN_X) && (fabsf(sb.dots[closest_to^1].y) < SB_OFF_SCREEN_Y)) {
|
||||
// this dot should be visible but isn't, since the candidate section failed.
|
||||
// fall through and try to pick out the sensor bar without previous information
|
||||
WIIUSE_DEBUG("IR: dot falls on screen, falling through\n");
|
||||
} else {
|
||||
// calculate the rotated dots frame
|
||||
// angle tends to drift, so recalculate
|
||||
sb.off_angle = -RAD_TO_DEGREE(atan2(sb.acc_dots[1].y - sb.acc_dots[0].y, sb.acc_dots[1].x - sb.acc_dots[0].x));
|
||||
sb.angle = ir->sensorbar.off_angle + orient->roll;
|
||||
rotate_dots(sb.acc_dots, sb.rot_dots, 2, ir->sensorbar.off_angle);
|
||||
WIIUSE_DEBUG("IR: kept track of single dot\n");
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
WIIUSE_DEBUG("IR: lost the dot and new one is too far away\n");
|
||||
}
|
||||
// try to find the dot closest to the sensor edge
|
||||
WIIUSE_DEBUG("IR: trying to find best dot\n");
|
||||
for(i=0; i<ir->num_dots; i++) {
|
||||
d = WMIN(1.0f - fabsf(dots[i].x), HEIGHT - fabsf(dots[i].y));
|
||||
if(d < best) {
|
||||
best = d;
|
||||
closest = i;
|
||||
}
|
||||
}
|
||||
WIIUSE_DEBUG("IR: best dot: %d\n",closest);
|
||||
// now try it as both places in the sensor bar
|
||||
// and pick the one that places the other dot furthest off-screen
|
||||
for(i=0; i<2; i++) {
|
||||
sbx[i].acc_dots[i] = acc_dots[closest];
|
||||
sbx[i].acc_dots[i^1].x = ir->sensorbar.acc_dots[i^1].x - ir->sensorbar.acc_dots[i].x + acc_dots[closest].x;
|
||||
sbx[i].acc_dots[i^1].y = ir->sensorbar.acc_dots[i^1].y - ir->sensorbar.acc_dots[i].y + acc_dots[closest].y;
|
||||
rotate_dots(sbx[i].acc_dots, sbx[i].dots, 2, -orient->roll);
|
||||
dx[i] = WMAX(fabsf(sbx[i].dots[i^1].x),fabsf(sbx[i].dots[i^1].y / HEIGHT));
|
||||
}
|
||||
if(dx[0] > dx[1]) {
|
||||
WIIUSE_DEBUG("IR: dot is LEFT: %.02f > %.02f\n",dx[0],dx[1]);
|
||||
sb = sbx[0];
|
||||
} else {
|
||||
WIIUSE_DEBUG("IR: dot is RIGHT: %.02f < %.02f\n",dx[0],dx[1]);
|
||||
sb = sbx[1];
|
||||
}
|
||||
// angle tends to drift, so recalculate
|
||||
sb.off_angle = -RAD_TO_DEGREE(atan2(sb.acc_dots[1].y - sb.acc_dots[0].y, sb.acc_dots[1].x - sb.acc_dots[0].x));
|
||||
sb.angle = ir->sensorbar.off_angle + orient->roll;
|
||||
rotate_dots(sb.acc_dots, sb.rot_dots, 2, ir->sensorbar.off_angle);
|
||||
WIIUSE_DEBUG("IR: found new dot to track\n");
|
||||
break;
|
||||
}
|
||||
sb.score = 0;
|
||||
ir->state = IR_STATE_SINGLE;
|
||||
} else {
|
||||
int bestidx = 0;
|
||||
float best = 0.0f;
|
||||
WIIUSE_DEBUG("IR: finding best candidate\n");
|
||||
// look for the best candidate
|
||||
// for now, the formula is simple: pick the one with the smallest distance
|
||||
for(i=0; i<num_candidates; i++) {
|
||||
if(candidates[i].score > best) {
|
||||
bestidx = i;
|
||||
best = candidates[i].score;
|
||||
}
|
||||
}
|
||||
WIIUSE_DEBUG("IR: best candidate: %d\n",bestidx);
|
||||
sb = candidates[bestidx];
|
||||
ir->state = IR_STATE_GOOD;
|
||||
}
|
||||
|
||||
ir->raw_valid = 1;
|
||||
ir->ax = ((sb.rot_dots[0].x + sb.rot_dots[1].x) / 2) * 512.0 + 512.0;
|
||||
ir->ay = ((sb.rot_dots[0].y + sb.rot_dots[1].y) / 2) * 512.0 + 384.0;
|
||||
ir->sensorbar = sb;
|
||||
ir->distance = (sb.rot_dots[1].x - sb.rot_dots[0].x) * 512.0;
|
||||
|
||||
}
|
||||
|
||||
#define SMOOTH_IR_RADIUS 8.0f
|
||||
#define SMOOTH_IR_SPEED 0.25f
|
||||
#define SMOOTH_IR_DEADZONE 2.5f
|
||||
|
||||
/**
|
||||
* @brief Smooth the IR pointer position
|
||||
*
|
||||
* @param ir Pointer to an ir_t structure.
|
||||
*/
|
||||
void apply_ir_smoothing(struct ir_t *ir) {
|
||||
f32 dx, dy, d, theta;
|
||||
|
||||
WIIUSE_DEBUG("Smooth: OK (%.02f, %.02f) LAST (%.02f, %.02f) ", ir->ax, ir->ay, ir->sx, ir->sy);
|
||||
dx = ir->ax - ir->sx;
|
||||
dy = ir->ay - ir->sy;
|
||||
d = sqrtf(dx*dx + dy*dy);
|
||||
if (d > SMOOTH_IR_DEADZONE) {
|
||||
if (d < SMOOTH_IR_RADIUS) {
|
||||
WIIUSE_DEBUG("INSIDE\n");
|
||||
ir->sx += dx * SMOOTH_IR_SPEED;
|
||||
ir->sy += dy * SMOOTH_IR_SPEED;
|
||||
} else {
|
||||
WIIUSE_DEBUG("OUTSIDE\n");
|
||||
theta = atan2f(dy, dx);
|
||||
ir->sx = ir->ax - cosf(theta) * SMOOTH_IR_RADIUS;
|
||||
ir->sy = ir->ay - sinf(theta) * SMOOTH_IR_RADIUS;
|
||||
}
|
||||
} else {
|
||||
WIIUSE_DEBUG("DEADZONE\n");
|
||||
}
|
||||
}
|
||||
|
||||
// max number of errors before cooked data drops out
|
||||
#define ERROR_MAX_COUNT 8
|
||||
// max number of glitches before cooked data updates
|
||||
#define GLITCH_MAX_COUNT 5
|
||||
// squared delta over which we consider something a glitch
|
||||
#define GLITCH_DIST (150.0f * 150.0f)
|
||||
|
||||
/**
|
||||
* @brief Interpret IR data into more user friendly variables.
|
||||
*
|
||||
* @param ir Pointer to an ir_t structure.
|
||||
* @param orient Pointer to an orient_t structure.
|
||||
*/
|
||||
void interpret_ir_data(struct ir_t* ir, struct orient_t *orient) {
|
||||
|
||||
float x,y;
|
||||
float d;
|
||||
|
||||
find_sensorbar(ir, orient);
|
||||
|
||||
if(ir->raw_valid) {
|
||||
ir->angle = ir->sensorbar.angle;
|
||||
ir->z = SB_Z_COEFFICIENT / ir->distance;
|
||||
orient->yaw = calc_yaw(ir);
|
||||
if(ir->error_cnt >= ERROR_MAX_COUNT) {
|
||||
ir->sx = ir->ax;
|
||||
ir->sy = ir->ay;
|
||||
ir->glitch_cnt = 0;
|
||||
} else {
|
||||
d = SQUARED(ir->ax - ir->sx) + SQUARED(ir->ay - ir->sy);
|
||||
if(d > GLITCH_DIST) {
|
||||
if(ir->glitch_cnt > GLITCH_MAX_COUNT) {
|
||||
apply_ir_smoothing(ir);
|
||||
ir->glitch_cnt = 0;
|
||||
} else {
|
||||
ir->glitch_cnt++;
|
||||
}
|
||||
} else {
|
||||
ir->glitch_cnt = 0;
|
||||
apply_ir_smoothing(ir);
|
||||
}
|
||||
}
|
||||
ir->smooth_valid = 1;
|
||||
ir->error_cnt = 0;
|
||||
} else {
|
||||
if(ir->error_cnt >= ERROR_MAX_COUNT) {
|
||||
ir->smooth_valid = 0;
|
||||
} else {
|
||||
ir->smooth_valid = 1;
|
||||
ir->error_cnt++;
|
||||
}
|
||||
}
|
||||
if(ir->smooth_valid) {
|
||||
x = ir->sx;
|
||||
y = ir->sy;
|
||||
if (ir_correct_for_bounds(&x, &y, ir->aspect, ir->offset[0], ir->offset[1])) {
|
||||
ir_convert_to_vres(&x, &y, ir->aspect, ir->vres[0], ir->vres[1]);
|
||||
ir->x = x;
|
||||
ir->y = y;
|
||||
ir->valid = 1;
|
||||
} else {
|
||||
ir->valid = 0;
|
||||
}
|
||||
} else {
|
||||
ir->valid = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Calculate yaw given the IR data.
|
||||
*
|
||||
* @param ir IR data structure.
|
||||
*/
|
||||
float calc_yaw(struct ir_t* ir) {
|
||||
float x;
|
||||
|
||||
x = ir->ax - 512;
|
||||
x *= WIIMOTE_FOV_COEFFICIENT / 512.0;
|
||||
|
||||
return RAD_TO_DEGREE( atanf(x) );
|
||||
}
|
||||
|
||||
22
external/libogc_ir/upstream/ir.h
vendored
Normal file
22
external/libogc_ir/upstream/ir.h
vendored
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
#ifndef __IR_H__
|
||||
#define __IR_H__
|
||||
|
||||
#include "wiiuse_internal.h"
|
||||
|
||||
#define WII_VRES_X 560
|
||||
#define WII_VRES_Y 340
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void calculate_basic_ir(struct wiimote_t* wm, ubyte* data);
|
||||
void calculate_extended_ir(struct wiimote_t* wm, ubyte* data);
|
||||
float calc_yaw(struct ir_t* ir);
|
||||
void interpret_ir_data(struct ir_t* ir, struct orient_t *orient);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
748
external/libogc_ir/upstream/wiiuse.h
vendored
Normal file
748
external/libogc_ir/upstream/wiiuse.h
vendored
Normal file
|
|
@ -0,0 +1,748 @@
|
|||
#ifndef __WIIUSE_H__
|
||||
#define __WIIUSE_H__
|
||||
|
||||
#if defined(_WIN32)
|
||||
/* windows */
|
||||
#include <windows.h>
|
||||
#elif defined(GEKKO)
|
||||
/* wii */
|
||||
#include <bte/bte.h>
|
||||
#elif defined(__linux__)
|
||||
/* nix */
|
||||
#include <bluetooth/bluetooth.h>
|
||||
#endif
|
||||
|
||||
#ifdef WIIUSE_INTERNAL_H_INCLUDED
|
||||
#define WCONST
|
||||
#else
|
||||
#define WCONST const
|
||||
#endif
|
||||
|
||||
/* led bit masks */
|
||||
#define WIIMOTE_LED_NONE 0x00
|
||||
#define WIIMOTE_LED_1 0x10
|
||||
#define WIIMOTE_LED_2 0x20
|
||||
#define WIIMOTE_LED_3 0x40
|
||||
#define WIIMOTE_LED_4 0x80
|
||||
|
||||
/* button codes */
|
||||
#define WIIMOTE_BUTTON_TWO 0x0001
|
||||
#define WIIMOTE_BUTTON_ONE 0x0002
|
||||
#define WIIMOTE_BUTTON_B 0x0004
|
||||
#define WIIMOTE_BUTTON_A 0x0008
|
||||
#define WIIMOTE_BUTTON_MINUS 0x0010
|
||||
#define WIIMOTE_BUTTON_ZACCEL_BIT6 0x0020
|
||||
#define WIIMOTE_BUTTON_ZACCEL_BIT7 0x0040
|
||||
#define WIIMOTE_BUTTON_HOME 0x0080
|
||||
#define WIIMOTE_BUTTON_LEFT 0x0100
|
||||
#define WIIMOTE_BUTTON_RIGHT 0x0200
|
||||
#define WIIMOTE_BUTTON_DOWN 0x0400
|
||||
#define WIIMOTE_BUTTON_UP 0x0800
|
||||
#define WIIMOTE_BUTTON_PLUS 0x1000
|
||||
#define WIIMOTE_BUTTON_ZACCEL_BIT4 0x2000
|
||||
#define WIIMOTE_BUTTON_ZACCEL_BIT5 0x4000
|
||||
#define WIIMOTE_BUTTON_UNKNOWN 0x8000
|
||||
#define WIIMOTE_BUTTON_ALL 0x1F9F
|
||||
|
||||
/* nunchul button codes */
|
||||
#define NUNCHUK_BUTTON_Z 0x01
|
||||
#define NUNCHUK_BUTTON_C 0x02
|
||||
#define NUNCHUK_BUTTON_ALL 0x03
|
||||
|
||||
/* classic controller button codes */
|
||||
#define CLASSIC_CTRL_BUTTON_UP 0x0001
|
||||
#define CLASSIC_CTRL_BUTTON_LEFT 0x0002
|
||||
#define CLASSIC_CTRL_BUTTON_ZR 0x0004
|
||||
#define CLASSIC_CTRL_BUTTON_X 0x0008
|
||||
#define CLASSIC_CTRL_BUTTON_A 0x0010
|
||||
#define CLASSIC_CTRL_BUTTON_Y 0x0020
|
||||
#define CLASSIC_CTRL_BUTTON_B 0x0040
|
||||
#define CLASSIC_CTRL_BUTTON_ZL 0x0080
|
||||
#define CLASSIC_CTRL_BUTTON_FULL_R 0x0200
|
||||
#define CLASSIC_CTRL_BUTTON_PLUS 0x0400
|
||||
#define CLASSIC_CTRL_BUTTON_HOME 0x0800
|
||||
#define CLASSIC_CTRL_BUTTON_MINUS 0x1000
|
||||
#define CLASSIC_CTRL_BUTTON_FULL_L 0x2000
|
||||
#define CLASSIC_CTRL_BUTTON_DOWN 0x4000
|
||||
#define CLASSIC_CTRL_BUTTON_RIGHT 0x8000
|
||||
#define CLASSIC_CTRL_BUTTON_ALL 0xFEFF
|
||||
|
||||
/* guitar hero 3 button codes */
|
||||
#define GUITAR_HERO_3_BUTTON_STRUM_UP 0x0001
|
||||
#define GUITAR_HERO_3_BUTTON_YELLOW 0x0008
|
||||
#define GUITAR_HERO_3_BUTTON_GREEN 0x0010
|
||||
#define GUITAR_HERO_3_BUTTON_BLUE 0x0020
|
||||
#define GUITAR_HERO_3_BUTTON_RED 0x0040
|
||||
#define GUITAR_HERO_3_BUTTON_ORANGE 0x0080
|
||||
#define GUITAR_HERO_3_BUTTON_PLUS 0x0400
|
||||
#define GUITAR_HERO_3_BUTTON_MINUS 0x1000
|
||||
#define GUITAR_HERO_3_BUTTON_STRUM_DOWN 0x4000
|
||||
#define GUITAR_HERO_3_BUTTON_ALL 0xFEFF
|
||||
|
||||
/* guitar hero world tour touch bar codes */
|
||||
#define GUITAR_HERO_3_TOUCH_AVAILABLE 0x1000
|
||||
#define GUITAR_HERO_3_TOUCH_GREEN 0x1001
|
||||
#define GUITAR_HERO_3_TOUCH_RED 0x1002
|
||||
#define GUITAR_HERO_3_TOUCH_YELLOW 0x1004
|
||||
#define GUITAR_HERO_3_TOUCH_BLUE 0x1008
|
||||
#define GUITAR_HERO_3_TOUCH_ORANGE 0x1010
|
||||
|
||||
/* wiimote option flags */
|
||||
#define WIIUSE_SMOOTHING 0x01
|
||||
#define WIIUSE_CONTINUOUS 0x02
|
||||
#define WIIUSE_ACCEL_THRESH 0x04
|
||||
#define WIIUSE_IR_THRESH 0x08
|
||||
#define WIIUSE_JS_THRESH 0x10
|
||||
#define WIIUSE_INIT_FLAGS WIIUSE_SMOOTHING
|
||||
|
||||
#define WIIUSE_ORIENT_PRECISION 100.0f
|
||||
|
||||
/* expansion codes */
|
||||
#define EXP_NONE 0
|
||||
#define EXP_NUNCHUK 1
|
||||
#define EXP_CLASSIC 2
|
||||
#define EXP_GUITAR_HERO_3 3
|
||||
#define EXP_WII_BOARD 4
|
||||
#define EXP_MOTION_PLUS 5
|
||||
|
||||
/* IR correction types */
|
||||
typedef enum ir_position_t {
|
||||
WIIUSE_IR_ABOVE,
|
||||
WIIUSE_IR_BELOW
|
||||
} ir_position_t;
|
||||
|
||||
/**
|
||||
* @brief Check if a button is pressed.
|
||||
* @param dev Pointer to a wiimote_t or expansion structure.
|
||||
* @param button The button you are interested in.
|
||||
* @return 1 if the button is pressed, 0 if not.
|
||||
*/
|
||||
#define IS_PRESSED(dev, button) ((dev->btns & button) == button)
|
||||
|
||||
/**
|
||||
* @brief Check if a button is being held.
|
||||
* @param dev Pointer to a wiimote_t or expansion structure.
|
||||
* @param button The button you are interested in.
|
||||
* @return 1 if the button is held, 0 if not.
|
||||
*/
|
||||
#define IS_HELD(dev, button) ((dev->btns_held & button) == button)
|
||||
|
||||
/**
|
||||
* @brief Check if a button is released on this event. \n\n
|
||||
* This does not mean the button is not pressed, it means \n
|
||||
* this button was just now released.
|
||||
* @param dev Pointer to a wiimote_t or expansion structure.
|
||||
* @param button The button you are interested in.
|
||||
* @return 1 if the button is released, 0 if not.
|
||||
*
|
||||
*/
|
||||
#define IS_RELEASED(dev, button) ((dev->btns_released & button) == button)
|
||||
|
||||
/**
|
||||
* @brief Check if a button has just been pressed this event.
|
||||
* @param dev Pointer to a wiimote_t or expansion structure.
|
||||
* @param button The button you are interested in.
|
||||
* @return 1 if the button is pressed, 0 if not.
|
||||
*/
|
||||
#define IS_JUST_PRESSED(dev, button) (IS_PRESSED(dev, button) && !IS_HELD(dev, button))
|
||||
|
||||
/**
|
||||
* @brief Return the IR sensitivity level.
|
||||
* @param wm Pointer to a wiimote_t structure.
|
||||
* @param lvl [out] Pointer to an int that will hold the level setting.
|
||||
* If no level is set 'lvl' will be set to 0.
|
||||
*/
|
||||
#define WIIUSE_GET_IR_SENSITIVITY(dev, lvl) \
|
||||
do { \
|
||||
if ((wm->state & 0x01000) == 0x01000) *lvl = 1; \
|
||||
else if ((wm->state & 0x02000) == 0x02000) *lvl = 2; \
|
||||
else if ((wm->state & 0x04000) == 0x04000) *lvl = 3; \
|
||||
else if ((wm->state & 0x08000) == 0x08000) *lvl = 4; \
|
||||
else if ((wm->state & 0x10000) == 0x10000) *lvl = 5; \
|
||||
else *lvl = 0; \
|
||||
} while (0)
|
||||
|
||||
#define WIIUSE_USING_ACC(wm) ((wm->state & 0x00100) == 0x00100)
|
||||
#define WIIUSE_USING_EXP(wm) ((wm->state & 0x00200) == 0x00200)
|
||||
#define WIIUSE_USING_IR(wm) ((wm->state & 0x00400) == 0x00400)
|
||||
#define WIIUSE_USING_SPEAKER(wm) ((wm->state & 0x00800) == 0x00800)
|
||||
|
||||
#define WIIUSE_IS_LED_SET(wm, num) ((wm->leds & WIIMOTE_LED_##num) == WIIMOTE_LED_##num)
|
||||
|
||||
/*
|
||||
* Largest known payload is 21 bytes.
|
||||
* Add 2 for the prefix and round up to a power of 2.
|
||||
*/
|
||||
#define MAX_PAYLOAD 32
|
||||
|
||||
/*
|
||||
* This is left over from an old hack, but it may actually
|
||||
* be a useful feature to keep so it wasn't removed.
|
||||
*/
|
||||
#ifdef WIN32
|
||||
#define WIIMOTE_DEFAULT_TIMEOUT 100
|
||||
#define WIIMOTE_EXP_TIMEOUT 100
|
||||
#endif
|
||||
|
||||
typedef unsigned char ubyte;
|
||||
typedef char sbyte;
|
||||
typedef unsigned short uword;
|
||||
typedef short sword;
|
||||
typedef unsigned int uint;
|
||||
typedef char sint;
|
||||
|
||||
|
||||
struct wiimote_t;
|
||||
struct vec3b_t;
|
||||
struct orient_t;
|
||||
struct gforce_t;
|
||||
|
||||
#ifdef GEKKO
|
||||
typedef void (*wii_event_cb)(struct wiimote_t*, s32 event);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Callback that handles a read event.
|
||||
*
|
||||
* @param wm Pointer to a wiimote_t structure.
|
||||
* @param data Pointer to the filled data block.
|
||||
* @param len Length in bytes of the data block.
|
||||
*
|
||||
* @see wiiuse_init()
|
||||
*
|
||||
* A registered function of this type is called automatically by the wiiuse
|
||||
* library when the wiimote has returned the full data requested by a previous
|
||||
* call to wiiuse_read_data().
|
||||
*/
|
||||
typedef void (*wiiuse_data_cb)(struct wiimote_t* wm, ubyte* data, unsigned short len);
|
||||
|
||||
typedef enum data_req_s
|
||||
{
|
||||
REQ_READY = 0,
|
||||
REQ_SENT,
|
||||
REQ_DONE
|
||||
} data_req_s;
|
||||
|
||||
/**
|
||||
* @struct data_req_t
|
||||
* @brief Data read request structure.
|
||||
*/
|
||||
struct data_req_t {
|
||||
lwp_node node;
|
||||
ubyte data[48]; /**< buffer where read data is written */
|
||||
unsigned int len;
|
||||
data_req_s state; /**< set to 1 if not using callback and needs to be cleaned up */
|
||||
wiiuse_data_cb cb; /**< read data callback */
|
||||
struct data_req_t *next;
|
||||
};
|
||||
|
||||
typedef void (*cmd_blk_cb)(struct wiimote_t *wm,ubyte *data,uword len);
|
||||
|
||||
typedef enum cmd_blk_s
|
||||
{
|
||||
CMD_READY = 0,
|
||||
CMD_SENT,
|
||||
CMD_DONE
|
||||
} cmd_blk_s;
|
||||
|
||||
struct cmd_blk_t
|
||||
{
|
||||
lwp_node node;
|
||||
|
||||
ubyte data[48];
|
||||
uint len;
|
||||
|
||||
cmd_blk_s state;
|
||||
cmd_blk_cb cb;
|
||||
|
||||
struct cmd_blk_t *next;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @struct vec2b_t
|
||||
* @brief Unsigned x,y byte vector.
|
||||
*/
|
||||
typedef struct vec2b_t {
|
||||
ubyte x, y;
|
||||
} vec2b_t;
|
||||
|
||||
|
||||
/**
|
||||
* @struct vec3b_t
|
||||
* @brief Unsigned x,y,z byte vector.
|
||||
*/
|
||||
typedef struct vec3b_t {
|
||||
ubyte x, y, z;
|
||||
} vec3b_t;
|
||||
|
||||
/**
|
||||
* @struct vec3b_t
|
||||
* @brief Unsigned x,y,z byte vector.
|
||||
*/
|
||||
typedef struct vec3w_t {
|
||||
uword x, y, z;
|
||||
} vec3w_t;
|
||||
|
||||
|
||||
/**
|
||||
* @struct vec3f_t
|
||||
* @brief Signed x,y,z float struct.
|
||||
*/
|
||||
typedef struct vec3f_t {
|
||||
float x, y, z;
|
||||
} vec3f_t;
|
||||
|
||||
|
||||
/**
|
||||
* @struct orient_t
|
||||
* @brief Orientation struct.
|
||||
*
|
||||
* Yaw, pitch, and roll range from -180 to 180 degrees.
|
||||
*/
|
||||
typedef struct orient_t {
|
||||
float roll; /**< roll, this may be smoothed if enabled */
|
||||
float pitch; /**< pitch, this may be smoothed if enabled */
|
||||
float yaw;
|
||||
|
||||
float a_roll; /**< absolute roll, unsmoothed */
|
||||
float a_pitch; /**< absolute pitch, unsmoothed */
|
||||
} orient_t;
|
||||
|
||||
|
||||
/**
|
||||
* @struct gforce_t
|
||||
* @brief Gravity force struct.
|
||||
*/
|
||||
typedef struct gforce_t {
|
||||
float x, y, z;
|
||||
} gforce_t;
|
||||
|
||||
|
||||
/**
|
||||
* @struct accel_t
|
||||
* @brief Accelerometer struct. For any device with an accelerometer.
|
||||
*/
|
||||
typedef struct accel_t {
|
||||
struct vec3w_t cal_zero; /**< zero calibration */
|
||||
struct vec3w_t cal_g; /**< 1g difference around 0cal */
|
||||
|
||||
float st_roll; /**< last smoothed roll value */
|
||||
float st_pitch; /**< last smoothed roll pitch */
|
||||
float st_alpha; /**< alpha value for smoothing [0-1] */
|
||||
} accel_t;
|
||||
|
||||
|
||||
/**
|
||||
* @struct ir_dot_t
|
||||
* @brief A single IR source.
|
||||
*/
|
||||
typedef struct ir_dot_t {
|
||||
ubyte visible; /**< if the IR source is visible */
|
||||
|
||||
short rx; /**< raw X coordinate (0-1023) */
|
||||
short ry; /**< raw Y coordinate (0-767) */
|
||||
|
||||
ubyte size; /**< size of the IR dot (0-15) */
|
||||
} ir_dot_t;
|
||||
|
||||
|
||||
typedef struct fdot_t {
|
||||
float x,y;
|
||||
} fdot_t;
|
||||
|
||||
typedef struct sb_t {
|
||||
fdot_t dots[2];
|
||||
fdot_t acc_dots[2];
|
||||
fdot_t rot_dots[2];
|
||||
float angle;
|
||||
float off_angle;
|
||||
float score;
|
||||
} sb_t;
|
||||
|
||||
/**
|
||||
* @enum aspect_t
|
||||
* @brief Screen aspect ratio.
|
||||
*/
|
||||
typedef enum aspect_t {
|
||||
WIIUSE_ASPECT_4_3,
|
||||
WIIUSE_ASPECT_16_9
|
||||
} aspect_t;
|
||||
|
||||
|
||||
/**
|
||||
* @struct ir_t
|
||||
* @brief IR struct. Hold all data related to the IR tracking.
|
||||
*/
|
||||
typedef struct ir_t {
|
||||
struct ir_dot_t dot[4]; /**< IR dots */
|
||||
ubyte num_dots; /**< number of dots at this time */
|
||||
|
||||
int state; /**< keeps track of the IR state */
|
||||
|
||||
int raw_valid; /**< is the raw position valid? */
|
||||
sb_t sensorbar; /**< sensor bar, detected or guessed */
|
||||
float ax; /**< raw X coordinate */
|
||||
float ay; /**< raw Y coordinate */
|
||||
float distance; /**< pixel width of the sensor bar */
|
||||
float z; /**< calculated distance in meters */
|
||||
float angle; /**< angle of the wiimote to the sensor bar*/
|
||||
|
||||
int smooth_valid; /**< is the smoothed position valid? */
|
||||
float sx; /**< smoothed X coordinate */
|
||||
float sy; /**< smoothed Y coordinate */
|
||||
float error_cnt; /**< error count, for smoothing algorithm*/
|
||||
float glitch_cnt; /**< glitch count, same */
|
||||
|
||||
int valid; /**< is the bounded position valid? */
|
||||
float x; /**< bounded X coordinate */
|
||||
float y; /**< bounded Y coordinate */
|
||||
enum aspect_t aspect; /**< aspect ratio of the screen */
|
||||
enum ir_position_t pos; /**< IR sensor bar position */
|
||||
unsigned int vres[2]; /**< IR virtual screen resolution */
|
||||
int offset[2]; /**< IR XY correction offset */
|
||||
|
||||
} ir_t;
|
||||
|
||||
|
||||
/**
|
||||
* @struct joystick_t
|
||||
* @brief Joystick calibration structure.
|
||||
*
|
||||
* The angle \a ang is relative to the positive y-axis into quadrant I
|
||||
* and ranges from 0 to 360 degrees. So if the joystick is held straight
|
||||
* upwards then angle is 0 degrees. If it is held to the right it is 90,
|
||||
* down is 180, and left is 270.
|
||||
*
|
||||
* The magnitude \a mag is the distance from the center to where the
|
||||
* joystick is being held. The magnitude ranges from 0 to 1.
|
||||
* If the joystick is only slightly tilted from the center the magnitude
|
||||
* will be low, but if it is closer to the outter edge the value will
|
||||
* be higher.
|
||||
*/
|
||||
typedef struct joystick_t {
|
||||
struct vec2b_t max; /**< maximum joystick values */
|
||||
struct vec2b_t min; /**< minimum joystick values */
|
||||
struct vec2b_t center; /**< center joystick values */
|
||||
struct vec2b_t pos; /**< raw position values */
|
||||
|
||||
float ang; /**< angle the joystick is being held */
|
||||
float mag; /**< magnitude of the joystick (range 0-1) */
|
||||
} joystick_t;
|
||||
|
||||
|
||||
/**
|
||||
* @struct nunchuk_t
|
||||
* @brief Nunchuk expansion device.
|
||||
*/
|
||||
typedef struct nunchuk_t {
|
||||
struct accel_t accel_calib; /**< nunchuk accelerometer calibration */
|
||||
struct joystick_t js; /**< joystick calibration */
|
||||
|
||||
int* flags; /**< options flag (points to wiimote_t.flags) */
|
||||
|
||||
ubyte btns; /**< what buttons have just been pressed */
|
||||
ubyte btns_last; /**< what buttons have just been pressed */
|
||||
ubyte btns_held; /**< what buttons are being held down */
|
||||
ubyte btns_released; /**< what buttons were just released this */
|
||||
|
||||
struct vec3w_t accel; /**< current raw acceleration data */
|
||||
struct orient_t orient; /**< current orientation on each axis */
|
||||
struct gforce_t gforce; /**< current gravity forces on each axis */
|
||||
} nunchuk_t;
|
||||
|
||||
|
||||
/**
|
||||
* @struct classic_ctrl_t
|
||||
* @brief Classic controller expansion device.
|
||||
*/
|
||||
typedef struct classic_ctrl_t {
|
||||
short btns; /**< what buttons have just been pressed */
|
||||
short btns_last; /**< what buttons have just been pressed */
|
||||
short btns_held; /**< what buttons are being held down */
|
||||
short btns_released; /**< what buttons were just released this */
|
||||
|
||||
ubyte rs_raw;
|
||||
ubyte ls_raw;
|
||||
|
||||
float r_shoulder; /**< right shoulder button (range 0-1) */
|
||||
float l_shoulder; /**< left shoulder button (range 0-1) */
|
||||
|
||||
struct joystick_t ljs; /**< left joystick calibration */
|
||||
struct joystick_t rjs; /**< right joystick calibration */
|
||||
ubyte type; /**< original, pro, wiiu pro */
|
||||
} classic_ctrl_t;
|
||||
|
||||
|
||||
/**
|
||||
* @struct guitar_hero_3_t
|
||||
* @brief Guitar Hero 3 expansion device.
|
||||
*/
|
||||
typedef struct guitar_hero_3_t {
|
||||
short btns; /**< what buttons have just been pressed */
|
||||
short btns_last; /**< what buttons have just been pressed */
|
||||
short btns_held; /**< what buttons are being held down */
|
||||
short btns_released; /**< what buttons were just released this */
|
||||
|
||||
ubyte wb_raw;
|
||||
float whammy_bar; /**< whammy bar (range 0-1) */
|
||||
|
||||
ubyte tb_raw;
|
||||
int touch_bar; /**< touch bar */
|
||||
|
||||
struct joystick_t js; /**< joystick calibration */
|
||||
} guitar_hero_3_t;
|
||||
|
||||
/**
|
||||
* @struct wii_board_t
|
||||
* @brief Wii Balance Board expansion device.
|
||||
*/
|
||||
typedef struct wii_board_t {
|
||||
float tl; /* Interpolated */
|
||||
float tr;
|
||||
float bl;
|
||||
float br; /* End interp */
|
||||
short rtl; /* RAW */
|
||||
short rtr;
|
||||
short rbl;
|
||||
short rbr; /* /RAW */
|
||||
short ctl[3]; /* Calibration */
|
||||
short ctr[3];
|
||||
short cbl[3];
|
||||
short cbr[3]; /* /Calibration */
|
||||
float x;
|
||||
float y;
|
||||
} wii_board_t;
|
||||
|
||||
typedef struct motion_plus_t
|
||||
{
|
||||
short rx, ry, rz;
|
||||
ubyte status;
|
||||
ubyte ext;
|
||||
} motion_plus_t;
|
||||
|
||||
/**
|
||||
* @struct expansion_t
|
||||
* @brief Generic expansion device plugged into wiimote.
|
||||
*/
|
||||
typedef struct expansion_t {
|
||||
int type; /**< type of expansion attached */
|
||||
|
||||
union {
|
||||
struct nunchuk_t nunchuk;
|
||||
struct classic_ctrl_t classic;
|
||||
struct guitar_hero_3_t gh3;
|
||||
struct wii_board_t wb;
|
||||
struct motion_plus_t mp;
|
||||
};
|
||||
} expansion_t;
|
||||
|
||||
|
||||
/**
|
||||
* @enum win32_bt_stack_t
|
||||
* @brief Available bluetooth stacks for Windows.
|
||||
*/
|
||||
typedef enum win_bt_stack_t {
|
||||
WIIUSE_STACK_UNKNOWN,
|
||||
WIIUSE_STACK_MS,
|
||||
WIIUSE_STACK_BLUESOLEIL
|
||||
} win_bt_stack_t;
|
||||
|
||||
|
||||
/**
|
||||
* @struct wiimote_state_t
|
||||
* @brief Significant data from the previous event.
|
||||
*/
|
||||
typedef struct wiimote_state_t {
|
||||
unsigned short btns;
|
||||
|
||||
struct ir_t ir;
|
||||
struct vec3w_t accel;
|
||||
struct expansion_t exp;
|
||||
} wiimote_state_t;
|
||||
|
||||
|
||||
/**
|
||||
* @enum WIIUSE_EVENT_TYPE
|
||||
* @brief Events that wiiuse can generate from a poll.
|
||||
*/
|
||||
typedef enum WIIUSE_EVENT_TYPE {
|
||||
WIIUSE_NONE = 0,
|
||||
WIIUSE_EVENT,
|
||||
WIIUSE_STATUS,
|
||||
WIIUSE_CONNECT,
|
||||
WIIUSE_DISCONNECT,
|
||||
WIIUSE_UNEXPECTED_DISCONNECT,
|
||||
WIIUSE_READ_DATA,
|
||||
WIIUSE_ACK,
|
||||
WIIUSE_NUNCHUK_INSERTED,
|
||||
WIIUSE_NUNCHUK_REMOVED,
|
||||
WIIUSE_CLASSIC_CTRL_INSERTED,
|
||||
WIIUSE_CLASSIC_CTRL_REMOVED,
|
||||
WIIUSE_GUITAR_HERO_3_CTRL_INSERTED,
|
||||
WIIUSE_GUITAR_HERO_3_CTRL_REMOVED,
|
||||
WIIUSE_WII_BOARD_INSERTED,
|
||||
WIIUSE_WII_BOARD_REMOVED,
|
||||
WIIUSE_MOTION_PLUS_ACTIVATED,
|
||||
WIIUSE_MOTION_PLUS_REMOVED
|
||||
} WIIUSE_EVENT_TYPE;
|
||||
|
||||
/**
|
||||
* @struct wiimote_t
|
||||
* @brief Wiimote structure.
|
||||
*/
|
||||
typedef struct wiimote_t {
|
||||
WCONST int unid; /**< user specified id */
|
||||
|
||||
#if defined(_WIN32)
|
||||
WCONST HANDLE dev_handle; /**< HID handle */
|
||||
WCONST OVERLAPPED hid_overlap; /**< overlap handle */
|
||||
WCONST enum win_bt_stack_t stack; /**< type of bluetooth stack to use */
|
||||
WCONST int timeout; /**< read timeout */
|
||||
WCONST ubyte normal_timeout; /**< normal timeout */
|
||||
WCONST ubyte exp_timeout; /**< timeout for expansion handshake */
|
||||
#elif defined(GEKKO)
|
||||
WCONST lwp_queue cmdq;
|
||||
WCONST struct bd_addr bdaddr; /**< bt address */
|
||||
WCONST char bdaddr_str[18]; /**< readable bt address */
|
||||
WCONST struct bte_pcb *sock; /**< output socket */
|
||||
WCONST wii_event_cb event_cb; /**< event callback */
|
||||
#elif defined(unix)
|
||||
WCONST bdaddr_t bdaddr; /**< bt address */
|
||||
WCONST char bdaddr_str[18]; /**< readable bt address */
|
||||
WCONST int out_sock; /**< output socket */
|
||||
WCONST int in_sock; /**< input socket */
|
||||
#endif
|
||||
|
||||
WCONST int state; /**< various state flags */
|
||||
WCONST ubyte leds; /**< currently lit leds */
|
||||
#ifdef GEKKO
|
||||
WCONST ubyte battery_level; /**< battery level */
|
||||
#else
|
||||
WCONST float battery_level; /**< battery level */
|
||||
#endif
|
||||
|
||||
WCONST int flags; /**< options flag */
|
||||
|
||||
WCONST ubyte handshake_state; /**< the state of the connection handshake */
|
||||
WCONST ubyte expansion_state; /**< the state of the expansion handshake */
|
||||
|
||||
WCONST struct data_req_t* data_req; /**< list of data read requests */
|
||||
|
||||
WCONST struct cmd_blk_t *cmd_head;
|
||||
WCONST struct cmd_blk_t *cmd_tail;
|
||||
|
||||
WCONST struct accel_t accel_calib; /**< wiimote accelerometer calibration */
|
||||
WCONST struct expansion_t exp; /**< wiimote expansion device */
|
||||
|
||||
WCONST struct vec3w_t accel; /**< current raw acceleration data */
|
||||
WCONST struct orient_t orient; /**< current orientation on each axis */
|
||||
WCONST struct gforce_t gforce; /**< current gravity forces on each axis */
|
||||
|
||||
WCONST struct ir_t ir; /**< IR data */
|
||||
|
||||
WCONST unsigned short btns; /**< what buttons are down */
|
||||
WCONST unsigned short btns_last; /**< what buttons were down before */
|
||||
WCONST unsigned short btns_held; /**< what buttons are and were held down */
|
||||
WCONST unsigned short btns_released; /**< what buttons were just released */
|
||||
|
||||
WCONST struct wiimote_state_t lstate; /**< last saved state */
|
||||
|
||||
WCONST WIIUSE_EVENT_TYPE event; /**< type of event that occured */
|
||||
WCONST ubyte event_buf[MAX_PAYLOAD]; /**< event buffer */
|
||||
|
||||
WCONST ubyte motion_plus_id[6];
|
||||
} wiimote;
|
||||
|
||||
#if defined(GEKKO)
|
||||
/**
|
||||
* @struct wiimote_listen_t
|
||||
* @brief Wiimote listen structure.
|
||||
*/
|
||||
typedef struct wiimote_listen_t {
|
||||
WCONST struct bd_addr bdaddr;
|
||||
WCONST struct bte_pcb *sock;
|
||||
WCONST struct wiimote_t *(*assign_cb)(struct bd_addr *bdaddr);
|
||||
WCONST struct wiimote_t *wm;
|
||||
} wiimote_listen;
|
||||
#endif
|
||||
|
||||
/*****************************************
|
||||
*
|
||||
* Include API specific stuff
|
||||
*
|
||||
*****************************************/
|
||||
|
||||
#ifdef _WIN32
|
||||
#define WIIUSE_EXPORT_DECL __declspec(dllexport)
|
||||
#define WIIUSE_IMPORT_DECL __declspec(dllimport)
|
||||
#else
|
||||
#define WIIUSE_EXPORT_DECL
|
||||
#define WIIUSE_IMPORT_DECL
|
||||
#endif
|
||||
|
||||
#ifdef WIIUSE_COMPILE_LIB
|
||||
#define WIIUSE_EXPORT WIIUSE_EXPORT_DECL
|
||||
#else
|
||||
#define WIIUSE_EXPORT WIIUSE_IMPORT_DECL
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* wiiuse.c */
|
||||
WIIUSE_EXPORT extern const char* wiiuse_version();
|
||||
|
||||
#ifndef GEKKO
|
||||
WIIUSE_EXPORT extern struct wiimote_t** wiiuse_init(int wiimotes);
|
||||
#else
|
||||
WIIUSE_EXPORT extern int wiiuse_register(struct wiimote_listen_t *wml, struct bd_addr *bdaddr, struct wiimote_t *(*assign_cb)(struct bd_addr *bdaddr));
|
||||
WIIUSE_EXPORT extern struct wiimote_t** wiiuse_init(int wiimotes, wii_event_cb event_cb);
|
||||
WIIUSE_EXPORT extern void wiiuse_sensorbar_enable(int enable);
|
||||
#endif
|
||||
|
||||
WIIUSE_EXPORT extern void wiiuse_disconnected(struct wiimote_t* wm);
|
||||
WIIUSE_EXPORT extern void wiiuse_cleanup(struct wiimote_t** wm, int wiimotes);
|
||||
WIIUSE_EXPORT extern void wiiuse_rumble(struct wiimote_t* wm, int status);
|
||||
WIIUSE_EXPORT extern void wiiuse_toggle_rumble(struct wiimote_t* wm);
|
||||
WIIUSE_EXPORT extern void wiiuse_set_leds(struct wiimote_t* wm, int leds,cmd_blk_cb cb);
|
||||
WIIUSE_EXPORT extern void wiiuse_motion_sensing(struct wiimote_t* wm, int status);
|
||||
WIIUSE_EXPORT extern int wiiuse_read_data(struct wiimote_t* wm, ubyte* buffer, unsigned int offset, unsigned short len, cmd_blk_cb cb);
|
||||
WIIUSE_EXPORT extern int wiiuse_write_data(struct wiimote_t *wm,unsigned int addr,ubyte *data,ubyte len,cmd_blk_cb cb);
|
||||
WIIUSE_EXPORT extern void wiiuse_status(struct wiimote_t *wm,cmd_blk_cb cb);
|
||||
WIIUSE_EXPORT extern struct wiimote_t* wiiuse_get_by_id(struct wiimote_t** wm, int wiimotes, int unid);
|
||||
WIIUSE_EXPORT extern int wiiuse_set_flags(struct wiimote_t* wm, int enable, int disable);
|
||||
WIIUSE_EXPORT extern float wiiuse_set_smooth_alpha(struct wiimote_t* wm, float alpha);
|
||||
WIIUSE_EXPORT extern void wiiuse_set_bluetooth_stack(struct wiimote_t** wm, int wiimotes, enum win_bt_stack_t type);
|
||||
WIIUSE_EXPORT extern void wiiuse_resync(struct wiimote_t* wm);
|
||||
WIIUSE_EXPORT extern void wiiuse_set_timeout(struct wiimote_t** wm, int wiimotes, ubyte normal_timeout, ubyte exp_timeout);
|
||||
WIIUSE_EXPORT extern int wiiuse_write_streamdata(struct wiimote_t *wm,ubyte *data,ubyte len,cmd_blk_cb cb);
|
||||
|
||||
/* connect.c */
|
||||
WIIUSE_EXPORT extern int wiiuse_find(struct wiimote_t** wm, int max_wiimotes, int timeout);
|
||||
WIIUSE_EXPORT extern int wiiuse_connect(struct wiimote_t** wm, int wiimotes);
|
||||
WIIUSE_EXPORT extern void wiiuse_disconnect(struct wiimote_t* wm);
|
||||
|
||||
/* events.c */
|
||||
WIIUSE_EXPORT extern int wiiuse_poll(struct wiimote_t** wm, int wiimotes);
|
||||
|
||||
/* ir.c */
|
||||
WIIUSE_EXPORT extern void wiiuse_set_ir_mode(struct wiimote_t *wm);
|
||||
WIIUSE_EXPORT extern void wiiuse_set_ir(struct wiimote_t* wm, int status);
|
||||
WIIUSE_EXPORT extern void wiiuse_set_ir_vres(struct wiimote_t* wm, unsigned int x, unsigned int y);
|
||||
WIIUSE_EXPORT extern void wiiuse_set_ir_position(struct wiimote_t* wm, enum ir_position_t pos);
|
||||
WIIUSE_EXPORT extern void wiiuse_set_aspect_ratio(struct wiimote_t* wm, enum aspect_t aspect);
|
||||
WIIUSE_EXPORT extern void wiiuse_set_ir_sensitivity(struct wiimote_t* wm, int level);
|
||||
|
||||
/* motion_plus.c */
|
||||
WIIUSE_EXPORT extern void wiiuse_set_motion_plus(struct wiimote_t *wm, int status);
|
||||
|
||||
/* speaker.c */
|
||||
WIIUSE_EXPORT extern void wiiuse_set_speaker(struct wiimote_t *wm, int status);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
277
external/libogc_ir/upstream/wiiuse_internal.h
vendored
Normal file
277
external/libogc_ir/upstream/wiiuse_internal.h
vendored
Normal file
|
|
@ -0,0 +1,277 @@
|
|||
/*
|
||||
* wiiuse
|
||||
*
|
||||
* Written By:
|
||||
* Michael Laforest < para >
|
||||
* Email: < thepara (--AT--) g m a i l [--DOT--] com >
|
||||
*
|
||||
* Copyright 2006-2007
|
||||
*
|
||||
* This file is part of wiiuse.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* $Header: /lvm/shared/ds/ds/cvs/devkitpro-cvsbackup/libogc/wiiuse/wiiuse_internal.h,v 1.8 2008-12-10 16:16:40 shagkur Exp $
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief General internal wiiuse stuff.
|
||||
*
|
||||
* Since Wiiuse is a library, wiiuse.h is a duplicate
|
||||
* of the API header.
|
||||
*
|
||||
* The code that would normally go in that file, but
|
||||
* which is not needed by third party developers,
|
||||
* is put here.
|
||||
*
|
||||
* So wiiuse_internal.h is included by other files
|
||||
* internally, wiiuse.h is included only here.
|
||||
*/
|
||||
|
||||
#ifndef WIIUSE_INTERNAL_H_INCLUDED
|
||||
#define WIIUSE_INTERNAL_H_INCLUDED
|
||||
|
||||
#if defined(__linux__)
|
||||
#include <arpa/inet.h> /* htons() */
|
||||
#include <bluetooth/bluetooth.h>
|
||||
#endif
|
||||
|
||||
#include "definitions.h"
|
||||
|
||||
/* wiiuse version */
|
||||
#define WIIUSE_VERSION "0.12"
|
||||
|
||||
/********************
|
||||
*
|
||||
* Wiimote internal codes
|
||||
*
|
||||
********************/
|
||||
|
||||
/* Communication channels */
|
||||
#define WM_OUTPUT_CHANNEL 0x11
|
||||
#define WM_INPUT_CHANNEL 0x13
|
||||
|
||||
#define WM_SET_REPORT 0x50
|
||||
#define WM_DATA 0xA0
|
||||
|
||||
/* commands */
|
||||
#define WM_CMD_RUMBLE 0x10
|
||||
#define WM_CMD_LED 0x11
|
||||
#define WM_CMD_REPORT_TYPE 0x12
|
||||
#define WM_CMD_IR 0x13
|
||||
#define WM_CMD_SPEAKER_ENABLE 0x14
|
||||
#define WM_CMD_CTRL_STATUS 0x15
|
||||
#define WM_CMD_WRITE_DATA 0x16
|
||||
#define WM_CMD_READ_DATA 0x17
|
||||
#define WM_CMD_STREAM_DATA 0x18
|
||||
#define WM_CMD_SPEAKER_MUTE 0x19
|
||||
#define WM_CMD_IR_2 0x1A
|
||||
|
||||
/* input report ids */
|
||||
#define WM_RPT_CTRL_STATUS 0x20
|
||||
#define WM_RPT_READ 0x21
|
||||
#define WM_RPT_ACK 0x22
|
||||
#define WM_RPT_BTN 0x30
|
||||
#define WM_RPT_BTN_ACC 0x31
|
||||
#define WM_RPT_BTN_ACC_IR 0x33
|
||||
#define WM_RPT_BTN_EXP 0x34
|
||||
#define WM_RPT_BTN_ACC_EXP 0x35
|
||||
#define WM_RPT_BTN_IR_EXP 0x36
|
||||
#define WM_RPT_BTN_ACC_IR_EXP 0x37
|
||||
|
||||
#define WM_BT_INPUT 0x01
|
||||
#define WM_BT_OUTPUT 0x02
|
||||
|
||||
/* Identify the wiimote device by its class */
|
||||
#define WM_DEV_CLASS_0 0x04
|
||||
#define WM_DEV_CLASS_1 0x25
|
||||
#define WM_DEV_CLASS_2 0x00
|
||||
#define WM_VENDOR_ID 0x057E
|
||||
#define WM_PRODUCT_ID 0x0306
|
||||
|
||||
/* controller status stuff */
|
||||
#define WM_MAX_BATTERY_CODE 0xC8
|
||||
|
||||
/* offsets in wiimote memory */
|
||||
#define WM_MEM_OFFSET_CALIBRATION 0x16
|
||||
#define WM_EXP_MEM_BASE 0x04A40000
|
||||
#define WM_EXP_MEM_ENABLE1 0x04A400F0
|
||||
#define WM_EXP_MEM_ENABLE2 0x04A400FB
|
||||
#define WM_EXP_MEM_KEY 0x04A40040
|
||||
#define WM_EXP_MEM_CALIBR 0x04A40020
|
||||
#define WM_EXP_MOTION_PLUS_ENABLE 0x04A600FE
|
||||
#define WM_EXP_ID 0x04A400FA
|
||||
|
||||
#define WM_REG_IR 0x04B00030
|
||||
#define WM_REG_IR_BLOCK1 0x04B00000
|
||||
#define WM_REG_IR_BLOCK2 0x04B0001A
|
||||
#define WM_REG_IR_MODENUM 0x04B00033
|
||||
|
||||
#define WM_REG_SPEAKER_REG1 0x04A20001
|
||||
#define WM_REG_SPEAKER_REG2 0x04A20008
|
||||
#define WM_REG_SPEAKER_REG3 0x04A20009
|
||||
#define WM_REG_SPEAKER_BLOCK 0x04A20001
|
||||
|
||||
/* ir block data */
|
||||
#define WM_IR_BLOCK1_LEVEL1 "\x02\x00\x00\x71\x01\x00\x64\x00\xfe"
|
||||
#define WM_IR_BLOCK2_LEVEL1 "\xfd\x05"
|
||||
#define WM_IR_BLOCK1_LEVEL2 "\x02\x00\x00\x71\x01\x00\x96\x00\xb4"
|
||||
#define WM_IR_BLOCK2_LEVEL2 "\xb3\x04"
|
||||
#define WM_IR_BLOCK1_LEVEL3 "\x02\x00\x00\x71\x01\x00\xaa\x00\x64"
|
||||
#define WM_IR_BLOCK2_LEVEL3 "\x63\x03"
|
||||
#define WM_IR_BLOCK1_LEVEL4 "\x02\x00\x00\x71\x01\x00\xc8\x00\x36"
|
||||
#define WM_IR_BLOCK2_LEVEL4 "\x35\x03"
|
||||
#define WM_IR_BLOCK1_LEVEL5 "\x07\x00\x00\x71\x01\x00\x72\x00\x20"
|
||||
#define WM_IR_BLOCK2_LEVEL5 "\x1f\x03"
|
||||
|
||||
#define WM_IR_TYPE_BASIC 0x01
|
||||
#define WM_IR_TYPE_EXTENDED 0x03
|
||||
#define WM_IR_TYPE_FULL 0x05
|
||||
|
||||
/* controller status flags for the first message byte */
|
||||
/* bit 1 is unknown */
|
||||
#define WM_CTRL_STATUS_BYTE1_ATTACHMENT 0x02
|
||||
#define WM_CTRL_STATUS_BYTE1_SPEAKER_ENABLED 0x04
|
||||
#define WM_CTRL_STATUS_BYTE1_IR_ENABLED 0x08
|
||||
#define WM_CTRL_STATUS_BYTE1_LED_1 0x10
|
||||
#define WM_CTRL_STATUS_BYTE1_LED_2 0x20
|
||||
#define WM_CTRL_STATUS_BYTE1_LED_3 0x40
|
||||
#define WM_CTRL_STATUS_BYTE1_LED_4 0x80
|
||||
|
||||
/* aspect ratio */
|
||||
#define WM_ASPECT_16_9_X 660
|
||||
#define WM_ASPECT_16_9_Y 370
|
||||
#define WM_ASPECT_4_3_X 560
|
||||
#define WM_ASPECT_4_3_Y 420
|
||||
|
||||
|
||||
/**
|
||||
* Expansion stuff
|
||||
*/
|
||||
|
||||
/* encrypted expansion id codes (located at 0x04A400FC) */
|
||||
#define EXP_ID_CODE_NUNCHUK 0xa4200000
|
||||
#define EXP_ID_CODE_CLASSIC_CONTROLLER 0xa4200101
|
||||
#define EXP_ID_CODE_CLASSIC_CONTROLLER_NYKOWING 0x90908f00
|
||||
#define EXP_ID_CODE_CLASSIC_CONTROLLER_NYKOWING2 0x9e9f9c00
|
||||
#define EXP_ID_CODE_CLASSIC_CONTROLLER_NYKOWING3 0x908f8f00
|
||||
#define EXP_ID_CODE_CLASSIC_CONTROLLER_GENERIC 0xa5a2a300
|
||||
#define EXP_ID_CODE_CLASSIC_CONTROLLER_GENERIC2 0x98999900
|
||||
#define EXP_ID_CODE_CLASSIC_CONTROLLER_GENERIC3 0xa0a1a000
|
||||
#define EXP_ID_CODE_CLASSIC_CONTROLLER_GENERIC4 0x8d8d8e00
|
||||
#define EXP_ID_CODE_CLASSIC_CONTROLLER_GENERIC5 0x93949400
|
||||
#define EXP_ID_CODE_CLASSIC_WIIU_PRO 0xa4200120
|
||||
#define EXP_ID_CODE_GUITAR 0xa4200103
|
||||
#define EXP_ID_CODE_WIIBOARD 0xa4200402
|
||||
#define EXP_ID_CODE_MOTION_PLUS 0xa4200405
|
||||
|
||||
#define EXP_HANDSHAKE_LEN 224
|
||||
|
||||
/********************
|
||||
*
|
||||
* End Wiimote internal codes
|
||||
*
|
||||
********************/
|
||||
|
||||
/* wiimote state flags - (some duplicated in wiiuse.h)*/
|
||||
#define WIIMOTE_STATE_DEV_FOUND 0x00001
|
||||
//#define WIIMOTE_STATE_DEV_REGISTER 0x00002
|
||||
#define WIIMOTE_STATE_HANDSHAKE 0x00004 /* actual connection exists but no handshake yet */
|
||||
#define WIIMOTE_STATE_HANDSHAKE_COMPLETE 0x00008 /* actual connection exists but no handshake yet */
|
||||
#define WIIMOTE_STATE_CONNECTED 0x00010
|
||||
#define WIIMOTE_STATE_EXP_HANDSHAKE 0x00020 /* actual connection exists but no handshake yet */
|
||||
#define WIIMOTE_STATE_EXP_FAILED 0x00040 /* actual connection exists but no handshake yet */
|
||||
#define WIIMOTE_STATE_RUMBLE 0x00080
|
||||
#define WIIMOTE_STATE_ACC 0x00100
|
||||
#define WIIMOTE_STATE_EXP 0x00200
|
||||
#define WIIMOTE_STATE_IR 0x00400
|
||||
#define WIIMOTE_STATE_SPEAKER 0x00800
|
||||
#define WIIMOTE_STATE_IR_SENS_LVL1 0x01000
|
||||
#define WIIMOTE_STATE_IR_SENS_LVL2 0x02000
|
||||
#define WIIMOTE_STATE_IR_SENS_LVL3 0x04000
|
||||
#define WIIMOTE_STATE_IR_SENS_LVL4 0x08000
|
||||
#define WIIMOTE_STATE_IR_SENS_LVL5 0x10000
|
||||
#define WIIMOTE_STATE_IR_INIT 0x20000
|
||||
#define WIIMOTE_STATE_SPEAKER_INIT 0x40000
|
||||
#define WIIMOTE_STATE_WIIU_PRO 0x80000
|
||||
|
||||
#define WIIMOTE_INIT_STATES (WIIMOTE_STATE_IR_SENS_LVL3)
|
||||
|
||||
/* macro to manage states */
|
||||
#define WIIMOTE_IS_SET(wm, s) ((wm->state & (s)) == (s))
|
||||
#define WIIMOTE_ENABLE_STATE(wm, s) (wm->state |= (s))
|
||||
#define WIIMOTE_DISABLE_STATE(wm, s) (wm->state &= ~(s))
|
||||
#define WIIMOTE_TOGGLE_STATE(wm, s) ((wm->state & (s)) ? WIIMOTE_DISABLE_STATE(wm, s) : WIIMOTE_ENABLE_STATE(wm, s))
|
||||
|
||||
#define WIIMOTE_IS_FLAG_SET(wm, s) ((wm->flags & (s)) == (s))
|
||||
#define WIIMOTE_ENABLE_FLAG(wm, s) (wm->flags |= (s))
|
||||
#define WIIMOTE_DISABLE_FLAG(wm, s) (wm->flags &= ~(s))
|
||||
#define WIIMOTE_TOGGLE_FLAG(wm, s) ((wm->flags & (s)) ? WIIMOTE_DISABLE_FLAG(wm, s) : WIIMOTE_ENABLE_FLAG(wm, s))
|
||||
|
||||
#define NUNCHUK_IS_FLAG_SET(wm, s) ((*(wm->flags) & (s)) == (s))
|
||||
|
||||
/* misc macros */
|
||||
#define WIIMOTE_ID(wm) (wm->unid)
|
||||
#define WIIMOTE_IS_CONNECTED(wm) (WIIMOTE_IS_SET(wm, WIIMOTE_STATE_CONNECTED))
|
||||
|
||||
/*
|
||||
* Smooth tilt calculations are computed with the
|
||||
* exponential moving average formula:
|
||||
* St = St_last + (alpha * (tilt - St_last))
|
||||
* alpha is between 0 and 1
|
||||
*/
|
||||
#define WIIUSE_DEFAULT_SMOOTH_ALPHA 0.3f
|
||||
|
||||
#define SMOOTH_ROLL 0x01
|
||||
#define SMOOTH_PITCH 0x02
|
||||
|
||||
#include <wiiuse/wiiuse.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct op_t
|
||||
{
|
||||
ubyte cmd;
|
||||
union {
|
||||
struct {
|
||||
uint addr;
|
||||
uword size;
|
||||
} readdata;
|
||||
struct {
|
||||
uint addr;
|
||||
ubyte size;
|
||||
ubyte data[16];
|
||||
} writedata;
|
||||
ubyte __data[MAX_PAYLOAD];
|
||||
};
|
||||
|
||||
void *buffer;
|
||||
int wait;
|
||||
} __attribute__((packed));
|
||||
|
||||
/* not part of the api */
|
||||
void wiiuse_init_cmd_queue(struct wiimote_t *wm);
|
||||
void wiiuse_send_next_command(struct wiimote_t *wm);
|
||||
int wiiuse_set_report_type(struct wiimote_t* wm,cmd_blk_cb cb);
|
||||
int wiiuse_sendcmd(struct wiimote_t *wm,ubyte report_type,ubyte *msg,int len,cmd_blk_cb cb);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* WIIUSE_INTERNAL_H_INCLUDED */
|
||||
Loading…
Add table
Add a link
Reference in a new issue