Skip to content

Instantly share code, notes, and snippets.

@Ryochan7
Last active July 24, 2018 06:06
Show Gist options
  • Save Ryochan7/a288dcfe70445cb722207a1739541540 to your computer and use it in GitHub Desktop.
Save Ryochan7/a288dcfe70445cb722207a1739541540 to your computer and use it in GitHub Desktop.
Changes made to MoltenGamepad for Wiimote Motion Plus support
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(&nothingX, &nothingY, -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(&current_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