Last active
March 23, 2016 08:08
-
-
Save Ryochan7/8cb6264f3b3d27b8daa3 to your computer and use it in GitHub Desktop.
WiimoteGlue Experiments
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/Makefile b/Makefile | |
index 0350d14..c937f90 100644 | |
--- a/Makefile | |
+++ b/Makefile | |
@@ -1,5 +1,6 @@ | |
LINK_LIBS += -ludev | |
LINK_LIBS += -lxwiimote | |
+LINK_LIBS += -lm | |
EXTRA_CFLAGS += $(CONFIG_FLAGS) | |
wiimoteglue: src/*.c | |
diff --git a/src/device_management.c b/src/device_management.c | |
index a5442a3..46827dd 100644 | |
--- a/src/device_management.c | |
+++ b/src/device_management.c | |
@@ -142,6 +142,8 @@ int open_wii_device(struct wiimoteglue_state *state, struct wii_device* dev) { | |
} else { | |
xwii_iface_close(wiidev,XWII_IFACE_IR); | |
} | |
+ | |
+ xwii_iface_open(wiidev, XWII_IFACE_MOTION_PLUS); | |
/*LEDs only checked after opening, | |
*and we want to store the state | |
@@ -311,4 +313,4 @@ int set_led_state(struct wiimoteglue_state* state, struct wii_device *dev, bool | |
} | |
} | |
return okay; | |
-} | |
\ No newline at end of file | |
+} | |
diff --git a/src/epoll.c b/src/epoll.c | |
index 07a5411..35cef21 100644 | |
--- a/src/epoll.c | |
+++ b/src/epoll.c | |
@@ -1,6 +1,8 @@ | |
#include <sys/epoll.h> | |
#include <string.h> | |
#include <stdio.h> | |
+#include <sys/timeb.h> | |
+#include <unistd.h> | |
#include "wiimoteglue.h" | |
@@ -8,9 +10,10 @@ | |
* This should prevent using unecessary CPU time. | |
*/ | |
-#define EPOLL_MAX_EVENTS 10 | |
+#define EPOLL_MAX_EVENTS 100 | |
struct epoll_event event; | |
struct epoll_event events[EPOLL_MAX_EVENTS]; | |
+struct timeb the_time; | |
int wiimoteglue_epoll_init(int *epfd) { | |
*epfd = epoll_create(EPOLL_MAX_EVENTS); | |
@@ -53,8 +56,14 @@ void wiimoteglue_epoll_loop(int epfd, struct wiimoteglue_state *state) { | |
int n; | |
int i; | |
+ ftime(&the_time); | |
+ | |
while (state->keep_looping > 0) { | |
- n = epoll_wait(epfd, events, EPOLL_MAX_EVENTS, -1); | |
+ | |
+ struct timeb current_time; | |
+ ftime(¤t_time); | |
+ n = epoll_wait(epfd, events, EPOLL_MAX_EVENTS, 0); | |
+ | |
for (i = 0; i < n; i++) { | |
if (events[i].data.ptr == state->monitor) { | |
//HANDLE UDEV STUFF | |
@@ -74,6 +83,19 @@ void wiimoteglue_epoll_loop(int epfd, struct wiimoteglue_state *state) { | |
wiimoteglue_handle_wii_event(state,events[i].data.ptr); | |
} | |
} | |
+ | |
+ if (n == 0) | |
+ { | |
+ wiimoteglue_handle_ir_event(state); | |
+ //wiimoteglue_handle_mp_event(state); | |
+ ftime(&the_time); | |
+ | |
+ struct timespec temptime; | |
+ temptime.tv_sec = 0; | |
+ //temptime.tv_nsec = 16000000; | |
+ temptime.tv_nsec = 10000000; | |
+ nanosleep(&temptime, 0); | |
+ } | |
} | |
} | |
diff --git a/src/main.c b/src/main.c | |
index 6fe4a7b..0ab1cbd 100644 | |
--- a/src/main.c | |
+++ b/src/main.c | |
@@ -121,6 +121,7 @@ int main(int argc, char *argv[]) { | |
init_keyboardmouse_mappings(&keymouse->maps); | |
set_slot_specific_mappings(&state.slots[0],&keymouse->maps); | |
+ initIRTesting(); | |
/*The device list is cyclic*/ | |
state.dev_list.next = &state.dev_list; | |
diff --git a/src/process_xwiimote_events.c b/src/process_xwiimote_events.c | |
index 26e1270..b7f8ea6 100644 | |
--- a/src/process_xwiimote_events.c | |
+++ b/src/process_xwiimote_events.c | |
@@ -3,6 +3,8 @@ | |
#include <linux/input.h> | |
#include <string.h> | |
#include <unistd.h> | |
+#include <math.h> | |
+#include <sys/timeb.h> | |
#include "wiimoteglue.h" | |
@@ -13,6 +15,80 @@ | |
* | |
*/ | |
+static struct timeHelper | |
+{ | |
+ bool running; | |
+ struct timeb startTime; | |
+}; | |
+ | |
+extern struct irpos lastPos; | |
+extern struct testir_info ir_stuff[4]; | |
+ | |
+static bool ratchet = false; | |
+static bool holdCursor = false; | |
+static unsigned int holdCursorCount = 0; | |
+#define HOLDCURSORNUMPOLL 1 | |
+ | |
+static struct xwii_event_abs *currentIREvent = 0; | |
+ | |
+static struct xwii_event_abs currentIREvent2[XWII_ABS_NUM]; | |
+static struct xwii_event_abs currentAccelEvent2[XWII_ABS_NUM]; | |
+static struct xwii_event_abs currentMpEvent[XWII_ABS_NUM]; | |
+ | |
+static struct event_map* devicemapping = 0; | |
+static struct event_map* mpmapping = 0; | |
+static bool hasMpEvent = false; | |
+ | |
+static double remainderX = 0.0; | |
+static double remainderY = 0.0; | |
+ | |
+static double previousPointerRatioX = 0.5; | |
+static double previousPointerRatioY = 0.5; | |
+ | |
+#define SMOOTHXBUFFERLEN 2 | |
+#define SMOOTHYBUFFERLEN 2 | |
+ | |
+static int smoothXBuffer[SMOOTHXBUFFERLEN]; | |
+static int smoothYBuffer[SMOOTHYBUFFERLEN]; | |
+static int smoothXBufferLen = SMOOTHXBUFFERLEN; | |
+static int smoothYBufferLen = SMOOTHYBUFFERLEN; | |
+ | |
+static int smoothXBufferHead = 0; | |
+static int smoothYBufferHead = 0; | |
+static int smoothXBufferTail = 0; | |
+static int smoothYBufferTail = 0; | |
+static int smoothXBufferCount = 0; | |
+static int smoothYBufferCount = 0; | |
+ | |
+static struct timeHelper deltaEasingTimeX; | |
+static struct timeHelper deltaEasingTimeY; | |
+ | |
+static double accelHelperX = 0.0; | |
+static double accelHelperY = 0.0; | |
+ | |
+static double accelTravelX = 0.0; | |
+static double accelTravelY = 0.0; | |
+ | |
+static struct timeHelper outOfReachElapsed; | |
+static bool outOfReachStatus = true; | |
+ | |
+static struct timeHelper initialInReachElapsed; | |
+static bool initialInReachStatus = false; | |
+ | |
+static struct timeHelper regionEasingX; | |
+ | |
+static unsigned int calibratePollCount = 0; | |
+static bool wmpCalibrated = false; | |
+static int wmpSumCalibrateX = 0; | |
+static int wmpSumCalibrateY = 0; | |
+static int wmpFinalCalibrateX = 0; | |
+static int wmpFinalCalibrateY = 0; | |
+static unsigned int ignoreMpEventCount = 0; | |
+ | |
+// Measured in milliseconds | |
+static const int OUTOFREACH_ELAPSED_TIME = 1000; | |
+static const int INITIAL_INREACH_ELAPSED_TIME = 125; | |
+static const double PI = acos(-1.0); | |
void handle_key(int uinput_fd, int button_map[], struct xwii_event_key *ev); | |
@@ -22,6 +98,24 @@ void handle_pro(int uinput_fd, struct event_map *map, struct xwii_event_abs ev[] | |
void handle_accel(int uinput_fd, struct event_map *map, struct xwii_event_abs ev[]); | |
void handle_IR(int uinput_fd, struct event_map *map, struct xwii_event_abs ev[]); | |
void handle_balance(int uinput_fd, struct event_map *map, struct xwii_event_abs ev[]); | |
+void handle_mp(int uinput_fd, struct event_map *map, struct xwii_event_abs ev[]); | |
+ | |
+static void rotateIRPoints(double *x, double *y, double rotation); | |
+static double findIRRotation(float rawirx1, float rawirx2, | |
+ float rawiry1, float rawiry2); | |
+ | |
+static void addSmoothBufferValues(int xval, int yval); | |
+static void getSmoothBufferValues(int *xval, int *yval); | |
+ | |
+static void moveVirtualMouseTwo(int uinput_fd, int x, int y, bool outOfRange); | |
+ | |
+static void calibrateMpPoll(struct xwii_event_abs ev[]); | |
+ | |
+static unsigned int timeElapsedInMilliseconds(struct timeHelper *time); | |
+static void timeRestart(struct timeHelper *time); | |
+static void timeStop(struct timeHelper *time); | |
+static void timeStart(struct timeHelper *time); | |
+static void timeInit(struct timeHelper *time); | |
int wiimoteglue_update_all_wiimote_ifaces(struct wii_device_list *devlist) { | |
if (devlist == NULL) | |
@@ -91,6 +185,7 @@ int wiimoteglue_update_extensions(struct wiimoteglue_state *state, struct wii_de | |
int wiimoteglue_handle_wii_event(struct wiimoteglue_state *state, struct wii_device *dev) { | |
struct xwii_event ev; | |
+ | |
if (dev == NULL) { | |
return -1; | |
} | |
@@ -109,8 +204,8 @@ int wiimoteglue_handle_wii_event(struct wiimoteglue_state *state, struct wii_dev | |
struct event_map* mapping; | |
- | |
mapping = dev->map; | |
+ bool ireventused = false; | |
switch(ev.type) { | |
case XWII_EVENT_KEY: | |
@@ -129,19 +224,44 @@ int wiimoteglue_handle_wii_event(struct wiimoteglue_state *state, struct wii_dev | |
handle_pro(dev->slot->uinput_fd, mapping, ev.v.abs); | |
break; | |
case XWII_EVENT_ACCEL: | |
+ //handle_accel(dev->slot->uinput_fd, mapping, ev.v.abs); | |
+ memcpy(currentAccelEvent2, ev.v.abs, sizeof(struct xwii_event_abs[XWII_ABS_NUM])); | |
+ | |
handle_accel(dev->slot->uinput_fd, mapping, ev.v.abs); | |
break; | |
case XWII_EVENT_IR: | |
+ //handle_IR(dev->slot->uinput_fd, mapping, ev.v.abs); | |
+ if (currentIREvent) | |
+ { | |
+ free(currentIREvent); | |
+ currentIREvent = 0; | |
+ } | |
+ | |
+ currentIREvent = (struct xwii_event_abs*)malloc(sizeof(struct xwii_event_abs[XWII_ABS_NUM])); | |
+ memcpy(currentIREvent, ev.v.abs, sizeof(struct xwii_event_abs[XWII_ABS_NUM])); | |
+ | |
+ memcpy(currentIREvent2, ev.v.abs, sizeof(struct xwii_event_abs[XWII_ABS_NUM])); | |
+ | |
+ //devicemapping = (struct event_map*)malloc(sizeof(struct event_map)); | |
+ //memcpy(devicemapping, mapping, sizeof(struct event_map)); | |
+ devicemapping = mapping; | |
handle_IR(dev->slot->uinput_fd, mapping, ev.v.abs); | |
break; | |
case XWII_EVENT_BALANCE_BOARD: | |
handle_balance(dev->slot->uinput_fd, mapping, ev.v.abs); | |
break; | |
+ case XWII_EVENT_MOTION_PLUS: | |
+ { | |
+ //handle_mp(dev->slot->uinput_fd, mapping, ev.v.abs); | |
+ mpmapping = mapping; | |
+ memcpy(currentMpEvent, ev.v.abs, sizeof(struct xwii_event_abs[XWII_ABS_NUM])); | |
+ hasMpEvent = true; | |
+ break; | |
+ } | |
case XWII_EVENT_WATCH: | |
case XWII_EVENT_GONE: | |
wiimoteglue_update_extensions(state,dev); | |
break; | |
- | |
} | |
} | |
@@ -160,6 +280,30 @@ void handle_key(int uinput_fd, int button_map[], struct xwii_event_key *ev) { | |
out.code = SYN_REPORT; | |
out.value = 0; | |
write(uinput_fd, &out, sizeof(out)); | |
+ | |
+ // Holding Nunchuk Z button locks view. | |
+ if (ev->code == XWII_KEY_Z && ev->state) | |
+ { | |
+ ratchet = true; | |
+ } | |
+ else if (ev->code == XWII_KEY_Z && !ev->state) | |
+ { | |
+ ratchet = false; | |
+ } | |
+ | |
+ if ((ev->code == XWII_KEY_A || ev->code == XWII_KEY_B) && ev->state) | |
+ { | |
+ // Pressing A or B button on Wiimote locks view for one poll. | |
+ // Duration could be longer but even one poll helps a lot. | |
+ holdCursor = true; | |
+ holdCursorCount = 0; | |
+ } | |
+ else if ((ev->code == XWII_KEY_A || ev->code == XWII_KEY_B) && !ev->state) | |
+ { | |
+ // Releasing A or B button on Wiimote locks view for one poll. | |
+ holdCursor = true; | |
+ holdCursorCount = 0; | |
+ } | |
} | |
void handle_nunchuk(int uinput_fd, struct event_map *map, struct xwii_event_abs ev[]) { | |
@@ -167,10 +311,10 @@ void handle_nunchuk(int uinput_fd, struct event_map *map, struct xwii_event_abs | |
memset(&out,0,sizeof(out)); | |
out.type = EV_ABS; | |
out.code = map->stick_map[WG_N_X][AXIS_CODE]; | |
- out.value = ev[0].x * map->stick_map[WG_N_X][AXIS_SCALE]; | |
+ out.value = (ev[0].x + 10) * map->stick_map[WG_N_X][AXIS_SCALE]; | |
write(uinput_fd, &out, sizeof(out)); | |
out.code = map->stick_map[WG_N_Y][AXIS_CODE]; | |
- out.value = ev[0].y * map->stick_map[WG_N_Y][AXIS_SCALE]; | |
+ out.value = (ev[0].y - 5) * map->stick_map[WG_N_Y][AXIS_SCALE]; | |
write(uinput_fd, &out, sizeof(out)); | |
out.type = EV_SYN; | |
@@ -182,13 +326,13 @@ void handle_nunchuk(int uinput_fd, struct event_map *map, struct xwii_event_abs | |
out.type = EV_ABS; | |
out.code = map->accel_map[WG_N_ACCELX][AXIS_CODE]; | |
- out.value = ev[1].x * map->accel_map[WG_N_ACCELX][AXIS_SCALE]; | |
+ out.value = ev[1].x * (map->accel_map[WG_N_ACCELX][AXIS_SCALE] / 2.0); | |
write(uinput_fd, &out, sizeof(out)); | |
out.code = map->accel_map[WG_N_ACCELY][AXIS_CODE]; | |
- out.value = ev[1].y * map->accel_map[WG_N_ACCELY][AXIS_SCALE]; | |
+ out.value = ev[1].y * (map->accel_map[WG_N_ACCELY][AXIS_SCALE] / 2.0); | |
write(uinput_fd, &out, sizeof(out)); | |
out.code = map->accel_map[WG_N_ACCELZ][AXIS_CODE]; | |
- out.value = ev[1].z * map->accel_map[WG_N_ACCELZ][AXIS_SCALE]; | |
+ out.value = ev[1].z * (map->accel_map[WG_N_ACCELZ][AXIS_SCALE] / 2.0); | |
write(uinput_fd, &out, sizeof(out)); | |
out.type = EV_SYN; | |
@@ -273,37 +417,401 @@ void handle_accel(int uinput_fd, struct event_map *map, struct xwii_event_abs ev | |
out.value = 0; | |
write(uinput_fd, &out, sizeof(out)); | |
} | |
+ | |
void handle_IR(int uinput_fd, struct event_map *map, struct xwii_event_abs ev[]) { | |
struct input_event out; | |
- memset(&out,0,sizeof(out)); | |
+ memset(&out, 0, sizeof(out)); | |
out.type = EV_ABS; | |
+ | |
int num = 0; | |
- float x = 1023; | |
- float y = 1023; | |
- int i; | |
+ int x = 1023; | |
+ int y = 1023; | |
+ | |
+ float ir_x[2]; | |
+ float ir_y[2]; | |
+ memset(&ir_x, 0, sizeof(ir_x)); | |
+ memset(&ir_y, 0, sizeof(ir_y)); | |
+ | |
+ bool outtest = true; | |
+ | |
+ int irfound = 0; | |
+ bool irseen[4]; | |
+ memset(&irseen, 0, sizeof(irseen)); | |
+ | |
+ for (int i = 0; i < 4; i++) | |
+ { | |
+ ir_stuff[i].x = ev[i].x; | |
+ ir_stuff[i].y = ev[i].y; | |
+ if ((ev[i].x != 0 || ev[i].y != 0) && | |
+ xwii_event_ir_is_valid(&ev[i])) | |
+ { | |
+ irfound++; | |
+ irseen[i] = true; | |
+ } | |
+ } | |
+ | |
+ if (irfound <= 1) | |
+ { | |
+ x = lastPos.x; | |
+ y = lastPos.y; | |
+ outtest = lastPos.outOfRange; | |
+ for (int i = 0; i < 4; i++) | |
+ { | |
+ ir_stuff[i].x = 1023; | |
+ ir_stuff[i].y = 1023; | |
+ ir_stuff[i].using = false; | |
+ } | |
+ | |
+ num = 0; | |
+ } | |
+ else if (irfound == 2) | |
+ { | |
+ int i = 0; | |
+ for (int j = 0; j < 4; j++) | |
+ { | |
+ ir_stuff[j].using = irseen[j]; | |
+ if (irseen[j]) | |
+ { | |
+ ir_x[i] = ir_stuff[j].x; | |
+ ir_y[i] = ir_stuff[j].y; | |
+ i++; | |
+ } | |
+ } | |
+ | |
+ x = (ir_x[0] + ir_x[1]) / 2.0; | |
+ y = (ir_y[0] + ir_y[1]) / 2.0; | |
+ num = 2; | |
+ } | |
+ // Perform action if more than 2 IR points are seen at once. | |
+ else if (irfound > 2) | |
+ { | |
+ int numActive = 0; | |
+ // Check for previously active points. | |
+ for (int i = 0; i < 4; i++) | |
+ { | |
+ if (ir_stuff[i].using && irseen[i]) | |
+ { | |
+ // Increment known seen IR trackers. | |
+ numActive++; | |
+ } | |
+ } | |
+ | |
+ // Only two points were previously seen. Use those IR points. | |
+ if (numActive == 2) | |
+ { | |
+ // Find two used IR trackers and get points. | |
+ int j = 0; | |
+ for (int i = 0; i < 4; i++) | |
+ { | |
+ if (ir_stuff[i].using) | |
+ { | |
+ // Found previously used IR tracker. Get IR point coordinates. | |
+ ir_x[j] = ir_stuff[i].x; | |
+ ir_y[j] = ir_stuff[i].y; | |
+ j++; | |
+ } | |
+ } | |
+ | |
+ x = (ir_x[0] + ir_x[1]) / 2.0; | |
+ y = (ir_y[0] + ir_y[1]) / 2.0; | |
+ num = 2; | |
+ } | |
+ // Don't apply mouse movement if not using only two IR points. | |
+ else | |
+ { | |
+ // Reset stats for IR trackers. | |
+ x = lastPos.x; | |
+ y = lastPos.y; | |
+ outtest = lastPos.outOfRange; | |
+ for (int i = 0; i < 4; i++) | |
+ { | |
+ ir_stuff[i].x = 1023; | |
+ ir_stuff[i].y = 1023; | |
+ ir_stuff[i].using = false; | |
+ } | |
+ | |
+ num = 0; | |
+ } | |
+ } | |
+ | |
+ /* | |
for (i = 0; i < 4; i++) { | |
int ir_x = ev[i].x; | |
int ir_y = ev[i].y; | |
+ | |
if (ir_x < x && ir_x != 1023 && ir_x > 1) { | |
x = ir_x; | |
y = ir_y; | |
num++; | |
} | |
} | |
- if (num != 0) { | |
- out.code = map->IR_map[WG_IR_X][AXIS_CODE]; | |
- out.value = (int) (-((x - 512) * map->IR_map[WG_IR_X][AXIS_SCALE])); | |
- write(uinput_fd, &out, sizeof(out)); | |
- out.code = map->IR_map[WG_IR_Y][AXIS_CODE]; | |
- out.value = (int) (((y - 380) * map->IR_map[WG_IR_Y][AXIS_SCALE])); | |
- write(uinput_fd, &out, sizeof(out)); | |
+ */ | |
+ | |
+ // Only use if two points have been found. | |
+ if (num != 0) | |
+ { | |
+ x = 1023 - x; | |
+ double xratio = x / 1023.0; | |
+ double yratio = y / 767.0; | |
+ | |
+ if (currentAccelEvent2) | |
+ { | |
+ double rotation = findIRRotation((double)ir_x[0], (double)ir_x[1], | |
+ (double)ir_y[0], (double)ir_y[1]); | |
+ | |
+ xratio = xratio - 0.5; | |
+ yratio = yratio - 0.5; | |
+ | |
+ rotateIRPoints(&xratio, &yratio, rotation); | |
+ | |
+ xratio = xratio + 0.5; | |
+ yratio = yratio + 0.5; | |
+ } | |
+ | |
+ //x = (int)floor(2557.50 * xratio - 767.19); | |
+ //y = (int)floor(1278.33 * yratio - 255.67); | |
+ | |
+ //x = (int)floor(2557.50 * xratio - 767.25); // Input: [0.3, 0.7] | |
+ //y = (int)floor(1534.00 * yratio - 460.20); // Input: [0.3, 0.8] | |
+ | |
+ x = (int)floor(3147.69 * xratio - 944.307); // input: [0.3, 0.625] | |
+ y = (int)floor(1917.50 * yratio - 575.25); // Input: [0.3, 0.7] | |
} | |
- out.type = EV_SYN; | |
- out.code = SYN_REPORT; | |
- out.value = 0; | |
- write(uinput_fd, &out, sizeof(out)); | |
+ if (x < 0) | |
+ { | |
+ x = 0; | |
+ } | |
+ else if (x > 1023) | |
+ { | |
+ x = 1023; | |
+ } | |
+ | |
+ if (y < 0) | |
+ { | |
+ y = 0; | |
+ } | |
+ else if (y > 767) | |
+ { | |
+ y = 767; | |
+ } | |
+ | |
+ lastPos.x = x; | |
+ lastPos.y = y; | |
+ lastPos.outOfRange = (num == 0); | |
} | |
+ | |
+void handle_mp(int uinput_fd, struct event_map *map, struct xwii_event_abs ev[]) | |
+{ | |
+ bool event_gen = false; | |
+ | |
+ if (holdCursor && holdCursorCount >= HOLDCURSORNUMPOLL) | |
+ { | |
+ holdCursor = false; | |
+ } | |
+ else if (holdCursor) | |
+ { | |
+ holdCursorCount++; | |
+ } | |
+ | |
+ bool moveMouse = !ratchet && !holdCursor; | |
+ | |
+ if (!wmpCalibrated) | |
+ { | |
+ if (ignoreMpEventCount >= 2) | |
+ { | |
+ calibrateMpPoll(ev); | |
+ moveMouse = moveMouse && wmpCalibrated; | |
+ if (wmpCalibrated) | |
+ { | |
+ ignoreMpEventCount = 0; | |
+ } | |
+ } | |
+ else | |
+ { | |
+ ignoreMpEventCount += 1; | |
+ moveMouse = false; | |
+ } | |
+ } | |
+ | |
+ if (moveMouse) | |
+ { | |
+ /*double calibrateX = -200.0; | |
+ double calibrateY = 750.0; | |
+ */ | |
+ double calibrateX = wmpFinalCalibrateX; | |
+ double calibrateY = wmpFinalCalibrateY; | |
+ | |
+ // Perform calibration compensation on raw coordinates. | |
+ int currentX = ev[0].x - calibrateX; | |
+ int currentY = ev[0].z - calibrateY; | |
+ double rotation = 0.0; | |
+ if (currentAccelEvent2) | |
+ { | |
+ rotation = atan2(currentAccelEvent2[0].x, currentAccelEvent2[0].z); | |
+ double nothingX = currentX; | |
+ double nothingY = currentY; | |
+ //printf("BEFORE: x(%d) | z(%d) | r(%f)\n", ev[0].x, ev[0].z, rotation); | |
+ // Transform coordinates depending on how the Wiimote is being | |
+ // held. | |
+ rotateIRPoints(¬hingX, ¬hingY, -rotation); | |
+ | |
+ // Temporarily disable second rotation transformation. | |
+ //rotateIRPoints(¬hingX, ¬hingY, 0.05); | |
+ //printf("AFTER: x(%f) | z(%f) | r(%f)\n", nothingX, nothingY, rotation); | |
+ ev[0].x = nothingX; | |
+ ev[0].z = nothingY; | |
+ } | |
+ else | |
+ { | |
+ ev[0].x = currentX; | |
+ ev[0].z = currentY; | |
+ } | |
+ | |
+ double deadzone = 225; | |
+ double tempdeadangle2 = atan2((ev[0].z), ev[0].x); | |
+ double tempdeadangle = atan2(ev[0].x, ev[0].z); | |
+ //double deadzoneX = deadzone * fabs(cos(rotation)); | |
+ //double deadzoneY = deadzone * 1.0 * fabs(sin(rotation)); | |
+ double deadzoneX = deadzone * fabs(cos(tempdeadangle2)); | |
+ double deadzoneY = deadzone * 1.0 * fabs(sin(tempdeadangle2)); | |
+ double deadzoneX2 = deadzone * fabs(cos(tempdeadangle2)); | |
+ double deadzoneY2 = deadzone * 1.0 * fabs(sin(tempdeadangle2)); | |
+ //printf("DEADS: x(%f) z(%f) r(%f)\n\n", deadzoneX, deadzoneY, rotation); | |
+ //printf("DEADS2: x(%f) z(%f) r(%f)\n", deadzoneX2, deadzoneY2, tempdeadangle2); | |
+ | |
+ double shiftX = 0.0; | |
+ double shiftY = 0.0; | |
+ | |
+ //printf("CHECKS: x(%f) z(%f)\n\n", abs(ev[0].x - calibrateX), abs(ev[0].z - calibrateY)); | |
+ | |
+ if (abs(ev[0].x) > deadzoneX) | |
+ { | |
+ double x_out = 0; | |
+ double signbit = ev[0].x >= 0 ? 1.0 : -1.0; | |
+ | |
+ double xratio = fmin((abs(ev[0].x) - deadzoneX) / (45000.0 - (deadzoneX)), 1.0); | |
+ x_out = (75.0 - 0.05) * (xratio) + 0.05; | |
+ x_out = x_out * signbit; | |
+ | |
+ //printf("INPUT X: %d | OUTPUT X: %f\n\n", ev[0].x, x_out); | |
+ | |
+ if ((remainderX >= 0) == (x_out >= 0)) | |
+ { | |
+ x_out += remainderX; | |
+ } | |
+ | |
+ // Make sure relative mouse movement does not exceed 127 pixels. | |
+ if (fabs(x_out) > 127) | |
+ { | |
+ x_out = (x_out < 0) ? -127 : 127; | |
+ } | |
+ | |
+ remainderX = 0.0; | |
+ | |
+ if (x_out > 0.0) | |
+ { | |
+ double temp = floor(x_out); | |
+ remainderX = x_out - temp; | |
+ x_out = temp; | |
+ } | |
+ else if (x_out < 0.0) | |
+ { | |
+ double temp = ceil(x_out); | |
+ remainderX = x_out - temp; | |
+ x_out = temp; | |
+ } | |
+ | |
+ if (x_out != 0.0) | |
+ { | |
+ struct input_event out; | |
+ memset(&out, 0, sizeof(out)); | |
+ out.type = EV_REL; | |
+ out.code = REL_X; | |
+ out.value = (int)x_out; | |
+ write(uinput_fd, &out, sizeof(out)); | |
+ | |
+ event_gen = true; | |
+ } | |
+ } | |
+ /*else | |
+ { | |
+ printf("JITTER X?: %d\n", ev[0].x); | |
+ } | |
+ */ | |
+ | |
+ if (abs(ev[0].z) > deadzoneY) | |
+ { | |
+ double y_out = 0; | |
+ double signbit = ev[0].z >= 0 ? -1.0 : 1.0; | |
+ | |
+ double yratio = fmin((abs(ev[0].z) - deadzoneY) / (45000.0 - (deadzoneY)), 1.0); | |
+ y_out = (75.0 - 0.05) * (yratio) + 0.05; | |
+ y_out = y_out * signbit; | |
+ | |
+ //printf("INPUT Y: %d | OUTPUT Y: %d | DEAD Y: %f\n\n", (ev[0].z - (int)calibrateY), y_out, deadzoneY); | |
+ | |
+ if ((remainderY >= 0) == (y_out >= 0)) | |
+ { | |
+ y_out += remainderY; | |
+ } | |
+ | |
+ // Make sure relative mouse movement does not exceed 127 pixels. | |
+ if (fabs(y_out) > 127) | |
+ { | |
+ y_out = (y_out < 0) ? -127 : 127; | |
+ } | |
+ | |
+ remainderY = 0.0; | |
+ | |
+ if (y_out > 0.0) | |
+ { | |
+ double temp = floor(y_out); | |
+ remainderY = y_out - temp; | |
+ y_out = temp; | |
+ } | |
+ else if (y_out < 0.0) | |
+ { | |
+ double temp = ceil(y_out); | |
+ remainderY = y_out - temp; | |
+ y_out = temp; | |
+ } | |
+ | |
+ if (y_out != 0.0) | |
+ { | |
+ struct input_event out; | |
+ memset(&out, 0, sizeof(out)); | |
+ out.type = EV_REL; | |
+ out.code = REL_Y; | |
+ out.value = (int)y_out; | |
+ write(uinput_fd, &out, sizeof(out)); | |
+ | |
+ event_gen = true; | |
+ } | |
+ } | |
+ /*else | |
+ { | |
+ printf("JITTER Y?: %d\n", ev[0].z); | |
+ } | |
+ */ | |
+ | |
+ if (event_gen) | |
+ { | |
+ struct input_event out; | |
+ memset(&out, 0, sizeof(out)); | |
+ out.type = EV_SYN; | |
+ out.code = SYN_REPORT; | |
+ out.value = 0; | |
+ write(uinput_fd, &out, sizeof(out)); | |
+ } | |
+ } | |
+ else | |
+ { | |
+ remainderX = 0.0; | |
+ remainderY = 0.0; | |
+ } | |
+} | |
+ | |
void handle_balance(int uinput_fd, struct event_map *map, struct xwii_event_abs ev[]) { | |
struct input_event out; | |
memset(&out,0,sizeof(out)); | |
@@ -340,4 +848,750 @@ void handle_balance(int uinput_fd, struct event_map *map, struct xwii_event_abs | |
} | |
+void initIRTesting() | |
+{ | |
+ memset(&ir_stuff, 0, sizeof(ir_stuff)); | |
+ for (int i = 0; i < 4; i++) | |
+ { | |
+ ir_stuff[i].x = 1023; | |
+ ir_stuff[i].y = 1023; | |
+ ir_stuff[i].using = false; | |
+ } | |
+ | |
+ lastPos.x = 1023; | |
+ lastPos.y = 1023; | |
+ lastPos.outOfRange = true; | |
+ | |
+ currentIREvent = 0; | |
+ memset(¤tAccelEvent2, 0, sizeof(currentAccelEvent2)); | |
+ memset(¤tIREvent2, 0, sizeof(currentIREvent2)); | |
+ memset(&smoothXBuffer, 0, sizeof(smoothXBuffer)); | |
+ memset(&smoothYBuffer, 0, sizeof(smoothYBuffer)); | |
+ timeInit(&deltaEasingTimeX); | |
+ timeInit(&deltaEasingTimeY); | |
+ timeInit(&outOfReachElapsed); | |
+ timeInit(&initialInReachElapsed); | |
+ timeInit(®ionEasingX); | |
+} | |
+ | |
+void rotateIRPoints(double *x, double *y, double rotation) | |
+{ | |
+ double sinAngle = sin(rotation); | |
+ double cosAngle = cos(rotation); | |
+ | |
+ double tempx = (*x) * cosAngle - (*y) * sinAngle; | |
+ double tempy = (*x) * sinAngle + (*y) * cosAngle; | |
+ *x = tempx; | |
+ *y = tempy; | |
+} | |
+ | |
+double findIRRotation(float rawirx1, float rawirx2, float rawiry1, float rawiry2) | |
+{ | |
+ double result = 0.0; | |
+ | |
+ int l = 0; | |
+ int leftPoint = 0; | |
+ int r = 0; | |
+ int orientation = 0; | |
+ | |
+ double accelX = currentAccelEvent2[0].x; | |
+ double accelZ = currentAccelEvent2[0].z; | |
+ | |
+ double absx = fabs(accelX); | |
+ double absz = fabs(accelZ); | |
+ | |
+ float tempirx[2]; | |
+ memset(&tempirx, 0, sizeof(tempirx)); | |
+ tempirx[0] = rawirx1; | |
+ tempirx[1] = rawirx2; | |
+ | |
+ float tempiry[2]; | |
+ memset(&tempiry, 0, sizeof(tempiry)); | |
+ tempiry[0] = rawiry1; | |
+ tempiry[1] = rawiry2; | |
+ | |
+ if (absz >= absx) | |
+ { | |
+ if (absz > 5) | |
+ { | |
+ orientation = (accelZ > 0) ? 0 : 2; | |
+ } | |
+ } | |
+ else | |
+ { | |
+ if (absx > 5) | |
+ { | |
+ orientation = (accelX > 0) ? 3 : 1; | |
+ } | |
+ } | |
+ | |
+ //orientation = 0; | |
+ //printf("ORIENTATION: %i\n", orientation); | |
+ | |
+ switch (orientation) | |
+ { | |
+ case 0: | |
+ { | |
+ l = (rawirx1 < rawirx2) ? 0 : 1; | |
+ break; | |
+ } | |
+ case 1: | |
+ { | |
+ l = (rawiry1 > rawiry2) ? 0 : 1; | |
+ break; | |
+ } | |
+ case 2: | |
+ { | |
+ l = (rawirx1 > rawirx2) ? 0 : 1; | |
+ break; | |
+ } | |
+ case 3: | |
+ { | |
+ l = (rawiry1 < rawiry2) ? 0 : 1; | |
+ break; | |
+ } | |
+ } | |
+ | |
+ leftPoint = l; | |
+ r = 1 - l; | |
+ | |
+ double dx = tempirx[r] - tempirx[l]; | |
+ double dy = tempiry[r] - tempiry[l]; | |
+ //double temper = (dx * dx) + (dy * dy); | |
+ double d = sqrt((dx * dx) + (dy * dy)); | |
+ | |
+ dx = dx / d; | |
+ dy = dy / d; | |
+ | |
+ result = atan2(dy, dx); | |
+ return result; | |
+} | |
+ | |
+void moveVirtualMouseTwo(int uinput_fd, int x, int y, bool outOfRange) | |
+{ | |
+ bool shouldMoveFPSCursor = !outOfReachStatus; | |
+ | |
+ if (!outOfRange) | |
+ { | |
+ outOfReachStatus = false; | |
+ if (outOfReachElapsed.running) | |
+ { | |
+ timeStop(&outOfReachElapsed); | |
+ } | |
+ | |
+ // Check if remote has moved into IR range. | |
+ if (initialInReachStatus) | |
+ { | |
+ if (!initialInReachElapsed.running) | |
+ { | |
+ // Start timer if not running. | |
+ timeRestart(&initialInReachElapsed); | |
+ } | |
+ | |
+ if (initialInReachElapsed.running) | |
+ { | |
+ unsigned int elapsed = timeElapsedInMilliseconds(&initialInReachElapsed); | |
+ if (elapsed < INITIAL_INREACH_ELAPSED_TIME) | |
+ { | |
+ shouldMoveFPSCursor = false; | |
+ } | |
+ else | |
+ { | |
+ shouldMoveFPSCursor = true; | |
+ initialInReachStatus = false; | |
+ timeStop(&initialInReachElapsed); | |
+ } | |
+ } | |
+ } | |
+ else | |
+ { | |
+ shouldMoveFPSCursor = true; | |
+ } | |
+ } | |
+ else if (!outOfReachStatus) | |
+ { | |
+ if (!outOfReachElapsed.running) | |
+ { | |
+ timeRestart(&outOfReachElapsed); | |
+ } | |
+ | |
+ if (outOfReachElapsed.running) | |
+ { | |
+ unsigned int elapsed = timeElapsedInMilliseconds(&outOfReachElapsed); | |
+ if (elapsed >= OUTOFREACH_ELAPSED_TIME) | |
+ { | |
+ outOfReachStatus = true; | |
+ timeStop(&outOfReachElapsed); | |
+ //printf("STOPPING OUT OF RANGE\n"); | |
+ } | |
+ else | |
+ { | |
+ outOfReachStatus = false; | |
+ } | |
+ } | |
+ } | |
+ | |
+ // Checks show that remote should be considered in IR range. | |
+ if (shouldMoveFPSCursor) | |
+ //if (!outOfReachStatus) | |
+ { | |
+ double xratio = x / 1023.0; | |
+ double yratio = y / 767.0; | |
+ addSmoothBufferValues(x, y); | |
+ | |
+ int smoothX = 0; | |
+ int smoothY = 0; | |
+ getSmoothBufferValues(&smoothX, &smoothY); | |
+ xratio = smoothX / 1023.0; | |
+ yratio = smoothY / 767.0; | |
+ | |
+ double deadzone = 0.018; | |
+ //double fps_mouse_speed = 25.0; | |
+ double fps_mouse_speed = 20.0; | |
+ | |
+ double tempdeadangle = atan2(-(yratio - 0.5), xratio - 0.5); | |
+ double deadzoneX = deadzone * fabs(cos(tempdeadangle)); | |
+ double deadzoneY = deadzone * 1.0 * fabs(sin(tempdeadangle)); | |
+ | |
+ double testAccelMulti = 4.0; | |
+ double testAccelMinTravel = 0.08; | |
+ double testAccelMaxTravel = 0.425; | |
+ double testAccelEasingDuration = 0.03; | |
+ double testRegionEasingXDuration = 0.025; | |
+ bool testDeltaAccel = true; | |
+ | |
+ double shiftX = 0.0; | |
+ double shiftY = 0.0; | |
+ | |
+ if (fabs(xratio - 0.5) > deadzoneX) | |
+ { | |
+ if (xratio >= 0.5) | |
+ { | |
+ shiftX = (xratio - 0.5 - deadzoneX) / (1.0 - 0.5 - deadzoneX); | |
+ } | |
+ else | |
+ { | |
+ shiftX = (xratio - (0.5 - deadzoneX)) / (1.0 - 0.5 - deadzoneX); | |
+ } | |
+ } | |
+ | |
+ if (fabs(yratio - 0.5) > deadzoneY) | |
+ { | |
+ if (yratio >= 0.5) | |
+ { | |
+ shiftY = (yratio - 0.5 - deadzoneY) / (1.0 - 0.5 - deadzoneY); | |
+ } | |
+ else | |
+ { | |
+ shiftY = (yratio - (0.5 - deadzoneY)) / (1.0 - 0.5 - deadzoneY); | |
+ } | |
+ } | |
+ | |
+ double signshiftX = (shiftX >= 0) ? 1.0 : -1.0; | |
+ double signshiftY = (shiftY >= 0) ? 1.0 : -1.0; | |
+ | |
+ double absX = fabs(shiftX); | |
+ double absY = fabs(shiftY); | |
+ | |
+ if (absX <= 0.75 && regionEasingX.running) | |
+ { | |
+ // No longer in easing region | |
+ timeStop(®ionEasingX); | |
+ } | |
+ else if (absX > 0.75 && regionEasingX.running && | |
+ (previousPointerRatioX >= 0.5) != (xratio >= 0.5)) | |
+ { | |
+ // Direction changed quickly. Restart easing timer. | |
+ timeRestart(®ionEasingX); | |
+ } | |
+ | |
+ if (absX <= 0.4) | |
+ { | |
+ shiftX = 0.395 * absX; | |
+ } | |
+ else if (absX <= 0.75) | |
+ { | |
+ shiftX = 1.0 * absX - 0.242; | |
+ } | |
+ else | |
+ { | |
+ double tempAbsx = absX; | |
+ bool enableRegionEasing = testRegionEasingXDuration > 0.0; | |
+ if (enableRegionEasing) | |
+ { | |
+ double easingDuration = testRegionEasingXDuration; | |
+ double easingElapsed = 0.0; | |
+ double elapsedDiff = 1.0; | |
+ double regionEasingXOffset = 0.8; | |
+ if (regionEasingX.running) | |
+ { | |
+ easingElapsed = timeElapsedInMilliseconds(®ionEasingX); | |
+ } | |
+ else | |
+ { | |
+ timeRestart(®ionEasingX); | |
+ } | |
+ | |
+ double adjustedEasingDuration = ((4.0 * absX) - 3.0) * easingDuration; | |
+ //double adjustedEasingDuration = easingDuration; | |
+ if (easingDuration > 0.0 && adjustedEasingDuration > 0.0 && | |
+ (easingElapsed * 0.001) < adjustedEasingDuration) | |
+ { | |
+ //elapsedDiff = (easingElapsed * 0.001) / easingDuration; | |
+ //double minAbsRegionX = 0.75; | |
+ double minAbsRegionX = absX + (regionEasingXOffset * (absX - 0.75)); | |
+ elapsedDiff = (easingElapsed * 0.001) / adjustedEasingDuration; | |
+ //elapsedDiff = (absX - 0.75) * elapsedDiff + 0.75; | |
+ elapsedDiff = (absX - minAbsRegionX) * elapsedDiff + minAbsRegionX; | |
+ } | |
+ else | |
+ { | |
+ elapsedDiff = absX; | |
+ } | |
+ | |
+ tempAbsx = elapsedDiff; | |
+ } | |
+ | |
+ shiftX = 1.968 * absX - 0.968; | |
+ } | |
+ | |
+ if (absY <= 0.4) | |
+ { | |
+ shiftY = 0.395 * absY; | |
+ } | |
+ else if (absY <= 0.75) | |
+ { | |
+ shiftY = 1.0 * absY - 0.242; | |
+ } | |
+ else | |
+ { | |
+ shiftY = 1.968 * absY - 0.968; | |
+ } | |
+ | |
+ // Add sign bit | |
+ shiftX = signshiftX * shiftX; | |
+ shiftY = signshiftY * shiftY; | |
+ | |
+ // Calculate delta acceleration slope and offset. | |
+ double accelSlope = (testAccelMulti - 1.0) / (testAccelMaxTravel - testAccelMinTravel); | |
+ double accelOffset = 1.0 - (accelSlope * testAccelMinTravel); | |
+ | |
+ // If deltaX >= 0.1 and displacement is increasing then | |
+ // use acceleration multiplier. | |
+ if (testDeltaAccel && fabs(previousPointerRatioX - xratio) >= testAccelMinTravel && | |
+ (xratio - previousPointerRatioX >= 0.0) == (xratio >= 0.5)) | |
+ { | |
+ double tempTravel = fmin(fabs(previousPointerRatioX - xratio), testAccelMaxTravel); | |
+ if (accelHelperX > 1.0) | |
+ { | |
+ // Already in acceleration mode. Add accel | |
+ // dead zone to travel. | |
+ tempTravel = fmin(tempTravel + testAccelMinTravel, testAccelMaxTravel); | |
+ } | |
+ | |
+ double tempDist = fmin(tempTravel, testAccelMaxTravel); | |
+ | |
+ shiftX = shiftX * (accelSlope * tempDist + accelOffset); | |
+ previousPointerRatioX = xratio; | |
+ accelHelperX = (accelSlope * tempDist + accelOffset); | |
+ accelTravelX = tempTravel; | |
+ timeRestart(&deltaEasingTimeX); | |
+ } | |
+ else if (testDeltaAccel && testAccelEasingDuration > 0.0 && | |
+ accelHelperX > 0.0 && | |
+ fabs(xratio - previousPointerRatioX) < testAccelMinTravel && | |
+ (previousPointerRatioX >= 0.5) == (xratio >= 0.5)) | |
+ { | |
+ unsigned int timeElapsed = timeElapsedInMilliseconds(&deltaEasingTimeX); | |
+ double elapsedDiff = 1.0; | |
+ double tempAccel = accelHelperX; | |
+ double tempTravel = accelTravelX; | |
+ | |
+ if ((xratio - previousPointerRatioX >= 0.0) != (xratio >= 0.5)) | |
+ { | |
+ // Travelling towards dead zone. Decrease acceleration and duration. | |
+ tempTravel = fmin(fabs(previousPointerRatioX - xratio), testAccelMaxTravel); | |
+ tempTravel = fmax(fmin((accelTravelX - tempTravel), testAccelMaxTravel), testAccelMinTravel); | |
+ tempAccel = (accelSlope * tempTravel + accelOffset); | |
+ } | |
+ | |
+ double elapsedDuration = testAccelEasingDuration * (tempAccel / testAccelMulti); | |
+ if ((timeElapsed * 0.001) < elapsedDuration) | |
+ { | |
+ elapsedDiff = ((timeElapsed * 0.001) / elapsedDuration); | |
+ elapsedDiff = (1.0 - tempAccel) * (elapsedDiff * elapsedDiff * elapsedDiff) + tempAccel; | |
+ shiftX = elapsedDiff * shiftX; | |
+ } | |
+ else | |
+ { | |
+ // Easing time has ended. Reset values. | |
+ previousPointerRatioX = xratio; | |
+ accelHelperX = 0.0; | |
+ accelTravelX = 0.0; | |
+ timeStop(&deltaEasingTimeX); | |
+ } | |
+ } | |
+ else | |
+ { | |
+ // Don't apply acceleration. Reset values. | |
+ previousPointerRatioX = xratio; | |
+ accelHelperX = 0.0; | |
+ accelTravelX = 0.0; | |
+ if (deltaEasingTimeX.running) | |
+ { | |
+ timeStop(&deltaEasingTimeX); | |
+ } | |
+ } | |
+ | |
+ // If deltaY >= 0.1 and displacement is increasing then | |
+ // use acceleration multiplier. | |
+ if (testDeltaAccel && fabs(previousPointerRatioY - yratio) >= testAccelMinTravel && | |
+ (yratio - previousPointerRatioY >= 0.0) == (yratio >= 0.5)) | |
+ { | |
+ double tempTravel = fmin(fabs(previousPointerRatioY - yratio), testAccelMaxTravel); | |
+ if (accelHelperY > 1.0) | |
+ { | |
+ // Already in acceleration mode. Add accel | |
+ // dead zone to travel. | |
+ tempTravel = fmin(tempTravel + testAccelMinTravel, testAccelMaxTravel); | |
+ } | |
+ | |
+ //double tempDist = fmin(tempTravel / 0.5, 1.0); | |
+ double tempDist = fmin(tempTravel, testAccelMaxTravel); | |
+ | |
+ shiftY = shiftY * (accelSlope * tempDist + accelOffset); | |
+ previousPointerRatioY = yratio; | |
+ accelHelperY = (accelSlope * tempDist + accelOffset); | |
+ accelTravelY = tempTravel; | |
+ timeRestart(&deltaEasingTimeY); | |
+ | |
+ //double tempDist = fmin((fabs(previousPointerRatioY - yratio) - 0.1) / 0.5, 1.0); | |
+ //shiftY = shiftY * (9.0 * tempDist + 1.0); | |
+ } | |
+ else if (testDeltaAccel && testAccelEasingDuration > 0.0 && | |
+ accelHelperY > 0.0 && | |
+ fabs(yratio - previousPointerRatioY) < testAccelMinTravel && | |
+ (previousPointerRatioY >= 0.5) == (yratio >= 0.5)) | |
+ { | |
+ unsigned int timeElapsed = timeElapsedInMilliseconds(&deltaEasingTimeY); | |
+ double elapsedDiff = 1.0; | |
+ double tempAccel = accelHelperY; | |
+ double tempTravel = accelTravelY; | |
+ | |
+ if ((yratio - previousPointerRatioY >= 0.0) != (yratio >= 0.5)) | |
+ { | |
+ // Travelling towards dead zone. Decrease acceleration and duration. | |
+ tempTravel = fmin(fabs(previousPointerRatioY - yratio), testAccelMaxTravel); | |
+ tempTravel = fmax(fmin((accelTravelY - tempTravel), testAccelMaxTravel), testAccelMinTravel); | |
+ tempAccel = (accelSlope * tempTravel + accelOffset); | |
+ } | |
+ | |
+ double elapsedDuration = testAccelEasingDuration * (tempAccel / testAccelMulti); | |
+ if ((timeElapsed * 0.001) < elapsedDuration) | |
+ { | |
+ elapsedDiff = ((timeElapsed * 0.001) / elapsedDuration); | |
+ elapsedDiff = (1.0 - tempAccel) * (elapsedDiff * elapsedDiff * elapsedDiff) + tempAccel; | |
+ shiftY = elapsedDiff * shiftY; | |
+ } | |
+ else | |
+ { | |
+ // Easing time has ended. Reset values. | |
+ previousPointerRatioY = yratio; | |
+ accelHelperY = 0.0; | |
+ accelTravelY = 0.0; | |
+ timeStop(&deltaEasingTimeY); | |
+ } | |
+ } | |
+ else | |
+ { | |
+ // Don't apply acceleration. Reset values. | |
+ previousPointerRatioY = yratio; | |
+ accelHelperY = 0.0; | |
+ accelTravelY = 0.0; | |
+ if (deltaEasingTimeY.running) | |
+ { | |
+ timeStop(&deltaEasingTimeY); | |
+ } | |
+ } | |
+ | |
+ // Find initial relative mouse speed. | |
+ double mouseX = fps_mouse_speed * shiftX; | |
+ double mouseY = fps_mouse_speed * shiftY; | |
+ | |
+ if ((remainderX >= 0) == (mouseX >= 0)) | |
+ { | |
+ mouseX += remainderX; | |
+ } | |
+ | |
+ if ((remainderY >= 0) == (mouseY >= 0)) | |
+ { | |
+ mouseY += remainderY; | |
+ } | |
+ | |
+ // Make sure relative mouse movement does not exceed 127 pixels. | |
+ if (fabs(mouseX) > 127) | |
+ { | |
+ mouseX = (mouseX < 0) ? -127 : 127; | |
+ } | |
+ | |
+ // Make sure relative mouse movement does not exceed 127 pixels. | |
+ if (fabs(mouseY) > 127) | |
+ { | |
+ mouseY = (mouseY < 0) ? -127 : 127; | |
+ } | |
+ | |
+ remainderX = 0.0; | |
+ remainderY = 0.0; | |
+ | |
+ if (mouseX > 0.0) | |
+ { | |
+ double temp = floor(mouseX); | |
+ remainderX = mouseX - temp; | |
+ mouseX = temp; | |
+ } | |
+ else if (mouseX < 0.0) | |
+ { | |
+ double temp = ceil(mouseX); | |
+ remainderX = mouseX - temp; | |
+ mouseX = temp; | |
+ } | |
+ | |
+ if (mouseY > 0.0) | |
+ { | |
+ double temp = floor(mouseY); | |
+ remainderY = mouseY - temp; | |
+ mouseY = temp; | |
+ } | |
+ else if (mouseY < 0.0) | |
+ { | |
+ double temp = ceil(mouseY); | |
+ remainderY = mouseY - temp; | |
+ mouseY = temp; | |
+ } | |
+ | |
+ struct input_event out; | |
+ memset(&out, 0, sizeof(out)); | |
+ | |
+ bool mouseEvent = (mouseX != 0 || mouseY != 0); | |
+ if (mouseEvent) | |
+ { | |
+ //printf("MOVING: X(%f) | Y(%f)\n\n", mouseX, mouseY); | |
+ | |
+ out.type = EV_REL; | |
+ out.code = REL_X; | |
+ out.value = (int)mouseX; | |
+ gettimeofday(&out.time, 0); | |
+ write(uinput_fd, &out, sizeof(out)); | |
+ | |
+ out.type = EV_REL; | |
+ out.code = REL_Y; | |
+ out.value = (int)mouseY; | |
+ gettimeofday(&out.time, 0); | |
+ write(uinput_fd, &out, sizeof(out)); | |
+ | |
+ out.type = EV_SYN; | |
+ out.code = SYN_REPORT; | |
+ out.value = 0; | |
+ gettimeofday(&out.time, 0); | |
+ write(uinput_fd, &out, sizeof(out)); | |
+ } | |
+ } | |
+ else | |
+ { | |
+ // Consider outside of IR range. Reset some values. | |
+ remainderX = 0.0; | |
+ remainderY = 0.0; | |
+ | |
+ accelHelperX = 0.0; | |
+ accelHelperY = 0.0; | |
+ accelTravelX = 0.0; | |
+ accelTravelY = 0.0; | |
+ | |
+ if (deltaEasingTimeX.running) | |
+ { | |
+ timeStop(&deltaEasingTimeX); | |
+ } | |
+ | |
+ if (deltaEasingTimeY.running) | |
+ { | |
+ timeStop(&deltaEasingTimeY); | |
+ } | |
+ | |
+ initialInReachStatus = true; | |
+ | |
+ if (regionEasingX.running) | |
+ { | |
+ timeStop(®ionEasingX); | |
+ } | |
+ } | |
+} | |
+ | |
+void wiimoteglue_handle_ir_event(struct wiimoteglue_state *state) | |
+{ | |
+ struct event_map *mapping = 0; | |
+ if (devicemapping) | |
+ { | |
+ mapping = devicemapping; | |
+ } | |
+ | |
+ if (currentIREvent2 && mapping) | |
+ { | |
+ handle_IR(state->virtual_keyboardmouse_fd, mapping, currentIREvent2); | |
+ | |
+ int x = lastPos.x; | |
+ int y = lastPos.y; | |
+ bool outOfRange = lastPos.outOfRange; | |
+ | |
+ moveVirtualMouseTwo(state->virtual_keyboardmouse_fd, x, y, outOfRange); | |
+ } | |
+} | |
+ | |
+void wiimoteglue_handle_mp_event(struct wiimoteglue_state *state) | |
+{ | |
+ if (mpmapping && hasMpEvent) | |
+ { | |
+ handle_mp(state->virtual_keyboardmouse_fd, mpmapping, currentMpEvent); | |
+ hasMpEvent = false; | |
+ mpmapping = 0; | |
+ } | |
+ else | |
+ { | |
+ remainderX = 0.0; | |
+ remainderY = 0.0; | |
+ } | |
+} | |
+ | |
+void addSmoothBufferValues(int xval, int yval) | |
+{ | |
+ smoothXBuffer[smoothXBufferTail] = xval; | |
+ smoothYBuffer[smoothXBufferTail] = yval; | |
+ | |
+ smoothXBufferTail++; | |
+ smoothXBufferTail++; | |
+ | |
+ smoothXBufferTail = smoothXBufferTail % smoothXBufferLen; | |
+ smoothXBufferTail = smoothXBufferTail % smoothYBufferLen; | |
+ | |
+ smoothXBufferCount = (int)fmin(smoothXBufferCount + 1, smoothXBufferLen); | |
+ smoothYBufferCount = (int)fmin(smoothYBufferCount + 1, smoothYBufferLen); | |
+ | |
+ if (smoothXBufferCount > 0 && smoothXBufferTail == smoothXBufferHead) | |
+ { | |
+ smoothXBufferHead = (smoothXBufferHead + 1) % smoothXBufferLen; | |
+ } | |
+ | |
+ if (smoothXBufferCount > 0 && smoothYBufferTail == smoothYBufferHead) | |
+ { | |
+ smoothYBufferHead = (smoothYBufferHead + 1) % smoothYBufferLen; | |
+ } | |
+} | |
+ | |
+void getSmoothBufferValues(int *xval, int *yval) | |
+{ | |
+ if (xval && yval && smoothXBufferCount > 0 && smoothYBufferCount > 0) | |
+ { | |
+ double tempx = 0.0; | |
+ double tempy = 0.0; | |
+ int xresult = 0; | |
+ int yresult = 0; | |
+ double currentWeight = 1.0; | |
+ double finalWeight = 0.0; | |
+ | |
+ for (int i = smoothXBufferTail; i != smoothXBufferHead; i = (i > 0) ? i-1 : smoothXBufferLen - 1) | |
+ { | |
+ int idx = i; | |
+ tempx += (smoothXBuffer[idx] * currentWeight); | |
+ finalWeight += currentWeight; | |
+ currentWeight *= 0.5; | |
+ } | |
+ | |
+ xresult = (int)(tempx / finalWeight); | |
+ *xval = xresult; | |
+ | |
+ currentWeight = 1.0; | |
+ finalWeight = 0.0; | |
+ | |
+ for (int i = smoothYBufferTail; i != smoothYBufferHead; i = (i > 0) ? i-1 : smoothYBufferLen - 1) | |
+ { | |
+ int idx = i; | |
+ tempy += (smoothYBuffer[idx] * currentWeight); | |
+ finalWeight += currentWeight; | |
+ currentWeight *= 0.5; | |
+ } | |
+ | |
+ | |
+ yresult = (int)(tempy / finalWeight); | |
+ *yval = yresult; | |
+ } | |
+} | |
+ | |
+void calibrateMpPoll(struct xwii_event_abs ev[]) | |
+{ | |
+ if (!wmpCalibrated) | |
+ { | |
+ wmpSumCalibrateX += ev[0].x; | |
+ wmpSumCalibrateY += ev[0].z; | |
+ calibratePollCount += 1; | |
+ | |
+ if (calibratePollCount >= 10) | |
+ { | |
+ wmpFinalCalibrateX = wmpSumCalibrateX / (int)calibratePollCount; | |
+ wmpFinalCalibrateY = wmpSumCalibrateY / (int)calibratePollCount; | |
+ wmpSumCalibrateX = wmpSumCalibrateY = 0; | |
+ wmpCalibrated = true; | |
+ } | |
+ } | |
+} | |
+ | |
+unsigned int timeElapsedInMilliseconds(struct timeHelper *time) | |
+{ | |
+ unsigned int result = 0; | |
+ if (time && time->running) | |
+ { | |
+ struct timeb current_time; | |
+ ftime(¤t_time); | |
+ result = ((unsigned int)(current_time.time * 1000 + current_time.millitm) - | |
+ (unsigned int)(time->startTime.time * 1000 + time->startTime.millitm)); | |
+ | |
+ result = (unsigned int)fmax(result, 0); | |
+ } | |
+ | |
+ return result; | |
+} | |
+ | |
+void timeRestart(struct timeHelper *time) | |
+{ | |
+ if (time) | |
+ { | |
+ ftime(&time->startTime); | |
+ time->running = true; | |
+ } | |
+} | |
+ | |
+void timeStop(struct timeHelper *time) | |
+{ | |
+ if (time && time->running) | |
+ { | |
+ ftime(&time->startTime); | |
+ time->running = false; | |
+ } | |
+} | |
+ | |
+void timeStart(struct timeHelper *time) | |
+{ | |
+ if (time) | |
+ { | |
+ ftime(&time->startTime); | |
+ time->running = true; | |
+ } | |
+} | |
+ | |
+void timeInit(struct timeHelper *time) | |
+{ | |
+ if (time) | |
+ { | |
+ time->running = false; | |
+ ftime(&time->startTime); | |
+ } | |
+} | |
diff --git a/src/uinput.c b/src/uinput.c | |
index 8a037ca..458e6ac 100644 | |
--- a/src/uinput.c | |
+++ b/src/uinput.c | |
@@ -139,7 +139,8 @@ int open_uinput_gamepad_fd(char* uinput_path) { | |
int open_uinput_keyboardmouse_fd(char* uinput_path) { | |
static int abs[] = { ABS_X, ABS_Y}; | |
- static int key[] = { BTN_LEFT, BTN_MIDDLE, BTN_RIGHT,BTN_TOUCH,BTN_TOOL_PEN}; | |
+ //static int key[] = { BTN_LEFT, BTN_MIDDLE, BTN_RIGHT,BTN_TOUCH,BTN_TOOL_PEN}; | |
+ static int key[] = { BTN_LEFT, BTN_MIDDLE, BTN_RIGHT}; | |
/* BTN_TOOL_PEN seems to successfully hint to evdev that | |
* we are going to be outputting absolute positions, | |
* not relative motions. | |
@@ -161,14 +162,14 @@ int open_uinput_keyboardmouse_fd(char* uinput_path) { | |
uidev.id.product = 0x1; | |
uidev.id.version = 1; | |
- ioctl(fd, UI_SET_EVBIT, EV_ABS); | |
+ /*ioctl(fd, UI_SET_EVBIT, EV_ABS); | |
for (i = 0; i < 2; i++) { | |
ioctl(fd, UI_SET_ABSBIT, abs[i]); | |
uidev.absmin[abs[i]] = -32768; | |
uidev.absmax[abs[i]] = 32768; | |
uidev.absflat[abs[i]] = 4096; | |
} | |
- | |
+ */ | |
/*Just set all possible keys that come before BTN_MISC | |
@@ -183,10 +184,14 @@ int open_uinput_keyboardmouse_fd(char* uinput_path) { | |
/*Set standard mouse buttons*/ | |
- for (i = 0; i < 5; i++) { | |
+ for (i = 0; i < 3; i++) { | |
ioctl(fd, UI_SET_KEYBIT, key[i]); | |
} | |
+ ioctl(fd, UI_SET_EVBIT, EV_REL); | |
+ ioctl(fd, UI_SET_RELBIT, REL_X); | |
+ ioctl(fd, UI_SET_RELBIT, REL_Y); | |
+ | |
write(fd, &uidev, sizeof(uidev)); | |
if (ioctl(fd, UI_DEV_CREATE) < 0) | |
perror("uinput device creation"); | |
diff --git a/src/wiimoteglue.h b/src/wiimoteglue.h | |
index d247024..4096b54 100644 | |
--- a/src/wiimoteglue.h | |
+++ b/src/wiimoteglue.h | |
@@ -8,9 +8,9 @@ | |
#define ABS_LIMIT 32767 | |
-#define TILT_LIMIT 80 | |
+#define TILT_LIMIT 95 | |
#define TILT_SCALE (ABS_LIMIT/TILT_LIMIT) | |
-#define NUNCHUK_LIMIT 90 | |
+#define NUNCHUK_LIMIT 92 | |
#define NUNCHUK_SCALE (ABS_LIMIT/NUNCHUK_LIMIT) | |
#define CLASSIC_LIMIT 22 | |
#define CLASSIC_SCALE (ABS_LIMIT/CLASSIC_LIMIT) | |
@@ -182,6 +182,27 @@ enum bal_axis { | |
WG_BAL_Y | |
}; | |
+struct testir_info | |
+{ | |
+ int x; | |
+ int y; | |
+ bool using; | |
+}; | |
+ | |
+struct testir_info ir_stuff[4]; | |
+ | |
+struct irpos | |
+{ | |
+ int x; | |
+ int y; | |
+ bool outOfRange; | |
+}; | |
+ | |
+struct irpos lastPos; | |
+ | |
+void initIRTesting(); | |
+ | |
+ | |
char* try_to_find_uinput(); | |
int wiimoteglue_uinput_close(int num_slots, struct virtual_controller slots[]); | |
int wiimoteglue_uinput_init(int num_slots, struct virtual_controller slots[], char* uinput_path); | |
@@ -200,6 +221,8 @@ int wiimoteglue_handle_input(struct wiimoteglue_state *state, int file); | |
int wiimoteglue_update_wiimote_ifaces(struct wii_device *dev); | |
int wiimoteglue_handle_wii_event(struct wiimoteglue_state *state, struct wii_device *dev); | |
+void wiimoteglue_handle_ir_event(struct wiimoteglue_state *state); | |
+void wiimoteglue_handle_mp_event(struct wiimoteglue_state *state); | |
struct virtual_controller* find_open_slot(struct wiimoteglue_state *state, int dev_type); | |
struct virtual_controller* lookup_slot(struct wiimoteglue_state* state, char* name); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Whoa. Quite a change compared to just taking the leftmost point. It looked pretty good in the video, at least as far I can tell by just watching the gameplay.
I'm glad WiimoteGlue offered you a starting point for experimentation. I've been using it to experiment as well, but mostly on the laughably terrible control scheme spectrum (such as playing a Zelda style game with the balance board).