Last active
July 24, 2018 06:06
-
-
Save Ryochan7/a288dcfe70445cb722207a1739541540 to your computer and use it in GitHub Desktop.
Changes made to MoltenGamepad for Wiimote Motion Plus support
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/source/core/devices/device.h b/source/core/devices/device.h | |
index b18ea24..7e548f1 100644 | |
--- a/source/core/devices/device.h | |
+++ b/source/core/devices/device.h | |
@@ -15,11 +15,10 @@ | |
#include "../../plugin/plugin.h" | |
- | |
class event_translator; | |
class advanced_event_translator; | |
class moltengamepad; | |
- | |
+class slot_manager; | |
class device_manager; | |
@@ -65,6 +64,7 @@ public: | |
void set_slot(output_slot* outdev); | |
output_slot* get_slot(); | |
+ slot_manager* get_slot_manager(); | |
void update_map(const char* evname, event_translator* trans); | |
void update_option(const char* opname, const MGField field); | |
@@ -143,6 +143,7 @@ protected: | |
void thread_loop(); | |
void process(void* tag); | |
+ void post_process(); | |
int process_option(const char* opname, const MGField field); | |
void print(std::string message); | |
diff --git a/source/core/devices/input_source.cpp b/source/core/devices/input_source.cpp | |
index b773376..cc27cdf 100644 | |
--- a/source/core/devices/input_source.cpp | |
+++ b/source/core/devices/input_source.cpp | |
@@ -180,6 +180,11 @@ output_slot* input_source::get_slot() { | |
return assigned_slot; | |
} | |
+slot_manager* input_source::get_slot_manager() | |
+{ | |
+ return manager->mg->slots; | |
+} | |
+ | |
void input_source::list_options(std::vector<option_info>& list) const { | |
devprofile->list_options(list); | |
} | |
@@ -336,7 +341,8 @@ void input_source::force_value(int id, int64_t value) { | |
void input_source::thread_loop() { | |
struct epoll_event event; | |
- struct epoll_event events[1]; | |
+ //struct epoll_event events[1]; | |
+ struct epoll_event events[50]; | |
memset(&event, 0, sizeof(event)); | |
memset(&last_recurring_update,0,sizeof(timespec)); | |
@@ -349,7 +355,8 @@ void input_source::thread_loop() { | |
timeout = timeout < 0 ? 0 : timeout; | |
} | |
- int n = epoll_wait(epfd, events, 1, timeout); | |
+ //int n = epoll_wait(epfd, events, 1, timeout); | |
+ int n = epoll_wait(epfd, events, 50, 0); | |
if (n < 0 && errno == EINTR) { | |
continue; | |
} | |
@@ -357,11 +364,15 @@ void input_source::thread_loop() { | |
perror("epoll wait:"); | |
break; | |
} | |
+ | |
if (do_recurring_events && (n == 0 || timeout == 0)) { | |
process_recurring_events(); | |
continue; | |
} | |
- if (events[0].data.ptr == this) { | |
+ | |
+ for (int i = 0; i < n; i++) | |
+ { | |
+ if (events[i].data.ptr == this) { | |
struct input_internal_msg msg; | |
int ret = 1; | |
ret = read(internalpipe, &msg, sizeof(msg)); | |
@@ -369,7 +380,19 @@ void input_source::thread_loop() { | |
handle_internal_message(msg); | |
} | |
} else { | |
- process(events[0].data.ptr); | |
+ process(events[i].data.ptr); | |
+ } | |
+ } | |
+ | |
+ if (n == 0) | |
+ { | |
+ post_process(); | |
+ | |
+ struct timespec temptime; | |
+ temptime.tv_sec = 0; | |
+ //temptime.tv_nsec = 16000000; | |
+ temptime.tv_nsec = 10000000; | |
+ nanosleep(&temptime, 0); | |
} | |
} | |
} | |
@@ -556,6 +579,14 @@ void input_source::process(void *tag) { | |
plugin.process_event(plug_data, tag); | |
} | |
+void input_source::post_process() | |
+{ | |
+ if (plugin.post_process) | |
+ { | |
+ plugin.post_process(plug_data); | |
+ } | |
+} | |
+ | |
int input_source::process_option(const char* opname, const MGField field) { | |
if (plugin.process_option) | |
return plugin.process_option(plug_data, opname, field); | |
diff --git a/source/core/eventlists/key_list.cpp b/source/core/eventlists/key_list.cpp | |
index 5f563c6..23dc7eb 100644 | |
--- a/source/core/eventlists/key_list.cpp | |
+++ b/source/core/eventlists/key_list.cpp | |
@@ -490,6 +490,7 @@ const event_listing key_list[] = { | |
{KEY_APPSELECT, "key_appselect", ""}, | |
{KEY_SCREENSAVER, "key_screensaver", ""}, | |
{KEY_VOICECOMMAND, "key_voicecommand", ""}, | |
+ {KEY_ASSISTANT, "key_assistant", ""}, | |
{KEY_BRIGHTNESS_MIN, "key_brightness_min", ""}, | |
{KEY_KBDINPUTASSIST_PREV, "key_kbdinputassist_prev", ""}, | |
{KEY_KBDINPUTASSIST_NEXT, "key_kbdinputassist_next", ""}, | |
@@ -515,6 +516,7 @@ const event_listing key_list[] = { | |
{KEY_FASTREVERSE, "key_fastreverse", ""}, | |
{KEY_SLOWREVERSE, "key_slowreverse", ""}, | |
{KEY_DATA, "key_data", ""}, | |
+ {KEY_ONSCREEN_KEYBOARD, "key_onscreen_keyboard", ""}, | |
{BTN_TRIGGER_HAPPY, "btn_trigger_happy", ""}, | |
{BTN_TRIGGER_HAPPY1, "btn_trigger_happy1", ""}, | |
{BTN_TRIGGER_HAPPY2, "btn_trigger_happy2", ""}, | |
diff --git a/source/core/output_slot.h b/source/core/output_slot.h | |
index c4e34fc..7d44f89 100644 | |
--- a/source/core/output_slot.h | |
+++ b/source/core/output_slot.h | |
@@ -3,6 +3,7 @@ | |
#include "uinput.h" | |
#include "eventlists/eventlist.h" | |
+#include <functional> | |
#include <iostream> | |
#include <string> | |
#include <map> | |
diff --git a/source/plugin/plugin.h b/source/plugin/plugin.h | |
index 2bfdab1..b81dea3 100644 | |
--- a/source/plugin/plugin.h | |
+++ b/source/plugin/plugin.h | |
@@ -101,6 +101,9 @@ struct device_plugin { | |
const char* (*get_type) (const void* plug_data); | |
//Called when the file descriptor provided via watch_file has data to be read. | |
int (*process_event) (void* plug_data, void* tag); | |
+ //Called after all events have been process in case a plugin wants | |
+ //to perform some processing using all data | |
+ void (*post_process) (void* plug_data); | |
//called when a device option is changed. | |
int (*process_option) (void* plug_data, const char* opname, MGField opvalue); | |
//Called to upload a force feedback effect. (A.K.A. Rumble vibration) | |
diff --git a/source/plugin/wiimote/wii_events.cpp b/source/plugin/wiimote/wii_events.cpp | |
index e979ab4..130a7d5 100644 | |
--- a/source/plugin/wiimote/wii_events.cpp | |
+++ b/source/plugin/wiimote/wii_events.cpp | |
@@ -127,9 +127,15 @@ void wiimote::process_core() { | |
send_value(offset + wm_down, ev.value); | |
break; | |
case BTN_A: | |
+ holdCursor = true; | |
+ holdCursorCount = 0; | |
+ holdCursorButtons = 1 << 0; | |
send_value(offset + wm_a, ev.value); | |
break; | |
case BTN_B: | |
+ holdCursor = true; | |
+ holdCursorCount = 0; | |
+ holdCursorButtons = 1 << 1; | |
send_value(offset + wm_b, ev.value); | |
break; | |
case BTN_1: | |
@@ -145,6 +151,14 @@ void wiimote::process_core() { | |
send_value(offset + wm_plus, ev.value); | |
break; | |
case BTN_MODE: | |
+ if (ev.value) | |
+ { | |
+ buttonstatus |= 1 << 0; | |
+ } | |
+ else | |
+ { | |
+ buttonstatus &= 0 << 0; | |
+ } | |
send_value(offset + wm_home, ev.value); | |
break; | |
case SYN_REPORT: | |
@@ -152,6 +166,9 @@ void wiimote::process_core() { | |
} | |
} | |
} | |
+ | |
+ computeForceRatchet(); | |
+ | |
if (ret < 0) perror("read core"); | |
}; | |
@@ -236,8 +253,10 @@ void wiimote::process_classic(int fd) { | |
if (ret < 0) perror("read classic ext"); | |
} | |
-#define NUNCHUK_STICK_SCALE ABS_RANGE/85 | |
+//#define NUNCHUK_STICK_SCALE ABS_RANGE/85 | |
+#define NUNCHUK_STICK_SCALE ABS_RANGE/92 | |
#define NUNCHUK_ACCEL_SCALE ABS_RANGE/90 | |
+ | |
void wiimote::process_nunchuk(int fd) { | |
struct input_event ev; | |
int ret = read(fd, &ev, sizeof(ev)); | |
@@ -248,24 +267,32 @@ void wiimote::process_nunchuk(int fd) { | |
send_value(nk_c, ev.value); | |
break; | |
case BTN_Z: | |
+ ratchet = ev.value == 1 ? true : false; | |
+ // contain separately in case of reverse ratchet | |
+ zEngaged = ev.value == 1 ? true : false; | |
send_value(nk_z, ev.value); | |
break; | |
} | |
else if (ev.type == EV_ABS) switch (ev.code) { | |
case ABS_HAT0X: | |
- send_value(nk_stick_x, ev.value * NUNCHUK_STICK_SCALE); | |
+ send_value(nk_stick_x, (ev.value + 10) * NUNCHUK_STICK_SCALE); | |
+ //send_value(nk_stick_x, ev.value * NUNCHUK_STICK_SCALE); | |
break; | |
case ABS_HAT0Y: | |
- send_value(nk_stick_y, -ev.value * NUNCHUK_STICK_SCALE); | |
+ send_value(nk_stick_y, -(ev.value - 5) * NUNCHUK_STICK_SCALE); | |
+ //send_value(nk_stick_y, -ev.value * NUNCHUK_STICK_SCALE); | |
break; | |
case ABS_RX: | |
- send_value(nk_accel_x, ev.value * NUNCHUK_ACCEL_SCALE); | |
+ send_value(nk_accel_x, ev.value * (NUNCHUK_ACCEL_SCALE / 2.0)); | |
+ //send_value(nk_accel_x, ev.value * NUNCHUK_ACCEL_SCALE); | |
break; | |
case ABS_RY: | |
- send_value(nk_accel_y, ev.value * NUNCHUK_ACCEL_SCALE); | |
+ send_value(nk_accel_y, ev.value * (NUNCHUK_ACCEL_SCALE / 2.0)); | |
+ //send_value(nk_accel_y, ev.value * NUNCHUK_ACCEL_SCALE); | |
break; | |
case ABS_RZ: | |
- send_value(nk_accel_z, ev.value * NUNCHUK_ACCEL_SCALE); | |
+ send_value(nk_accel_z, ev.value * (NUNCHUK_ACCEL_SCALE / 2.0)); | |
+ //send_value(nk_accel_z, ev.value * NUNCHUK_ACCEL_SCALE); | |
break; | |
} | |
else { | |
@@ -295,12 +322,15 @@ void wiimote::process_accel(int fd) { | |
if (ret > 0) { | |
switch (ev.code) { | |
case ABS_RX: | |
+ accelcache[0] = ev.value; | |
send_value(offset + 0, ev.value * WIIMOTE_ACCEL_SCALE); | |
break; | |
case ABS_RY: | |
+ accelcache[1] = ev.value; | |
send_value(offset + 1, ev.value * WIIMOTE_ACCEL_SCALE); | |
break; | |
case ABS_RZ: | |
+ accelcache[2] = ev.value; | |
send_value(offset + 2, ev.value * WIIMOTE_ACCEL_SCALE); | |
break; | |
case SYN_REPORT: | |
@@ -513,6 +543,78 @@ void wiimote::process_pro(int fd) { | |
} | |
} | |
+ | |
+void wiimote::process_mp(int fd) | |
+{ | |
+ struct input_event ev; | |
+ int ret = 0; | |
+ while (ret = read(fd, &ev, sizeof(ev)) > 0) | |
+ { | |
+ switch(ev.code) | |
+ { | |
+ case ABS_RX: | |
+ mpcache[0] = ev.value; | |
+ hasMpEvent = true; | |
+ break; | |
+ case ABS_RY: | |
+ mpcache[1] = ev.value; | |
+ hasMpEvent = true; | |
+ break; | |
+ case ABS_RZ: | |
+ mpcache[2] = ev.value; | |
+ hasMpEvent = true; | |
+ break; | |
+ } | |
+ } | |
+} | |
+ | |
+void wiimote::computeForceRatchet() | |
+{ | |
+ static bool hamtaro = false; | |
+ | |
+ if (buttonstatus & 0x1) | |
+ { | |
+ if (!comboForceRatchet.running && !hamtaro) | |
+ { | |
+ timeRestart(&comboForceRatchet); | |
+ forceRatchet = false; | |
+ } | |
+ else | |
+ { | |
+ if (timeElapsedInMilliseconds(&comboForceRatchet) > 1000) | |
+ { | |
+ forceRatchet = true; | |
+ hamtaro = true; | |
+ timeStop(&comboForceRatchet); | |
+ } | |
+ } | |
+ } | |
+ else if (zEngaged) | |
+ { | |
+ if (comboForceRatchet.running) | |
+ { | |
+ timeStop(&comboForceRatchet); | |
+ } | |
+ | |
+ forceRatchet = false; | |
+ hamtaro = false; | |
+ } | |
+ else | |
+ { | |
+ if (comboForceRatchet.running) | |
+ { | |
+ if (!(timeElapsedInMilliseconds(&comboForceRatchet) > 1000)) | |
+ { | |
+ forceRatchet = false; | |
+ } | |
+ | |
+ timeStop(&comboForceRatchet); | |
+ } | |
+ | |
+ hamtaro = false; | |
+ } | |
+} | |
+ | |
#include <iostream> | |
int wiimote::upload_ff(const ff_effect* effect) { | |
int fd = buttons.fd; | |
diff --git a/source/plugin/wiimote/wii_plugin.cpp b/source/plugin/wiimote/wii_plugin.cpp | |
index 6672c65..56df4b1 100644 | |
--- a/source/plugin/wiimote/wii_plugin.cpp | |
+++ b/source/plugin/wiimote/wii_plugin.cpp | |
@@ -55,6 +55,10 @@ int wiimote_plugin_init(plugin_api api) { | |
((wiimote*)ref)->process(tag); | |
return 0; | |
}; | |
+ wiidev.post_process = [] (void* wm) -> void { | |
+ ((wiimote*)wm)->process_motionplus_mouse(); | |
+ }; | |
+ | |
wiidev.process_option = [] (void* ref, const char* opname, MGField opvalue) { | |
return ((wiimote*)ref)->process_option(opname, opvalue); | |
}; | |
diff --git a/source/plugin/wiimote/wiimote.cpp b/source/plugin/wiimote/wiimote.cpp | |
index dbf2472..e4e6ed1 100644 | |
--- a/source/plugin/wiimote/wiimote.cpp | |
+++ b/source/plugin/wiimote/wiimote.cpp | |
@@ -1,12 +1,69 @@ | |
#include "wiimote.h" | |
+#include "../../core/devices/device.h" | |
#include <iostream> | |
#include <cstring> | |
#include <sys/epoll.h> | |
#include <fcntl.h> | |
#include <errno.h> | |
+#include <math.h> | |
+ | |
+#define HOLDCURSORNUMPOLL 1 | |
+#define HOLDCURSORNUMPOLLB 2 | |
+//#define WEIGHTMODIFIER 0.25 | |
+//#define WEIGHTMODIFIER 0.75 | |
+//#define WEIGHTMODIFIER 0.76 | |
+#define WEIGHTMODIFIER 0.76 | |
+#define REMAINDERCUTOFF 0.03 | |
+//#define MPDEADZONE 77 | |
+#define MPDEADZONE 77 | |
+//#define MPMINMOUSEOFFSET 0.0615 | |
+//#define MPMINMOUSEOFFSET 0.06162 | |
+#define MPMINMOUSEOFFSET 0.0616205 | |
+//#define MPMINMOUSEOFFSET 0.0616206 | |
+ | |
+static double remainderX = 0.0; | |
+static double remainderY = 0.0; | |
+ | |
+//#define SMOOTHXBUFFERLEN 4 | |
+#define SMOOTHXBUFFERLEN 3 | |
+//#define SMOOTHXBUFFERLEN 2 | |
+#define SMOOTHYBUFFERLEN SMOOTHXBUFFERLEN | |
+static double smoothXBuffer2[SMOOTHXBUFFERLEN]; | |
+static double smoothYBuffer2[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 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 int wmpHighEndX = 0; | |
+static int wmpHighEndY = 0; | |
+static unsigned int ignoreMpEventCount = 0; | |
+ | |
+static void rotateIRPoints(double *x, double *y, double rotation); | |
+static void addSmoothBufferValues2(double xval, double yval); | |
+static void getSmoothBufferValues3(double *xval, double *yval); | |
+static void clearSmoothBuffers2(); | |
+static void calibrateMpPoll(int *mpache); | |
device_methods wiimote::methods; | |
+wiimote::wiimote() | |
+{ | |
+ clearSmoothBuffers2(); | |
+ timeInit(&comboForceRatchet); | |
+} | |
+ | |
wiimote::~wiimote() { | |
clear_node(&base); | |
clear_node(&buttons); | |
@@ -159,12 +216,14 @@ void wiimote::store_node(struct udev_device* dev, const char* name) { | |
//we aren't using it now, but grab it so that it is hidden if desired. | |
wiimote_manager::grab_permissions(dev,true); | |
} | |
+ | |
break; | |
case MP: | |
methods.print(ref,"added motion+"); | |
//we never use it, but grab it so that it is hidden if desired. | |
- wiimote_manager::grab_permissions(dev,true); | |
+ //wiimote_manager::grab_permissions(dev,true); | |
motionplus.dev = udev_device_ref(dev); | |
+ open_node(&motionplus); | |
break; | |
case E_NK: | |
methods.print(ref,"added nunchuk"); | |
@@ -407,6 +466,7 @@ void wiimote::process(void* tag) { | |
if (tag == &accel) type = ACCEL; | |
if (tag == &pro) type = WII_U_PRO; | |
if (tag == &balance) type = BALANCE; | |
+ if (tag == &motionplus) type = MP; | |
switch (type) { | |
case CORE: | |
process_core(); | |
@@ -429,5 +489,534 @@ void wiimote::process(void* tag) { | |
case WII_U_PRO: | |
process_pro(pro.fd); | |
break; | |
+ case MP: | |
+ process_mp(motionplus.fd); | |
+ break; | |
} | |
} | |
+ | |
+void wiimote::process_motionplus_mouse() | |
+{ | |
+ // Ignore method for now. Just use currently cached values. | |
+ if (!hasMpEvent && !wmpCalibrated) | |
+ { | |
+ remainderX = 0.0; | |
+ remainderY = 0.0; | |
+ addSmoothBufferValues2(0.0, 0.0); | |
+ return; | |
+ } | |
+ | |
+ static bool disDis = false; | |
+ | |
+ bool event_gen = false; | |
+ | |
+ /*if (holdCursor) | |
+ { | |
+ //printf("HOLDCURSORBUTTONS %d %d", holdCursorButtons, holdCursorCount); | |
+ if ((holdCursorButtons & 0x2) == 0x2 && holdCursorCount >= HOLDCURSORNUMPOLLB) | |
+ { | |
+ holdCursor = false; | |
+ holdCursorButtons = 0; | |
+ //printf("B RELEASE\n"); | |
+ } | |
+ else if ((holdCursorButtons & 0x1 == 0x1) && holdCursorCount >= HOLDCURSORNUMPOLL) | |
+ { | |
+ holdCursor = false; | |
+ holdCursorButtons = 0; | |
+ //printf("A RELEASE\n"); | |
+ } | |
+ else | |
+ { | |
+ holdCursorCount++; | |
+ //printf("++\n"); | |
+ //holdCursor = false; | |
+ } | |
+ } | |
+ */ | |
+ | |
+ if (holdCursor && holdCursorCount >= HOLDCURSORNUMPOLL) | |
+ { | |
+ holdCursor = false; | |
+ } | |
+ else if (holdCursor) | |
+ { | |
+ holdCursorCount++; | |
+ } | |
+ | |
+ bool moveMouse = !forceRatchet && !ratchet && !holdCursor; | |
+ if (!wmpCalibrated) | |
+ { | |
+ if (ignoreMpEventCount >= 2) | |
+ { | |
+ calibrateMpPoll(mpcache); | |
+ moveMouse = moveMouse && wmpCalibrated; | |
+ if (wmpCalibrated) | |
+ { | |
+ printf("CALIBRATION FINISHED\n"); | |
+ ignoreMpEventCount = 0; | |
+ } | |
+ } | |
+ else | |
+ { | |
+ ignoreMpEventCount += 1; | |
+ moveMouse = false; | |
+ } | |
+ } | |
+ | |
+ if (moveMouse) | |
+ { | |
+ double calibrateX = wmpFinalCalibrateX; //0.0; | |
+ double calibrateY = wmpFinalCalibrateY; //0.0; | |
+ int tempcache[3] = {0, 0, 0}; | |
+ | |
+ int currentX = mpcache[0] - calibrateX; | |
+ int currentY = mpcache[2] - calibrateY; | |
+ double rotation = 0.0; | |
+ if (accel.dev) | |
+ { | |
+ rotation = atan2(accelcache[0], accelcache[2]); | |
+ | |
+ double nothingX = currentX; | |
+ double nothingY = currentY; | |
+ if (!disDis) | |
+ { printf("RAW: x(%d) | z(%d) | r(%f)\n", mpcache[0], mpcache[2], rotation); | |
+ printf("BEFORE: x(%d) | z(%d) | r(%f)\n", currentX, currentY, rotation); | |
+ } | |
+ | |
+ rotateIRPoints(¬hingX, ¬hingY, -rotation); | |
+ | |
+ tempcache[0] = nothingX; | |
+ tempcache[2] = nothingY; | |
+ } | |
+ else | |
+ { | |
+ tempcache[0] = currentX; | |
+ tempcache[2] = currentY; | |
+ } | |
+ | |
+ double deadzone = MPDEADZONE; | |
+ double tempdeadangle2 = atan2((tempcache[2]), tempcache[0]); | |
+ double hypno = sqrt(pow(tempcache[0], 2) + pow(tempcache[2], 2)); | |
+ double deadzoneX = deadzone * fabs(cos(tempdeadangle2)); | |
+ double deadzoneY = deadzone * 1.0 * fabs(sin(tempdeadangle2)); | |
+ double normX = fabs(cos(tempdeadangle2)); | |
+ double normY = fabs(sin(tempdeadangle2)); | |
+ double minOffsetX = (fabs(cos(tempdeadangle2)) * MPMINMOUSEOFFSET); | |
+ double minOffsetY = (fabs(sin(tempdeadangle2)) * MPMINMOUSEOFFSET); | |
+ //printf("TEST NORMS: x(%f) y(%f)\n", normX, normY); | |
+ //printf("MIN OFFSETS: x(%f) y(%f)\n", minOffsetX, minOffsetY); | |
+ if (!disDis) | |
+ { | |
+ printf("CAL: x(%d) | y(%d)\n", wmpFinalCalibrateX, wmpFinalCalibrateY); | |
+ //printf("DEADS: static(%f) | dyn(%f) | tempX(%f) | tempY(%f)\n", 78.0, deadzone, tempDeadAdjX, tempDeadAdjY); | |
+ disDis = true; | |
+ } | |
+ | |
+ double x_out = 0.0; | |
+ double y_out = 0.0; | |
+ double mpmaxfeels = 90.0; | |
+ double xratio = 0.0; | |
+ double yratio = 0.0; | |
+ static bool deadStatusX = true; | |
+ static bool deadStatusY = true; | |
+ static double mpSenScale = 0.0013342470315873829; | |
+ | |
+ if (abs(tempcache[0]) > deadzoneX) | |
+ { | |
+ double signbit = tempcache[0] >= 0 ? 1.0 : -1.0; | |
+ x_out = (abs(tempcache[0]) - deadzoneX) * mpSenScale + minOffsetX; | |
+ //xratio = fmin((abs(tempcache[0]) - deadzoneX) / (45000.0 - (deadzoneX)), 1.0); | |
+ //double old_x_out = (60.0 - minOffsetX) * (xratio) + minOffsetX; | |
+ //printf("NEWX: %f | OLDX: %f\n", x_out * signbit, old_x_out * signbit); | |
+ //x_out = (60.0 - 0.0) * (xratio) + 0.0; | |
+ x_out = x_out * signbit; | |
+ //if (deadStatusX) | |
+ { | |
+ //remainderX = 0.0; | |
+ deadStatusX = false; | |
+ } | |
+ } | |
+ else | |
+ { | |
+ //deadStatusX = true; | |
+ remainderX = 0.0; | |
+ } | |
+ | |
+ if (abs(tempcache[2]) > deadzoneY) | |
+ { | |
+ double signbit = tempcache[2] >= 0 ? -1.0 : 1.0; | |
+ y_out = (abs(tempcache[2]) - deadzoneY) * mpSenScale + minOffsetY; | |
+ //yratio = fmin((abs(tempcache[2]) - deadzoneY) / (45000.0 - (deadzoneY)), 1.0); | |
+ //y_out = (60.0 - minOffsetY) * (yratio) + minOffsetY; | |
+ //y_out = (60.0 - 0.0) * (yratio) + 0.0; | |
+ y_out = y_out * signbit; | |
+ //if (deadStatusY) | |
+ { | |
+ //remainderY = 0.0; | |
+ deadStatusY = false; | |
+ } | |
+ | |
+ } | |
+ else | |
+ { | |
+ //deadStatusY = true; | |
+ remainderY = 0.0; | |
+ } | |
+ | |
+ if (x_out != 0.0 || y_out != 0.0) | |
+ { | |
+ 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 ((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; | |
+ | |
+ x_out = x_out - (fmod(x_out * 1000.0, 1.0) / 1000.0); | |
+ y_out = y_out - (fmod(y_out * 1000.0, 1.0) / 1000.0); | |
+ | |
+ //remainderX = x_out - (int)x_out; | |
+ //remainderY = y_out - (int)y_out; | |
+ | |
+ x_out = x_out; | |
+ y_out = y_out; | |
+ | |
+ double smoothX = x_out;//0.0; | |
+ double smoothY = y_out;//0.0; | |
+ | |
+ addSmoothBufferValues2(x_out, y_out); | |
+ getSmoothBufferValues3(&smoothX, &smoothY); | |
+ | |
+ if (smoothX > 0.0) | |
+ { | |
+ double temp = floor(smoothX); | |
+ remainderX = smoothX - temp; | |
+ smoothX = temp; | |
+ } | |
+ else if (smoothX < 0.0) | |
+ { | |
+ double temp = ceil(smoothX); | |
+ remainderX = smoothX - temp; | |
+ smoothX = temp; | |
+ } | |
+ else | |
+ { | |
+ remainderX = 0.0; | |
+ } | |
+ | |
+ if (smoothY > 0.0) | |
+ { | |
+ double temp = floor(smoothY); | |
+ remainderY = smoothY - temp; | |
+ smoothY = temp; | |
+ } | |
+ else if (smoothY < 0.0) | |
+ { | |
+ double temp = ceil(smoothY); | |
+ remainderY = smoothY - temp; | |
+ smoothY = temp; | |
+ } | |
+ else | |
+ { | |
+ remainderY = 0.0; | |
+ } | |
+ | |
+ double testvar = 0.15; | |
+ double testpow = 1.407; | |
+ double tabsX = fabs(smoothX); | |
+ if (tabsX <= normX * testvar) | |
+ { | |
+ double signX = smoothX >= 0.0 ? 1.0 : -1.0; | |
+ smoothX = signX * pow(tabsX / testvar, testpow) * testvar; | |
+ } | |
+ | |
+ double tabsY = fabs(smoothY); | |
+ if (tabsY <= normY * testvar) | |
+ { | |
+ double signY = smoothY >= 0.0 ? 1.0 : -1.0; | |
+ smoothY = signY * pow(tabsY / testvar, testpow) * testvar; | |
+ } | |
+ | |
+ if (smoothX != 0.0 || smoothY != 0.0) | |
+ { | |
+ //printf("NEW EVENT: x(%f) y(%f).\n", smoothX, smoothY); | |
+ struct input_event outX; | |
+ memset(&outX, 0, sizeof(outX)); | |
+ outX.type = EV_REL; | |
+ outX.code = REL_X; | |
+ outX.value = (int)smoothX; | |
+ ref->get_slot_manager()->keyboard->take_event(outX); | |
+ | |
+ struct input_event outY; | |
+ memset(&outY, 0, sizeof(outY)); | |
+ outY.type = EV_REL; | |
+ outY.code = REL_Y; | |
+ outY.value = (int)smoothY; | |
+ ref->get_slot_manager()->keyboard->take_event(outY); | |
+ | |
+ struct input_event outSyn; | |
+ memset(&outSyn, 0, sizeof(outSyn)); | |
+ outSyn.type = EV_SYN; | |
+ outSyn.code = SYN_REPORT; | |
+ outSyn.value = 0; | |
+ ref->get_slot_manager()->keyboard->take_event(outSyn); | |
+ } | |
+ } | |
+ else | |
+ { | |
+ remainderX = fmod(remainderX * 1000.0, 1.0) / 1000.0; | |
+ remainderY = fmod(remainderY * 1000.0, 1.0) / 1000.0; | |
+ //addSmoothBufferValues2(remainderX, remainderY); | |
+ remainderX = 0.0; | |
+ remainderY = 0.0; | |
+ addSmoothBufferValues2(remainderX, remainderY); | |
+ | |
+ double smoothX = x_out;//0.0; | |
+ double smoothY = y_out;//0.0; | |
+ getSmoothBufferValues3(&smoothX, &smoothY); | |
+ | |
+ if (smoothX > 0.0) | |
+ { | |
+ double temp = floor(smoothX); | |
+ remainderX = smoothX - temp; | |
+ smoothX = temp; | |
+ } | |
+ else if (smoothX < 0.0) | |
+ { | |
+ double temp = ceil(smoothX); | |
+ remainderX = smoothX - temp; | |
+ smoothX = temp; | |
+ } | |
+ else | |
+ { | |
+ remainderX = 0.0; | |
+ } | |
+ | |
+ if (smoothY > 0.0) | |
+ { | |
+ double temp = floor(smoothY); | |
+ remainderY = smoothY - temp; | |
+ smoothY = temp; | |
+ } | |
+ else if (smoothY < 0.0) | |
+ { | |
+ double temp = ceil(smoothY); | |
+ remainderY = smoothY - temp; | |
+ smoothY = temp; | |
+ } | |
+ else | |
+ { | |
+ remainderY = 0.0; | |
+ } | |
+ } | |
+ } | |
+ else | |
+ { | |
+ remainderX = 0.0; | |
+ remainderY = 0.0; | |
+ addSmoothBufferValues2(0.0, 0.0); | |
+ } | |
+ | |
+ hasMpEvent = false; | |
+} | |
+ | |
+void rotateIRPoints(double *x, double *y, double rotation) | |
+{ | |
+ double sinAngle = sin(rotation); | |
+ double cosAngle = cos(rotation); | |
+ | |
+ double tempx = *x; | |
+ double tempy = *y; | |
+ double origx = tempx; | |
+ double origy = tempy; | |
+ | |
+ tempx = origx * cosAngle - origy * sinAngle; | |
+ tempy = origx * sinAngle + origy * cosAngle; | |
+ *x = tempx; | |
+ *y = tempy; | |
+} | |
+ | |
+void addSmoothBufferValues2(double xval, double yval) | |
+{ | |
+ smoothXBuffer2[smoothXBufferTail] = xval; | |
+ smoothYBuffer2[smoothYBufferTail] = yval; | |
+ | |
+ smoothXBufferTail++; | |
+ smoothYBufferTail++; | |
+ | |
+ smoothXBufferTail = smoothXBufferTail % smoothXBufferLen; | |
+ smoothYBufferTail = smoothYBufferTail % 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 getSmoothBufferValues3(double *xval, double *yval) | |
+{ | |
+ if (xval && yval && smoothXBufferCount > 0 && smoothYBufferCount > 0) | |
+ { | |
+ double tempx = 0.0; | |
+ double tempy = 0.0; | |
+ double xresult = 0.0; | |
+ double yresult = 0.0; | |
+ double currentWeight = 1.0; | |
+ double finalWeight = 0.0; | |
+ | |
+ for (int i = 0; i < smoothXBufferCount; i++) //(int i = smoothXBufferTail; i != smoothXBufferHead; i = (i > 0) ? i-1 : smoothXBufferLen - 1) | |
+ { | |
+ int idx = (smoothXBufferTail - i-1 + smoothXBufferLen) % smoothXBufferLen; | |
+ //int idx = abs((smoothXBufferTail - 1) - i) % smoothXBufferLen; | |
+ //idx = abs(idx); | |
+ | |
+ tempx += (smoothXBuffer2[idx] * currentWeight); | |
+ finalWeight += currentWeight; | |
+ currentWeight *= WEIGHTMODIFIER; | |
+ } | |
+ | |
+ xresult = tempx / finalWeight; | |
+ *xval = xresult; | |
+ | |
+ currentWeight = 1.0; | |
+ finalWeight = 0.0; | |
+ | |
+ //printf("START: [%i] ", smoothYBufferTail); | |
+ for (int i = 0; i < smoothYBufferCount; i++) //(int i = smoothYBufferTail; i != smoothYBufferHead; i = (i > 0) ? i-1 : smoothYBufferLen - 1) | |
+ { | |
+ int idx = (smoothYBufferTail - i-1 + smoothYBufferLen) % smoothYBufferLen; | |
+ //printf("%i ", idx); | |
+ //int idx = abs((smoothYBufferTail - 1) - i) % smoothYBufferLen; | |
+ | |
+ tempy += (smoothYBuffer2[idx] * currentWeight); | |
+ finalWeight += currentWeight; | |
+ currentWeight *= WEIGHTMODIFIER; | |
+ } | |
+ | |
+ //printf("\n"); | |
+ | |
+ yresult = tempy / finalWeight; | |
+ *yval = yresult; | |
+ } | |
+} | |
+ | |
+void clearSmoothBuffers2() | |
+{ | |
+ memset(&smoothXBuffer2, 0, sizeof(smoothXBuffer2)); | |
+ memset(&smoothYBuffer2, 0, sizeof(smoothYBuffer2)); | |
+ | |
+ smoothXBufferHead = 0; | |
+ smoothYBufferHead = 0; | |
+ smoothXBufferTail = 0; | |
+ smoothYBufferTail = 0; | |
+ smoothXBufferCount = 0; | |
+ smoothYBufferCount = 0; | |
+} | |
+ | |
+void calibrateMpPoll(int *mpcache) | |
+{ | |
+ if (!wmpCalibrated) | |
+ { | |
+ wmpSumCalibrateX += mpcache[0]; | |
+ wmpSumCalibrateY += mpcache[2]; | |
+ calibratePollCount += 1; | |
+ | |
+ if (abs(mpcache[0]) > abs(wmpHighEndX)) | |
+ { | |
+ wmpHighEndX = mpcache[0]; | |
+ } | |
+ | |
+ if (abs(mpcache[2]) > abs(wmpHighEndY)) | |
+ { | |
+ wmpHighEndY = mpcache[2]; | |
+ } | |
+ | |
+ 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/source/plugin/wiimote/wiimote.h b/source/plugin/wiimote/wiimote.h | |
index 399c45a..95d119c 100644 | |
--- a/source/plugin/wiimote/wiimote.h | |
+++ b/source/plugin/wiimote/wiimote.h | |
@@ -5,6 +5,7 @@ | |
#include <iostream> | |
#include <thread> | |
#include <sys/epoll.h> | |
+#include <sys/timeb.h> | |
#include <mutex> | |
#include <unistd.h> | |
#include <linux/input.h> | |
@@ -28,11 +29,19 @@ struct dev_node { | |
int fd = -1; | |
}; | |
- | |
+unsigned int timeElapsedInMilliseconds(struct timeHelper *time); | |
+void timeRestart(struct timeHelper *time); | |
+void timeStop(struct timeHelper *time); | |
+void timeStart(struct timeHelper *time); | |
+void timeInit(struct timeHelper *time); | |
enum ext_type {NUNCHUK, CLASSIC, GUITAR, DRUMS, UNKNOWN}; | |
- | |
+struct timeHelper | |
+{ | |
+ bool running; | |
+ struct timeb startTime; | |
+}; | |
struct wii_leds { | |
@@ -63,6 +72,7 @@ public: | |
modes mode = MODE_UNCERTAIN; | |
+ wiimote(); | |
~wiimote(); | |
virtual void handle_event(struct udev_device* dev); | |
@@ -95,10 +105,23 @@ public: | |
protected: | |
void process(void*); | |
virtual int process_option(const char* opname, const MGField value); | |
+ void process_motionplus_mouse(); | |
private: | |
+ bool ratchet = false; | |
+ bool holdCursor = false; | |
+ unsigned int holdCursorButtons = 0; | |
+ bool forceRatchet = false; | |
+ bool zEngaged = false; | |
+ unsigned int buttonstatus = 0; | |
+ unsigned int holdCursorCount = 0; | |
+ struct timeHelper comboForceRatchet; | |
+ | |
irdata ircache[4]; | |
int balancecache[4] = {0, 0, 0, 0}; | |
+ int mpcache[3] = {0, 0, 0}; | |
+ int accelcache[3] = {0, 0, 0}; | |
+ bool hasMpEvent = false; | |
std::mutex mode_lock; | |
bool wm_accel_active = false; | |
bool nk_accel_active = false; | |
@@ -128,8 +151,10 @@ private: | |
void process_ir(int fd); | |
void process_pro(int fd); | |
void process_balance(int fd); | |
+ void process_mp(int fd); | |
void compute_ir(); | |
void compute_balance(); | |
+ void computeForceRatchet(); | |
void process(int type, int event_id, int64_t value); | |
void clear_node(struct dev_node* node); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment